Project showcase
Elliot the Line Follower Robot

Elliot the Line Follower Robot © GPL3+

A PID controlled line follower robot, named Elliot.

  • 9,214 views
  • 5 comments
  • 20 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
09670 01
SparkFun Dual H-Bridge motor drivers L298
×1
Tens70
9V battery (generic)
×1
Keystone 233 image 75px
9V Battery Clip
×1
6V NiMh 2000mAh rechargeable battery
×1
Adafruit industries ada64 image 75px
Solderless Breadboard Half Size
×1
11026 02
Jumper wires (generic)
×1
IR Sensors
I used 5 of these
×1
Angle Bracket
×1
Painter's stick
×1
DC motor (generic)
×1
Robot Chassis
I got this on Amazon.com, it also included two geared DC motors.
×1
Caster wheel
×1
Electrical tape
A whole bunch of this...
×1

About this project

The goal

The goal for this project was to create a line follower robot and learn, experiment and implement PID control, doing so in a cheap and affordable way.

The design

The design of this robot was intended to be cheap and to build a decently paced line following robot that uses PID control for best results. The IR sensors as seen in the image are mounted onto a painter's stick, and mounted to an angle bracket. I have chosen an Arduino Uno for the micro controller and a L298N motor controller module to drive the DC motors. For power supply, I chose a 6V NiMh battery for the motors, and a 9V battery primarily for the Arduino Uno and the IR sensors. All components are attached to a fixture that I purchased online.

How it works

The IR sensors mounted in front of the robot are used as digital sensors rather than analog sensors as they could be used as. Therefore, each sensor will return either a 1 (High) or 0 (Low), depending on the surrounding environment. A brief description of how these sensors work is as follows: basically each sensor is comprised of both an IR led and IR receiver. Infrared light/rays is emitted from the IR led and when an object is in close range to the sensor the infrared rays are absorbed by the object but enough is reflected back to the receiver, therefore it knows an object is there and vice versa. Now in our case we want to distinguish between the colors black and white. Truly it works in the same manner as it does when detecting objects. When white or many other colors are in its range the IR receiver will detect the reflected IR rays and we can distinguish that as white. While on the other hand when a black surface is below the sensor the IR rays are only absorbed by the black surface and will not trip out the receiver. Now that we get our readings from the sensors through software, we can now determine an error based on the readings and do the PID calculations. The output that is calculated is the value we are going to change each motor's speed by (so the PWM value). After I went through quite some time of tweaking the code and going through the PID tuning process, I was able to get results from Elliot that pleased me.

Conclusion

Again, I'm very happy with how this project turned out and found it as a very rewarding experience. I would also definitely recommend and encourage anyone starting with Robotics or have some experience already to build one of these, as it can build many skills and introduce you to the world of robotics. Below I have attached videos of some of the runs I did with this robot. The first two videos is the robot running the more simple track as that was my first goal for the robot, and the last video is the more difficult track that I had also built.

Code

PID Line Follower Robot CodeC/C++
float pTerm, iTerm, dTerm;
int error;
int previousError;
float kp = 11; //11
float ki = 0;
float kd = 11; //11
float output;
int integral, derivative;
int irSensors[] = {13, 12, 11, 8, 7}; //IR sensor pins
int irReadings[5];
int motor1Forward = A0;
int motor1Backward = A1;
int motor1pwmPin = 5;
int motor2Forward = A3;
int motor2Backward = A2;
int motor2pwmPin = 3;
int motor1newSpeed;
int motor2newSpeed;
int motor2Speed = 70; //Default 70
int motor1Speed = 120; //Default 120

void setup() {
  //Declare all IR sensors as inputs
  for (int pin = 0; pin < 5; pin++) {
    int pinNum = irSensors[pin];
    pinMode(pinNum, INPUT);
  }
  pinMode(motor1Forward, OUTPUT);
  pinMode(motor1Backward, OUTPUT);
  pinMode(motor1pwmPin, OUTPUT);
  pinMode(motor2Forward, OUTPUT);
  pinMode(motor2Backward, OUTPUT);
  pinMode(motor2pwmPin, OUTPUT);
}

void loop() {
  //Put all of our functions here
  readIRSensors();
  calculateError();
  pidCalculations();
  changeMotorSpeed();
}

void readIRSensors() {
  //Read the IR sensors and put the readings in irReadings array
  for (int pin = 0; pin < 5; pin++) {
    int pinNum = irSensors[pin];
    irReadings[pin] = digitalRead(pinNum);
  }
}

void calculateError() {
  //Determine an error based on the readings
  if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 0) && (irReadings[3] == 0) && (irReadings[4] == 1)) {
    error = 4;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 0) && (irReadings[3] == 1) && (irReadings[4] == 1)) {
    error = 3;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 0) && (irReadings[3] == 1) && (irReadings[4] == 0)) {
    error = 2;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 1) && (irReadings[3] == 1) && (irReadings[4] == 0)) {
    error = 1;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 1) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    error = 0;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 1) && (irReadings[2] == 1) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    error = -1;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 1) && (irReadings[2] == 0) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    error = -2;
  } else if ((irReadings[0] == 1) && (irReadings[1] == 1) && (irReadings[2] == 0) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    error = -3;
  } else if ((irReadings[0] == 1) && (irReadings[1] == 0) && (irReadings[2] == 0) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    error = -4;
  } else if ((irReadings[0] == 0) && (irReadings[1] == 0) && (irReadings[2] == 0) && (irReadings[3] == 0) && (irReadings[4] == 0)) {
    if (previousError == -4) {
      error = -5;
    } else {
      error = 5;
    }
  } else if ((irReadings[0] == 1) && (irReadings[1] == 1) && (irReadings[2] == 1) && (irReadings[3] == 1) && (irReadings[4] == 1)) {
    error = 0;
  }
}

void pidCalculations() {
  pTerm = kp * error;
  integral += error;
  iTerm = ki * integral;
  derivative = error - previousError;
  dTerm = kd * derivative;
  output = pTerm + iTerm + dTerm;
  previousError = error;
}

void changeMotorSpeed() {
  //Change motor speed of both motors accordingly
  motor2newSpeed = motor2Speed + output;
  motor1newSpeed = motor1Speed - output;
  //Constrain the new speed of motors to be between the range 0-255
  constrain(motor2newSpeed, 0, 255);
  constrain(motor1newSpeed, 0, 255);
  //Set new speed, and run motors in forward direction
  analogWrite(motor2pwmPin, motor2newSpeed);
  analogWrite(motor1pwmPin, motor1newSpeed);
  digitalWrite(motor2Forward, HIGH);
  digitalWrite(motor2Backward, LOW);
  digitalWrite(motor1Forward, HIGH);
  digitalWrite(motor1Backward, LOW);
}

Schematics

PID Line Follower Robot Schematic
Sorry if this is not the best diagram/schematic, and if you have any questions about the IR sensor wiring I'd be happy to help. The reason for this is I had trouble finding IR sensor modules on Fritzing.
p1ph3ZBEhAZKlBi9Uj1M.fzz

Comments

Similar projects you might like

Easiest Line Follower Robot

Project tutorial by Zubayer Al Billal Khan

  • 12,717 views
  • 10 comments
  • 30 respects

PID Control Line Follower Robot

Project tutorial by Team KittenBot

  • 14,361 views
  • 5 comments
  • 25 respects

Line Follower Robot

Project showcase by Lomas Subedi

  • 4,129 views
  • 2 comments
  • 9 respects

3D Printed and Expandable Robot for Arduino

Project showcase by Matthew Hallberg

  • 2,468 views
  • 3 comments
  • 13 respects

Line Follower Robot - PID Control - Android Setup

Project tutorial by MJRoBot

  • 28,083 views
  • 7 comments
  • 33 respects

Line Follower Robot Using Arduino & 1Sheeld

Project tutorial by Ashraf Nabil

  • 2,161 views
  • 0 comments
  • 5 respects
Add projectSign up / Login