One-sentence summary
In this project I build a real robot that follows a line on the floor by itself, using two line sensors, two motors, and a motor driver, adjusting the motor speeds based on the left–right sensor readings.
Why it matters
In the previous project the robot spotted an obstacle and fled from it. Now we flip the task: the robot will not run away from something, it will follow a drawn path. This is another face of the same "sense–decide–act" loop.
Line following is the most classic project in robotics. And not only in competitions: transport vehicles that roam between warehouse shelves and factory conveyor lines follow floor markings with similar logic. The idea that works on a small robot works in large systems too.
This project brings the heart of the whole module together in one device. The sensors detect the line, the program decides with a condition, and the motors turn that decision into motion. Electronics, code, and mechanics all work at once. When I first built mine, the robot drifted right even on a straight line; finding and fixing the reason was the most instructive part.
Materials, wiring, and power
Materials list
What a simple line-following robot needs:
- A two-wheel chassis with two DC gear motors.
- A motor driver board (for example an L298N).
- Two infrared (IR) line sensors.
- An Arduino (for example an Uno).
- A separate battery pack for the motors (for example 4–6 AA batteries).
- Jumper wires and a breadboard for connections.
Why a separate battery and a motor driver?
Motors draw far more current than an Arduino pin can supply. Connect a motor straight to a pin and the pin is damaged, maybe the whole board. So we place a motor driver in between: the Arduino sends a small "spin at this speed" signal, and the driver pulls the power from a separate battery.
Think of a doorbell: your finger presses a small button, but the power that makes the sound comes from the wiring in the wall. A motor driver is that kind of go-between.
Two rules matter a lot:
- The motors are powered from a separate battery pack; the Arduino from USB or its own battery.
- The negative terminals (GND) of both power sources must be connected together (common ground). Without a common ground, the driver cannot read the Arduino's signal correctly.
Never use mains (wall socket) electricity. This project uses only low-voltage batteries.
Calibrate the sensors
Before writing code, we must measure what the sensors actually report. Calibration answers the question, "In which case does the sensor read 1, and in which case 0?"
Read with Serial
Print the sensor values to the screen with a small test program:
const int LEFT_SENSOR = 2;
const int RIGHT_SENSOR = 3;
void setup() {
Serial.begin(9600);
pinMode(LEFT_SENSOR, INPUT);
pinMode(RIGHT_SENSOR, INPUT);
}
void loop() {
Serial.print(digitalRead(LEFT_SENSOR));
Serial.print(" ");
Serial.println(digitalRead(RIGHT_SENSOR));
delay(200);
}
Hold the sensor over the black line, then over the white surface. Note how the values change. On some modules the line reads 1, on others 0. In this project we assume "line = 1"; if your module is the opposite, you just flip the comparisons in the code.
Sensor height and position
The sensors are mounted very close to the floor (about 3–8 mm) so they look at either side of the line. Too high and they cannot tell the line apart; too low and they scrape the ground. If your module has a small adjustment screw, tune the threshold until black and white are clearly separated.
Program the robot
The robot's two wheels turn with separate motors. There is no steering wheel; to turn, you drive the two wheels at different speeds. This is called differential drive.
Pseudocode
Repeat forever
left = read left sensor
right = read right sensor
If left is white and right is white
drive both motors fast (go straight)
Else if left is line and right is white
slow the left motor (turn left)
Else if left is white and right is line
slow the right motor (turn right)
Else
handle the junction or lost case
The logic may seem backwards at first: if the left sensor sees the line, we turn left. That is because if the left sensor touched the line, the robot has drifted right; to recentre, we must pull left.
Example 1: Pins and setup
const int LEFT_SENSOR = 2; // left IR sensor
const int RIGHT_SENSOR = 3; // right IR sensor
const int LEFT_ENA = 5; // left motor speed (PWM)
const int LEFT_IN1 = 7; // left motor direction
const int LEFT_IN2 = 8;
const int RIGHT_ENB = 6; // right motor speed (PWM)
const int RIGHT_IN3 = 9; // right motor direction
const int RIGHT_IN4 = 10;
const int FAST = 160; // 0–255
const int SLOW = 70;
void setup() {
pinMode(LEFT_SENSOR, INPUT);
pinMode(RIGHT_SENSOR, INPUT);
pinMode(LEFT_ENA, OUTPUT); pinMode(LEFT_IN1, OUTPUT); pinMode(LEFT_IN2, OUTPUT);
pinMode(RIGHT_ENB, OUTPUT); pinMode(RIGHT_IN3, OUTPUT); pinMode(RIGHT_IN4, OUTPUT);
digitalWrite(LEFT_IN1, HIGH); digitalWrite(LEFT_IN2, LOW); // left forward
digitalWrite(RIGHT_IN3, HIGH); digitalWrite(RIGHT_IN4, LOW); // right forward
}
We set the direction to forward once in setup(). In the loop we will only change the speed.
Example 2: Main loop and a motor helper
void driveMotors(int leftSpeed, int rightSpeed) {
analogWrite(LEFT_ENA, leftSpeed);
analogWrite(RIGHT_ENB, rightSpeed);
}
void loop() {
int left = digitalRead(LEFT_SENSOR); // 1 = line seen
int right = digitalRead(RIGHT_SENSOR);
if (left == 0 && right == 0) { // both white
driveMotors(FAST, FAST); // go straight
} else if (left == 1 && right == 0) { // line on the left
driveMotors(SLOW, FAST); // turn left
} else if (left == 0 && right == 1) { // line on the right
driveMotors(FAST, SLOW); // turn right
} else { // both on the line
driveMotors(FAST, FAST); // junction: keep straight
}
}
driveMotors is a small helper function; it sets the left and right speed in one line. This keeps the loop easy to read.
Junction and lost cases
On a real track, two special cases confuse the robot.
If both sensors see the line, this is usually a junction or a thick marking. On a simple robot the decision is easy: keep going straight. The final else in the code above does exactly this.
If both sensors see white for a long time, the robot may have lost the line completely. If you only say "go straight," the robot drives off the track. A smarter solution is to remember the last direction it saw:
If both are white for a long time
search for the line by turning toward the last turn direction
So if the robot last saw the line on its left, then when it loses the line it turns left to try to find it again.
Test course and fixing one bug
First test the robot with the wheels in the air, holding it in your hand. Then draw a simple course on white paper with black tape or a thick marker: a straight line, then a gentle curve.
| # | Test | Expected result |
|---|---|---|
| 1 | Place it on a straight line | The robot moves straight |
| 2 | Nudge the robot slightly right | Left sensor sees the line, it corrects left |
| 3 | Drive through the gentle curve | The robot turns while following the line |
One bug and its fix: the robot won't go straight
On my first try, the robot kept drifting right even while both sensors saw white. What I expected: go dead straight. What actually happened: it veered right.
Goal: The robot goes straight when both sensors see white
Problem: The robot drifts right on a straight line
Check: The two motors don't spin at the same speed at the same PWM
Fix: Add a small balance offset to the slower motor
The problem was not in the code, it was mechanical: at the same FAST value, the left motor spun a little faster than the right. Two motors are never exactly identical. When I applied a small reduction to the left motor while going straight (for example FAST - 15), the robot straightened out. This small adjustment is called trim, and it differs a little for every robot.
Mini practice
Improve the robot with your own idea. Try one of these:
- Change the
FASTandSLOWvalues and watch whether the robot turns more smoothly or more sharply. - Add the "lost case" logic above into real code: keep the last turn direction in a variable and search that way when the line disappears.
- Add a junction to the course and note what the robot does there; if you like, write a rule that slows it down at a junction.
Write your change in one sentence: what does the robot do now, and what does it do better?
Common mistakes
Forgetting the common ground
If you do not connect the GND terminals of the Arduino and the motor battery together, the driver cannot read the signals. The robot either does not move at all or behaves randomly. Common ground is the most often skipped step in this project.
Connecting a motor straight to the Arduino
If you plug a motor into an Arduino pin, the pin draws too much current and is damaged. Motors must always be powered from the driver board and a separate battery.
Assuming the sensor value
On some modules the line reads 1, on others 0. Do not trust the comparisons in the code before calibrating; measure with Serial first.
Ignoring the trim difference
Two motors never spin exactly the same at the same PWM. If the robot won't go straight, the code may not be wrong; a small trim adjustment usually fixes it.
Safety note
This robot moves, so a few rules matter. Test on a wide, empty floor and stay away from a table edge the robot could fall off. Keep fingers, hair, and cables away from the wheels and gears; spinning parts can pinch. Do your first tries at low speed and with the wheels in the air.
Always run the motors with a motor driver and a separate, low-voltage battery pack; connect the grounds of both sources together. Never use mains (wall socket) electricity. If a battery heats up, a wire smells burnt, or the robot behaves oddly, remove the battery right away. Do any step involving motors, batteries, or cutting tools together with an adult.
Lesson summary
- A line-following robot follows the line by adjusting motor speeds based on the left–right readings of two IR sensors.
- To turn, we drive the two wheels at different speeds; this is called differential drive.
- The motors are powered from a separate battery through a motor driver; the grounds of both power sources must be common.
- A sensor's
0/1value depends on the module; calibrate with Serial before writing code. - If the robot won't go straight, the problem is usually not the code but motor balance; a small trim adjustment fixes it.
Check questions
- In a line-following robot, why do we connect the motors to a motor driver rather than straight to the Arduino?
- When using two power sources, which connection must be common, and why?
- If the left sensor sees the line and the right sensor sees white, which way does the robot turn, and why?
- Why do we calibrate before writing code?
- If the robot keeps drifting to one side on a straight line, what is the first thing you should check?
Answers
- Motors draw more current than an Arduino pin can supply. Connected directly, the pin or board is damaged. The driver pulls power from a separate battery and feeds the motor; the Arduino only sends a small control signal.
- The negative terminals (GND / ground) of the two power sources must be connected together. Without a common ground, the driver cannot correctly read the level of the signal the Arduino sends, and the robot will not work properly.
- The robot turns left. If the left sensor touched the line, the robot has drifted right; slowing the left motor pulls it left and brings it back to the centre of the line.
- Because, depending on the sensor module, the line sometimes reads
1and sometimes0. If we compare in code without measuring, the robot may behave in reverse. Measuring with Serial shows the correct values. - Motor balance. Two motors do not spin exactly the same at the same PWM; applying a small reduction (trim) to the faster motor while going straight usually solves it.
Source and verification note
For “Project: Line-Following Robot”, verification focuses on whether the relationship between Materials, wiring, and power and Why a separate battery and a motor driver? remains consistent across examples. Robot behaviour cannot be explained by code alone; mechanical structure, power system, sensor placement and surface conditions must be evaluated together. Test results should be recorded over several runs on the same course.
Next lesson
Introduction to Data and Artificial Intelligence module: We begin to explore how to gather the sensor data robots collect, make sense of it, and how a computer starts to "learn" from that data.