1 ShaftEncoder
1 ShaftEncoder
2/27/2013
Table of Contents
1 Overview/Objective (Walter)
2 Reference Material (Paul)
3 Mission Checklist (Paul)
4 How it Works (Walter)
5 Instructions
5.1 Software Downloads (Paul)
5.2 Shaft Encoder Demo (Paul)
5.3 Installing shaft encoders on Rover (Walter)
5.4 Traveling a set distance (Walter)
5.5 Using Matlab (Paul)
6 Make the Rover Go Straight(Walter)
8 Code (Walter)
8.1 Calibration Code
8.2 Go1Foot
8.3 Matlab Script
1 Overview/Objective
The purpose of incorporating a shaft encoder is to have an accurate way of measuring how far
the rover has traveled. In previous semesters the rovers were told to go forward for a certain
amount of time, now we are able to tell it to go a certain number of inches.
2 Reference Material
1. Arduino IDE for Arduino UNO Link
2. Adafruit Motor Shield library Link
3. Alps EC11B15202AA rotary encoder cut sheet Link
3 Mission Checklist
□ Connect LED’s to the shaft encoder on a breadboard. The LED’s should visually show
the type of output shaft encoder produces.
□ Use shaft encoder to have rover travel a predetermined distance. Monitor rover
movement on Matlab.
4 How it Works
If you’ve ever seen the inside of a roller ball mouse you may have noticed the optical shaft
encoder. The ball of the mouse would roll against the rim of the shaft encoder, causing it to turn.
The computer would read how many pulses occurred and the mouse would move on the screen
accordingly.
Figure 5.1
Our encoder behaves similarly. The input channels are configured with pull up resistors and by
default have a logic of 1 or HIGH. When channel A hits its first “click” it will essentially close a
switch between A and C. C is connected to ground causing our input to be read as logic 0 or
LOW. The next click for channel A will open the switch and we will have our HIGH value again.
The optical encoder only represents one of the channels of our shaft encoder, so why do we
have two?
If we only use one channel and rotate the shaft clockwise we would see
1010101010101....
If we use one channel and rotate the shaft counter clockwise we would see
101010101010....
With two channels we can count from 0 to 3 and tell if we are moving
clockwise: 10,11,01,00,10,11.... (2,3,1,0,2,3....)
counterCW: 01,11,10,00,01,11... (1,3,2,0,1,3...)
However we do not need to use the sensor to find this information as we will be telling the rover
weather we are going forwards or backwards. The only use for the shaft encoder is to
accurately record how far we have gone. Therefore we will only need one channel
5 Instructions
5.1 Software downloads
∙ Inside the zip file there will be a header file and a c++ source file. Both these files must be in
the same folder as the sketch included at the end of this lab.
5.2 Shaft Encoder Demo
The rotary encoder used in this lab is a quadrature encoder. Refer to the encoder
documentation. The encoder has a ground pin (pin C) and two signal pins (pins A and B). The
pins not only give the number of revolutions the encoder has turned through, but the pins can
also determine which way the encoder has turned. LEDs will be used in order to demonstrate
this point. Wire a Arduino / breadboard as shown in Figure 1.
Figure 1. How to wire the shaft encoder to LED’s (Image developed using Fritzing)
As the encoder turns, it will establish a ground that will turn the LEDs on or off. When the
encoder is turned the LEDs light off in a pattern that is indicative of the direction the encoder is
turning.
5.3 Installing shaft encoders on Rover
1. Solder 68 inch wires on each of the 3 pins or preferably crimp together a female connector
that will go over the 3 pins. These pins break off easily, try to minimize any bending. Do not
panic if one of the outside pins break off as you will only need one of them. If the middle pin or
both the outside pins break off then get a new encoder.
2. Remove track and back wheels from the rover.
3. Remove the original shaft that comes with the chassis kit.
4. Insert shaft encoder in place of the original shaft, make sure pins are pointing towards the
arduino. Figure 4.1 has the pins facing the wrong way.
5. Slide the nut over the shaft and tighten it down so that the side with pins can not rotate. The
shaft should still be able to rotate. Check Figure 4.1.
6. Reinstalling the wheels we can see that they stick out a bit more due to the shaft encoder.
You can see this in Figure 4.2. Try flipping the wheels around and installing them the opposite
direction. This should put them back in line.
7. Now for the fun part, the wheel needs to turn the shaft encoder. The best method would be to
drill a hole in the wheel that would allow a small bolt to come in facing the flat side of the shaft
and pinch it in place. It is well advised not to glue the wheel to the shaft encoder. If the pins of
your shaft encoder break off you will need to replace it.
8. Run the wires through the large hole visible in Figure 4.2
9. For the sake of making things simple, connect channel A or B of the shaft encoders to I/O pin
2 and Analog pin 0. Connect both C pins to ground. Check Figure 4.3.
Figure 4.3
5.4 Traveling a set distance
Read through the code at the end of this lab named Go1Foot. It has very detailed comments
that explain exactly what is going on. For a general understanding, the code tells each motor to
go forward until one of the motors reaches a certain number of pulses. Once one of the
encoders reaches this number both motors will turn off so that the rover will not turn when it
reaches its destination. It is important to make sure the rover has both motors going at the
same speed. You can set both motors to 200 and manually increase the speed of the slower
motor until they both reach the same speed. You can also check out section 6 on the Calibration
code if you feel like having the arduino try to do this for you. Once you have it going straight you
should be able to tell the rover the exact distance to travel using the conversion of (80
pulses/1foot). We reached this number by telling the arduino to go 50 clicks which caused the
arduino to go 7.5 inches. If we wanted 12 inches that would be 12in*(50 click/7.5in)=80 clicks
per foot. Try getting your rover to go 5 feet to see how accurate this is.
Matlab can be used to graph out rover displacement. The program reads a serial output from the
Arduino and displays the data on a plot. In order to start the program, a serial object has to be
created in Matlab. This object contains all the parameters used to establish communication.
The rover uses one encoder channel to determine movement. The encoder has 30 transitions
per revolution. As discussed before, the encoder is the center of the rover rear wheel. Rover
displacement per transition can be given by the following expression:
Upload the Matlab Code into the Arduino. This code outputs the number of times the encoder
has changed states. This data is then outputted through the serial pins. A matlab script takes
this data and manipulates it in order to get distance traveled and velocity. The matlab script can
be run at any time. Once rover is moving, run the script. A graph should appear that shows
displacement and velocity plotted on the same graph. Refer to the Matlab Script at the end of this
report.
Figure 5.5
void setup()
{
Serial.begin(115200);
Serial.println("Motor setup");
void loop()
{
turnEncoder1=0;
turnEncoder2=0;
while(turnEncoder1<NumbPulse || turnEncoder2<NumbPulse)
{
boolean stateA1 = digitalRead(pin2);
boolean stateA2 = digitalRead(pinA0);
Serial.print("Left:");
Serial.print(turnEncoder1);
Serial.print("steps, Right:");
Serial.print(turnEncoder2);
Serial.println("steps");
motor1.run(RELEASE); // stopped
motor2.run(RELEASE);
Serial.println("Both motors stopped");
delay(1000);
x=0;
if (turnEncoder1>turnEncoder2)
{
x=turnEncoder1turnEncoder2;
if (x>2 && x<5)
{
M2speed++;
}
if (x>4)
{
M2speed += 2;
}
}
if (turnEncoder2>turnEncoder1)
{
x=turnEncoder2turnEncoder1;
if (x>2 && x<5)
{
M1speed++;
}
if (x>4)
{
M1speed += 2;
}
}
if (x<3)
{
counter++;
if (counter== 5)
{
Serial.println("***********************************");
Serial.print("set M1 speed to ");
Serial.println(M1speed);
Serial.print("set M2 speed to ");
Serial.println(M2speed);
Serial.println("***********************************");
delay(20000);
}
}
else
{
counter=0;
}
Serial.print("counter=");
Serial.println(counter);
Serial.print("M1speed=");
Serial.println(M1speed);
Serial.print("M2speed=");
Serial.println(M2speed);
delay(5000);
}
Go1Foot
#include <AFMotor.h>
void setup()
{
Serial.begin(115200); // set up Serial library at 115200 bps
void loop()
{
turnEncoder1=0; //Reset counters if making another travel
turnEncoder2=0;
// while neither motor has reached their last step, continue to run forward
// and keep track of what step you are on
while(turnEncoder1<NumbPulse && turnEncoder2<NumbPulse)
{
boolean stateA1 = digitalRead(pin2); //Read shaft encoders and see if it has
boolean stateA2 = digitalRead(pinA0); //changed from low to high or vice versa
}
//While walking, tell us how many steps you have left to take
Serial.print(y);
Serial.print("Left:");
Serial.print(turnEncoder1);
Serial.print("steps, Right:");
Serial.print(turnEncoder2);
Serial.println("steps");
}
#include <AFMotor.h>
void setup()
{
Serial.begin(9600); // set up Serial library at 9600 bps
void loop()
{
turnEncoder1=0; //Reset counters if making another travel
turnEncoder2=0;
AvgStep=0;
// while neither motor has reached their last step, continue to run forward
// and keep track of what step you are on
while(turnEncoder1<NumbPulse && turnEncoder2<NumbPulse)
{
boolean stateA1 = digitalRead(pin2); //Read shaft encoders and see if it has
boolean stateA2 = digitalRead(pinA0); //changed from low to high or vice versa
//Find the average step taken between both shafts and send to MATLAB
AvgStep=((turnEncoder1+turnEncoder2)/2);
Serial.println(AvgStep, DEC);
delay(10);
}
Matlab Script
%Clear all the variables and clear command window
clear all
clc
while(t<interv)
b = fscanf(s,'%d'); %Reads what is outputed from Arduino
if(t==1) %have to perform this if,else loop to ensure treal can be used in plot
treal(t,1) = 0;
else
treal(t,1) = treal(t1,1)+tstep;
end
x(t,1) = b;
dis(t,1) = (2*pi*r*b)/(30);
if(t>2)
v(t,1) = (dis(t,1)dis(t1,1))/(treal(t,1)treal(t1,1));
plot(treal,dis);
hold on
plot(treal,v,'');
legend('displacement','velocity');
end
%axis([10,interv,50,1050]);
t = t+pass;
drawnow
end
fclose(s)