# main.py
# Raspberry Pi Pico Reaction Timer Game
# Version: Final with Coarse/Fine LEDs, All-Phase False Start, and Simplified RGB Status
import time
import random
from machine import Pin
# --- Pin Definitions ---
countdown_leds = [Pin(2, Pin.OUT), Pin(3, Pin.OUT), Pin(4, Pin.OUT), Pin(5, Pin.OUT), Pin(6, Pin.OUT)]
reaction_leds_coarse = [
Pin(7, Pin.OUT), Pin(8, Pin.OUT), Pin(9, Pin.OUT), Pin(10, Pin.OUT),
Pin(11, Pin.OUT), Pin(13, Pin.OUT), Pin(15, Pin.OUT)
]
reaction_leds_fine = [
Pin(19, Pin.OUT), Pin(20, Pin.OUT), Pin(21, Pin.OUT), Pin(22, Pin.OUT)
]
false_start_led = Pin(12, Pin.OUT)
# RGB LED (Common Cathode, GP16, GP17, GP18)
# IMPORTANT: The longest leg (Common Cathode) connects DIRECTLY to GND.
# Each shorter color leg (Red, Green, Blue) connects to its respective Pico GPIO pin
# via a 220 Ohm resistor. (Ensure your specific RGB LED's pinout for R/G/B matches this code).
rgb_red_pin = Pin(18, Pin.OUT)
rgb_green_pin = Pin(17, Pin.OUT)
rgb_blue_pin = Pin(16, Pin.OUT)
# Push Button (GP14, configured with internal pull-up resistor)
# Connect one leg of the push button to GP14.
# Connect the other leg of the push button directly to a GND (Ground) pin or rail.
button_pin = Pin(14, Pin.IN, Pin.PULL_UP)
# --- Global Variables for Timing ---
start_time = 0
end_time = 0
# --- Helper Functions ---
def light_leds(led_list, state):
for led_pin in led_list:
led_pin.value(state)
# Modified: Sets the RGB LED to Red or Green based on game status
def set_rgb_status(is_game_active):
if is_game_active:
# Game is playing (countdown or waiting for reaction) -> Green
rgb_red_pin.value(0)
rgb_green_pin.value(1)
rgb_blue_pin.value(0) # Blue always off
else:
# Game is not playing (waiting for start, displaying result/false start) -> Red
rgb_red_pin.value(1)
rgb_green_pin.value(0)
rgb_blue_pin.value(0) # Blue always off
# Helper: Manages a delay while continuously checking for a false start.
def _delay_with_false_start_check(duration_ms):
start_tick = time.ticks_ms()
while time.ticks_diff(time.ticks_ms(), start_tick) < duration_ms:
if button_pin.value() == 0: # Button pressed (LOW)
handle_false_start()
return True # False start detected!
time.sleep(0.005) # Check every 5ms
return False # No false start during this delay
# --- Game Logic Functions ---
def wait_for_button_press():
print("DEBUG: Waiting for initial button press to start game...")
# Ensure all display LEDs are off for a clean start
light_leds(countdown_leds, 0)
light_leds(reaction_leds_coarse, 0)
light_leds(reaction_leds_fine, 0)
false_start_led.value(0)
set_rgb_status(False) # Set RGB to Red (game not active)
while button_pin.value():
time.sleep(0.01)
time.sleep(0.05)
print("DEBUG: Button pressed, release to start countdown...")
def wait_for_release_and_start_timer():
global start_time, end_time
while not button_pin.value():
time.sleep(0.01)
time.sleep(0.05)
print("DEBUG: Button released, starting game sequence...")
set_rgb_status(True) # Set RGB to Green (game active)
start_countdown()
def start_countdown():
print("DEBUG: Countdown sequence initiated...")
# Phase 1: Sequential Countdown LED lighting with continuous false start check
for i in range(len(countdown_leds)):
countdown_leds[i].value(1)
delay_for_this_led_ms = random.uniform(1200, 1200) #1.2 seconds
if _delay_with_false_start_check(delay_for_this_led_ms):
return # False start occurred, exit
light_leds(countdown_leds, 1) # Ensure all countdown LEDs are lit
# Phase 2: Final random wait before "GO!" with continuous false start check
random_wait_time_ms = random.uniform(1000, 3000) # 0.5 to 3 seconds
print(f"DEBUG: Final random wait for GO! signal for {random_wait_time_ms:.0f} ms...")
if _delay_with_false_start_check(random_wait_time_ms):
return # False start occurred, exit
# --- GO! Signal ---
light_leds(countdown_leds, 0) # Turn off countdown LEDs
# RGB remains Green from wait_for_release_and_start_timer
print("DEBUG: GO! Press the button NOW!")
global start_time
start_time = time.ticks_ms()
# --- Wait for Reaction (Button Press) ---
while button_pin.value():
pass # Wait for button to go LOW
# Button has been pressed for reaction
global end_time
end_time = time.ticks_ms()
reaction_time_ms = time.ticks_diff(end_time, start_time)
# Handle button debounce after detection
time.sleep(0.05) # Debounce press
while not button_pin.value(): # Wait for button release
time.sleep(0.01)
time.sleep(0.05) # Debounce release
display_reaction(reaction_time_ms) # Display the measured reaction time
wait_for_acknowledge()
def handle_false_start():
print("DEBUG: False Start!")
set_rgb_status(False) # Set RGB to Red (game not active)
false_start_led.value(1) # Light up false start LED
light_leds(countdown_leds, 0)
light_leds(reaction_leds_coarse, 0)
light_leds(reaction_leds_fine, 0)
#time.sleep(2) # Display false start indication for 2 seconds
wait_for_acknowledge()
def display_reaction(reaction_time_ms):
print(f"DEBUG: Measured Reaction Time: {reaction_time_ms} ms")
light_leds(reaction_leds_coarse, 0)
light_leds(reaction_leds_fine, 0)
num_coarse_leds = reaction_time_ms // 50
if num_coarse_leds > len(reaction_leds_coarse):
num_coarse_leds = len(reaction_leds_coarse)
light_leds(reaction_leds_coarse[0:num_coarse_leds], 1)
remainder_ms = reaction_time_ms % 50
num_fine_leds = remainder_ms // 10
if num_fine_leds > len(reaction_leds_fine):
num_fine_leds = len(reaction_leds_fine)
light_leds(reaction_leds_fine[0:num_fine_leds], 1)
set_rgb_status(False) # Set RGB to Red (game not active, displaying result)
print(f"DEBUG: Reaction displayed. Waiting for acknowledge.")
def wait_for_acknowledge():
print("DEBUG: Press button to acknowledge and restart game...")
# Wait for button release if it's still pressed from reaction/false start
while not button_pin.value():
time.sleep(0.01)
time.sleep(0.05)
# Now, wait for the user to press the button for acknowledgment
while button_pin.value():
time.sleep(0.01)
time.sleep(0.05)
print("DEBUG: Acknowledged! Restarting game...")
time.sleep(0.5)
# Turn off all LEDs to clear the board for the next round
light_leds(countdown_leds, 0)
light_leds(reaction_leds_coarse, 0)
light_leds(reaction_leds_fine, 0)
false_start_led.value(0)
set_rgb_status(False) # Ensure RGB is Red (waiting for next game)
# --- Main Game Loop ---
def main_game_loop():
print("Welcome to Raspberry Pi Pico Reaction Timer!")
set_rgb_status(False) # Initial status: Red (waiting to play)
while True:
wait_for_button_press()
wait_for_release_and_start_timer()
# --- Run the Game ---
main_game_loop()