Build a speed trap for toy cars

Two infrared sensors in a printed tunnel time a toy car over 10 cm. The LCD shows its speed in metres per second, and how fast that would be for a real car.
  • Level:Intermediate
  • Duration: 1 h
  • Ages 11+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Build a speed trap for toy cars – EEMENTOR STEM™ lesson

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

Breadboard wiring diagram: Build a speed trap for toy cars
Breadboard view. Check each connection against the wiring table below.
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.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

45-in-1 Sensor Kit | Compatible with Arduino IDE and ESP32 $37.00

Shop the kit