๐Ÿš€ 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

ComponentQuantityPins
D1 R32 board1USB
RGB LED12 (R), 4 (G), 5 (B)
Touch sensors312, 13, 14
Buzzer126
  • 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.
On this page