Build a Line Follower Robot with Arduino
Line following is the classic school-competition event, and the first project where your robot makes decisions faster than you can. This guide bolts two IR sensors onto the 2WD robot car, gets a simple bang-bang follower running, then shows the PID approach used by competition teams.
How IR line sensing works
Each sensor module (typically a TCRT5000) contains an infrared LED and a phototransistor side by side, facing the floor. White surfaces reflect the IR back strongly; matte black tape absorbs it. An on-board comparator turns that difference into a clean digital HIGH/LOW, with a small potentiometer to set the threshold. Mount them 3–8 mm above the floor — too high and everything looks black, touching the floor and they snag.
Extra parts needed
| Part | Notes | Indicative price (India) |
|---|---|---|
| IR line sensor modules ×2 (TCRT5000 type) | Digital-output modules with trim pot | ₹40–80 each |
| Female–female jumper wires ×6 | Sensor to Arduino | ₹30–60 |
| Black electrical tape / matte black chart tape, 19–25 mm | For the track | ₹30–80 |
| White chart paper or a light plain floor | Track surface | ₹20–60 |
Prices shown are indicative online street prices in India as of mid-2026. They vary by seller and stock — treat them as a budgeting guide, not a quote.
Mounting and wiring
Mount both sensors at the front of the chassis, facing down, spaced slightly wider than the tape (about 30–40 mm apart for 19–25 mm tape). On the standard Hobby Robots pinout the motor driver uses D2, D4–D8, so the sensors go to the analog pins used as digital inputs:
| Sensor pin | Left sensor | Right sensor |
|---|---|---|
| VCC | Arduino 5V | Arduino 5V |
| GND | Arduino GND | Arduino GND |
| OUT / DO | Arduino A0 | Arduino A1 |
Verify the sensors first
Before touching the motor code, print the raw readings (Serial.println(digitalRead(A0)); in a loop) while holding the car over white paper and over the tape. Most modules read HIGH over black; some are inverted, and each module’s indicator LED tells you at a glance. If yours are inverted, just add a ! in front of both digitalRead calls in the follower sketch. Adjust each module’s trim pot until the output flips crisply right at the tape edge.
The bang-bang follower
The logic is four lines of common sense: both sensors on the line → drive straight; only the left sensor sees black → the car has drifted right, steer left; and vice versa; neither sees black → the line was lost, rotate until it is found again.
// Hobby Robots — 2-sensor line follower
// Assumes the drive() function and pinout from the robot car guide.
// Sensors: LOW over white floor, HIGH over black line (verify yours!).
const int ENA = 5, IN1 = 7, IN2 = 8;
const int ENB = 6, IN3 = 4, IN4 = 2;
const int SENSOR_L = A0;
const int SENSOR_R = A1;
const int BASE = 160; // cruising speed (0..255)
const int TURN = 120; // inner-wheel speed during a correction
void drive(int left, int right) {
digitalWrite(IN1, left >= 0 ? HIGH : LOW);
digitalWrite(IN2, left >= 0 ? LOW : HIGH);
analogWrite (ENA, min(abs(left), 255));
digitalWrite(IN3, right >= 0 ? HIGH : LOW);
digitalWrite(IN4, right >= 0 ? LOW : HIGH);
analogWrite (ENB, min(abs(right), 255));
}
void setup() {
pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
pinMode(SENSOR_L, INPUT);
pinMode(SENSOR_R, INPUT);
delay(2000);
}
void loop() {
bool leftOnLine = digitalRead(SENSOR_L); // HIGH = sees black
bool rightOnLine = digitalRead(SENSOR_R);
if (leftOnLine && rightOnLine) {
drive(BASE, BASE); // line under both: straight ahead
} else if (leftOnLine) {
drive(TURN, BASE + 40); // drifting right: steer left
} else if (rightOnLine) {
drive(BASE + 40, TURN); // drifting left: steer right
} else {
drive(-140, 140); // lost the line: rotate to search
}
}Tuning it
- Wobbles violently: lower
BASE; bang-bang control always oscillates, and speed amplifies it. - Overshoots corners: lower
BASEfurther, or increase the steering difference (raise the+40, lowerTURN). - Loses the line on gentle curves: sensors are too far apart or too high off the floor.
- Random twitching: sunlight contains lots of IR — test away from direct sun, and re-set the trim pots in the room where you run.
The PID upgrade
Bang-bang control only knows three states, so it zig-zags. Competition robots use a 5- or 8-channel sensor array, compute a weighted position of the line under the array (e.g. −2000 to +2000), and feed that error into a proportional–derivative controller — steering hard when far off the line, gently when nearly centred, and damping the oscillation with the D term:
// Position from a 5-channel analog array: -2000..+2000 (0 = centred)
float Kp = 0.08, Kd = 0.6; // start here, tune on your track
int lastError = 0;
void followPID(int position) {
int error = position; // target is 0
int correction = Kp * error + Kd * (error - lastError);
lastError = error;
drive(BASE - correction, BASE + correction);
}Start with the P term only (Kd = 0), raise Kp until the robot just starts to oscillate, then add Kd until the oscillation dies. A 5-channel array costs ₹150–300 and is the single best upgrade for competition line events.
Building a good test track
- Matte surface, matte tape. Glossy tape or polished floors bounce IR unpredictably.
- Minimum curve radius about 3× the car’s wheelbase to start; tighten it as tuning improves.
- Include one straight, one gentle S-curve, and one sharp corner — that trio exposes every tuning flaw.
- Keep tape joins smooth; a wrinkle reads like a gap.