Introduction: DIY Pi Pico Reaction Light Game

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

Step 1: Lcd Screen

wire and attach the lcd screen to your pi pico

Step 2: Buttons

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

Step 3:

add the code to Thonny

Step 4: Diagram

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

Step 5: 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

Step 6: Lcd Screen

this is the order that should appear on your lcd screen