Arduino Line Follower

Introduction: Arduino Line Follower

The line follower follows a 1.5cm black line on a white background. It uses 8 infrared sensors to detect the light and then follow it using PID logic. The IR sensor works by emmitting infrared rays and then varying the resistance based on the intensity of light recieved. Based on this the arduino detects where the line exactly is relative to it.

Step 1: Tools and Components Required

Components:

  1. Arduino Nano x 1
  2. TB6612FNG x 1
  3. Electronic Speed Controller (ESC) x 1
  4. Elecronic Ducted Fan (EDF) x 1
  5. Pololu 12v micro metal gear motor x 2
  6. QRD1113 IR sensors x 8
  7. 50 Ohms resistors x 8
  8. JSumo IR Switch x 1Turnigy 460 mah 2s 20C - 40C LiPo battery x 1
  9. Step Up voltage regulator x 1

Tools:

  • Soldering Iron
  • Screw Driver

Step 2: Arduino Connections

This image shows the connection of all the parts to each other and to the Arduino

Step 3: Sensor Array

This image shows the structure and connections of the sensor array

Step 4: Code

This is the code of the line follower. It uses PID logic to follow the line

.ino

#include<Servo.h>
//---------------------------------------------------speed declaration-----------------------------------------------------------
int P, D, I;
float error, previousError;
int lsp, rsp;
int lfspeed = 160;//<<<<<<<<<<<<<<<<<---------Change speed here<<<<<<<<<<<<<<<<<<<<<<<
int minspeed = 0 ;
int maxspeed = 255;
long denominator = 0;
long numerator = 0;
float pos;
int numBlack = 0;
float Kp = 0.025;
float Kd = 1.45;
float Ki = 0.00022;
float PIDvalue = 0;
int lastposition = 3500;
Servo ESC;
int sensor[8][3];
voidstart()
{
ESC.attach(9, 1000, 2000);
ESC.write(0);
delay(2000);
ESC.write(220);
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
while (!digitalRead(6)) {}
motor1(100);
motor2(100);
delay(10);
}
//-------------------------------------------------------Calibrate----------------------------------------------------------------
voidcalib()
{
for (int i = 0; i < 8; i++) // Initialising array values
{
sensor[i][0] = 500; //min values
sensor[i][1] = 500; //max values
sensor[i][2] = 500; //calibrated values//
}
int csp = 50;
for (int a = 0; a < 4; a++)
{
motor1(csp);
motor2(-csp);
for (int c = 0; c < 2000; c++)
{
for (int i = 0; i < 8; i++)
{
if (analogRead(i) < sensor[i][0])
{
sensor[i][0] = analogRead(i);
}
if (analogRead(i) > sensor[i][1])
{
sensor[i][1] = analogRead(i);
}
}
}
csp = csp * -1;
}
digitalWrite(13, LOW);
motor1(0);
motor2(0);
}
voidgetLine()
{
denominator = 0;
numerator = 0;
numBlack = 0;
for (int i = 0; i < 8; i++)
{
sensor[i][2] = map(analogRead(i), sensor[i][0], sensor[i][1], 0, 1000);
denominator += sensor[i][2];
if (sensor[i][2] >100) numBlack++;
}
numerator = ((sensor[1][2]) + (2 * sensor[2][2]) + (3 * sensor[3][2]) + (4 * sensor[4][2]) + (5 * sensor[5][2]) + (6 * sensor[6][2]) + (7 * sensor[7][2]));
error = ((sensor[3][2] + 2 * sensor[2][2] + 4 * sensor[1][2] + 8 * sensor[0][2])) - ((sensor[4][2] + 2 * sensor[5][2] + 4 * sensor[6][2] + 8 * sensor[7][2]));
if (numBlack >0 && numBlack < 6)
{
pos = 1000 * numerator / denominator;
}
}
//-------------------------------------------------------Setup Code----------------------------------------------------------------
voidsetup()
{
Serial.begin(9600);
ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits
// uncomment as required
// ADCSRA |= bit (ADPS0); // 2
// ADCSRA |= bit (ADPS1); // 4
//ADCSRA |= bit (ADPS0) | bit (ADPS1); // 8
ADCSRA |= bit (ADPS2); // 16
//ADCSRA |= bit (ADPS0) | bit (ADPS2); // 32
// ADCSRA |= bit (ADPS1) | bit (ADPS2); // 64
// ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // 128
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // turn on Arduino's LED to indicate we are in calibration mode
calib();
digitalWrite(13, LOW); // turn off Arduino's LED to indicate we are through with calibration
start();
}
voidloop()
{
while (digitalRead(6))
{
getLine();
if (pos < 1000)
{
lsp = -130;
rsp = 120;
}
elseif (pos >6000)
{
lsp = 120;
rsp = -130;
}
else
{
P = error;
I = I + error;
D = error - previousError;
PIDvalue = (Kp * P) + (Ki * I) + (Kd * D);
previousError = error;
lsp = lfspeed - PIDvalue;
rsp = lfspeed + PIDvalue;
lsp = constrain(lsp, minspeed, maxspeed);
rsp = constrain(rsp, minspeed, maxspeed);
}
motor1(rsp);
motor2(lsp);
}
motor1(0);
motor2(0);
delay(50);
motor1(-50);
motor2(-50);
ESC.write(0);
delay(100);
motor1(0);
motor2(0);
delay(1000);
}
voidmotor1(int spd)
{
if (spd >0)
{
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
analogWrite(3, spd);
}
elseif (spd < 0)
{
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
analogWrite(3, spd * -1);
}
else
{
digitalWrite(8, LOW);
digitalWrite(7, LOW);
analogWrite(3, 0);
}
}
voidmotor2(int spd)
{
if (spd >0)
{
digitalWrite(10, HIGH);
digitalWrite(12, LOW);
analogWrite(11, spd);
}
elseif (spd < 0)
{
digitalWrite(10, LOW);
digitalWrite(12, HIGH);
analogWrite(11, spd * -1);
}
else
{
digitalWrite(10, LOW);
digitalWrite(12, LOW);
analogWrite(3, 0);
}
}
view raw.ino hosted with ❤ by GitHub

Be the First to Share

    Recommendations

    • Tinkercad Student Design Contest

      Tinkercad Student Design Contest
    • Back to School: Student Design Challenge

      Back to School: Student Design Challenge
    • Robots Contest

      Robots Contest

    3 Comments

    0
    MubashirH
    MubashirH

    1 year ago

    Too much short details you don't describe about DAF ,ESC how to use it and motor gear ratio and there no schematic diagram to undrestand etc kindly share your full experience of making this bot

    0
    Penolopy Bulnick
    Penolopy Bulnick

    1 year ago

    Thanks for sharing your line following robot :)