Line Follower Robot With Arduino - Very Fast and Very Simple - 11 Steps (With Pictures) - Instructables
Line Follower Robot With Arduino - Very Fast and Very Simple - 11 Steps (With Pictures) - Instructables
By Mati_DIY in CircuitsRobots
Hey! In this Instructable you will learn how to make a line follower robot, made to follow a race
track as fast as possible. This type of robot is very popular and can be used to teach some very
powerful physics, electronics and programing skills and concepts while still being very fun and
simple to make.
The original objective of this robot was to take it to competitions where it would race against other
robots, so my design always focused in achieving the highest speed while conforming to the rules
of the competitions. Nonethless, every or almost every aspect of this robot can be modified to
adjust for the needs, skills or budget of the maker.
My robot, called Yeti, is almost 12cm wide and 20cm long, which are the competitions limits in my
country, and the cost was aproximately 75 US dollars, but the price might be different for you
depending on what components you choose.
The race track can be either a black line on a white background or the other way around. The
competitions I go to have a 2cm line width of white over black and also have small horizontal lines
at the start and end of every straight section for the robot to detect and change speeds taking
advantage of the straight path.
Tools needed:
Materials needed:
2 motors
2 motor brackets
2 wheels
1 ball caster
Arduino UNO
Some screws to hold things together - 1/8 inch or less if you want them to be able to hold the
Arduino
LiPo battery of required voltage - Can be exchanged for regular batteries
1 L293 chip
1 16 (8x2) IC socket
1 L7805 chip
2 100nF capacitors
1 sliding switch (recommended)
2 push-buttons
8 push-up resistors (can be anything from 10k ohm to 100k ohm)
6 220 ohm resistors
6 CNY70 infrared sensors
About 50 pins
13 dupont cables female to female
Something to make the base, I used 3d printing but it can easily be made with wood, plastic,
cardboard or whichever material you have and think would work
Before designing the robot and choosing its parts, it is very important to analize certain aspects
of the robot to ensure we will get the most speed out of it.
Weight: If Force = Mass*Acceleration, it is pretty clear that with the same motors, meaning the
same force, we need to decrease mass to get the most acceleration, which translates to the
highest speed. So as a first key concept we need to keep the weight of the robot into consideration
since less weight = more speed. This means we have to choose the smallest battery possible
without it being so small that it runs out too fast, the lightest wheels possible without loosing the
much needed traction, and also light materials in general like making a thin plastic base instead of
using heavier materials.
Torque vs Speed: When choosing our motors we will see that often times the same model has
different torque and speed options you can choose from. For this robot, we want the most speed
we can get while still having enough torque to take advantage of it, since if we have too little torque
the robot will struggle to move its weight in spite of having high speed rated motors. I found that
the motors I chose, which are linked above, did the job flawlessly.
Height, Length, Width and Center of Mass: To make the most out of the force that the motors are
making, we should make sure that all parts of the robots are as close to the source of the force as
possible. So the center of mass should be right between the motors. This means that the heavier
components like the battery and the electronics should be as close as possible to the motors.
Furthermore, the height should be the least possible, just like the length and width, but we have to
take into consideration that since the pivot point of the robot are the motors, then the furthest
ahead the line sensors are, the sooner the robot detects when it has to turn and so the pivot point,
which is far back, can start turning before it actually goes out of the line giving the robot a quick
response time. Also, since the sensors will be at the front of the robot, far from the motors and
wheels, and the angle at which the robot turns gets bigger the closer together the wheels are, then
for this long robot I chose to have the wheels at a considerable distance from each other making
slower turns to have more control, sensitivity, and reduce robot oscilations.
Arduino is a very powerful and versatile tool, but for our robot we will need some functionality that
the Arduino doesn't have. For this aditional electronics I decided to make a small PCB shield that
plugs on top of the Arduino. If you don't know how to make PCBs you can check another
instructable on making one or have one made for you online and shipped to your house. If you
prefer, you can even make the circuit on a breadboard.
The most essential part here is the H-Bridge IC, which is the L293. Although it may not be the most
efficient motor driver, it is widely available, relatively cheap, and its 600mA per motor maximum
current is sufficient for my chosen motors which in my tests consumed around 300mA each, since
they made very little effort due to the light robot and low friction.
This IC is connected to the battery, the motors, and the Arduino. The Arduino sends information to
the IC in the form of PWM so that the L293 transforms that information to the corresponding
voltage which is fed to the motors, in a way that by varying the duty cycle of the PWM we can vary
the speed of the motors. For more information about this topic you can research "PWM". It is very
important that the pins of the Arduino that transmit this information are PWM-capable, in the case
of the Arduino UNO these pins are numbers 3, 5, 6, 9, 10 and 11. You can simply connect both
ENABLEs of the L293 to 5v and then the 4 inputs to any Arduino digital pins as long as at least 1
pin per motor is PWM-capable.
Apart from the L293, I added to the shield a switch connected to the battery to turn on the robot
just for convinience, 2 push-buttons to calibrate the robot or to start the race which have proven to
be useful, an L7805 to regulate the battery's voltage to the 5v that Arduino needs and 8 pins to
connect the sensors that have 5v, GND, and the 6 analog inputs of the Arduino.
If you want to make this PCB, I have included the files of the Proteus 8.1 Project (PCB design
software), a PDF to print for etching the PCB, the gerber files if you want to have it made for you,
and the schematics if you want to design this yourself or if you use another design software.
Step 3: Electronics: Line Sensors
The track consists of a colored line on a different colored background, usually white and black.
These colors have different brightness and so we can use infrared sensors that emit and recive
reflected IR light. If the sensor, pointing to the ground, is over a bright surface like white, it will
recieve a lot of reflected light, but if it is on a dark surface it will recieve little reflected light. The
sensors I chose to use are the widely popular CNY70. I designed a PCB that has 5 of this sensors in
the form of an arc to have a wider angle of sensing. I used 5 because an odd number of sensors
allows me to have the middle sensor right over the line, so that I'm sure to be on top of the line.
Every one of the 5 sensors are detecting the brightness under them and depending on these
readings, the Arduino can know where the line is in relation to the middle of the robot, where it
should be. Since the Arduino UNO has 6 analog inputs, I also added a 6th sensor at the side, in
order to detect the straight path indicator at the side of the tracks, so that since it is easier to follow
the line in a straight path I can increase the speed in these parts. I have included the same files as
the shield but for this board, sadly I lost the design for the single sensor on the side but it is not
necesary at all to follow the line but rather an aditional feature. In this case I decided to have the
PCB made for me, as a test, and it came out great!
The method I chose for making the base of the robot was 3D printing. It allows me to make several
iterations of the design and test what works best. Also, the plastic is very light but strong enough
for this application. If you want you can make this part out of any material you want since it is a
very simple part and easy to make or design, just take care of all the dimensions and distances, so
that everything fits. I designed 2 parts, one for the main body of the robot and another for holding
the sensor. This allowed me to print 2 sensor holders of different lengths and change them if a
track at a competition is particulary difficult and I need to put a shorter sensor holder to have more
maneuverability. You can find my designs at this Thingiverse post and I encourage you to design
your own or modify mine to your liking: 3D printed base
Step 5: Assembly: Motors, Wheels and Battery
At first you need to solder some cables to the motors. I found that cutting a dupont cable in half is
perfect for soldering each half to a pin of the motor.
The motors are attached to the base with 1/8 inch screws and with the 3d printed bracket linked at
the beginning, but you can also buy a motor bracket if you adjust the holes in the design of the
base.
For the wheels, I found that I could get a lot of traction by making my own covers out of silicone.
What I did was use the wide Pololu wheels, took the black cover out, 3D printed a little cup 45mm in
inner diameter, put the white plastic part of the wheel in the cup and filled the exterior with molding
silicone. In this way I had the plastic part sorrounded with silicone, and when it finished hardening I
had my high traction wheels. If you want to make this you have to make a cup about 40 or 45 mm
in inner diameter and hold the plastic part of the wheels in the middle. Make sure it is in the EXACT
middle! Then you should pour the silicone. This is silicon used for making the molds but here I used
it for the molded part itself. Beware of having the plastic part loose because it may float and you
want it to be perfectly parallel to the plane of the wheel.
The wheels go pressed gently into the motor shaft, taking care to align the D shaped hole with the
shaft, and the pressure will keep them secure in place.
In my design I took into consideration the dimensions of my battery and so it fits tightly between
the motors, make any modifications needed to the base if your battery needs more space or if it is
smaller and you want a more compact robot. The battery is simply held by the components around
it and the cable connection. Since this robot doesn't shake, vibrate, or bump into stuff, the battery
won't jump around and there won't be too much tension on the battery cable.
Step 6: Assembly: Arduino and Shield
The Arduino should be screwed to the base and then the Shield needs to be inserted on top of it. I
found that 2 screws could very easily hold the Arduino but you can add up to four if you modify the
base. You should then connect to the shield the 2 motors and the battery, the sensors will be
connected later. The USB port in the Arduino should be facing to the back of the robot since we will
be connecting to it when we program the robot.
Now that we have the base completed, we need to attach the sensor holder which holds the sensor
board and a ball caster that provides a low friction support to the robot.
The sensor holder is screwed to the base in two points and then the sensors and the ball caster are
screwed to the sensor holder with 2mm screws. If you want you can now attach a 6th sensor to the
holder and connect it to the main sensor board. Now we have to connect the sensor board to the
shield with 8 dupont cables. In the design of the sensor holder I made a hole through which the
cables can pass but that is just for convenience.
We have now finished assembling the robot. If you already have all the parts ready, the whole
assembly takes between 15 and 20 minutes, and maybe a little bit more if you are unexperienced
with tightening screws and connecing electronics.
All that needs to be done now is programming the robot with the Arduino IDE. I will asume you
know how to program an Arduino in general, but if you don't, you can check an instructable on
doing so.
Step 8: Programming: Line Sensors Calibration
This will be the first thing the robot has to do before it can start the race, and it is calibrating the
line sensors. Not all tracks are the same, and sometimes there is little light in the room while other
times all windows are open and sun is shining through lighting up the track with nasty infrared light.
In order to make the robot be able to function in all enviroments, it first calibrates its sensors. To do
this, you simply press the first button, and the robot will rotate around the line trying to have all its
sensors go through every possible state, so basically, it wants to teach the sensors what is white
and what is black in this particular track so its important that during the less than 3 seconds of
calibration, where the Arduino takes thousands of samples of the sensors, that all sensors go over
white and over black, and also that they don't see the floor, get lifted so that they see nothing, or
anything weird, they should just see the track. If you mess up the calibration which sometimes
happen if, for example, you realize that the last sensor didn't actually go over the line, then you
should turn off and on the robot and do the calibration again.
For the time that it is calibrating, this is the code that sets the maximum and minimum values for
each sensor:
int CNYread[CANT_SENS_MAX]; //Maximum sensor quantity is 6
for(int x = 0; x <= CANT_SENS_MAX-1; x++){
CNYread[x] = analogRead(CNY[x]);
CNYmin[x] = (CNYread[x] < CNYmin[x]) ? CNYread[x] : CNYmin[x];
CNYmax[x] = (CNYread[x] > CNYmax[x]) ? CNYread[x] : CNYmax[x];
}
When we press the second button, once the robot is calibrated, the first thing our program will do
for following the line is detecting its position in order to make changes in the speed of the motors.
Since the line might be between 2 sensors, or maybe the line is so wide that the sensors next to the
one over the line reflect some light and give an intermediate value, then we need an algorithm that
makes an average out of the readings in order to determine the lines position. The way the
algorithm works is by asigning a numerical "weight" to each sensor, which are 0, 1000, 2000, 3000,
4000. The analog value of each sensor is scaled from the measured range during the calibration to
a new range between 0 and 1000 for convenience and uniformity. Depending if the line is white or
black we might have to flip this value. Then every value is multiplied by their weight, summed
together, and divided by the sum of the readings. It will look something like this:
Line_position = (Value[0]*weight[0] + Value[1]*weight[1] + ... ) /
(Value[0]+Value[1]+Value[2]+ ... );
If you wish to further investigate about the weighted average you can find really good resources
online.
Step 10: Programming: the PD Algorithm for Following the Line
This is the most important part of the code, it is the algorithm that takes the position of the line as
an input and outputs 2 values for the speed of the motors.
It takes an error value going from -2000 to 2000 (it is just the line position from 0 to 4000, -2000),
and calculates a correction value based on 2 things: The distance to the line which is the
proportional part, and the rate of change of the line position which is the derivative part. From there
the name PD or Proportional-Derivative. The program I made is also prepared for using a PID
algorithm which includes the integral of the line position, but I didn't found it to be useful. It is best
to stick to PD.
The proportional part is the easier to understand, if I am far from the line I make a big turn, if I am
close to the line I make a small turn and if I am on top of the line I make no turn at all. By tweaking
a KP variable we can set the relationship between the error and correction values to make the
smoothest possible following of the line and avoid overshooting for the line. This looks like this:
proportional_correction = KP * line_position
The derivative part is a little more complicated, but still simple enough. The correction here
corresponds to the substraction between the actual position and the last position. If the
substraction is positive then the value is increasing, which means I should make a correction the
other way to stop it from increasing. If the substraction is negative then the value is decreasing,
which means I should make a correction the other way to stop it from decreasing. If the
substraction is null then I make no correction at all. In conclusion, the derivative correction tries to
avoid change and keep the line in whichever position it is, even if it is not in the right position. If we
multiply this correction with a KD variable, we can tweak the variable and eliminate any oscilation
that the proportional might cause. This will look like this:
derivative_correction = KD * (line_position - last_line_position)
last_line_position = line_position //update the last value
Each of the two corrections is essential, the proportional for making sure the line is right in the
middle, and the derivative for smoothing the change and avoid an oscilating robot.
The final correction is the sum of both, and it corresponds to the difference between the speeds of
both motors, which causes the robot to turn.
correction = proportional_correction + derivative_correction
This marks the end of the program explanation, the full program is attached to this instructables if
you want to use it.
This version uses the 6th sensor but if you comment the updatePID function in the start part it will
be stuck on straight (called RECTA) and will always use the same KP, KD, and maxVel values.
When I made the program I wrote several variable names in spanish since it is my native language,
so you are very welcome to ask anything you want about the program. Also, suggestions and
improvements are greatly appreciated.
EEVBlog made an awesome video explaining PID controllers and it may be helpful to you:
EEVacademy #6 - PID Controllers Explained
Step 11: Final Results and National Championship !
In my opinion this robot is an excelent and very fun project to make. In the last year I took my robot,
Yeti, to my county's national championship and it won 1st place! I hope you have as much fun with
it as I did and you can learn something from this Instructable. I would love to answer your
questions and see the line followers that you have managed to create.
These are two videos from the final match on the championship: