Hardik's Notes · Build

Build it this weekend: a reaction timer

One button, one LED and 30 lines of MicroPython on a Raspberry Pi Pico. It measures how fast you press, in milliseconds.

A small circuit board with a glowing yellow LED and a breadboard strip. A yellow stopwatch with no numbers stands beside it.

What will you make?

A reaction timer. The Pico waits two to five seconds, then lights an LED. You press the button. It prints how long you took. Press early and it tells you off.

What do you need?

  • A Raspberry Pi Pico (or Pico W) with MicroPython installed
  • One push button
  • One LED
  • One 330 ohm resistor (it keeps the LED safe)
  • A breadboard and four jumper wires
  • A USB cable and a computer with Thonny or another MicroPython editor

How do you wire it?

  1. Put the LED on the breadboard. Connect its long leg to GP15 through the resistor.
  2. Connect the LED's short leg to any GND pin on the Pico.
  3. Put the button across the middle gap of the breadboard.
  4. Connect one side of the button to GP14.
  5. Connect the other side of the button to any GND pin.

The button needs no resistor. The code turns on the Pico’s own pull-up resistor (a tiny resistor inside the chip). The pin reads 1 when the button is up and 0 while it is pressed.

What is the code?

Save this as main.py on the Pico so it runs when you plug it in.

from machine import Pin
import time
import random

led = Pin(15, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)  # reads 0 while pressed

best = None

while True:
    led.off()
    print("Get ready. Press the button when the light comes on.")
    wait_ms = random.randint(2000, 5000)
    start_wait = time.ticks_ms()
    cheated = False
    while time.ticks_diff(time.ticks_ms(), start_wait) < wait_ms:
        if button.value() == 0:
            cheated = True
            break
    if cheated:
        print("Too early. Let go and try again.")
        while button.value() == 0:
            pass
        time.sleep_ms(1000)
        continue
    led.on()
    start = time.ticks_ms()
    while button.value() == 1:
        pass
    reaction = time.ticks_diff(time.ticks_ms(), start)
    led.off()
    print("Your time:", reaction, "ms")
    if best is None or reaction < best:
        best = reaction
        print("New best.")
    print("Best so far:", best, "ms")
    time.sleep_ms(2000)

How does it work?

  • random.randint(2000, 5000) picks the wait, in milliseconds, so you cannot guess the moment.
  • time.ticks_ms() is a clock in milliseconds. time.ticks_diff() subtracts two readings safely. MicroPython’s docs say to use it instead of plain subtraction, because the clock can wrap around.
  • If the button reads 0 during the wait, you pressed early.
  • After the LED lights, the loop spins until the button reads 0. The time since the light is your reaction.

If it doesn’t work

  • Nothing happens. Check the code is saved as main.py on the Pico, then unplug and replug it.
  • The LED never lights. Turn it round. LEDs only work one way.
  • It always says “Too early”. The button wire may be on the wrong side. The button’s two sides must go to GP14 and GND.
  • Nothing prints. Open the shell in Thonny to read the messages. The Pico prints them over USB.

Make it yours

  • Run five rounds and print the average.
  • Add a second LED that lights when you beat your best.
  • Make the wait longer, or the light dimmer.
  • Race a friend: two buttons, and the first press wins.

What’s the catch?

The Pico times in whole milliseconds, but a button bounces for a moment when pressed. That is fine for a game. It is not a lab instrument.

Sources

Beyond the notebook

This is what we do in schools.

A year-long programme for classes 6 to 12. Creativity, taught as a skill, inside the classroom you already have, led by your teachers.

See the programme