Sensors
Ultrasonic, infrared, encoders, IMUs and lidar: how each works and how it lies to you.
Day 7 · 55 min
After this lesson
- You can explain time-of-flight ranging and quadrature encoding.
- You can fuse a gyro and accelerometer with a complementary filter.
- You can filter a noisy sensor with an exponential moving average.
How robot sensors work, and how they lie
Every sensor turns a physical quantity into a number through a model, and every model has conditions under which it fails. Knowing those conditions is most of the job: the code that reads a sensor is ten lines, the code that copes with its failures is the rest.
Ultrasonic ranging: the HC-SR04
The HC-SR04 measures time of flight. Hold TRIG high for 10 µs and the module sends a burst of eight 40 kHz cycles, then holds ECHO high until it hears the reflection. Distance is d = t · 343 / 2, with t in seconds and 343 m/s the speed of sound at 20 °C. The round trip costs about 58 µs per centimetre, so an object 1 m away gives a 5.8 ms pulse. The module is rated for 2-400 cm with a measuring angle of about 15°. If nothing comes back it gives up after about 38 ms, and you should wait at least 60 ms between pings so a late echo is not taken for the next one.
It lies in four predictable ways:
- Angled smooth surfaces. At 40 kHz the wavelength is 8.6 mm, so painted walls, glass and boxes act as mirrors. A wall tilted more than about 15° from square sends the echo away and the sensor reports nothing at all.
- Soft surfaces. Fabric, foam and fur absorb sound, so echoes become weak and intermittent.
- Temperature. Sound travels at about 331.3 + 0.606·T m/s, so its speed changes 5.5% between 0 °C and 30 °C.
- Crosstalk. Two sensors pinging together hear each other. Fire them in turn.
The module runs on 5 V and its ECHO output is 5 V, so a 3.3 V microcontroller needs a divider on that pin.
Infrared reflectance: the TCRT5000
A TCRT5000 puts a 950 nm infrared LED beside a phototransistor. A white floor reflects the light and turns the transistor on; black tape absorbs it. The sensor works best about 2.5 mm from the surface, and sunlight, which is rich in infrared, can swamp it. Read the analog output, record each sensor's black and white values, and set the threshold halfway between them rather than trusting a fixed number.
Quadrature encoders
An encoder turns rotation into pulses. A quadrature encoder has two channels, A and B, offset by a quarter cycle (90 electrical degrees). Whichever channel leads gives the direction, and counting both edges of both channels (×4 decoding) gives four counts per pulse. Datasheets quote pulses per revolution (PPR) of one channel; counts per revolution (CPR) includes the decoding. The course robot's N20 motors carry 7 PPR magnetic encoders on the motor shaft, so ×4 decoding gives 28 counts per motor turn and 1,400 per wheel turn behind the 50:1 gearbox. Count edges in hardware (the ESP32's pulse-counter unit) or in short interrupts; a polled loop misses edges at speed.
IMUs: accelerometer, gyroscope, magnetometer
- The accelerometer measures specific force, gravity included, over ±2-16 g. At rest it gives tilt from the direction of gravity, but vibration and acceleration corrupt it.
- The gyroscope measures angular rate, typically ±250-2000 °/s. It is smooth, but its zero-rate offset (up to ±20 °/s uncalibrated on an MPU-6050) integrates into drift: an uncorrected 0.5 °/s bias is 30° of heading error per minute. Average it for two seconds at rest and subtract it.
- The magnetometer senses Earth's 25-65 µT field for heading, but motors, steel and wiring distort it, so it needs hard- and soft-iron calibration.
The complementary filter fuses gyro and accelerometer for tilt: angle = α·(angle + rate·dt) + (1 − α)·accelAngle. With α ≈ 0.98 at 100 Hz, the crossover time constant α·dt/(1 − α) is about 0.5 s: the gyro tracks fast motion and the accelerometer removes slow drift. It cannot fix yaw, because gravity carries no heading information.
Lidar and cameras
Lidar times light instead of sound: 6.7 ns per metre of range. A spinning 2D unit such as the RPLIDAR A1 gives 360° scans out to 12 m at about 5.5 Hz; single-point sensors such as the VL53L1X reach about 4 m over I2C. Both struggle with glass, mirrors and black surfaces. Cameras give the richest data at the highest compute cost; they need lens calibration (focal length and distortion from about 20 checkerboard images) and suffer from motion blur and lighting changes.
Sampling, noise and filtering
Sample at least twice as fast as the fastest change you care about (Nyquist), and in practice 5-10 times faster. Averaging N independent samples cuts noise by √N, so 16 samples give a 4× improvement. The workhorse filter is the exponential moving average, y += α·(x − y): one multiply, with α = dt/(τ + dt) setting the time constant τ. Its price is lag: with τ = 40 ms it delays a slow signal by about 40 ms, and lag inside a control loop costs stability. For spikes and dropouts, such as an ultrasonic timeout, a median of three readings beats any average.
Calibration and fusion
Calibration maps raw readings to truth: offsets (gyro bias at rest), scale (drive exactly 1 m and count ticks to find the effective wheel diameter) and ranges (black and white values per line sensor). Fusion then combines sensors whose errors differ. Encoders are precise over short distances but slip; a gyro holds heading through a slip but drifts; an occasional absolute fix, such as a wall, a line or a lidar scan, resets both. The Kalman filter is the formal, optimal version of that idea; the complementary filter is its simplest cousin.
Interactive: ping a wall, spin an encoder
Ultrasonic ping: time of flight and the lost echo
An HC-SR04 sends eight 40 kHz cycles and times the echo. Sound is slowed about 170× here. Tilt the wall past about 15° and the echo misses the receiver.
- Echo pulse
- 6989 µs
- Firmware reads (343 m/s)
- 119.9 cm
- True distance to the wall
- 120.0 cm
- Speed of sound
- 343.4 m/s, error -0.1 cm
Tilt the wall to 10° and the reading barely changes; at 20° the echo is gone. Then drop the temperature to 0 °C at 380 cm: the firmware's fixed 343 m/s overestimates the range by about 13 cm.
Quadrature encoder: two channels, direction and count
The N20's magnetic disc has 7 pole pairs, so each Hall sensor gives 7 pulses per motor turn. B sits a quarter cycle behind A. Watch which channel leads when you reverse.
- Direction
- clockwise (A leads B)
- Count (×4)
- 0
- Resolution at the wheel
- 10.13 counts/mm
- Wheel travel (50:1, 44 mm)
- 0.00 mm
Pause, then press Step to walk through one edge at a time and watch the AB state move around the ring. Reverse the speed and the order of edges, not their shape, changes.
In practice
Practice
Filter a noisy range reading
Write an exponential moving average for the HC-SR04 that starts from the first valid sample and ignores timeouts. Pick α for a 40 ms time constant at 100 Hz.
Answer. α = dt/(τ + dt) = 0.01/0.05 = 0.2. Invalid readings are rejected before they reach the filter, so a single timeout cannot drag the estimate toward 0.
// Exponential moving average for a sensor read at a fixed rate.
// alpha = dt / (tau + dt). At 100 Hz (dt = 0.01 s) and tau = 0.04 s, alpha = 0.2.
class Ema {
public:
explicit Ema(float alpha) : alpha_(alpha) {}
float update(float x) {
if (!primed_) { // start from the first real sample, not from 0
y_ = x;
primed_ = true;
} else {
y_ += alpha_ * (x - y_);
}
return y_;
}
float value() const { return y_; }
private:
float alpha_;
float y_ = 0.0f;
bool primed_ = false;
};
Ema rangeCm(0.2f);
// Called whenever a new HC-SR04 reading arrives (about every 50 ms).
void onUltrasonic(float cm) {
if (cm < 2.0f || cm > 400.0f) { // 0 means "timeout": unknown, not near and not far
return; // keep the last estimate, count the miss elsewhere
}
rangeCm.update(cm);
}Practice
Ticks per millimetre for the course robot
The N20 encoder gives 7 pulses per motor revolution, the gearbox is 50:1 and the wheel is 44 mm across. How many ticks per millimetre do you get, and what does that mean for measuring speed at 100 Hz?
Encoder on the motor shaft 7 pulses per revolution (one channel)
Gearbox 50 : 1
Wheel 44 mm diameter -> circumference = pi x 44 = 138.2 mm
x1 decoding (A rising edges): 7 x 50 = 350 ticks per wheel turn
350 / 138.2 = 2.53 ticks per mm (0.40 mm per tick)
x4 decoding (every edge): 7 x 4 x 50 = 1,400 counts per wheel turn
1,400 / 138.2 = 10.1 counts per mm (0.10 mm per count)
Speed measurement at 0.2 m/s with a 100 Hz loop (2 mm of travel per cycle):
x1 -> about 5 ticks per cycle -> one tick is a 20 % speed step
x4 -> about 20 counts per cycle -> one count is a 5 % speed stepAnswer. About 2.5 ticks per mm counting only A's rising edges, or 10.1 counts per mm with ×4 decoding. At low speed a 100 Hz loop sees only a handful of ticks per cycle, so use ×4 decoding, or measure the time between edges instead of counting them.
Real-world scenario
Real-world scenario
Robot drives into angled walls its ultrasonic sensor never reported
An obstacle-avoiding robot uses one forward-facing HC-SR04 and turns away whenever the reading drops below 25 cm. In square-on bench tests it never touches a wall. During a hallway demo it drives straight into walls it meets at a shallow angle, and into a fabric-covered partition. Early in the project the team made the firmware convert a pulseIn() timeout, which returns 0, into 400 cm, because zeros were causing spurious stops in open rooms.
Symptoms
- Square-on walls are detected reliably from a few centimetres to beyond 2 m.
- Walls met roughly 30-45° off square are never reported; the log shows 0 (converted to 400 cm) for the last second before every impact.
- The fabric-covered partition gives readings that jump between a plausible 40-60 cm and 0.
- A second HC-SR04 angled 30° outward and fired at the same moment as the first made the readings noisier, not better.
Interview questions
screenHow does an HC-SR04 measure distance, and what limits it?
screenWhat is a quadrature encoder, and how do you get direction from it?
deepExplain how a complementary filter estimates tilt from a gyro and an accelerometer. How do you choose α, and what can it not fix?
deepYou need to filter a noisy sensor that feeds a control loop. How do you choose the filter?
screenWhy does position from an IMU alone drift so fast?
Quiz
References and further reading
Where the ideas in this lesson come from, and what to read next. Books are the standard texts; papers are the original sources; standards are what employers work to.
- Book
Roland Siegwart, Illah R. Nourbakhsh and Davide Scaramuzza (2011). Introduction to Autonomous Mobile Robots. MIT Press, 2nd edition.
Read: The perception chapter: sensor classification, ultrasonic, encoders, IMUs.
- Book
Sebastian Thrun, Wolfram Burgard and Dieter Fox (2005). Probabilistic Robotics. MIT Press.
Read: Chapter 6 on measurement models and sensor noise.
- Paper
R. E. Kalman (1960). A New Approach to Linear Filtering and Prediction Problems. Journal of Basic Engineering 82(1), 35-45.doi:10.1115/1.3662552
Read: Read the abstract and the idea of blending prediction with measurement.