Engineering

Outreach

Resources

Enrichment

Green Engineers

Mechatronics Studio

Contact Us

Mechatronics Learning Studio

Line Follower

Tanner Wharton, Brandon Lowe, Department of Mechanical Engineering, University of Ottawa

 

Overview

The Line Follower was designed to follow lines and to stop when a sufficient amount of light is applied to the front photocell. This system was realized by using two infrared sensors to detect the line, a photocell to detect the light in front of the vehicle, an Arduino board as a microcontroller, and two DC motors as actuators, along with other various electronic components. Also, the frame for the vehicle was designed on Solidworks, and then 3D printed.

Introduction

The task of designing and implementing a mechatronics system was given for the class ELG 3336. For our project, it was decided that building a line following robot would be a feasible goal, and, time permitting, modifications could be made to the design to further enhance the system. This project would not only develop our knowledge of electronics, but also expand our understanding of the designing and implementation processes that accompany such a venture. The fundamental goal to accomplish was to build small vehicle that would follow a black line on a sufficiently contrasting surface. Once that goal was realized, the illuminated stopping capability became the next goal to accomplish. The entirety of the project can be separated into 4 steps: purchasing the materials, designing and printing the frame, creating the circuit and coding the Arduino. Each step will be discussed in the following subsections.

Materials

Most of the components were purchased from online sources or from hobby shops. The materials needed for the project are:

  • Arduino Uno

  • Wire Snips and Strippers

  • Breadboard

  • 9V Battery

  • One Photocell

  • 2-IR Emitter/Sensor

  • 100, 220, 279, and 5.6k ohm resistors

  • Yellow and Red LED’s

  • 2 Wheels and One Ball Caster

  • 2 DC Motors

  • NPN Transistors

  • Diodes

Frame

As previously mentioned, the frame was 3D printed. This has many advantages, such as having custom holes to fit the components with accurate dimensions, the ability to convert one’s design into reality along with simplification of the building process. The original design for the frame was made on Solidworks, a computer aided drafting software. By taking measurements of all the components needed for the line follower, fitted holes could be added to the draft on the computer. Once the draft was deemed sufficient for implementation, the file was given away for printing. The frame turned out great, although a few modifications had to be made. As it happens, when a 3D printer creates an object, the final dimensions of the object are never the same as the original ones. This lack of accuracy is due to shrinkage in the plastic after the printing process. But, with the help of a grinder, the component holes could be enlarged and the project could continue.

 

Circuit

 

The circuit of this project has seven main components that make up the system. 

1.      

A  Arduino Board

A programmable microcontroller that reads and transmits signals to and from various components (the code can be found below). 

                      

2.      

     Breadboard

A solderless circuit framework, that allows the connection of electrical components in a neat and organized fashion with minimal use of wires.

3.  

     Infrared Sensors/Transmitters

 This electronic component can receive and send light from the infrared spectrum, which has a slightly longer wavelength than that of the visible spectrum so it cannot be seen by human eyes.

 

The infrared sensor is used in this circuit to differentiate between black and white surfaces.  It differentiates by using a built in transistor that is sensitive to the amount of infrared light reflected or absorbed by the surface being subjected to infrared light (circled in red).

 

                

 

4.  Photocell

The photocell is a light based resistor that changes resistance based on the amount of light is subjected to

the photo cell is used in this circuit to detect if a bright light (traffic light) is present and enable or disable the DC motors based on the readings.  

 

                    

 

5.  DC Motors

The DC motors are used to drive the car in this project, these specific motors have had their speed reduced in a small gear box in order to increase the torque.  Using the Arduino the IR sensors are used to keep a black line between two IR sensors, and when the line is detected the motors react accordingly.

 

              

6.  

     LEDs (Light Emitting Diodes)

The LED’s are programmed to react when an IR sensor detects a line; these LED’s are located on the breadboard.  There are also LED’s programmed to react to the stimulation of the photocell by a bright light in which case they are illuminated and the DC motors are disabled.

7.  

     Transistors

The transistors are used as switches in order to control the magnitude of the signal and therefore the speed of the DC motors.  The only downfall of this setup is that the motors cannot run in reverse. See the following pictures where transistors are circled with gree.

 

           

 

Code

// Sensors (Into Arduino)

const int RIGHT_IR = A0;

const int PHOTO = A3;

const int LEFT_IR = A5;

// Signals (Out of Arduino)

const int LEFT_MOTOR = 11;

const int RIGHT_MOTOR = 3;

const int LEFT_LED = 4;

const int RIGHT_LED = 10;

const int BRAKE_LIGHTS = 7;

// Other Variables

int motor_high_right = 105;

int motor_high_left = 105;

int motor_mid_right = 55;

int motor_mid_left = 55;

int motor_off = 0;

int right_ir_mid = 950;

int left_ir_mid  = 950;

int photo_mid    = 150;

 

 

 

// MAIN FUNCTIONS

void setup()

{

  pinMode(RIGHT_MOTOR, OUTPUT);

  pinMode(LEFT_MOTOR, OUTPUT);

  pinMode(LEFT_LED, OUTPUT);

  pinMode(RIGHT_LED, OUTPUT);

  pinMode(BRAKE_LIGHTS, OUTPUT);

  //right_ir_mid = calibrate(RIGHT_IR, RIGHT_LED);

  //left_ir_mid  = calibrate(LEFT_IR,  LEFT_LED);

  //photo_mid    = calibrate(PHOTO, BRAKE_LIGHTS); 

}

 

void loop()

{

  boolean right_sensor = value_higher_than_mid(RIGHT_IR, right_ir_mid, RIGHT_LED);

  boolean left_sensor  = value_higher_than_mid(LEFT_IR, left_ir_mid, LEFT_LED);

  boolean photo_sensor  = value_higher_than_mid(PHOTO, photo_mid, BRAKE_LIGHTS);

 

  move_car(right_sensor, left_sensor, photo_sensor);

 

}

 

 

// MOVEMENT FUNCTIONS

void move_car(boolean sense_right, boolean sense_left, boolean sense_photo)

  if(sense_photo == true)

  {

    brake();

  }

 

  else if((sense_right == true)&&(sense_left == false)&&(sense_photo == false))

  {

    turn_right();

   

    delay(2000);

   

    move_straight();

  }

 

  else if((sense_right == false)&&(sense_left == true)&&(sense_photo == false))

  {

    turn_left();

   

    delay(2000);

   

    move_straight();

  }

  else if ((sense_right == false)&&(sense_left == false)&&(sense_photo == false))

  {

    move_straight();

  }

 

}

 

 

 

void move_straight()

{

  analogWrite(RIGHT_MOTOR, motor_high_right);

  analogWrite(LEFT_MOTOR, motor_high_left);

}

 

void turn_left()

{

  analogWrite(RIGHT_MOTOR, motor_mid_right);

  analogWrite(LEFT_MOTOR, motor_off);

}

 

void turn_right()

{

  analogWrite(LEFT_MOTOR, motor_mid_left);

  analogWrite(RIGHT_MOTOR, motor_off);

 

}

 

void brake()

{

  analogWrite(LEFT_MOTOR, motor_off);

  analogWrite(RIGHT_MOTOR, motor_off);

}

 

 

 

//SENSOR FUNCTIONS

 

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(sensor_value < SENSOR_MID)

  {

    digitalWrite(SENSOR_INDICATOR, HIGH);

   

    lower_than_mid = true;

  }

 

  return lower_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(sensor_value > SENSOR_MID)

  {

    digitalWrite(SENSOR_INDICATOR, HIGH);

   

    higher_than_mid = true;

  }

 

  return higher_than_mid;

}