The Reaction Game Using Multi-Function Shield
HARDWARE REQUIRED:
- PICUNO Microcontroller board
- 1 × Multi-Function Shield
- USB cable
DESCRIPTION:
This project turns your Multifunction Shield into a fun game to test your reaction speed. The program will wait for a random amount of time and then suddenly light up one of the first three LEDs. The player's goal is to press the button directly underneath the lit LED as quickly as possible. The game provides instant feedback with sounds from the buzzer for success or failure.
CIRCUIT DETAILS:
- Plug the Multi-function Shield directly on top of the PICUNO board. The shield's components have fixed connections to the board's pins.
- LEDs (D1-D4) are connected to GPIO 13, 12, 11, and 10.
- Buttons (S1-S3) are connected to Analog Pins A1, A2, and A3.
- Buzzer is connected to GPIO 3.
SCHEMATIC:
No external wiring is required. Place the Multi-Function shield directly on top of the PICUNO board.
Multi-Function shield:
LEDs (D1-D4) → GPIO 13, 12, 11, 10.
Buttons (S1-S3) → A1, A2, A3.
Buzzer → GPIO 3
CODE -- C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 // --- Pin Definitions --- const int ledPins[] = {13, 12, 11}; const int buttonPins[] = {A1, A2, A3}; const int BUZZER_PIN = 3; void setup() { for (int i = 0; i < 3; i++) { pinMode(ledPins[i], OUTPUT); digitalWrite(ledPins[i], HIGH); pinMode(buttonPins[i], INPUT_PULLUP); } pinMode(BUZZER_PIN, OUTPUT); randomSeed(analogRead(A0)); // Seed the random number generator Serial.begin(9600); Serial.println("Reaction Game Started!"); delay(1000); } void loop() { Serial.println("Get ready..."); for (int i = 0; i < 3; i++) { digitalWrite(ledPins[i], HIGH); } // Wait for a random time between 1 and 2 seconds delay(random(1000, 2000)); int ledToPress = random(0, 3); digitalWrite(ledPins[ledToPress], LOW); Serial.print("LED "); Serial.print(ledToPress + 1); Serial.println(" is ON!"); unsigned long startTime = millis(); unsigned long timeLimit = 1000; bool answered = false; bool playerWon = false; while ((millis() - startTime < timeLimit) && !answered) { for (int i = 0; i < 3; i++) { if (digitalRead(buttonPins[i]) == LOW) { answered = true; if (i == ledToPress) { playerWon = true; } break; // Exit the for loop } } } if (playerWon) { Serial.println("Correct!"); tone(BUZZER_PIN, 1500, 150); // Success sound } else { Serial.println("Too slow or wrong button!"); tone(BUZZER_PIN, 200, 300); // Fail sound } delay(2000); }
randomSeed(analogRead(A0)) - This command uses the random electrical noise from an unconnected Analog pin (A0) to "seed" the random number generator, ensuring that the sequence of lit LEDs is different every time you turn the device on.
random(min, max) - This function generates a random number within a specified range. It's used to create the random delay before an LED lights up and to choose which of the three LEDs will be the target.
digitalRead(buttonPins[i]) == LOW - This is how the code checks if a button has been pressed. Because the pins are configured with INPUT_PULLUP, their default state is HIGH.
tone(BUZZER_PIN, frequency, duration) - This function creates the sound effects. It generates a sound wave of a specific frequency on the buzzer pin for a set duration, providing instant audio feedback for a correct or incorrect answer.
random(min, max) - This function generates a random number within a specified range. It's used to create the random delay before an LED lights up and to choose which of the three LEDs will be the target.
digitalRead(buttonPins[i]) == LOW - This is how the code checks if a button has been pressed. Because the pins are configured with INPUT_PULLUP, their default state is HIGH.
tone(BUZZER_PIN, frequency, duration) - This function creates the sound effects. It generates a sound wave of a specific frequency on the buzzer pin for a set duration, providing instant audio feedback for a correct or incorrect answer.
CODE -- PYTHON:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 from machine import Pin, PWM from time import sleep_ms, ticks_ms, ticks_diff import urandom import time # --- Pin Definitions --- leds = [Pin(13, Pin.OUT, value=1), Pin(12, Pin.OUT, value=1), Pin(11, Pin.OUT, value=1)] buttons = [Pin(27, Pin.IN, Pin.PULL_UP), Pin(28, Pin.IN, Pin.PULL_UP), Pin(29, Pin.IN, Pin.PULL_UP)] buzzer = PWM(Pin(3)) def play_tone(freq, duration): buzzer.freq(freq) buzzer.duty_u16(32768) # 50% volume sleep_ms(duration) buzzer.duty_u16(0) print("Reaction Game Started!") sleep_ms(1000) while True: print("Get ready...") for led in leds: led.high() # random time between 1 and 2 seconds sleep_ms(urandom.randint(1000, 2000)) # Pick a random LED to light up led_to_press = urandom.randint(0, 2) leds[led_to_press].low() start_time = ticks_ms() time_limit = 700 # 1 second to react player_won = False answered = False print(f"LED {led_to_press + 1} is ON!") # Game loop to wait for player's reaction while ticks_diff(ticks_ms(), start_time) < time_limit and not answered: for i in range(3): if buttons[i].value() == 0: answered = True if i == led_to_press: # Correct button player_won = True break if player_won: print("Correct!") play_tone(1500, 150) # Success sound else: print("Too slow or wrong button!") play_tone(200, 300) # Fail sound sleep_ms(2000)
urandom.randint() - This function is used to make the game unpredictable. It generates a random number for the delay time and for which LED to light up.
leds[led_to_press].low() - Turns on the target LED. The LEDs on this shield are "active low," meaning they light up when the pin is set to a LOW voltage.
Game Logic - The code waits for a button press. It checks if the button that was pressed (i) corresponds to the LED that was lit (led_to_press).
Timer (ticks_ms) - The game gives the player a 1-second time limit to press the correct button.
leds[led_to_press].low() - Turns on the target LED. The LEDs on this shield are "active low," meaning they light up when the pin is set to a LOW voltage.
Game Logic - The code waits for a button press. It checks if the button that was pressed (i) corresponds to the LED that was lit (led_to_press).
Timer (ticks_ms) - The game gives the player a 1-second time limit to press the correct button.