Introduction: Line Follower Robot With Arduino - Very Fast and Very Simple

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:

  • Soldering Iron, and solder
  • Wire Snips
  • Needle Nose Pliers
  • PCB etching tools and materials - Can be replaced with a breadboard but will take up more space
  • PC (for programming the robot)

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

Materials chosen in this robot:

Step 1: Key Concepts for Achieving Maximum Speed

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.

Step 2: Electronics: Arduino Shield

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!

Step 4: Making the Structure

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.

Step 7: Assembly: Sensor Board, Ball Caster and Sensor Holder

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];
}	

Step 9: Programming: Reading the Sensors - Weighted Average

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

if(correction > 0){
	motorSpeed(maxVel, maxVel-correction);	//motorSpeed sets both motors speed
}else{
	motorSpeed(maxVel+correction, maxVel);	//maxVel is the maximum speed
}

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.

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:


Comments

author
Sadrul IslamT (author)2017-08-02

can i use 12v - (30:1) Micro Metal Gear motor .

author
Mati_DIY (author)Sadrul IslamT2017-08-06

Yes you can! Although you would need a 3 cell lipo battery to supply the 12v since a 2 cell isn't enough. Alternatively you can use a DC-DC step-up converter module. This module can output a higher voltage than the one at the input, but at a lower current. Also remember to get a small battery so that it is as light as possible. Hope this helps!

author
FabriiD (author)2017-06-27

hola saludos de argentina, me podrías explicar como esta alimentado el arduino porque no se lo ve conectado, y me podrías mostrar a que conectores del arduino están conectados cada pin de la plaqueta del puente h, muchas gracias.

author
Mati_DIY (author)FabriiD2017-07-14

Hola, perdón por la tardanza. El shield tiene un integrado, el 7805, que regula una tensión mayor a 7 v (aprox) a una constante de 5 v para alimentar el Arduino. En la cuarta foto de la sección del shield está el esquemático del circuito que regula la tensión. De esta forma conecto una batería de 7,4 v al shield y al mismo tiempo usa ese voltaje para los motores y usa 5v (obtenidos del 7805) para el Arduino. En la quinta foto de la parte del shield se muestra el circuito de la parte del controlador de motores. Los inputs del controlador están conectados a las patas 2, 3, 4 y 5 del Arduino. Las patas 3 y 5 controlan la velocidad con PWM y la 2 y 4 controlan la dirección. En el programa de Arduino adjunto hay una función para controlar los motores si todo esta conectado como en el esquemático. Saludos

author
arduisot (author)2017-06-27

Is there a diagram that shows the connections between the shield and the arduino? Can you explain the connections please?

author
Mati_DIY (author)arduisot2017-07-14

Hi! If you go to the shield section you will find some images of the shematic circuit. there are 3 conectors from the shield to the Arduino, J1 goes to the digital pins, J2 to the power pins and J3 to the analog pins. In the schematic they are layed out in a similar way to what their actual positions are in the board to keep track of them. J1, J2 and J3 are pins soldered on the bottom of the board and connect on top of the Arduino. In this way, the circuit for the motor controller and the buttons are connected to power an to the digital pins, and the sensor connector is, through the board, connected to the analog pins.

author
SaumikC (author)2017-06-04

i want to make it...It would be my first project..But i am poor in
coding...Would you tell me the step of input code in the arduino...Can i
use this code in Arduino UNO R3??And i want to use IR sensor.. So what
change should be maintain by me in code??

author
Mati_DIY (author)SaumikC2017-06-06

Hi! Maybe this is too much for a first project. I would suggest trying some simpler projects to get a little more experienced with coding and electronics. The first thing to try with Arduino could be blinking a LED: https://www.instructables.com/id/Basic-Arduino-Tut.... Then you could work your way up by doing other simple projects.

To answer your questions, you can use this code for an Arduino UNO R3. You can use any sensor you want that outputs an analog signal corresponding to the brightness of the track. You would have to change the line that says:

#define COLOR NEGRO

And mantain NEGRO or change it to BLANCO depending on the color of the track and the way your sensors output voltage.

Hope it helps

author
tonyD175 (author)2017-04-19

Hello, I'm new to Arduino code. Could you please tell me what are the meanings of those functions "calibrar(calVel, -calVel, 300);" and "dR(BOT1) == 0"? I saw them in your code.

Capture.JPG
author
Mati_DIY (author)tonyD1752017-04-19

Hi! I'm sorry if I didn't explain in detail some parts of the code.

In order to code faster I defined 'digitalRead' as 'dR' with the #define command.

BOT1 is defined to the arduino pin number connected to the 1st button (or "BOT" short for "botón" - button in spanish).

So, dR(BOT1) returns the value of the BOT1 pin which will be 0 or 1 changing when the button is pressed. Since the buttons are 1 when released and 0 when pressed (because of the way it is wired), "dR(BOT1) == 0" is asking whether the button is pressed.

"calibrar" means to calibrate and it is a function I defined. You enter 2 speeds, one for each motor, and then the time. The function will set calVel (calibration velocity) to the left motor and negative calVel to the right motor, for 300 miliseconds. The robot will rotate in its place and for 300ms it will take many readings of the sensors to determine the maximum and minimum values it can possibly have. In this way if you use calibrar() a couple of times alternating the speeds the robot will rotate back and forth while calibrating the sensors with all the readings it is making.

I hope this clears it up. If there is any other thing you would like to know please ask :)

author
tonyD175 (author)Mati_DIY2017-04-19

Thank you!!:)

author
Luis976566 (author)2017-04-13

can i use motors 50:1 in this project ?

with same coding .

author
Mati_DIY (author)Luis9765662017-04-14

Yes you can, the code works with any motors, just be aware that the robot will be a little bit slower

author
jhonny360 (author)2017-04-05

i'm new to these, So now i just wanted to copy paste.but the problem i getting is 3d parts dimensions can you give those as calculated on sheet because ed printing opportunity i don't have.Thanks in advance.it will be very very great of you.

author
Mati_DIY (author)jhonny3602017-04-05

Hi! If you don't have access to a 3d printer you will have to make the structure and the motor brackets in some other way.
If you are using the Pololu motors as I am, you can buy brackets from them as well here: https://www.pololu.com/product/989
To make the structure you can use MDF, plastic, or even foamboard. You will need to cut it with a saw or a cutter and drill the holes. Even if you don't have a drill, you can stick the components with double sided tape since the robot is very lightweight.
I attached 2 images with dimensions for a basic structure that will work with the Pololu motor brackets. If you want to use the 3d printed brackets you would need to change the distances of the holes. The structure I made is based on these dimensions but with some reduced areas and rounded edges.
Good luck with the robot!

base yeti dimensiones.jpgbase yeti dimensiones 2.jpg
author
leeviathan (author)2017-04-02

in the circuit diagram what component is J1,J2,J3?

author
Mati_DIY (author)leeviathan2017-04-04

Hi, J1, J2 & J3 are upside down pins to connect to the arduino as a shield. J, as in 'Jack', is the default designator for male connectors in many design softwares. You can learn about designators here: https://en.wikipedia.org/wiki/Reference_designator

author
dpp (author)2017-04-02

will it able to movein sharp turn

author
Mati_DIY (author)dpp2017-04-04

Apart from the tuning of the software, it generally depends on the traction of the wheels to keep up with the speed of the robot. It may happen that the robot goes so fast that the wheels start drifting.

The slower the robot goes the sharper the turns it can make, and also, with higher traction the robot can go faster and also make sharper turns.

In my case, with the robot from the pictures, at FULL speed (even higher than the video) it can make up to about 7cm-8cm (~3in) radius turns. However, I can make it go slower to achieve even sharper turns.

author
dpp (author)2017-03-29

hello
which library will be required

author
Mati_DIY (author)dpp2017-04-04

The only library needed is the TimerOne library. You can download it here: https://code.google.com/archive/p/arduino-timerone...

And if you want to learn about it you can go to: http://playground.arduino.cc/Code/Timer1

Using this library makes it easy to implement timers in the code and avoid using delays which are generally not preferred.

author
Luis976566 (author)2017-03-23

Hello!

if I use only 5 sensors can I still use the code that you shared?

author
Mati_DIY (author)Luis9765662017-03-23

Yes! In fact the code is already made for 5 sensors.

If you need another number of sensors you can modify the number in the line that says:

#define CANT_SENS 5

Which is the amount of sensors or "Cantidad de Sensores"

author
Dhaval Parmar (author)2017-03-14

can i use TCRT5000l sensor in this project ?
with same coding .

author
Mati_DIY (author)Dhaval Parmar2017-03-18

Yes, as long as it outputs an analog voltage

author
Dhaval Parmar (author)2017-02-24

please show me the backside of shield

author
Mati_DIY made it! (author)Dhaval Parmar2017-02-27

Here you go

20170227_152503.jpg
author
Dhaval Parmar (author)Mati_DIY2017-02-27

thanks

author
DIY Hacks and How Tos (author)2016-12-31

Line followers make a great intro to robotics project. I just wish that my class had a track like this when we did the project.

About This Instructable

8,572views

67favorites

License:

Bio: I'm a 17 years old electronics engineering student
More by Mati_DIY:Simple Line Follower Robot With No Programming - Analog Line FollowerHow to make a PIC programmer - PicKit 2 'clone'Line Follower Robot With Arduino - Very Fast and Very Simple
Add instructable to: