Police speed traps measure how long a car takes to drive a known distance. This one does the same for toy cars. Two infrared sensors look down from the roof of a printed tunnel, exactly 10 cm apart. The UNO notes the moment a car passes the first one, then the second, and works out the speed. The LCD shows it in metres per second and km/h, and because most toy cars are a 64th of the real size, it also shows the speed a real car would need to look as fast.
What you'll learn
- How to measure a short time precisely with
micros() - How to work out speed from distance and time
- How to use a sensor's "resting" value so it works with any car colour
- How scale models change the way speed feels
What you need
- UNO R3 board and USB cable (UNO R3 Starter Kit)
- Obstacle avoidance sensor module (45-in-1 Sensor Kit)
- Line tracking sensor module (45-in-1 Sensor Kit)
- 1602 LCD display, 10 kΩ potentiometer and 1 resistor, 220 Ω (UNO R3 Starter Kit)
- A toy car and a track or a smooth floor
- The printed parts from the 3D printing box below (speed trap tunnel), or the cardboard version described there
- Breadboard and jumper wires (UNO R3 Starter Kit)
Wiring

| From | To |
|---|---|
| Obstacle sensor OUT | UNO pin 2 |
| Line tracking sensor S | UNO pin 3 |
| Both sensors + and − | 5V and GND |
| LCD VSS, RW and K | GND |
| LCD VDD | 5V |
| LCD V0 | Middle pin of the potentiometer |
| LCD RS | UNO pin 12 |
| LCD E | UNO pin 11 |
| LCD D4, D5, D6, D7 | UNO pins 7, 6, 5, 4 |
| LCD A (backlight +) | 220 Ω resistor, then 5V |
| Potentiometer outer pins | 5V and GND |
Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.
The LCD has 16 connections in a row. If yours has no pins, solder 16 pins from the 40-pin male header in the kit first, so it plugs into the breadboard. Ask an adult to help if you're new to soldering.
Note that the LCD's data pins move to 7, 6, 5 and 4 in this lesson, because pins 2 and 3 are needed for the sensors.
Adjust the sensors
Both sensors have a small LED that lights when they see something, and a screw to set how far they look. Put the tunnel on the track, push a car underneath by hand and turn each screw until its LED lights while the car is under it and goes out when the car has passed.
The sketch
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
const int GATE1_PIN = 2;
const int GATE2_PIN = 3;
const float GATE_DISTANCE = 0.100; // metres between the two sensors
const int SCALE = 64; // most toy cars are 1:64
const unsigned long TIMEOUT = 3000000; // give up after 3 seconds
int rest1, rest2;
float best = 0;
bool carAt(int pin, int rest) {
return digitalRead(pin) != rest; // anything different from "nothing there"
}
void setup() {
lcd.begin(16, 2);
pinMode(GATE1_PIN, INPUT);
pinMode(GATE2_PIN, INPUT);
delay(500);
rest1 = digitalRead(GATE1_PIN); // learn what "empty track" looks like
rest2 = digitalRead(GATE2_PIN);
lcd.print("Speed trap ready");
lcd.setCursor(0, 1);
lcd.print("Send a car!");
}
void loop() {
if (!carAt(GATE1_PIN, rest1)) return; // wait for a car at the first sensor
unsigned long t1 = micros();
while (!carAt(GATE2_PIN, rest2)) { // ...and at the second one
if (micros() - t1 > TIMEOUT) {
lcd.clear();
lcd.print("Too slow or");
lcd.setCursor(0, 1);
lcd.print("missed. Again!");
while (carAt(GATE1_PIN, rest1)) delay(5);
return;
}
}
unsigned long t2 = micros();
float seconds = (t2 - t1) / 1000000.0;
float metresPerSecond = GATE_DISTANCE / seconds;
float kmh = metresPerSecond * 3.6;
if (kmh > best) best = kmh;
lcd.clear();
lcd.print(metresPerSecond, 2);
lcd.print("m/s ");
lcd.print(kmh, 1);
lcd.print("km/h");
lcd.setCursor(0, 1);
lcd.print("Real: ");
lcd.print((int)(kmh * SCALE));
lcd.print(" km/h");
delay(1000); // let the car leave the tunnel
while (carAt(GATE1_PIN, rest1) || carAt(GATE2_PIN, rest2)) delay(5);
}
How it works
Speed is distance divided by time. The distance is fixed by the printed tunnel: 0.1 m. The time comes from micros(), which counts microseconds since the UNO started. At 2 m/s a car needs only 50 ms for 10 cm, so measuring in milliseconds would round off too much.
The two sensors are different. The obstacle sensor switches to LOW when it sees something, and the line tracking sensor changes depending on whether the surface under it reflects light. A dark car and a white car can even give opposite readings. So the sketch doesn't care whether a reading is HIGH or LOW: it learns the "empty track" value of each sensor at the start, and anything different means a car.
Multiplying m/s by 3.6 gives km/h. A 1:64 toy car is 64 times smaller than the real one, so to look the same, a real car would have to drive 64 times faster. That's why a toy car at 10 km/h looks like a racing car at 640 km/h!
Try this next
- Keep a top-3 list of the fastest runs and show it when nobody is racing.
- Build a ramp and measure how the start height changes the speed.
- Add a third sensor 10 cm further on to see whether the car is speeding up or slowing down.
Troubleshooting
- "Too slow or missed" every time: the second sensor doesn't see the car. Adjust its screw while a car stands under it.
- It measures without a car: the sensors are set too sensitive and see the floor. Turn their screws back a little, and restart the UNO with the track empty.
- The speed is far too high: one sensor sees the car through both slots. Check that each sensor looks straight down.
- The LCD lights up but shows nothing, or only black boxes: turn the potentiometer slowly from one end to the other until the text appears.
- A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.