A line following robot uses infrared sensors to detect a contrasting line on the floor and steers to stay on it. It is the standard beginner competition task because it rewards clean wiring, good calibration and a well-tuned control loop — not expensive hardware.
This guide assumes an Arduino Uno or Nano, an L298N motor driver, two TT gear motors and three to five TCRT5000 infrared sensors. You can complete it in two weekends.
Safety first: use protected lithium cells, a proper charger, a fuse or resettable polyfuse, and never power motors from the Arduino 5V pin. If a battery or wire gets hot, disconnect immediately.
How a line follower works
Each IR sensor shines infrared light at the floor and measures the reflection. A white surface reflects strongly; a black line absorbs it. The sensor module outputs a digital HIGH or LOW depending on its comparator threshold.
With three sensors, the logic is simple:
| Left | Centre | Right | Meaning | Action |
|---|---|---|---|---|
| Line | Line | No line | Drifting right | Turn left |
| No line | Line | No line | Centred | Go straight |
| No line | Line | Line | Drifting left | Turn right |
| No line | No line | No line | Line lost | Stop or search |
With five sensors you get finer position estimates, which makes PID control much smoother. Use three for your first build, then upgrade.
Parts list
- Arduino Uno or Nano (and USB cable)
- L298N or TB6612FNG motor driver
- 2 × TT gear motors with wheels, plus a caster wheel
- 3 × TCRT5000 infrared line sensors (5 for the advanced build)
- Robot chassis or a rigid cardboard/acrylic plate
- 2 × 18650 protected cells + holder + charger (or a 6–9V battery pack for testing)
- Buck converter if your driver does not provide 5V logic power
- Jumper wires, screw terminals, zip ties, double-sided tape
- Black electrical tape and white paper/card for the track
Wiring
Keep motor power and logic power separate. The L298N has a 12V input, a 5V output (only use it if your input is above ~7V and the onboard regulator is enabled) and logic inputs.
| Component | Pin | Arduino / power |
|---|---|---|
| L298N | IN1 / IN2 / ENA | D5 / D6 / D9 (PWM) |
| L298N | IN3 / IN4 / ENB | D7 / D8 / D10 (PWM) |
| L298N | 12V / GND | Battery + / battery − |
| L298N | 5V (if enabled) | Arduino 5V (logic only) |
| Left sensor | OUT / VCC / GND | D2 / 5V / GND |
| Centre sensor | OUT / VCC / GND | D3 / 5V / GND |
| Right sensor | OUT / VCC / GND | D4 / 5V / GND |
| Motors | OUT1–OUT4 | Left motor / right motor |
All grounds must be connected together. If the robot behaves erratically when the motors start, the cause is almost always a shared-ground or power-supply problem.
Test before you mount: upload the code, lift the robot off the table, and confirm each wheel turns the correct direction. Swap the two motor wires if a wheel is reversed.
Calibrate the sensors
Every surface reflects differently. Put the robot on the track, open the serial monitor and print each sensor value. Adjust the potentiometer on each TCRT5000 until the LED changes state at the edge of the line.
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
}
void loop() {
Serial.print(digitalRead(2));
Serial.print(" ");
Serial.print(digitalRead(3));
Serial.print(" ");
Serial.println(digitalRead(4));
delay(100);
}
Record the values on white and on black. If a sensor never changes, it is too far from the floor, the potentiometer is at an extreme, or the wiring is wrong. Aim for at least 10 mm of reliable difference.
Working Arduino code
This version uses three sensors and a simple proportional steering term. It is intentionally readable. Tune BASE_SPEED and TURN_SPEED for your motors and track.
// Line follower — 3 sensors, L298N
const uint8_t LEFT_SENSOR = 2;
const uint8_t CENTER_SENSOR = 3;
const uint8_t RIGHT_SENSOR = 4;
const uint8_t ENA = 9; // left motor PWM
const uint8_t IN1 = 5;
const uint8_t IN2 = 6;
const uint8_t ENB = 10; // right motor PWM
const uint8_t IN3 = 7;
const uint8_t IN4 = 8;
const uint8_t BASE_SPEED = 150;
const uint8_t TURN_SPEED = 110;
void setMotors(int left, int right) {
left = constrain(left, -255, 255);
right = constrain(right, -255, 255);
digitalWrite(IN1, left >= 0 ? HIGH : LOW);
digitalWrite(IN2, left >= 0 ? LOW : HIGH);
digitalWrite(IN3, right >= 0 ? HIGH : LOW);
digitalWrite(IN4, right >= 0 ? LOW : HIGH);
analogWrite(ENA, abs(left));
analogWrite(ENB, abs(right));
}
void setup() {
pinMode(LEFT_SENSOR, INPUT);
pinMode(CENTER_SENSOR, INPUT);
pinMode(RIGHT_SENSOR, INPUT);
pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
}
void loop() {
bool left = digitalRead(LEFT_SENSOR);
bool center = digitalRead(CENTER_SENSOR);
bool right = digitalRead(RIGHT_SENSOR);
if (!left && center && !right) {
setMotors(BASE_SPEED, BASE_SPEED); // centred
} else if (left && !right) {
setMotors(TURN_SPEED, BASE_SPEED + 40); // drift left, steer right
} else if (!left && right) {
setMotors(BASE_SPEED + 40, TURN_SPEED); // drift right, steer left
} else if (center) {
setMotors(BASE_SPEED, BASE_SPEED); // still on the line
} else {
setMotors(0, 0); // line lost: stop safely
}
}
Sensor polarity depends on your module and surface. If the robot steers away from the line, invert the conditions rather than rewiring everything.
From bang-bang to PID
The code above is “bang-bang” control: full steering when an outer sensor sees the line. It works, but it oscillates. PID uses how far off-centre you are (proportional), how long you have been off-centre (integral) and how fast the error is changing (derivative) to produce smoother steering.
With five sensors, compute a weighted error:
// Sensor weights: far left -2, left -1, centre 0, right +1, far right +2
// Read all five, then:
int error = 0;
int active = 0;
for (int i = 0; i < 5; i++) {
if (sensor[i] == LINE_VALUE) {
error += (i - 2);
active++;
}
}
if (active == 0) {
// line lost: use the last error direction to search
} else {
error = error * 100 / active;
}
float correction = Kp * error + Kd * (error - lastError);
lastError = error;
setMotors(BASE_SPEED + correction, BASE_SPEED - correction);
Start with Kp = 1.2 and Kd = 0.6 for a small robot, then tune one term at a time. Increase Kp until the robot follows aggressively but does not oscillate; add Kd to damp the oscillation. Add a small Ki only if the robot consistently drifts to one side on straights.
Tuning method: test on the same track every time, change one value, run three laps, and write down the result. Guessing without notes is why people spend weeks tuning.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Robot spins in place | One motor reversed | Swap that motor's two wires or invert its code direction |
| Motors stutter when sensors read | Shared power / ground noise | Separate motor and logic supplies; common ground; add a capacitor |
| Robot ignores the line | Sensor threshold wrong or too high | Recalibrate 5–10 mm above the floor |
| Oscillates violently | Kp too high or speed too fast | Lower Kp and base speed |
| Drifts on straights | Motor mismatch or wheel slip | Calibrate a small trim, check tyre grip and alignment |
| Resets when motors start | Battery voltage sag | Use a fresh, adequate battery; add a bulk capacitor |
Upgrades that actually matter
- Five sensors — smoother error estimation and better PID.
- Encoders — measure real speed and build a velocity loop.
- TB6612FNG driver — smaller, cooler and more efficient than an L298N.
- Line-lost recovery — remember the last error and reverse-search instead of stopping.
- Battery monitoring — warn before voltage sag causes random resets.
- Better tyres — grip changes lap times more than most code changes.
When your robot completes a full lap reliably, you are ready for a school or national competition. Read the Bangladesh olympiad guide next, and post your build in the community for feedback.
সংক্ষেপে বাংলায়
লাইন ফলোয়ার রোবট বানাতে যা লাগে: আরডুইনো, L298N মোটর ড্রাইভার, দুটি TT গিয়ার মোটর, তিনটি TCRT5000 ইনফ্রারেড সেন্সর, চাকা ও ব্যাটারি। সেন্সর সাদাsurface-এ আলো প্রতিফলিত করে আর কালো লাইনে তা শোষিত হয় — এই পার্থক্য দিয়েই রোবট লাইন চিনে।
প্রথমে সেন্সরের potentiometer ঠিক করে কালো ও সাদার মান যাচাই করুন, তারপর মোটর আলাদা পাওয়ার সাপ্লাই থেকে চালান এবং সব ground একসাথে যুক্ত করুন। তিন সেন্সরের সাধারণ কোড দিয়ে শুরু করুন; রোবট স্থির হলে পাঁচ সেন্সর ও PID যোগ করুন। Kp দিয়ে শুরু করে এক এক করে টিউন করুন। বিস্তারিত কোড ও ওয়্যারিং টেবিল এই গাইডে দেওয়া আছে।
Frequently asked questions
How many sensors does a line following robot need?
Three sensors are enough to follow a line reliably. Five sensors give a smoother position estimate and work much better with PID control, which is why most competition robots use five or more.
Can I build a line follower without PID?
Yes. Simple if-else logic with three sensors works for a first robot. PID becomes worthwhile when you want smooth, fast laps without oscillation.
Why does my line follower keep losing the line?
The most common causes are wrong sensor height, an uncalibrated threshold, too much ambient light, or driving too fast for the sensor spacing. Recalibrate on the actual track and lower the base speed.
What battery should I use for a line following robot?
Two protected 18650 lithium-ion cells in series (7.4V nominal) with a proper charger and a fuse are a common choice. Avoid unprotected cells and never charge them unattended.
Build something this week.
Take a free course, join the WhatsApp community, and get feedback on your build from students across Bangladesh.