How to Make a Line Follower Robot Using Arduino

A line follower robot is an autonomous mobile robot that moves along a predefined path, typically represented by a black line on a white surface or a white line on a dark surface. Such robots are commonly used in industrial automation, logistics systems, and as learning projects in robotics and embedded systems.

This article explains the basic working principle, required components, circuit connections, and assembly steps for building a simple line follower robot using Arduino.

 

Working Principle of a Line Follower Robot

A line follower robot detects and follows a line using optical sensors. The detection mechanism relies on the fact that dark surfaces absorb more light, while light surfaces reflect it. Line sensor modules generally consist of an infrared (IR) LED as a transmitter and a photodiode as a receiver.

When infrared light falls on a white surface, most of it is reflected back to the receiver. When the light falls on a black line, it is absorbed and very little is reflected. This difference in reflection is used to determine the robot’s position relative to the line.

 

Navigation of the Robot

The robot uses two motors, one on the left side and one on the right side, to control movement. Two line sensors are placed at the front of the robot to monitor the path.

Based on sensor inputs, the robot performs the following actions:

Move Forward: Both sensors detect a white surface.

Turn Left: Left sensor detects the black line, right sensor detects white.

Turn Right: Right sensor detects the black line, left sensor detects white.

Stop: Both sensors detect the black line simultaneously.

Motor direction is adjusted accordingly to maintain alignment with the path.

 

Hardware Components

Arduino Uno board

L293D motor driver shield

Line sensor modules (2 units)

DC geared motors and wheels

Robot chassis

Jumper wires

USB programming cable

Battery pack

Black tape for track creation

 

L293D Motor Driver Shield

DC motors require higher current and voltage than what a microcontroller can supply directly. The L293D motor driver shield safely interfaces motors with Arduino by handling power requirements and enabling bi-directional motor control. This allows the robot to move forward, reverse, and turn without damaging the controller.

Circuit Diagram of Line Follower Robot

 

The circuit consists of an Arduino board, two line sensors, an L293D motor driver shield, and DC motors. The motor driver shield is mounted directly on the Arduino. Line sensor outputs are connected to the analog input pins of the Arduino. Motors on the left and right sides are connected to separate motor ports on the shield.

During programming, external motor power should be disconnected to prevent accidental damage.

 

Assembly Process

Fix the DC motors to the robot chassis and solder extension wires.

Mount the line sensors at the front of the chassis, maintaining a spacing of approximately 11–11.5 cm between them.

Ensure the sensors are positioned about 2 cm above the ground for accurate detection.

Attach the Arduino and motor driver shield securely to the chassis.

Connect the motors and sensors according to the circuit layout.

Upload the Arduino program after disconnecting motor power.

Attach the battery pack and reconnect power once programming is complete.

 

Final Setup

Create a track using non-shiny black tape with a width of approximately 5 cm. Once powered, the robot will follow the line by continuously adjusting motor direction based on sensor readings.

CODE
/* 
Library used: Adafruit Motor Shield library V1 version: 1.0.1
For this code to run as expected: 
1.The centre to centre distance between the Line sensors should be 11 to 11.5 cm
2. The width of black tape should be 4.8 to 5 cm
3. The distance of the sensor LED from the flat ground surface should be 2 cm.
*/
#include <AFMotor.h>
// MACROS for Debug print, while calibrating set its value to 1 else keep it 0
#define DEBUG_PRINT 0
// MACROS for Analog Input
#define LEFT_IR A0
#define RIGHT_IR A1
// MACROS to control the Robot
#define DETECT_LIMIT 300
#define FORWARD_SPEED 60
#define TURN_SHARP_SPEED 150
#define TURN_SLIGHT_SPEED 120
#define DELAY_AFTER_TURN 140
#define BEFORE_TURN_DELAY 10
// BO Motor control related data here
// Here motors are running using M3 and M4 of the shield and Left Motor is connected to M3 and Right Motor is connected to M4 using IC2 of the shield
AF_DCMotor motorL(3);  // Uses PWM0B pin of Arduino Pin 5 for Enable
AF_DCMotor motorR(4);  // Uses PWM0A pin of Arduino Pin 6 for Enable
// variables to store the analog values
int left_value;
int right_value;
// Set the last direction to Stop
char lastDirection = 'S';  
void setup() {
#if DEBUG_PRINT  
  Serial.begin(9600);
#endif  
  // Set the current speed of Left Motor to 0
  motorL.setSpeed(0);
  // turn on motor
  motorL.run(RELEASE);
  // Set the current speed of Right Motor to 0
  motorR.setSpeed(0);
  // turn off motor
  motorR.run(RELEASE);
  // To provide starting push to Robot these values are set
  motorR.run(FORWARD);
  motorL.run(FORWARD);
  motorL.setSpeed(255);
  motorR.setSpeed(255);
  delay(40);  // delay of 40 ms
}
void loop() {
  left_value = analogRead(LEFT_IR);
  right_value = analogRead(RIGHT_IR);
#if DEBUG_PRINT
  // This is for debugging. To check the analog inputs the DETECT_LIMIT MACRO value 300 is set by analysing the debug prints
  Serial.print(left_value);
  Serial.print(",");
  Serial.print(right_value);
  Serial.print(",");
  Serial.print(lastDirection);
  Serial.write(10);
#endif
  // Right Sensor detects black line and left does not detect
  if (right_value >= DETECT_LIMIT && !(left_value >= DETECT_LIMIT)) {
    turnRight();
  }
  // Left Sensor detects black line and right does not detect
  else if ((left_value >= DETECT_LIMIT) && !(right_value >= DETECT_LIMIT)) {
    turnLeft();
  }
  // both sensors doesn't detect black line
  else if (!(left_value >= DETECT_LIMIT) && !(right_value >= DETECT_LIMIT)) {
    moveForward();
  }
  // both sensors detect black line
  else if ((left_value >= DETECT_LIMIT) && (right_value >= DETECT_LIMIT)) {
    stop();
  }
}
void moveForward() {
  if (lastDirection != 'F') {
    // To provide starting push to Robot when last direction was not forward
    motorR.run(FORWARD);
    motorL.run(FORWARD);
    motorL.setSpeed(255);
    motorR.setSpeed(255);
    lastDirection = 'F';
    delay(20);
  } else {
    // If the last direction was forward
    motorR.run(FORWARD);
    motorL.run(FORWARD);
    motorL.setSpeed(FORWARD_SPEED);
    motorR.setSpeed(FORWARD_SPEED);
  }
}
void stop() {
  if (lastDirection != 'S') {
    // When stop is detected move further one time to check if its actual stop or not, needed when the robot turns
    motorR.run(FORWARD);
    motorL.run(FORWARD);
    motorL.setSpeed(255);
    motorR.setSpeed(255);
    lastDirection = 'S';
    delay(40);
  } else {
    // When stop is detected next time then stop the Robot
    motorL.setSpeed(0);
    motorR.setSpeed(0);
    motorL.run(RELEASE);
    motorR.run(RELEASE);
    lastDirection = 'S';
  }
}
void turnRight(void) {
  // If first time Right Turn is taken
  if (lastDirection != 'R') {
    lastDirection = 'R';
    // Stop the motor for some time
    motorL.setSpeed(0);
    motorR.setSpeed(0);
    delay(BEFORE_TURN_DELAY);
    // take Slight Right turn
    motorL.run(FORWARD);
    motorR.run(BACKWARD);
    motorL.setSpeed(TURN_SLIGHT_SPEED);
    motorR.setSpeed(TURN_SLIGHT_SPEED);
  } else {
    // take sharp Right turn
    motorL.run(FORWARD);
    motorR.run(BACKWARD);
    motorL.setSpeed(TURN_SHARP_SPEED);
    motorR.setSpeed(TURN_SHARP_SPEED);
  }
  delay(DELAY_AFTER_TURN);
}
void turnLeft() {
  // If first time Left Turn is taken
  if (lastDirection != 'L') {
    lastDirection = 'L';
    // Stop the motor for some time
    motorL.setSpeed(0);
    motorR.setSpeed(0);
    delay(BEFORE_TURN_DELAY);
    // take slight Left turn
    motorR.run(FORWARD);
    motorL.run(BACKWARD);
    motorL.setSpeed(TURN_SLIGHT_SPEED);
    motorR.setSpeed(TURN_SLIGHT_SPEED);
  } else {
    // take sharp Left turn
    motorR.run(FORWARD);
    motorL.run(BACKWARD);
    motorL.setSpeed(TURN_SHARP_SPEED);
    motorR.setSpeed(TURN_SHARP_SPEED);
  }
  delay(DELAY_AFTER_TURN);
}
License
All Rights
Reserved
licensBg
0