IR Line Follower Robot with Arduino and Three TCRT5000 Sensors

The line follower is the first autonomous robot most engineering students build, and it is a regular event at college tech fests. The robot follows a black line on a white surface, or a white line on black, using infrared reflectance sensors under its nose. It teaches sensor calibration, decision logic and motor control in one small project.

This tutorial uses three digital IR modules based on the TCRT5000 on the 2WD chassis from the previous tutorial. You will learn how the sensor works, how to mount and calibrate it, and how to write a clear state-based steering program. The next tutorial in the series replaces this simple logic with PID control for smoother, faster tracking.

How the IR Reflectance Sensor Works

The TCRT5000 contains an infrared LED and a phototransistor side by side, facing the same direction. A white surface reflects much of the IR light back into the phototransistor, while a black surface absorbs most of it. The common blue modules add an LM393 comparator that compares the phototransistor voltage with a threshold set by a trimmer potentiometer, giving a clean digital output, and an indicator LED that shows the output state.

On most of these modules the digital output goes LOW when enough light is reflected (white surface) and HIGH over black, but this is not universal, so the code below makes the polarity a single constant you can change after testing. The sensor works best at a small height above the surface; the TCRT5000 datasheet shows the strongest response at only a few millimetres, so mount the modules close to the floor.

Hardware and Mounting

ComponentConnectionNotes
Left IR module OUTArduino A0 (used as digital input)VCC to 5 V, GND to GND
Centre IR module OUTArduino A1Mounted on the robot centre line
Right IR module OUTArduino A2Same height as the others
TB6612FNG driverPins 4, 5, 6, 7, 8, 9, 10Same wiring as the 2WD chassis tutorial
TrackBlack electrical tape about 18 to 20 mm wide on white chart paperUse smooth curves at first

Space the sensors so that when the centre sensor is over the middle of the line, the left and right sensors are just outside it on white. With 18 mm tape, a centre-to-centre spacing slightly larger than the line width works well. Mount the sensor bar ahead of the drive wheels; the further forward it is, the earlier the robot sees a curve, but the more it swings during turns.

Calibrating each sensor

  1. Power the robot and place one sensor over white paper.
  2. Turn its trimmer until the indicator LED just changes state, then turn slightly past that point.
  3. Move the sensor over the black tape and check that the LED changes state cleanly.
  4. Repeat for all three sensors, then check readings in the Serial Monitor using the debug output in the sketch.

Steering Logic and Code

With three sensors there are eight possible combinations. The table maps the important ones to an action. A 1 means that sensor sees the line.

LeftCentreRightMeaningAction
010Centred on lineGo straight
110Line drifting leftGentle left
100Line far leftSharp left
011Line drifting rightGentle right
001Line far rightSharp right
000Line lostTurn towards the side last seen
111Junction or wide markerGo straight (or stop)
Three-sensor line follower with lost-line recovery
// Three-sensor IR line follower: Arduino Uno + TB6612FNG
const int S_LEFT = A0, S_CENTER = A1, S_RIGHT = A2;
const int PWMA = 5, AIN1 = 7, AIN2 = 8;    // left motor
const int PWMB = 6, BIN1 = 9, BIN2 = 10;   // right motor
const int STBY = 4;

// Set to HIGH if your module outputs HIGH over the black line (most do).
const int ON_LINE = HIGH;

const int BASE   = 140;   // straight speed
const int GENTLE = 70;    // inner wheel speed on gentle turns
const int SHARP  = 120;   // spin speed on sharp turns

int lastSeen = 0;         // -1 = line was left, +1 = line was right

void motor(int pwmPin, int in1, int in2, int s) {
  s = constrain(s, -255, 255);
  digitalWrite(in1, s > 0 ? HIGH : LOW);
  digitalWrite(in2, s < 0 ? HIGH : LOW);
  analogWrite(pwmPin, abs(s));
}
void drive(int l, int r) {
  motor(PWMA, AIN1, AIN2, l);
  motor(PWMB, BIN1, BIN2, r);
}

void setup() {
  pinMode(S_LEFT, INPUT); pinMode(S_CENTER, INPUT); pinMode(S_RIGHT, INPUT);
  int pins[] = {PWMA, AIN1, AIN2, PWMB, BIN1, BIN2, STBY};
  for (int p : pins) pinMode(p, OUTPUT);
  digitalWrite(STBY, HIGH);
  Serial.begin(9600);
}

void loop() {
  bool L = digitalRead(S_LEFT)   == ON_LINE;
  bool C = digitalRead(S_CENTER) == ON_LINE;
  bool R = digitalRead(S_RIGHT)  == ON_LINE;

  if (L && !R) lastSeen = -1;      // remember which side had the line
  if (R && !L) lastSeen = +1;

  if (C && !L && !R)      drive(BASE, BASE);          // centred
  else if (L && C && !R)  drive(GENTLE, BASE);        // gentle left
  else if (L && !C)       drive(-SHARP, SHARP);       // sharp left (spin)
  else if (R && C && !L)  drive(BASE, GENTLE);        // gentle right
  else if (R && !C)       drive(SHARP, -SHARP);       // sharp right (spin)
  else if (L && C && R)   drive(BASE, BASE);          // junction: go straight
  else {                                              // line lost
    if (lastSeen < 0) drive(-SHARP, SHARP);
    else              drive(SHARP, -SHARP);
  }

  // Debug: uncomment to check sensor states in the Serial Monitor
  // Serial.print(L); Serial.print(C); Serial.println(R);
}

How the Code Behaves

The loop runs without any delay, so the sensors are checked thousands of times per second and the robot reacts immediately. The lastSeen variable is the key to reliability: when the robot overshoots a sharp curve all three sensors see white, and without memory it would not know which way to turn. By remembering which outer sensor last saw the line, it spins back the right way.

Tuning comes down to three numbers. Raise BASE once the robot follows the track reliably. If it wobbles from side to side on straights, increase GENTLE so the correction is softer. If it runs off tight curves, increase SHARP or slow down BASE.

Troubleshooting

  • Robot turns away from the line: the motor sides or the sensor sides are swapped. Swap the left and right sensor pins in the code.
  • Sensors work on the bench but fail on the track: room lighting or sunlight contains IR. Shield the sensors with black tape around the sides and recalibrate on the actual track.
  • Readings flicker over the edge of the line: normal at the boundary; slightly adjust the trimmers so the threshold is near the middle of the white-to-black range.
  • Robot wobbles badly at high speed: this is the limit of on-off control. Move to analog readings and PID, explained in the next tutorial.

Summary

A TCRT5000 module turns surface reflectance into a digital signal through an LM393 comparator. Three sensors mounted close to the floor and calibrated on the real track give enough information for a state table that steers gently, sharply or recovers a lost line using memory. This simple design completes most beginner tracks; for speed, PID control is the next step.