DIY Pi Pico Reaction Light Game

by Connork in Circuits > Raspberry Pi

14 Views, 0 Favorites, 0 Comments

DIY Pi Pico Reaction Light Game

Screenshot 2025-11-10 at 9.06.52 am.png

In this project, you’ll build Reaction Time Game using the Raspberry Pi Pico. The game tests how fast you can react to a signal by measuring your response time and displaying your score from a buzzer.


Previous Research-

https://www.instructables.com/Pi-Pico-Reaction-Light-Game/

https://shop.sb-components.co.uk/blogs/posts/raspberry-pi-pico-reaction-game?srsltid=AfmBOoqzpTANkvOOVYRhRsrxkGmpupI1OuThkonJMX1QT70Om5keymFt

This design is very similar to mine as you will need the same materials- Pi Pico, two push-button switches, selection of female-to-female (F2F) jumper wires, micro USB cable, Pico to your Raspberry Pi or other computer running the Thonny.

How it works.

Press the small button to start.

After a random delay, the buzzer sounds.

The first player to hit their button wins.

The LCD displays “Player 1 Wins” or “Player 2 Wins.”

Press Reset to play again.

Supplies


Materials

Pi pico rasberry pi x1

female to female wires x4

hook up wire (assorted)

lcd screen x1

Lcd Screen

wire and attach the lcd screen to your pi pico

Buttons

solder your wire to the buttons and proceed to attach them to your pico

add the code to Thonny

Diagram

Screenshot 2025-10-20 at 10.36.24 am.png

this is the diagram to follow along (without the smaller button and buzzer)

Code

from machine import Pin, PWM, I2C

from time import sleep, sleep_ms

from lcd_i2c import I2cLcd

import urandom


# -----------------------------

# I2C LCD Setup

# -----------------------------

# Adjust the I2C pins and LCD address if your hardware is different.

i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)

lcd_addr = 0x27 # Common addresses are 0x27 and 0x3F

lcd = I2cLcd(i2c, lcd_addr, 2, 16)


# -----------------------------

# Buttons and Buzzer

# -----------------------------

# The keys of this dictionary are the pin numbers.

buttons = {

2: Pin(2, Pin.IN, Pin.PULL_UP), # Player 1

3: Pin(3, Pin.IN, Pin.PULL_UP), # Player 2

4: Pin(4, Pin.IN, Pin.PULL_UP) # Reset

}

buzzer = PWM(Pin(5))


# -----------------------------

# Game and Button State

# -----------------------------

gameStarted = False

winnerDeclared = False

# This new dictionary will track the last state of each button (1=released, 0=pressed)

# We initialize them to 1 because the PULL_UP resistor makes them released by default.

last_button_states = {2: 1, 3: 1, 4: 1}


# -----------------------------

# Helper Functions

# -----------------------------

def check_press(pin_number):

"""

A non-blocking function to check for a button press.

Returns True only on the initial press (the moment it goes from high to low).

"""

global last_button_states

is_pressed = False


current_state = buttons[pin_number].value()

last_state = last_button_states[pin_number]


# Check for a change from released (1) to pressed (0)

if last_state == 1 and current_state == 0:

sleep_ms(50) # Debounce delay

# Re-check the state after debouncing

if buttons[pin_number].value() == 0:

is_pressed = True


# Update the last known state for this button

last_button_states[pin_number] = current_state

return is_pressed


def buzz(frequency, duration_ms):

"""Play a tone on the buzzer."""

buzzer.freq(frequency)

buzzer.duty_u16(32768) # Set volume to 50% duty cycle

sleep_ms(duration_ms)

buzzer.duty_u16(0) # Turn buzzer off


def startGame():

"""Starts a new game round."""

global gameStarted, winnerDeclared

lcd.clear()

lcd.write("Get ready...")

delay_time = urandom.randint(2, 5)

sleep(delay_time)


lcd.clear()

lcd.write("GO!")

buzz(1000, 300)

gameStarted = True

winnerDeclared = False


def declareWinner(player):

"""Displays the winner message and plays a sound."""

global gameStarted, winnerDeclared

winnerDeclared = True

gameStarted = False

lcd.clear()

lcd.write(f"Player {player} Wins!")

buzz(1500, 400)


def resetGame():

"""Resets the game to the initial waiting screen."""

global gameStarted, winnerDeclared

lcd.clear()

lcd.write("Press RESET to")

lcd.move_to(0, 1)

lcd.write("start again")

winnerDeclared = False

gameStarted = False

buzzer.duty_u16(0)


# -----------------------------

# Startup Message

# -----------------------------

lcd.clear()

lcd.write("Reaction Game")

sleep(2)

resetGame() # Go to the standard reset screen


# -----------------------------

# Main Loop

# -----------------------------

while True:

if winnerDeclared:

if check_press(4): # Check Reset Button

resetGame()


elif not gameStarted:

if check_press(4): # Check Reset Button

startGame()


else: # Game is running

if check_press(2): # Check Player 1

declareWinner(1)

elif check_press(3): # Check Player 2

declareWinner(2)


sleep_ms(10) # Small delay for stability

Lcd Screen

Screenshot 2025-11-10 at 9.08.58 am.png
Screenshot 2025-11-10 at 9.09.43 am.png
Screenshot 2025-11-10 at 9.09.30 am.png
Screenshot 2025-11-10 at 9.09.19 am.png

this is the order that should appear on your lcd screen