Building a Line Follower Robot
CPP Robotics Club
Ball Caster: This will be the front-turning wheel that will
allow the robot to swivel one way or the other without scraping the
chassis. The ball caster is easy to mount; add the spacer to give
it enough height so that the platform stays level with the ground
(or you can leave it out as long as the sensors that will be
mounted are not too close to the ground). Then add the ball caster
and use the bolts and nuts to mount it to the chassis. There is an
instructions manual to put the ball caster together that came in
the box.Gearbox and wheels: This gearbox has 2 different speed
settings and we will be using the slowest speed (the higher number
ratio). There are four large gears and one very small white-grey
gear that we will be using to get the slow speed. There is a
diagram that came with the gearbox that shows how to mount the
gears in what order.NOTE: There are 3 possible wholes that the axel
can go through shown in the diagram. The one that will be used in
this project is the center hole (C) between the set of 3 holes (2
of them labeled A and B) towards the front of the gearbox housing
and the one lone hole near the motors that does not go through the
outside pieces (the center main piece of the housing has the hole
going through each side).
When mounting the axel to drive the wheel, instead of using one
long rod to spin the wheels, use 2 short rods so that each motor
assembly spins independent of each other.
Once the gearbox is put together, mount the wheels by sliding
them on the end of each axel (make sure they are all the way on the
axel or they will not fit through the wheel holes in the
chassis).Step 2: Understanding the Electronics
http://www.pololu.com/catalog/product/958The sensors are an
Infrared (IR) LED and phototransistor pair that work together to
determine the reflectance of a surface. The theory is that the
sensors will shine light to a surface and, depending on the type of
surface and the color, the reflected light will be determined by
the phototransistor and return a certain value to the
microcontroller. Infrared light cannot be seen by the human eye,
but almost all digital cameras can (even phone cameras).
http://www.sparkfun.com/commerce/product_info.php?products_id=9950The
Arduino is already pre-built out of the box; that will be used
later when we finally build the program and test out the robot.
This is the brain of the robot; this will hold the code that will
allow the robot to follow the line and this will have most of the
signal connections plugged in from the motor control board and
sensors.Wiring:Figure 1 is a diagram of how the electronics will be
wired (theoretically). Figure 2 will show the actual wiring;
meaning which actual pin of each component is wired to
another.Figure 1: Diagram of circuit
Figure 2: Layout of circuit
For the Vin, the Arduino will also be connected to it since the
microcontroller can operate between 9-12V. Be careful when putting
together the plug for it, because the Arduino will not work with
the Negative wire connecting to the Positive wire; it has to be
Positive to Positive and Negative to Negative (in general terms,
connect red to red wire and black to black wire). Figure 3. Plug to
Arduino
Fugire 4. Sensor wiring
Step 3: Soldering parts
Transistors:
To solder all the components, start with the Transistors (the
ones with the screw hole and metal tab) to the PCB board. There are
2 different types of transistors that will be used; a TIP 102 NPN
Transistor and an AP1084T33L Voltage Regulator. The Voltage
regulator will have a thicker metal tab than the 102s so make sure
to tell the difference. Leave enough room for the signal and motor
wires as well as jumper wires (in Figure 2, if your board has more
holes than the picture, leave one space in between transistors to
ensure you have enough holes for wiring). Bend the legs so that the
transistors dont slide out in the process of soldering. While
soldering, use your pliers and clamp on the leg that is being
solder. If you have self clamping pliers, use those. NOTE: Reason
for clamping the leg is to keep the transistor from overheating,
which can make the component useless if it gets too hot and melts
the insides.DC Barrel Jack (plug) and 9 volt connector:To set up
the plug for the Arduino, first unscrew the plastic cover off. You
will see 2 tabs (one longer than the other) sticking out the rear
of the main plug section. The smaller tab in the middle is the
Positive (+) tab; that will be connected to the Arduino+ rail in
the board diagram (refer to Figures 1, 2, and 3). Solder a wire
(usually red is the default color for power, but any color will do)
to the tab but do not solder the other end yet. Then solder another
wire to the longer tab (Negative (-)) but do not solder the other
end yet; this will later be soldered to the - rail on the motor
control board (refer to Figures 1, 2, and 3). After both wires are
soldered to the plug, feed the free ends through the plastic screw
cap and screw it back on the plug. Then solder the other ends to
the correct rails on the motor control board.Solder the positive
wire (usually red) of the 9 volt battery snap to the 9 volt rail
and solder the black negative wire to the Negative terminal (refer
to Figure 2).
Wiring Jumper Wires:The only jumper wires you will need on the
motor control board are connecting the power supply to the
transistors (refer to Figure 2). Make sure to clamp to the leg of
the transistor to keep them from overheating!
Wiring Transistors:
After all the Transistors are soldered add and solder wires to
the signal rail of the 2 TIP102 transistors (refer to Figure 2 and
solder where the blue dots indicate on the PCB board). Look on the
diagram (Figure 2) and find the 2 signal wires from the TIP102
transistors; solder a separate header to each of them.Wiring Sensor
Wires:Then solder 3 separate wires to the sensors, but be careful
because these can easily melt due to their size; make sure to only
hold the soldering iron for a short period of time! On the sensors,
take the wires connected to VIN on each sensor and solder both to 1
header pin. Take the 2 GND wires and do the same. For the OUT
wires, solder a separate header to both, do not solder both wires
to one header. Then mount the sensors to the open holes on the ball
caster bracket as long as they are close (at least a penny thick)
but not touching the ground (you can hot glue them on).
Wiring Motor Wires:On the motors there will be 2 tabs that stick
out of the back end. Solder a wire to each; theoretically, we need
to have both motors spin in opposite directions of each other
because of the orientation of the gearbox. The top wire (closest to
the chassis when the gearbox is mounted) on each motor we will
consider to be the positive wire and those will be connected to the
motor controller. The bottom terminal (closest to the ground) of
each motor will be soldered to the ground (or negative) rail on the
motor control board (refer to Figure 2). Then place the chassis
with the mounted gearbox on a surface with the motor tabs facing
you. Imagining that your driving it, take the left wire of the
positive motor tab and solder it to the motor controller (refer to
Figure 2). Then do the same to the right positive motor wire.BIG
NOTE: Before applying power to the boards, check to make sure that
none of the wiring or soldering is crossing over to the wrong
component. This will possibly damage either the motor controller or
the Arduino or both. So always double check to make sure nothing is
crossing over!Connect the 9V battery and check to see if any of the
components are starting to get really hot. If just one gets hot,
disconnect the 9V battery immediately and look for any
shorts.Connecting Electroncis to Arduino:
Now that everything is wired and ready to work, the wires will
need to be plugged into the Arduino. For the sensor wires, the VIN
wire will go into the 5V pin on the Arduino located near the analog
pins. The GND wire from the sensors will go into the GND pin next
to the 5V pin. Depending which sensor is on what side, take the
right sensors signal wire and plug it into analog pin 2. Take the
left sensors signal wire and plug it into analog pin 0. Locate the
transistor signal wires and determine which one is the right motor
and which is the left motor (refer to Figure 2 and look for the 2
blue wires; those are the signal wires to vary the speed of the
motors). Take the left motor signal wire and plug it into digital
pin 3 on the Arduino. Then take the right motor signal wire and
plug it into digital pin 6.
Step 4: Build ProgrammingThe Arduino is based around the C/C++
language in the computer world. Most of the coding is predefined
and does not need to be made from scratch (which will make this
build a lot easier). Here is a list of commands that we will be
using:
#define
int
void setup()
void loop()
pinMode()
analogRead()
analogWrite()
delay()
if()
else
//, /* */
Each of the commands has their own functions and can be used in
a number of combinations. #define:The #define command allows you to
set a certain digital pin to a specific name (the analog pins do
not need to be), such as #define LED 13. This will set the LED to
be used on digital pin 13 of the Arduino.
Int:int is used to hold a variable (whole numbers for this
particular command) and will be used to hold our sensor readings
and move the robot around. Such as:
int i = 0
voids:void setup and void loop are the main sections of the code
that are required to run the Arduino program. The setup predefines
what each pin is going to be used as (for digital pins only). Such
as pinMode (LED, OUTPUT) will mean that it will apply 5V to digital
pin 13 defined earlier. It can also be set as INPUT to read a
sensor that returns a 0 or 1 value. void loop is the main function
of the code that will run what you write. In this case, we want it
to read the sensors and then turn on the motors and either speed up
or slow down the motors accordingly.
Analogs:
analogRead is used for reading the inputs from the analog pins
on the Arduino (we will be using 2 of these pins for the robot).
The value that will be returned will range from 0-1023, since the
Arduino use a 10 bit analog to digital converter. analogWrite is
used to write a Pulse Width Modulation signal (PWM) to the
specified digital pin. A PWM signal ranges from 0 to 255 and can be
used to vary the speed of the motor to that pin. To write one of
these analog commands you do the following:
analogRead(0)The 0 means that it will read from pin 0 of the
analog inputs.
analogWrite(LED,255)
This will write a PWM signal of 255 (which is the highest value)
to pin 3 of the digital pins. This also means that the power output
from digital pin 3 will be a full 5V.
NOTE: There are only certain pins that are PWM and are labeled
on the Arduino board face.
Pulse Width Modulation (PWM):How a PWM signal works is a square
wave is generated with one high point and one low point (0v=low and
5v=high). This acts as a throttle for the motor controllers to
change the speed; for the Arduino, the values that are used for the
PWM signal is from 0-255. Here is a problem, we have a sensor that
can read a value up to 1023, but we can only write a signal at a
max of 255. To compensate for the huge range, we divide the sensor
signal by 4 to closely get the 255 PWM value we need.
Delay:The delay( ) command pauses the code for a certain amount
of time before continuing. This is based in milliseconds, so to
stop the code for 1 second, we write:
delay(1000);
ifs and elses:if and else statements are comparison commands.
The if statement checks to see if a certain range or behavior has
been met. Such as:
int i=0
if (i==0)
{
Then do this
}
There is a BIG difference between = and ==. The single = means
that the particular int will equal that number. The double == means
that the int must equal to the number specified in the if ()
statement.
The else statement means that if the if statement is not
satisfied, then you do this other command. Such as:
int i=1
if (i==0)
{
Then do this
}
else
{
Do this instead
}
The { } are needed when you want to only do this set of commands
at one time (this particularly deals with multiple actions or a for
loop (this will not used in the code covered)).
Commenting (or leaving out):To have certain parts of a code not
work (but you dont want to delete it yet), you use two different
forms of commenting. One is //; this will comment out a part of one
line so that the Arduino knows to skip that part of a code.
NOTE: This comment form can be used in two ways; 1) you can
comment a whole entire line out so it will not be used or 2) you
can comment a section of the line out but still use the other that
was not commented out.
Ex:
1) //pinMode(LED,OUTPUT);
a. This will comment the whole line out and will not be used
2) pinMode(LED,OUTPUT); // This will set LED pin as output
a. This form will compute the pinMode action but will skip over
the comment section to the right of the backslashes
// form only comments out anything to the right of the
backslashes.
The second commenting form is /**/ where is the code sectioned
out. This form only comments out the code in between the /* and the
*/. Such as:
pinMode(/*LED,OUTPUT*/);
This will comment out the section so that the Arduino skips over
the code within the parentheses and moves on to the rest of the
code. This method can be used to comment out entire sections of
code.
Layout order of code:Now here is how to organize the code to
work properly:
#define ___
int ___;
void setup( )
{
pinMode( , );
}
void loop( )
{
Commands;
}
The semicolons are needed for anything that does not do some
type of specific or main function. Such as int, pinMode, etc. This
will be explained in the workshop or can be understood more at
arduino.cc.Uploading the code to the Microcontroller:
After making your code, go to Tools > Boards and select which
microcontroller you have. Then under Tools > Serial choose which
port your microcontroller is set to (you may have to keep selecting
and uploading until the correct one is selected if there is more
than one selected). Along the toolbar, the button with the arrow
pointing right towards 2 sets of vertical dotted lines is the
Upload button; this will transfer the code you made to the
microcontrollers memory. If all goes well, it will indicate that
the code has been uploaded successfully; otherwise it will give an
error and a small description on what the error is.EXTRA: Serial
Connection (reading sensors feedback)
The following line of code can be added to look at the numbers
being returned from the sensors. The communication used is called
Serial. There are 2 parts that have to be used in order to see the
numbers being fed from the sensors to the Arduino.
First is in the void setup(). Somewhere in the {}, write out
Serial.begin(9600);. This will let the Arduino know that data will
be sent back to the computer (in this case, numbers will be sent
from the sensors, travel through the serial of the Arduino and be
displayed on the computer screen).
Second is in the void loop(). In the {}, near the end before the
delay, there are 2 command lines that have to be used to properly
see the numbers. One is Serial.print() and the other is
Serial.println (). The difference between the two codes is that
println will start a new line after it prints the line of code in
between (). print will just keep printing until the code specifies
to start a new line.
To set up the serial monitor to view the numbers, first we need
to code lines that will allow to print on the computer screen. To
start off, we will use a variable from the code below for now, we
will use the L_sens variable. Type out Serial.print(LM); this will
print out the words LM because the quotations mean it will print
out text (space also counts as text). Next, type
Serial.print(L_sens); without the quotations, the code will now
search for that exact variable from the rest of the code to see if
there is a number associated with it. If so, the number will be
printed out. Now to create a tab as if you pressed tab in Microsoft
Word, type Serial.print(\t); this will create a space similar to a
tab space. Continue to add printing codes until you are ready to
print on another line (Serial.pring();).
To see any of the text or values after you upload the code, you
need to open the Serial Monitor built into the Arduino program. In
the main Arduino window, along the top there is a tool bar, select
the icon that looks like a box hanging on a string and pulley. This
is the Serial Monitor that will allow you to see the numbers the
sensors are returning.
Here is the extra code that is not necessary, but can be helpful
to determine a better value for the code to work off of:
void setup(){ Serial.begin (9600);
}void loop()
{
Serial.print("LM");
Serial.print(L_sens);
Serial.print("\t");
Serial.print("RM");
Serial.print(R_sens);
Serial.print("\t");
Serial.println("");
delay(100);}
The delay(100) is just a slower speed to see the values better
on the monitor when they print out, or else the printing is going
so fast that the numbers are not readable.The code:Here is the code
for the Hammerhead style to be used in the robot:
#define Left_mot 3 // Left motor PWM
#define Right_mot 6 // Right motor PWM
int L_sens; // Left Sensor
int R_sens; // Right Sensor
int state, prev_state; //which state the robot is in (turning
left, turning right, straight)
void setup(){ // Will apply 5V to each of these pins when
needed
pinMode (Left_mot, OUTPUT);
pinMode (Right_mot, OUTPUT);
}
void loop() // start of main function and will keep
repeating
{
state = 1; //state will equal 1 and bot will go straight
//-----------------------------------------------------------------------------------
while (state ==1) //state will make robot go straight or
continue with the last state it was in
{
if (state == 1)
{
analogWrite(Left_mot,70);
analogWrite(Right_mot,70);
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
if (R_sens < 120) // Compares the right sensor to a certain
range
{
state = 2;
}
else if (L_sens < 120) // Compares the left sensor to a
certain range
{
state = 3;
}
}
else if (prev_state == 2) //looks at previous state before
change of surface
{
analogWrite(Right_mot,15); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,100); // Writes a PWM signal to the Left
motor pin
if (R_sens < 120) // Compares the right sensor to a certain
range
{
state = 2;
}
}
else if (prev_state == 3) //looks at previous state before
change of surface
{
analogWrite(Right_mot,100); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,15); // Writes a PWM signal to the Left
motor pin
if (L_sens < 120) // Compares the left sensor to a certain
range
{
state = 3;
}
}
delay(50); // pauses the code for a certain time
}
//-----------------------------------------------------------------------------------
while (state == 2) // state where robot is turning right
{
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
analogWrite(Right_mot,15); // Writes a PWM signal to the Left
motor pin
analogWrite(Left_mot,100); // Writes a PWM signal to the Right
motor pin
if (L_sens < 120) // Compares the right sensor to a certain
range
{
prev_state = state;
state = 3;
}
else if (R_sens < 120 && L_sens < 120)
{
prev_state = state;
state = 1;
}
delay(50); // pauses the code for a certain time
}
//---------------------------------------------------
while (state == 3) // state where robot is turning left
{
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
analogWrite(Right_mot,100); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,15); // Writes a PWM signal to the Left
motor pin
if (R_sens < 120) // Compares the right sensor to a certain
range
{
state = 2;
}
else if (R_sens < 120 && L_sens < 120)
{
prev_state = state;
state = 1;
}
delay(50); // pauses the code for a certain time
}
}
Here is the code for the Inverse style to be used in the
robot:
#define Left_mot 3 // Left motor PWM
#define Right_mot 6 // Right motor PWM
int L_sens; // Left Sensor
int R_sens; // Right Sensor
int state, prev_state; //which state the robot is in (turning
left, turning right, straight)
void setup(){ // Will apply 5V to each of these pins when
needed
pinMode (Left_mot, OUTPUT);
pinMode (Right_mot, OUTPUT);
}
void loop() // start of main function and will keep
repeating
{
state = 1; //state will equal 1 and bot will go straight
prev_state = 0;
//-----------------------------------------------------------------------------------
while (state ==1) //state will make robot go straight or
continue with the last state it was in
{
if (state == 1 && prev_state == 0)
{
analogWrite(Left_mot,70);
analogWrite(Right_mot,70);
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
if (R_sens > 120) // Compares the right sensor to a certain
range
{
state = 3; // goes to while loop state == 3 below
}
else if (L_sens > 120) // Compares the left sensor to a
certain range
{
state = 2; // goes to while loop state == 2 below
}
}
else if (prev_state == 2) //looks at previous state before
change of surface
{
analogWrite(Right_mot,15); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,100); // Writes a PWM signal to the Left
motor pin
if (L_sens < 120) // Compares the left sensor to a certain
range
{
prev_state = 0; // goes to while loop state ==1 &&
prev_state == 0 above
}
}
else if (prev_state == 3) //looks at previous state before
change of surface
{
analogWrite(Right_mot,100); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,15); // Writes a PWM signal to the Left
motor pin
if (R_sens < 120) // Compares the right sensor to a certain
range
{
prev_state = 0; // goes to while loop state ==1 &&
prev_state == 0 above
}
}
delay(50); // pauses the code for a certain time
}
//-----------------------------------------------------------------------------------
while (state == 2) // state where robot is turning right
{
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
analogWrite(Right_mot,15); // Writes a PWM signal to the Left
motor pin
analogWrite(Left_mot,100); // Writes a PWM signal to the Right
motor pin
if (R_sens > 120) // Compares the right sensor to a certain
range
{
prev_state = state;
state = 3;
}
else if (R_sens > 120 && L_sens > 120 || R_sens
< 120 && L_sens < 120)
{
prev_state = state;
state = 1;
}
delay(50); // pauses the code for a certain time
}
//---------------------------------------------------
while (state == 3) // state where robot is turning left
{
L_sens = analogRead(0)/4; // Reads the left sensor
R_sens = analogRead(2)/4; // Reads the right sensor
analogWrite(Right_mot,100); // Writes a PWM signal to the Right
motor pin
analogWrite(Left_mot,15); // Writes a PWM signal to the Left
motor pin
if (R_sens < 120 && L_sens < 120 || R_sens >
120 && L_sens > 120)
{
prev_state = state;
state = 1;
}
delay(50); // pauses the code for a certain time
}
}NOTE: The picture shown here is the prototype, the one you will
be making will differ for some parts.
Ball Caster, sensors (front end)
Gearbox
Wheels
Hole C is where the axel will go for the wheels to properly fit
onto the chassis.
Set of 3 holes towards the front of the robot (2 are A and
B)
The hole that doesnt go all the way through (for outside
pieces)
AP1084 Voltage Regulator
TIP102
Arduino
Positive (+)
Arduino negative (-)
The silver bar on the black transistors is the heatsink (the
silver metal tab on the actual transistor).
17