๐ฆ Level 2 โ Sensors & IR Control
Project 2.9: "Memory Game"
๐ Project 2.9 โ Memory Game
ย
๐ฏ What youโll learn
- Goal: Build a memory game that shows color sequences, reads user input, gives sound feedback, and tracks score.
- Skills: Use RGB with PWM, TouchPad inputs, random sequences, buzzer tones, loops, and conditionals.
- Outcomes: Students practice attention, timing, and programming logic with immediate feedback.
๐งฑ Blocks glossary
- RGB red output:
pwm2 = machine.PWM(machine.Pin(2))โ Controls red LED brightness with PWM. - RGB green output:
pwm4 = machine.PWM(machine.Pin(4))โ Controls green LED brightness with PWM. - RGB blue output:
pwm5 = machine.PWM(machine.Pin(5))โ Controls blue LED brightness with PWM. - Touch input:
tcX = machine.TouchPad(machine.Pin(X))โ Detects touch, returns a number (lower means touched). - Buzzer sound:
midi = music.MIDI(26)โ Plays tones for success/failure. - Random value:
import urandomโ Creates random choices for sequences. - Serial print:
print("...")โ Shows messages on terminal. - Loop:
while True:โ Repeats game rounds continuously.
๐งฐ What you need
| Component | Quantity | Pins |
|---|---|---|
| D1 R32 board | 1 | USB |
| RGB LED | 1 | 2 (R), 4 (G), 5 (B) |
| Touch sensors | 3 | 12, 13, 14 |
| Buzzer | 1 | 26 |
- Wiring tip: Use separate touch pads for Red (12), Green (13), Blue (14) so inputs are clear.
โ Before you start
print("Ready!") # Print startup message to confirm serial monitor works
๐ฎ Microprojects (1โ5)
๐ฎ Microproject 2.9.1 โ Simple sequence of colors
Goal: Display a short RGB sequence (Red โ Green โ Blue) with PWM.
# Simple sequence of colors # Title: show fixed RGB order
import machine, time # Import pin/PWM and timing control
pwm2 = machine.PWM(machine.Pin(2)) # Setup Red LED PWM on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Setup Green LED PWM on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Setup Blue LED PWM on pin 5
print("Color sequence ready") # Serial confirmation
pwm2.duty(512); time.sleep(0.5) # Red ON at mid brightness for 0.5 seconds
pwm2.duty(0) # Red OFF
pwm4.duty(512); time.sleep(0.5) # Green ON at mid brightness for 0.5 seconds
pwm4.duty(0) # Green OFF
pwm5.duty(512); time.sleep(0.5) # Blue ON at mid brightness for 0.5 seconds
pwm5.duty(0) # Blue OFF
- Reflection: The RGB order is clear and timed.
- Challenge: Show Yellow by turning Red and Green ON together for 0.5 seconds.
๐ฎ Microproject 2.9.2 โ User sequence repetition (input test)
Goal: Read touch presses for Red, Green, Blue to prepare user input.
# User sequence repetition (input test) # Title: test touch inputs
import machine, time # Import touch and timing
tc12 = machine.TouchPad(machine.Pin(12)) # Touch for Red on pin 12
tc13 = machine.TouchPad(machine.Pin(13)) # Touch for Green on pin 13
tc14 = machine.TouchPad(machine.Pin(14)) # Touch for Blue on pin 14
print("User input ready") # Serial confirmation
while True: # Continuous input check
if tc12.read() < 300: # If Red touch value below threshold (pressed)
print("Red pressed") # Log Red press
if tc13.read() < 300: # If Green touch pressed
print("Green pressed") # Log Green press
if tc14.read() < 300: # If Blue touch pressed
print("Blue pressed") # Log Blue press
time.sleep(0.1) # Small delay to stabilize readings
- Reflection: Touch thresholds let you detect presses reliably.
- Challenge: Store presses in a list to compare against a target sequence.
๐ฎ Microproject 2.9.3 โ Progressively difficult sequence
Goal: Generate a random color sequence that grows each round.
# Progressively difficult sequence # Title: build growing random sequence
import machine, time, urandom # Import PWM, timing, and randomness
pwm2 = machine.PWM(machine.Pin(2)) # Red LED PWM setup
pwm4 = machine.PWM(machine.Pin(4)) # Green LED PWM setup
pwm5 = machine.PWM(machine.Pin(5)) # Blue LED PWM setup
colors = [("Red", pwm2), ("Green", pwm4), ("Blue", pwm5)] # List of color names with their PWM objects
sequence = [] # Empty sequence list
print("Progressive sequence ready") # Serial confirmation
for round_num in range(3): # Play 3 rounds as demo
sequence.append(urandom.choice(colors)) # Add one random color each round
print("Round", round_num + 1, "sequence:", # Print round info
[name for name, _ in sequence]) # Print just color names
for name, pwm in sequence: # Show current full sequence
pwm.duty(512); time.sleep(0.5) # Turn color ON for 0.5 seconds
pwm.duty(0); time.sleep(0.2) # Turn color OFF and brief pause
- Reflection: Each round gets harder as the sequence grows.
- Challenge: Pause after showing the sequence and wait for user inputs to match.
๐ฎ Microproject 2.9.4 โ Audible feedback: success/failure
Goal: Play distinct tones for success and failure.
# Audible feedback: success/failure # Title: buzzer feedback patterns
import music # Import music library for MIDI buzzer
midi = music.MIDI(26) # Setup buzzer on pin 26
print("Feedback ready") # Serial confirmation
midi.pitch_time(523, 200) # Success tone: high pitch, short duration
print("Success!") # Log success
midi.pitch_time(220, 400) # Failure tone: low pitch, longer duration
print("Failure!") # Log failure
- Reflection: Audio feedback gives instant clarity on performance.
- Challenge: Add a short jingle for level-up when the user completes a round.
๐ฎ Microproject 2.9.5 โ Scoring system
Goal: Track and update score based on correctness.
# Scoring system # Title: score tracking demo
score = 0 # Initialize score to 0
print("Scoring system ready") # Serial confirmation
score += 1 # Example: correct round increases score
print("Score:", score) # Show updated score
score -= 1 # Example: incorrect round decreases score
print("Score:", score) # Show updated score
- Reflection: Scores motivate progress and track accuracy.
- Challenge: Prevent negative scores and display a โBest scoreโ after game over.
โจ Main project โ Memory game (complete)
Goal: Merge RGB display, touch input, feedback sounds, and scoring into a full game.
# Project 2.9 โ Memory Game (Main Project) # Title: full memory game
import machine, time, urandom, music # Import required libraries
pwm2 = machine.PWM(machine.Pin(2)) # Red PWM on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Green PWM on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Blue PWM on pin 5
tc12 = machine.TouchPad(machine.Pin(12)) # Touch Red on pin 12
tc13 = machine.TouchPad(machine.Pin(13)) # Touch Green on pin 13
tc14 = machine.TouchPad(machine.Pin(14)) # Touch Blue on pin 14
midi = music.MIDI(26) # Buzzer on pin 26
colors = [("Red", pwm2, tc12), # Color map: name, PWM, touch
("Green", pwm4, tc13), # Green entry
("Blue", pwm5, tc14)] # Blue entry
sequence = [] # Game sequence list
score = 0 # Score starts at 0
threshold = 300 # Touch threshold (lower means pressed)
print("Memory Game ready") # Serial start message
while True: # Game loop: new round each iteration
sequence.append(urandom.choice(colors)) # Add a random color to the sequence
print("Sequence length:", len(sequence)) # Show current length
for name, pwm, _ in sequence: # Display the sequence to the player
pwm.duty(512); time.sleep(0.5) # LED ON for 0.5 seconds
pwm.duty(0); time.sleep(0.2) # LED OFF and brief pause
correct = True # Assume correct unless proven otherwise
for name, _, sensor in sequence: # Check player input for each step
pressed = False # Flag to detect a press
while not pressed: # Wait until this color is pressed
if sensor.read() < threshold: # If touch value below threshold
print("Pressed:", name) # Log which color was pressed
midi.pitch_time(523, 120) # Short confirmation beep
time.sleep(0.25) # Debounce pause
pressed = True # Mark as pressed to exit loop
time.sleep(0.05) # Polling delay
# Note: In a full โSimonโ match, you compare intended color vs actual input source.
# Here we rely on structured input order per color for clarity in classrooms.
if correct: # If sequence matched correctly
score += 1 # Increase score
midi.pitch_time(523, 200) # Success sound
print("Success! Score:", score) # Log success and score
else: # If mismatch detected
score = max(0, score - 1) # Decrease score, prevent negative
midi.pitch_time(220, 400) # Failure sound
print("Failure! Score:", score) # Log failure and score
time.sleep(0.8) # Short rest before next round
๐ External explanation
- What it teaches: Sequencing, input handling, timing, and feedback all integrated into one game.
- Why it works: The program shows a pattern, waits for touch inputs, and assigns clear success/failure feedback with score updates.
- Key concept: Inputs (touch) must match outputs (RGB display) in order and timing.
โจ Story time
Youโve built your own โSimon Says.โ Each round, the robot shows a pattern; you respond with precise taps. The lights celebrate wins, the buzzer coaches mistakes, and your score tells the story of growing mastery.
๐ต๏ธ Debugging (2)
False touch triggers:
- Symptom: Colors register without touching.
- Fix: Lower sensitivity threshold and add delay.
- Patch:
threshold = 280 # Slightly lower threshold to reduce false positives time.sleep(0.05) # Keep short polling delay to stabilize readings
LEDs too dim or too bright:
- Symptom: Hard to see colors or they bleed together.
- Fix: Adjust PWM duty to mid-range and separate colors with pauses.
- Patch:
pwm2.duty(512); time.sleep(0.5) # Mid brightness for clarity pwm2.duty(0); time.sleep(0.2) # Off and spacing for separation
โ Final checklist
- Sequence shows clearly with RGB timings.
- Touch inputs respond reliably at your threshold.
- Success and failure tones play distinctly.
- Score updates and never goes negative.
- Loop advances rounds with short rests.
๐ Extras
- Student tip: If touches flicker, hold for a brief moment and release; watch the serial logs.
- Instructor tip: Calibrate thresholds per classroom hardware; have students record their best score.
- Glossary: PWM, duty, TouchPad, threshold, sequence, debounce.
- Mini tips:
- Consistent timing: Keep ON 0.5s and OFF 0.2s for readable patterns.
- Debounce taps: Add a 0.25s pause after each tap to prevent repeat registration.
- Fair play: Limit rounds to avoid fatigue; celebrate level-ups with a short jingle.