PROJECT REPORT
Project Title:
Line Following Robot
Faculty Information:
Name of Faculty Sabab Zaman
Designation Department of EEE
Student Information:
AL Emran 25300133
Rakibul Hasan 25300056
Sinthia Sikder 25300139
Name And ID
Md polash Sarker 23300089
Sarat Chandro Ghosh 25300070
Badhon Devnath 25300137
Date: 08/06/2026
Objective:
• Improve knowledge of robotics as well as microcontroller programming
and electronic circuit design and construction.
• Construct a robot which is capable of following a black line and complex
path.
• It should be capable of performing various degrees of turns.
• Learn to assemble and troubleshoot an electronic circuit
Apparatus:
1. Chasis Board
2. Castor Wheel
3. Yellow Wheel – 2
4. Arduino Nano
5. Motor Driver l298n
6. IR Sensor - 5
7. Step Down Buck Convertor
8. Gear Motor - 2
9. Lithium Ion Battery - 3
10. 3s Case for Lithium Ion Battery
11. Breadboard
12. Switch
13. Voltmeter
14. Jumper Wire
15. Mulitimeter
Component Explanation:
We going to talk about some key components of robot :
1. Chasis Board :
The robots body is a critical aspact.
Varius types of board can be used for
the Chasis. But for this project, The
material is used called hard card board.
Components are mounted top of the
board. Also on the back of the board
there are two motors with wheels and a
front wheel on the top part of the board
2. Arduino Nano :
This is the brain of the robot. The Arduino
Nano is a compact, breadboard-friendly
micro- controller board based on the
ATmega328P chip. It can deliver up to
16MHZ of clock speed and operates on 5v.
It includes:
1. Digital IO Pins → 14 pins and 6 of them supports PWM.
2. Analog Input Pins → 6 pins of analog input processing.
3. USB Connectivity → Allows programming via USB Cable.
4. Other Feature → Includes a power jack and a reset button etc.
The Arduino Nano serve as a central controller, managing all robots
operation. It processes data from the sensor and sends the signal to the
motor driver that controls the motor.
3. IR Sensor :
The IR sensor detects the line and transmit digital
reading to the Arduino through the analog pins (A0-
A4) on the Arduino board. The sensor reads between
white and black surface based on following values :
• White Surface → 0
• Black Surface → 1
This data allows the robot to differentiate between white and black
background accurately.
4. Motor Driver l298n :
This L298N Motor Driver Module is a high
power motor driver module for driving DC and
Stepper Motors. This module consists of an L298
motor driver IC and a 78M05 5V
regulator. L298N Module can control up to 2 DC
motors with directional and speed control.
It includes:
• Control Pins :
ENA → Enables PWM signal for motor 1.
ENB → Enables PWM signal for motor 2.
IN1 & IN2 → It controls motor 1 forward speed direction.
IN3 & IN4 → It controls motor 2 backward speed direction.
• Power Pins :
12V → 12v input from DC power source.
5V → Supply power for the IC inside the l298n logic unit.
GND → Ground pin.
• Output Pin :
OUT1 & OUT2 → Output pin of motor 1
OUT3 & OUT4 → Output pin of motor 2
Motors driver are a crucial components for the robot. This ensure that the
both motor are same type, speed and power requirments to maintain
smooth and consistant operation.
5. Step Down Buck Converter :
A DC buck converter is a highly efficient
switched-mode step-down voltage
regulator. For this project, the input for the
buck converter is 12v and the output is 5v
for the Arduino Nano and Sensor. The
buck converter operate on up to 35v. It has
a potentiometer to control the voltage for
the output.
6. Gear Motor:
Yellow gear motors are inexpensive,
lightweight DC motors widely used in
DIY projects and robotics. They feature
an integrated plastic gearbox that trades
high motor speed for high output torque.
It operates on 6 to 12v and the speed
depends on the input voltage. It has high
torque that is typically 100 to 400 rpm.
7. Power Supply(11.6v) :
For the project, a 3s 3.7v rating lithium ion
battery is used to power the robot. The 3s
lithium ion battery powers the motor
driver for the motor and buck converter
for the Arduino and sensor. This battery
has typically 2000 to 3000 mAh of
capacity.
To keep the battery safe, we use a voltmeter to monitor the voltage of
battery that way it can not be damaged.
Working Principle:
How the Hardware is Connected:
• The Power (Battery): The 3s Lithium ion battery connects directly to the
Motor Driver's heavy-duty power inputs to turn the motors.
• A wire also runs from the battery to the buck converter to Arduino
(into the VIN pin) to give the brain its power and also the sensors.
• The sensor:
• Each sensor has a data wire that plugs into the Arduino's input pins
(A0, A1, A2, A3, A4) and VCC is connected to buck converter and
the ground is connected to Arduino GND pin of all sensor.
• The Arduino:
• The Arduino connects to the motor driver using directional pins (5,
6, 7, 8) to control whether the wheels spin forward or backward.
• It also connects using PWM (speed control) pins (9 and 10) to tell
the driver how much voltage to send to the motors.
• The Motors:
• The driver has screw terminals that connect directly to the Left
Motor and Right Motor to feed them raw power.
How It Follows a Line:
The robot steers using a concept called Differential Steering. It doesn't have a
steering wheel that tilts. It changes direction by making one wheel spin faster
than the other.
The Arduino looks at the 5 sensors and constantly adjusts the wheel speeds to
follow the line using three simple rules:
Drive Straight (Line is in the middle):
• the middle sensor (A2) sees black and the pattern 00100.
• The Arduino sends equal power to both wheels like Left Speed = 43, Right
Speed = 43. Because both wheels move at the exact same pace, the robot
drives straight.
Adjust Right (Robot to the left):
• The line slides over to the right-side sensors (A3 or A4) and the pattern
00011. This means the robot's body has drifted too far to the left.
• The Arduino instantly speeds up the Left wheel and slows down the Right
wheel. Because the left side moves faster, it swings the robot's body around
to the right, putting the line back in the center.
Adjust Left (Robot to the right):
• The line slides over to the left-side sensors (A0 or A1) and the pattern
11000. This means the robot's body has drifted too far to the right.
• The Arduino speeds up the Right wheel and slows down the Left wheel.
The faster right wheel pushes the robot's body back to the left until it
centers itself on the track again.
PID And Turns:
It performs middle and slight turn via PID control. PID is known as Proportional
Integral Derivative. It calculates the difference (error) between the robot's actual
position and the center of the line, dynamically adjusting motor speeds to correct
the robot's path.
• Calculate Error : Use an IR sensor array to compute a weighted average
of the robot's position. If the line is perfectly centered, the error is 0. A
negative error means the robot drifted left; a positive error means it drifted
right.
• Calculate P, I, and D terms:
P = Kp * error
Integral = Integral + error
D = Kd * (error – previous error)
• Sum and Apply: Add them together to get the total correction value.
• Steer the Motors: Adjust the base speed of the left and right motors by
adding and subtracting the correction value.
For other turn it performs:
Right turn → 00111,00011,00001
Left turn → 11100, 11000,10000
T-junction → 11111 (the priority for T-junction is always forward)
Gap → for the small gap, if the sensor see white line (00000) it perform a little
delay using a loop.
Memory → if the sensor does not see any black line, there is a variable that stores
last perform turn (like left, right) then it turns opposite direction until sensor finds
the black line.
Because the sensor is not perfect, we have to filter some glitch patturns that the
sensor when performing right or left turn. They are:
Glitch filter → 10100,10110,00101,01101 etc
Code Initialization:
For motor:
• ENA → 9
• ENB → 10
• IN1 → 5
• IN2 → 6
• IN3 → 7
• IN4 → 8
For sensor:
• S1 → A0 → Left most sensor
• S2 → A1
• S3 → A2
• S4 → A3
• S5 → A4 → Right most sensor
Circuit Diagram:
Code:
#define ENA 9 // ENA
#define IN1 5 // IN1
#define IN2 6 // IN2
#define ENB 10 // ENB
#define IN3 7 // IN3
#define IN4 8 // IN4
const int SENSOR_PINS[] = {A0, A1, A2, A3, A4};
//11 to 11.5v safe spot
float Kp = 3.5;
float Kd = 9.0;
float Ki = 0.00;
// speed configaration
const int BASE_SPEED = 50;
const int MAX_SPEED = 75;
const int MIN_SPEED = -90;
int lastError = 0;
float integral = 0;
char lastDirection = 'S';
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
for (int i = 0; i < 5; i++) {
pinMode(SENSOR_PINS[i], INPUT); //
}
}
void loop() {
//manually read sensor output
int rawPattern = readRawSensorBits();
// T-junction
if (rawPattern == 0b11111) {
// slight forward
controlMotors(BASE_SPEED, BASE_SPEED);
delay(50);
int postPattern = readRawSensorBits();
// check again
if (postPattern & 0b00100) {
controlMotors(BASE_SPEED, BASE_SPEED);
return;
}
executeSharpTurnRight();
return;
}
//right turn
else if (rawPattern == 0b00001 || rawPattern == 0b00011 || rawPattern ==
0b00111 || rawPattern == 0b00101 || rawPattern == 0b01101 || rawPattern ==
0b01011 || rawPattern == 0b01111) {
executeSharpTurnRight();
return;
}
//left turn
else if (rawPattern == 0b10000 || rawPattern == 0b11000 || rawPattern ==
0b11100 || rawPattern == 0b10100 || rawPattern == 0b10110 || rawPattern ==
0b11010 || rawPattern == 0b11110) {
executeSharpTurnLeft();
return;
}
// gap logic
int currentError = calculatePositionError(rawPattern);
if (currentError == 999) {
handleLineGap();
return;
}
// PID tracking
int proportional = currentError;
int derivative = currentError - lastError;
integral += currentError;
int turnControl = (Kp * proportional) + (Kd * derivative) + (Ki * integral);
lastError = currentError;
int leftMotorSpeed = BASE_SPEED + turnControl;
int rightMotorSpeed = BASE_SPEED - turnControl;
//controling the motor based on error
controlMotors(leftMotorSpeed, rightMotorSpeed);
}
void executeSharpTurnRight() {
//memory
lastDirection = 'R';
// Move slight forward
controlMotors(BASE_SPEED, BASE_SPEED);
delay(150);
controlMotors(75, -90);
delay(50);
//until it sees middle line
while (digitalRead(SENSOR_PINS[2]) == 0) {
controlMotors(75, -90);
}
controlMotors(-90, 75);
delay(15);
lastError = 0;
integral = 0;
controlMotors(BASE_SPEED, BASE_SPEED);
}
void executeSharpTurnLeft(){
//memory
lastDirection = 'L';
//move slight forward
controlMotors(BASE_SPEED, BASE_SPEED);
delay(150);
controlMotors(-90, 75);
delay(50);
// until it sees middle line
while (digitalRead(SENSOR_PINS[2]) == 0) {
controlMotors(-90, 75);
}
controlMotors(75, -90);
delay(15);
lastError = 0;
integral = 0;
controlMotors(BASE_SPEED, BASE_SPEED);
}
void handleLineGap() {
// drive slight forward
controlMotors(BASE_SPEED, BASE_SPEED);
// for some time go forward until it sees line
for (int i = 0; i < 30; i++) {
delay(2);
if (readRawSensorBits() != 0b00000) {
return;
}
}
// If it does not sees line go to recover
recoverLostTrack();
}
int readRawSensorBits() {
int pattern = 0;
if (digitalRead(SENSOR_PINS[0]) == 1) pattern += 16;
if (digitalRead(SENSOR_PINS[1]) == 1) pattern += 8;
if (digitalRead(SENSOR_PINS[2]) == 1) pattern += 4;
if (digitalRead(SENSOR_PINS[3]) == 1) pattern += 2;
if (digitalRead(SENSOR_PINS[4]) == 1) pattern += 1;
return pattern;
}
int calculatePositionError(int pattern) {
long activeSensorsSum = 0;
long weightedSum = 0;
if (pattern & 16) { activeSensorsSum++; weightedSum += -2; }
if (pattern & 8) { activeSensorsSum++; weightedSum += -1; }
if (pattern & 4) { activeSensorsSum++; weightedSum += 0; }
if (pattern & 2) { activeSensorsSum++; weightedSum += 1; }
if (pattern & 1) { activeSensorsSum++; weightedSum += 2; }
if (activeSensorsSum == 0) return 999;
if (weightedSum > 0) lastDirection = 'R';
else if (weightedSum < 0) lastDirection = 'L';
else if (pattern & 4) lastDirection = 'S';
return (weightedSum * 10) / activeSensorsSum;
}
void controlMotors(int speedL, int speedR) {
speedL = constrain(speedL, MIN_SPEED, MAX_SPEED);
speedR = constrain(speedR, MIN_SPEED, MAX_SPEED);
analogWrite(ENA, abs(speedL));
digitalWrite(IN1, speedL >= 0 ? HIGH : LOW);
digitalWrite(IN2, speedL >= 0 ? LOW : HIGH);
analogWrite(ENB, abs(speedR));
digitalWrite(IN3, speedR >= 0 ? HIGH : LOW);
digitalWrite(IN4, speedR >= 0 ? LOW : HIGH);
}
void recoverLostTrack() {
if (lastDirection == 'R') {
controlMotors(BASE_SPEED + 10, -(BASE_SPEED + 10));
} else if (lastDirection == 'L') {
controlMotors(-(BASE_SPEED + 10), BASE_SPEED + 10);
} else {
controlMotors(0, 0);
}}
Figure Of The Project:
Future Plan:
This project work helped us to understand the core fundamentals of a line
following robot. Now for the future, we want to create a lightweight, powerful
and implement a efficient algorithm to perform in national competitive LFR
competition.
Conclusion:
The line following robot is a system that has ability to recognize it’s path, move
and change the robot’s position toward the line in the best way to remain in track.
This project report presents a IR sensor based line follower robot design which
always directs along the black line on white surface. The robot is able to detect
it’s path in case it is out of path.
The line following robot project challenged the group to cooperate, communicate,
and expand understanding of electronics, mechanical systems, and their
integration with programming. The successful completion of every task
demonstrated the potential of gaining knowledge and a positive group dynamic.