Arduino Line Following Robot for Beginners

by Khevna in Circuits > Arduino

169960 Views, 465 Favorites, 0 Comments

Arduino Line Following Robot for Beginners

LineFollowerFrontCover.jpg
* Updated 08/24/2013 to include more pricing, source information, and top/bottom/wheel templates

Mostly functional for general public, use at own risk!


Hey hey! This is a Programmable Line Following Robot for Beginners. This project is designed to work in tandem with our Arduino Traffic Light for Beginners instructable. However it will work just fine without!

We estimate this can take approximately 10 to 15 hours of work for someone who hasn't done any electronics or programming. If that's a bit much, we recommend checking out this instructable! Depending on how you source your parts, the average cost for this project will probably be between $40 and $60.

This project was designed for a summer camp at a Hackerspace in Ann Arbor, MI. If you aren't already familiar with what a Hackerspace/Makerspace is, we highly recommend you check one out! They can be a wonderful resource for both tools and information. Things like access to a LASER cutter can make this project look significantly better with minimal effort. Find one near you!



Suggested Tools
- Soldering Iron
- Wire Snips
- Pliers (Needle Nose Preferred)
- Wire Strippers (22 AWG)
- Utility Knife
- Phillips Head Screwdriver (No. 1)
- Pencil
- Arduino UNO
- Breadboard
- 9V Battery Holder with 2.1mm Barrel Connector
- LASER Cutter
- Heat Gun

Suggested Materials
- 1 x ($1.50) - Photocell (Sparkfun)
- 2 x ($2.26) - QRD1114 - IR Emitter/Sensor (Sparkfun)
- 3 x ($1.00) - 100 Ohm Resistors - Brown Black Brown (Sparkfun)
- 2 x ($1.00) - 220 Ohm Resistors - Red Red Brown (Sparkfun)
- 2 x ($1.00) - 270 Ohm Resistors -Red Purple Brown (Sparkfun)
- 2 x ($1.00) - 5.6k Ohm Resistors -Green Blue Red) (Sparkfun)
- 2 x ($1.00) - Yellow LEDs -Indicators Lights on Car) (Sparkfun)
- 2 x ($1.00) - Red LEDs -Brake Lights on Car (Sparkfun)
- 1 x ($17.00) - 22 AWG Solid Core Wire in Red, Black, Yellow, Blue, and White colors (Sparkfun)
- 1 x ($2.00) -  Solarbotics Plastic Caster (Solarbotics)
- 2 x ($11.50) - DC Gear Motor (GM2) (Solarbotics)
- 2 x ($2.00) - NPN Transistors (Adafruit)
- 2 x ($1.50) - Diode 1N2001 (Adafruit)
- 1 x 9v Battery (Local Hardware Store)

- 1 x LASER Cut Acrylic Top Plate *
- 1 x LASER Cut Acrylic Bottom Plate *
- 2 x LASER Cut Acrylic Wheels *

- 2 x Thick Rubber Bands - 3.5cm diameter x 1cm width (Local Hardware/Craft Store)
- 1 x 8" Zip Tie (Local Hardware Store)
- 2 x ($0.50) - Machine Nuts - #3 1/2" Micro (Local Hardware Store)
- 2 x ($0.50) - Machine Screws - #3 1/2" Micro (Local Hardware Store)
- 2 x ($0.50) - Machine Screws - #2 1/4"  (Local Hardware Store)
- 4 x ($0.50) - Machine Screws - (~1/8" Diameter, ~1.5" Length ) (Local Hardware Store)
- 12 x ($1.00) - ?? Nuts for Machine Screws(Local Hardware Store)
- 1 x ($2.00) - Double Sided Sticky Foam Tape ~10cm length x ~1cm wide) (Local Hardware Store)
- 1 x ($2.00) - White Electrical Tape Roll (Local Hardware Store)
- 1 x ($3.00) - Foam Core Board24x36" 1/4" thick 
- 1 x ($3.00) - Heat Shrink Tube: 25cm of 3/32" (~2.4mm) diameter.

Highly Recommended
- Clean workspace
- Good lighting
- Someone awesome to work with

Short on resources?
- Find out if there's a local hackerspace near by!
- Need it today? Radioshack. Can you wait a few days? Adafruit, and Sparkfun are excellent resources.

Who made this?
- This instructable was brought to you by Khevna Shah and Josh Williams, and much help from the World's Friendliest Hackerspace: All Hands Active

* Don't have a LASER Cutter?
- See the PDF files! They contain a printable version of the Top and Bottom car plates, along with wheels. Print them out and purchase a sheet of 1/8" Baltic Birch. Along with a drill, a good assortment of bits and an appropriate saw will make for a classy wooden version!

Prepare Your Workstation

1- Tools & Materials.jpg
2 - LED Clip.jpg
3 - LED Clip.jpg
4 - Resistor Clip.jpg
5 - Resistor Clip.jpg
6-IR Closeup.jpg
6-IR-Trim-Animation.gif
7-PhotoCellTrim.gif
8-Diode.gif
7 - Wire Sizes.jpg

Solder IR Sensors

IRSensorToolsMaterials.jpg
1 - IR.jpg
2 - IR Twist.jpg
3 - IR Twisted.jpg
IR-Solder-Animation.gif
1-HeatShrink.jpg
2-Heatshrink.jpg
3-HeatShrink.jpg
4-HeatShrink.jpg

Solder Photocell

PhotocellToolsMaterials.jpg
Photocell1.jpg
Photocell4.jpg
Photocell5.jpg
Photocell7.jpg
Photocell8.jpg

Solder Brake Lights

BrakeLightsToolsMaterials.jpg
BrakeLightPrepAnimation128l.gif

Soldering Your Motors

MotorToolsMaterials.jpg
1 - Motor on Plate.jpg
2 - Motor On Plate Soldered.jpg
3 - Motor Mounting Materials.jpg
4 - Measure Tape.jpg
5 - Apply Tape.jpg
6 - Tape Applied.jpg
7 - Remove Backing.jpg
8 - Mount Motor.jpg
9 - Secure Motor.jpg
10 - Complete.jpg

Mount Your Arduino & Breadboard!

0 - TopPlateToolsMaterials.jpg
1 - Top Plate Blank.jpg
3 - Top Plate Up.jpg
4 - Top Plate Screw.jpg
5 - Top Plate Nut.jpg
6 - Top Plate Nut Tighten.jpg
7 - Top Plate Second Screw Nut.jpg
8 - Top Plate BB.jpg
9 - Top Plate Zip Tie.jpg
10 - Top Plate Zip Tie.jpg
11 - Top Plate Zip Tie Secure.jpg
12 - Top Plate Zip Tie Snip.jpg
13 - Top Plate Complete.jpg

Stack the Plates!

0 - StackPlatesMaterials.jpg
1 - Top & Bottom Plates.jpg
2 - Bottom Plate Screw.jpg
3 - Botom Plate Screws.jpg
4 - Bottom Plate Nut.jpg
5 - Bottom Plate Nut Secure.jpg
6 - Bottom Plate Second Nut.jpg
7 - Bottom Plate Second Nuts.jpg
8 - Feeding Wires.jpg
9 - Wires & Screws.jpg
10 - Mounting Top Plate.jpg
11 - Top Plate Second Nut Raise.jpg
12 - Top Plate Third Nut.jpg
13 - All Nuts.jpg

Wheels & Casters!

0 - Wheels & Casters.jpg
1 - Wheel Screw.jpg
2 - Wheel Screw.jpg
3 - Wheel Screwed.jpg
4 - Stretch Rubber Band.jpg
5 - More Band.jpg
6 - More Band.jpg
7 - Band Complete.jpg
8 - Position on Motor.jpg
9 - Positioned.jpg
10 - Securing.jpg
11 - Do for Second Wheel.jpg
12 - Caster.jpg
13 - Caster Secured.jpg

Insert Battery Pack & Brake Lights!

1 - Insert Battery.jpg
2 - Position Brake Wires.jpg
3 - Position Brake Lights.jpg
4 - Connect Wires.jpg
5 - All Good.jpg

Insert IR Sensors & Photocell

1 - Insert IR.jpg
2 - IR Inserted.jpg
3 - Second IR.jpg
4 - Insert PC.jpg
5 - PC Inserted.jpg

Breadboarding!

BreadboardCarStageWire.jpg
LineFollowerFritz03_bb.png
LineFollowerFritz04_bb.png
LineFollowerFritz05_bb.png
LineFollowerFritz06_bb.png
LineFollowerFritz07_bb.png
LineFollowerFritz08_bb.png
LineFollowerFritz09_bb.png
LineFollowerFritz10_bb.png
LineFollowerFritz11_bb.png
LineFollowerFritz12_bb.png
LineFollowerFritz13_bb.png
LineFollowerFritz14_bb.png
LineFollowerFritz15_bb.png
LineFollowerFritz16_bb.png
LineFollowerFritz17_bb.png
LineFollowerFritz18_bb.png
LineFollowerFritz19_bb.png
LineFollowerFritz20_bb.png
LineFollowerFritz21_bb.png
LineFollowerFritz22_bb.png
LineFollowerFritz23_bb.png
LineFollowerFritz24_bb.png
LineFollowerFritz25_bb.png
LineFollowerFritz26_bb.png
LineFollowerAllStepsLowRes.gif

Code Review: Variables

NewAnimatedVariable.gif
Variables have 3 properties: type, name, and value.

For instance:  int GREEN = 2; has a type of int, a name of GREEN, and a value of 2.

A variable gets created when you put the type in front of it! If you don't put the type in front, the variable is being used not created.

A variable is used in place of a value.

Anywhere you want to use a 2 you can use GREEN.

A variable ONLY exists between the first { looking up and the corresponding (not nearest) } down in the code.

void setup()
{
  // a variable created in here doesn't exist in loop
}

void loop()
{
  // a variable created in here doesn't exist in setup
}


Variable Types:

A number variable called an int (short for integer). An int can be any whole number from -32,768 to 32,767. More details here: http://arduino.cc/en/Reference/Int

A long is like an integer but bigger! A long goes from -2,147,483,648 to 2,147,483,647. The word unsigned means that instead of going from -2,147,483,648 to 2,147,483,647, it goes from 0 to 4,294,967,295. Since time is never negative, we use an unsigned number for it!
More details here: http://arduino.cc/en/Reference/Long
and here: http://arduino.cc/en/Reference/UnsignedLong


A boolean can be either true or false just like an int has a range of -32,768 to 32,767.

Code Review: Functions

Functions.gif
Remember how we talked about Functions having three parts? Input, Instructions, and Output?

Let's talk about Instructions:

Functions
are just like variables. Once you create them, you can replace the sets of instructions you put into the function in the rest of your program.

Turning this set of instructions:

void loop()
{
  digitalWrite(GREEN, HIGH);
  digitalWrite(YELLOW, LOW);
  digitalWrite(RED, LOW);

}


Into this:

void loop()
{
  green_light();
}

void green_light()
{
  digitalWrite(GREEN, HIGH);
  digitalWrite(YELLOW, LOW);
  digitalWrite(RED, LOW);
}


A function is used in place of instructions.

Anywhere you want to make a green light, you can now write green_light();.

Let's talk about outputs:

The setup and the loop function have outputs too. They're void. Void is computer language for nothing. Our function will output a boolean.

First you need to tell the Arduino that you want your function to output a boolean.
Then you need to actually return (ouput) a boolean value.

An example of this is:
boolean my_awesome_function()
{
  boolean i_love_kittens = true;
  return i_love_kittens;
}

Code Review: If Statements

Code-IfAnimation.gif
You create if statements like this:

if(sensor_value < sensor_mid)
{
  // if sensor value is less than sensor mid do something

else if  (sensor_value > sensor_mid)
{
  // if sensor value is greater than sensor mid do something
}
else if  (sensor_value == sensor_mid)
{
  // if sensor value is equal to sensor mid do something
}
// ... have as many else if statements as you want here
else
{
  // do something else
}

You can use the following comparisons:

 less than
 greater than
== equal to
!= not equal to
<= less than or equal to
>= greater than or equal to
&& and

** Remember that ONE equal sign is used for setting information to variables and TWO is to compare!

Code Review: While Loops

Code-WhileAnimation.gif
A while loop is like an if statement, while the condition provided is true, it executes. The difference between an if statement and a while statement is that the while statement keeps on executing until the condition is false -- just like how the loop function runs until you turn off your Arduino.

An example of this is:
while(current_time < end_time)
{
  // do something

  // now update the current time
  current_time = millis();
}

The code you put in the "do something" area will keep going until the time goes past end_time


Code Review: LEDs

Green_On.gif
For you to turn on your LED, two things must happen.

First, you need to tell the Arduino that you will OUTPUT data on the pin you plugged the Green LED into.

You can do this by using the pinMode function.

An example of this is: pinMode(3, OUTPUT); where my pin number is 3.


Second, you need to send a HIGH signal to the LED to turn it on! (A "LOW" signal will turn the LED off.)

You can do this by using the digitalWrite function.

An example of this is: digitalWrite(3, HIGH); where my pin number is 3.


Code Review: Sensors

Code-Sensors.jpg
You can read input values from the analog pins!

You can do this by using the analogRead function.

An example of this is: analogRead(A0); where my analog pin number is A0.


The analogRead function returns (outputs) an int (integer) between 0 and 1023.
More details here: http://arduino.cc/en/Reference/AnalogRead

Here is an example piece of code that stores the value that is returned by the analogRead function in a variable:

int SENSOR_PIN = A0;
int sensor_value = 0;

void setup()
{
}

void loop()
{
  sensor_value = analogRead(SENSOR_PIN);
}

Code Review: Calibrating

Code-CalibrationAnimation.gif
When calibrating, you want to start the low value at the maximum value (1023) and the high value at the lowest possible value (0).

Then you want to create a loop to run for about 5 seconds by creating a current time and end time variable.

In the loop, you want to read the sensor value.

If the sensor value is higher than the highest value, make the highest value the sensor value.

If the sensor value is lower than the lowest value, make the lowest value the sensor value.

Don't forget to update time!

At the end, set the mid value to be between the highest and lowest value ( (high+low)/2 ).

Get Started!

Basic Arduiono Code Diagram (1).png
Start by creating a new file!

Add in the basic program:

void setup()
{
  // code in here runs once
}

void loop()
{
  // after the setup function, code in here runs over and over
}


More Helpful Functions!

Next, you're going to create two functions!

A void move_car() function and a void go_straight() function!

Inside the move_car() function, let's tell the car to go_straight();.

Inside the loop function call your move_car() function.

In the next step, we'll learn how to make the car go straight!

** Don't remember functions? Look back at the code review for help!

Making the Car Go Straight!

We're going to start by creating variables for the motor pins:

int RIGHT_MOTOR = 11;
int LEFT_MOTOR = 3;

Next, just like the LEDs, we'll have to tell the Arduino that we'll be outputting to these pins by setting the pinMode.

You can do this by using the pinMode function.

An example of this is: pinMode(RIGHT_MOTOR, OUTPUT); where my pin number is RIGHT_MOTOR.


Let's create an int MOTOR_ON variable and set it to 105 because 105 is about as fast as our line follower can go and still make all the tight curves on our track.


After that, instead of using digitalWrite which only lets us write HIGH and LOW, we're going to use the analogWrite function. analogWrite allows you to write any number between 0 and 255 to the digital pins.

You can do this by using the analogWrite function.

An example of this is: analogWrite(RIGHT_MOTOR, MOTOR_ON); where my motor speed is MOTOR_ON.


Now, in the go_straight function, turn on both motors using the analogWrite function.

What About Left and Right?

Create these two functions:

void go_left()

void go_right()

Create an int MOTOR_OFF variable and set it to 0.

To go right, the left motor needs to be on and the right motor needs to be off.

Remember to use the analogWrite function.

Functions With Inputs

Go back and review the different parts of functions (Step 13).

We already talked about instructions and output, but we haven't talked about inputsInputs allow us to send information to functions.

Earlier in the project, we used the pinMode function. We sent the information about the pin number, 3, and mode, OUTPUT, to the function by passing in values. We called the function like this: pinMode(3, OUTPUT);

Similarly, we can create our own custom functions with inputs. You can have as many inputs as you want!

Here is an example (we won't be using this!):

void loop()
{
  feed_kitten(3);  // this calls feed_kitten with the number 3, this means that the
//number_of_treats variable gets created with the value 3

  feed_kitten(10);  // now the number_of_treats variable gets created with the value 10
  feed_kitten(1);
}

void feed_kitten(int number_of_treats)
{
  // now every time feed_kitten gets created, it gets created with number_of_treats
// defined as the number that was passed in.

}

In our feed_kitten function, we're going to be telling that function a different number of treats.

Function Syntax Example:

return_variable_type function_name(type variable_name, type variable_name, ... type variable_name)
{
  return_variable_type some_variable;
  some_instructions_here;
  return some_variable;
}


IR Sensors: Reading Lows and Highs

Let's create a simple function that has the inputs, SENSOR_PIN, SENSOR_MID, and SENSOR_INDICATOR, and returns true if the sensor is lower than mid and returns false otherwise.

boolean value_lower_than_mid(int SENSOR_PIN,int SENSOR_MID, int SENSOR_INDICATOR)
{
  boolean lower_than_mid = false;
  
  digitalWrite(SENSOR_INDICATOR, LOW);

  int sensor_value = analogRead(SENSOR_PIN);

  // if the sensor_value is less than sensor mid
  // set lower_than_mid to true AND turn on your indicator (HIGH)
  // your code here

  return lower_than_mid;
}


Now can you create a function value_higher_than_mid()?

boolean value_higher_than_mid(int SENSOR_PIN, int SENSOR_MID, int SENSOR_INDICATOR)
{
  boolean higher_than_mid = false;
  
  digitalWrite(SENSOR_INDICATOR, LOW);

  int sensor_value = analogRead(SENSOR_PIN);

  // if the sensor_value is greater than sensor mid
  // set higher_than_mid to true AND turn on your indicator (HIGH)
  // your code here

  return higher_than_mid;
}

Create create a variable for the LEFT_SENSOR, RIGHT_SENSOR, and the MIDDLE_SENSOR. Set them to the corresponding pins on your Arduino board. (Look at your circuit). Can't figure out what to do with a sensor? Check the code review about sensors.

Also create a variables for left_sensor_mid, right_sensor_mid, middle_sensor_mid. Set these to 511 for now. We will calibrate them in the next step.

Also, create a variables for RIGHT_INDICATOR, LEFT_INDICATOR, MIDDLE_INDICATOR. These are your yellow front lights and your red brake lights.

Remember to set your pin modes for all the lights to output in the setup function.


Note: For our stop light indicator, middle sensor, we're going to use value_higher_than_mid. For the two IR sensors, left and right sensor, we're going to use value_lower_than_mid.

Now try calling your new functions in your loop function.
Here is an example of how to call this function:

boolean saw_right = value_lower_than_mid(RIGHT_SENSOR, right_sensor_mid, RIGHT_INDICATOR);
boolean saw_left = ?
boolean saw_middle = ?


Try running your code! You'll see that every time the sensors see less than mid (or higher than mid) the lights will turn on.

IR Sensors: Calibration Function 2.0

For the car, we'll be calibrating three different sensors. So, instead of creating three different calibration functions, we'll create one in which we could pass in the pin number of the sensor we wanted to calibrate and then return (output) the value of the sensor_mid.

Try creating this function:
int calibrate(int SENSOR_PIN, int INDICATOR_PIN)
{
  int sensor_mid = 0;
  int sensor_high = 0;
  int sensor_low = 1023;

  unsigned long current_time = millis();
  unsigned long end_time = current_time + 5000;

  // turn on your indicator light here (set it to HIGH!)
  // your code here

  while (current_time < end_time)
  {
    // now update the current time
    current_time = millis();

    // get a new sensor_value here!
    // your code here
   
    // record the minimum sensor value
    if (sensor_value < sensor_low)
    {
      // your code here
    }

    // record the maximum sensor value
    // your code here
    {
      sensor_high = sensor_value;
    }
  }
 
  // turn OFF your indicator light here (set it to LOW!)
  // your code here

  //set mid to be the MIDDLE! :)
  sensor_mid = (sensor_high + sensor_low)/2;
  
  return sensor_mid;
}
Can't quite remember how to make a calibration function, check the code review about calibration.


In the setup function, try adding calibration for each sensor.
Here is an example:

right_sensor_mid = calibrate(RIGHT_SENSOR, RIGHT_INDICATOR);

Sensors + Car

Now let's make our car follow lines and stop at lights.

First, we're going to modify our move_car function so that it takes in inputs!

Here is an example:

void move_car(boolean saw_right, boolean saw_left, boolean saw_middle)

Next, in our loop function, we're going to call the modified move_car function.

Now, let's make our move_car function do more than go straight! We want to add the following if statements (review step 14) in move_car:

If the front sensor sees something, then stop the car, do you have a stop car function yet? No? Add one!

If the right sensor sees something and the left sensor doesn't see something, turn right!

If the left sensor sees something and the right sensor doesn't see something, turn left!

If the right sensor and the left sensor both see nothing, go straight.

If the right sensor and the left sensor both see something, stop the car / go straight, YOU PICK!

Here are some example if statements to help you out:

if(saw_middle == true)
{
  stop_car();

else if  ((saw_right == true) && (saw_left == false))
{
  // do something
}
else if  ((saw_right == false) && (saw_left == true))
{
  // do something
}
// ... keep adding else if statements!

 

The Final Code

comingsoon.png
This step will be up after camps are over!