Note

Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.

Why Join?

  • Expert Support: Solve post-sale issues and technical challenges with help from our community and team.

  • Learn & Share: Exchange tips and tutorials to enhance your skills.

  • Exclusive Previews: Get early access to new product announcements and sneak peeks.

  • Special Discounts: Enjoy exclusive discounts on our newest products.

  • Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.

👉 Ready to explore and create with us? Click [here] and join today!

4.8 GAME - 10 Second Challenge

Introduction

Test your focus and timing with the “10 Second Challenge” game! In this project, you’ll create a magic wand by attaching a tilt switch to a stick. Shake the wand to start a timer on a 4-digit segment display. Shake it again to stop the timer. The goal is to stop the timer as close to 10.00 seconds as possible. Compete with friends to see who is the ultimate time wizard!


What You’ll Need

Below is the list of components required for this project:

COMPONENT INTRODUCTION

PURCHASE LINK

Breadboard

BUY

Jumper Wires

BUY

Resistor

BUY

4-Digit 7-Segment Display

-

74HC595

BUY

Tilt Switch

-

Fusion HAT+

-

Raspberry Pi

-


Circuit Diagram

Below is the schematic diagram for the “10 Second Challenge”:

../_images/4.1.15_sch.png

Wiring Diagram

Follow the wiring instructions shown below to set up the circuit:

../_images/4.1.15_bb.png

Running the Example

All example code used in this tutorial is available in the ai-lab-kit directory. Follow these steps to run the example:

cd ~/ai-lab-kit/python/
sudo python3 4.8_GAME_10Second.py

When the script runs:

  • Shake the wand to start the timer on the 4-digit segment display.

  • Shake the wand again to stop the timer.

  • If the timer reads 10.00 seconds, you win the round!

  • Shake the wand one more time to reset the game and start a new round.


Code

Here is the Python code for the project:

#!/usr/bin/env python3

# Import Pin control, modes, and pull-up/down definitions
from fusion_hat.pin import Pin, Mode, Pull
# Import time for delays
import time
# Import threading to use Timer for repeated callbacks
import threading

# Initialize the button connected to GPIO 22, set as input with pull-down resistor
sensorPin = Pin(22, mode=Mode.IN, pull=Pull.DOWN)

# Define GPIO pins for the 74HC595 shift register
SDI = Pin(17, mode=Mode.OUT)    # Serial Data Input
RCLK = Pin(4, mode=Mode.OUT)    # Register Clock (latch)
SRCLK = Pin(27, mode=Mode.OUT)  # Shift Register Clock

# Define GPIO pins controlling digit selection on the 4-digit 7-segment display
placePin = [Pin(pin, mode=Mode.OUT) for pin in (23, 24, 25, 12)]

# Define the segment encoding for digits 0–9 (common cathode)
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# Counter value, timer object, and game state variable
counter = 0
timer1 = None
gameState = 0

def clearDisplay():
   """Clear all segments by shifting out 'all off' bits to the 74HC595."""
   for _ in range(8):
      SDI.on()      # Send high bits (turned off segments)
      SRCLK.on()    # Pulse shift clock
      SRCLK.off()
   RCLK.on()         # Latch the data
   RCLK.off()

def hc595_shift(data):
   """Shift out one byte to the 74HC595 to control segment lighting."""
   for i in range(8):
      SDI.value(0x80 & (data << i))  # Output next bit
      SRCLK.on()                     # Clock pulse
      SRCLK.off()
   RCLK.on()                          # Latch data to output
   RCLK.off()

def pickDigit(digit):
   """Enable one of the 4 digits on the display by activating its control pin."""
   for pin in placePin:
      pin.off()          # Disable all digits
   placePin[digit].on()   # Enable selected digit

def display():
   """Render the current 4-digit counter value onto the 7-segment display."""
   global counter

   # Units digit
   clearDisplay()
   pickDigit(3)
   hc595_shift(number[counter % 10])

   # Tens digit
   clearDisplay()
   pickDigit(2)
   hc595_shift(number[counter % 100 // 10])

   # Hundreds digit (minus 0x80 to enable decimal point if needed)
   clearDisplay()
   pickDigit(1)
   hc595_shift(number[counter % 1000 // 100] - 0x80)

   # Thousands digit
   clearDisplay()
   pickDigit(0)
   hc595_shift(number[counter % 10000 // 1000])

def stateChange():
   """Handle button-triggered mode changes: start or stop the timer."""
   global gameState, counter, timer1

   # When gameState = 0 → Reset counter and start timer
   if gameState == 0:
      counter = 0           # Reset counter
      time.sleep(1)         # Small delay before start
      timer()               # Start counting

   # When gameState = 1 → Stop the timer
   elif gameState == 1 and timer1 is not None:
      timer1.cancel()       # Stop Timer thread
      time.sleep(1)

   # Toggle between state 0 and 1
   gameState = (gameState + 1) % 2

def loop():
   """Main loop: refresh the display and detect button presses."""
   global counter
   currentState = 0
   lastState = 0

   while True:
      display()                     # Continuously update display
      currentState = sensorPin.value()   # Read button state
      # Detect falling edge: button released → pressed transition
      if (currentState == 0) and (lastState == 1):
            stateChange()             # Trigger state change
      lastState = currentState      # Save state for edge detection

def timer():
   """Timer callback: increments counter every 0.01 seconds using threading.Timer."""
   global counter, timer1
   timer1 = threading.Timer(0.01, timer)  # Create next timer event
   timer1.start()                         # Start timer loop
   counter += 1                           # Increase counter value

try:
   loop()                                 # Run main loop
except KeyboardInterrupt:
   if timer1:
      timer1.cancel()                    # Cleanly stop timer on exit

Understanding the Code

  1. Button Input: The tilt switch is connected to GPIO pin 22, which detects when the wand is shaken.

  2. 74HC595 Shift Register: The shift register controls which digits are illuminated on the 7-segment display.

  3. Timer Logic: A threading timer increments the counter every 0.01 seconds, ensuring precise timing.

  4. State Management: The game switches between states (start, stop) based on button input, resetting the counter as needed.

  5. Display Update: The 7-segment display shows the timer value, formatted to two decimal places.


Troubleshooting

  1. 7-Segment Display Not Showing Numbers:

    • Cause: Incorrect wiring or GPIO pin configuration.

    • Solution:

      • Verify connections to the 74HC595 shift register and 7-segment display.

      • Ensure the number segment codes match the display’s configuration.

  2. Switch Tilts Not Detected:

    • Cause: Tilt switch wiring or debounce issues.

    • Solution:

      • Confirm the tilt switch is connected to GPIO 22.

      • Add a short debounce delay in the loop() function:

        time.sleep(0.05)
        
  3. Counter Not Incrementing:

    • Cause: Timer function not starting correctly.

    • Solution:

      • Check the timer() function and ensure timer1.start() is called.

      • Debug by printing the counter value inside timer().

  4. Display Shows Incorrect Digits:

    • Cause: Segment codes in the number list do not match the hardware.

    • Solution: Test individual digits with static segment codes to verify the mapping.


Extendable Ideas

  1. Adjustable Timer Speed: Add a mechanism to change the timer’s increment rate (e.g., using a second button to switch between 0.01, 0.1, and 1-second increments).

  2. Countdown Mode: Implement a countdown mode where the counter starts at a predefined value and decrements to 0.

  3. Pause and Resume: Add a separate button to pause and resume the counter without resetting.

  4. Audio Feedback: Use a buzzer to emit beeps when the counter reaches certain milestones (e.g., multiples of 10).


Conclusion

The “10 Second Challenge” demonstrates how simple components like a tilt switch and a 7-segment display can create an engaging interactive game. This project highlights the use of GPIO control, timers, and state management in Python, making it a fun and educational experience. Challenge yourself and your friends to achieve perfect timing!