Tutorial · Beginner · 20 min

Read an IR Reflectance Sensor Array for Line Following

How a line follower turns a row of IR reflectance sensors into one steering error: analog vs digital, calibration, and the weighted-average position formula.

Published

A line-following robot is only as good as the number it steers on. That number comes from a row of infrared reflectance sensors pointed at the floor: the line is one colour, the background another, and the sensors report how much IR light bounces back. This guide turns that raw row of readings into a single, smooth line position—the error your controller acts on.

How a reflectance sensor sees the line

Each sensor pairs an IR LED with a phototransistor. The LED shines down; the phototransistor measures the reflection. A matte black line reflects little IR (low reading); the lighter background reflects more (high reading). Sweep the array across a black-on-white track and each sensor swings between a “on the line” value and an “off the line” value.

Two things change those raw values run to run: sensor height above the surface and ambient light. That is why you never hard-code thresholds—you calibrate.

Analog vs digital sensors

  • Analog sensors give a continuous value (e.g. 0–1023 on an Arduino ADC). You can tell how far the line is from each sensor, which lets you compute a smooth position and steer proportionally.
  • Digital sensors report only on/off after an internal threshold. Simpler to wire, but you lose the in-between information, so steering is coarser.

For proportional line following—the kind you tune with a PID controller—use analog readings. This is the approach the line follower simulator models.

Calibrate first

Before a run, sweep every sensor across both the line and the background and record each sensor’s minimum and maximum. Then normalise each live reading into 0–1000 against its own range:

// Per-sensor calibration captured during a sweep.
int minv[N], maxv[N];

int normalized(int raw, int i) {
  long span = maxv[i] - minv[i];
  if (span <= 0) return 0;                       // sensor never saw contrast
  long v = (long)(raw - minv[i]) * 1000 / span;  // 0 (background) … 1000 (line)
  return constrain(v, 0, 1000);
}

Calibrating per sensor cancels out uneven LED brightness and slight height differences across the bar, so one sensor is not quietly biasing the whole estimate.

From readings to one line position

Now collapse the array into a single position with a reflectance-weighted average. Give each sensor a fixed position (…−2, −1, 0, +1, +2… across the bar) and weight it by its normalised reading. The result is the line’s location relative to the bar centre—positive on one side, negative on the other, zero when the line sits dead centre.

Bar chart of five reflectance sensors across the robot bar. The line sits right of center, so the right-hand sensors read strongest. A dashed line marks the bar center (error zero) and a solid line marks the reflectance-weighted position at plus 0.69, the computed steering error.
The weighted average of the sensor readings gives a smooth line position: here the line sits right of center, so the error is positive and the controller steers back toward zero. Download SVG
// Sensor positions across the bar, e.g. { -2000,-1000,0,1000,2000 }.
long readLinePosition() {
  long weighted = 0, total = 0;
  for (int i = 0; i < N; i++) {
    int v = normalized(analogRead(pins[i]), i);
    weighted += (long)v * position[i];
    total    += v;
  }
  if (total == 0) return lastPosition;  // line lost — reuse last direction
  lastPosition = weighted / total;
  return lastPosition;                  // 0 = centered, sign = which side
}

Two details make this robust:

  • Divide by the total reading, not the sensor count, so a faint line and a bold line both map onto the same position scale.
  • When every sensor loses the line (total == 0), reuse the last known position instead of returning zero. That makes the robot keep turning toward where the line was, rather than driving straight off a sharp corner.

How many sensors?

Five is a good starting point—enough to see direction and magnitude while keeping the maths easy to inspect. Three works at low speed; competition robots use eight or more for finer resolution at speed. More sensors mainly buys you a smoother position estimate on tight curves.

Where this goes next

That single position value is the error term. Feed it into a control loop that speeds one wheel and slows the other, and you have a line follower. Learn that loop in Tune a PID controller, then try the whole thing end to end in the line follower simulator.

Explore the graph

Part of these builds

Projects and learning paths that include this tutorial.

Further reading

References