๐ฆ Level 2 โ Sensors & IR Control
Project 2.11: "Interactive Musical Instrument"
๐ Project 2.11 โ Interactive Musical Instrument
ย
๐ฏ What youโll learn
- Goals: Change instrument modes with IR, play scales with touch, add sound effects, record/playback, and run a lightโandโsound concert.
- Skills: Inputs (IR, TouchPad), outputs (buzzer, RGB via PWM), mode switching, lists, loops, and conditionals.
- Outcomes: A fun, playable instrument where students practice timing, mapping inputs to sounds, and creating performances.
๐งฑ Blocks glossary
- IR receive:
ir_rx = irremote.NEC_RX(pin, buffer)โ Create IR receiver and read button codes. - IR code:
ir_rx.code[0]โ Access the first code captured from the remote. - Touch input:
tcX = machine.TouchPad(machine.Pin(X))โ Read touch value (lower = pressed). - Buzzer:
midi = music.MIDI(26)โ Play tones/effects on pin 26. - RGB PWM:
pwmX = machine.PWM(machine.Pin(X))andpwmX.duty(value)โ Control LED brightness. - Loop and flow:
while True:andif/elif/else:โ Continuous play and decision logic. - Serial:
print("...")โ Feedback for students and instructors.
๐งฐ What you need
| Part | How many? | Pins |
|---|---|---|
| D1 R32 | 1 | USB |
| IR receiver | 1 | 18 |
| Touch sensors | 3 | 12, 13, 14 |
| Buzzer | 1 | 26 |
| RGB LED | 1 | 2 (R), 4 (G), 5 (B) |
- Wiring tip: Keep grounds common; place touch pads where students can press comfortably; secure RGB orientation (R=2, G=4, B=5).
โ Before you start
print("Ready!") # Print startup message to confirm serial monitor works
๐ฎ Microprojects (1โ5)
๐ฎ Microproject 2.11.1 โ Instrument modes via IR
Goal: Switch between Piano and Drum modes using the IR remote.
# Instrument modes via IR # Title: change instrument modes with remote
import irremote, music, time # Import IR for codes, music for buzzer, time for delays
ir_rx = irremote.NEC_RX(18,8) # Setup IR receiver on pin 18 with buffer size 8
midi = music.MIDI(26) # Setup buzzer on pin 26
mode = "Piano" # Start in Piano mode by default
print("Instrument modes ready") # Serial confirmation for students
while True: # Infinite loop to keep reading remote and acting
if ir_rx.any(): # Check if any IR signal was received
code = ir_rx.code[0] # Read the first code from the IR buffer
if code == 0xA90: # Example code for Piano mode
mode = "Piano" # Switch to Piano mode
print("Mode:", mode) # Print current mode
elif code == 0xA91: # Example code for Drum mode
mode = "Drum" # Switch to Drum mode
print("Mode:", mode) # Print current mode
if mode == "Piano": # If Piano mode is active
midi.pitch_time(440, 200) # Play note A (440 Hz) for 200 ms
elif mode == "Drum": # If Drum mode is active
midi.play(midi.DADADADUM) # Play predefined drum-like effect
time.sleep(1) # Delay to avoid constant rapid playback
- Reflection: IR buttons can change how the instrument behaves in real time.
- Challenge: Add a third mode โGuitarโ with
midi.pitch_time(659, 200)for a bright tone.
๐ฎ Microproject 2.11.2 โ Musical scales
Goal: Play notes C, D, and E using touch sensors.
# Musical scales # Title: play notes with touch sensors
import machine, music, time # Import machine for TouchPad, music for buzzer, time for delays
tc12 = machine.TouchPad(machine.Pin(12)) # Touch sensor on pin 12 for note C
tc13 = machine.TouchPad(machine.Pin(13)) # Touch sensor on pin 13 for note D
tc14 = machine.TouchPad(machine.Pin(14)) # Touch sensor on pin 14 for note E
midi = music.MIDI(26) # Buzzer setup on pin 26
threshold = 300 # Touch threshold (lower values mean pressed)
print("Musical scales ready") # Serial confirmation
while True: # Continuous loop for input
if tc12.read() < threshold: # If C touch pressed
midi.pitch_time(261, 200) # Play note C (261 Hz) for 200 ms
print("Note C") # Feedback for students
if tc13.read() < threshold: # If D touch pressed
midi.pitch_time(293, 200) # Play note D (293 Hz) for 200 ms
print("Note D") # Feedback for students
if tc14.read() < threshold: # If E touch pressed
midi.pitch_time(329, 200) # Play note E (329 Hz) for 200 ms
print("Note E") # Feedback for students
time.sleep(0.1) # Short delay to stabilize reading
- Reflection: Touch inputs map cleanly to musical notes.
- Challenge: Expand to a full pentatonic scale by adding two more touch pads.
๐ฎ Microproject 2.11.3 โ Sound effects
Goal: Play simple effects to enrich performance.
# Sound effects # Title: quick buzzer effects
import music # Import music for buzzer control
midi = music.MIDI(26) # Setup buzzer on pin 26
print("Sound effects ready") # Serial confirmation
midi.play(midi.DADADADUM) # Play drum-like effect
midi.pitch_time(880, 100) # Play high beep (880 Hz) for 100 ms
midi.pitch_time(220, 400) # Play low beep (220 Hz) for 400 ms
- Reflection: Effects add texture and variety to songs.
- Challenge: Create your own โcomboโ effect by chaining three tones with different durations.
๐ฎ Microproject 2.11.4 โ Recording and playback
Goal: Record a short sequence of notes and replay them.
# Recording and playback # Title: store notes and replay
import machine, music, time # Import TouchPad, buzzer, and timing
tc12 = machine.TouchPad(machine.Pin(12)) # Touch for note C
tc13 = machine.TouchPad(machine.Pin(13)) # Touch for note D
tc14 = machine.TouchPad(machine.Pin(14)) # Touch for note E
midi = music.MIDI(26) # Buzzer setup
threshold = 300 # Touch threshold for presses
recorded = [] # Empty list to store recorded notes
print("Recording ready") # Serial confirmation
while True: # Main loop
if tc12.read() < threshold: # If C pressed
recorded.append(261) # Store frequency for C (261 Hz)
midi.pitch_time(261, 200) # Play C to confirm
print("Recorded C") # Log recording step
if tc13.read() < threshold: # If D pressed
recorded.append(293) # Store D (293 Hz)
midi.pitch_time(293, 200) # Play D to confirm
print("Recorded D") # Log recording step
if tc14.read() < threshold: # If E pressed
recorded.append(329) # Store E (329 Hz)
midi.pitch_time(329, 200) # Play E to confirm
print("Recorded E") # Log recording step
if len(recorded) >= 3: # If three notes are recorded
print("Playback:", recorded) # Show the recorded notes list
for note in recorded: # Iterate through recorded notes
midi.pitch_time(note, 200) # Play each note with 200 ms duration
time.sleep(0.3) # Pause between notes for clarity
recorded = [] # Clear list after playback
time.sleep(0.1) # Small delay for stability
- Reflection: Students see input โ memory โ output clearly.
- Challenge: Increase capacity to 5 notes and add a โclearโ IR button to reset.
๐ฎ Microproject 2.11.5 โ Interactive concert
Goal: Combine RGB lights and tones into a short performance loop.
# Interactive concert # Title: lights and sounds performance
import machine, music, time # Import PWM for RGB, music for buzzer, time for delays
pwm2 = machine.PWM(machine.Pin(2)) # Red LED PWM on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Green LED PWM on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Blue LED PWM on pin 5
midi = music.MIDI(26) # Buzzer setup on pin 26
print("Concert ready") # Serial confirmation
for i in range(3): # Repeat the performance three times
pwm2.duty(800); midi.pitch_time(440, 200) # Red ON + note A (440 Hz)
time.sleep(0.3) # Pause to separate events
pwm4.duty(800); midi.pitch_time(523, 200) # Green ON + note C (523 Hz)
time.sleep(0.3) # Pause to separate events
pwm5.duty(800); midi.pitch_time(659, 200) # Blue ON + note E (659 Hz)
time.sleep(0.3) # Pause to separate events
pwm2.duty(0); pwm4.duty(0); pwm5.duty(0) # Turn all LEDs OFF
time.sleep(0.5) # Short rest before next loop
- Reflection: Visual rhythm helps students feel musical structure.
- Challenge: Make a longer pattern and add a final โapplauseโ jingle with three quick beeps.
โจ Main project โ Interactive musical instrument (complete)
Goal: Merge IR modes, touch scales, effects, recording/playback, and RGB feedback into one instrument.
# Project 2.11 โ Interactive Musical Instrument # Title: full interactive instrument
import machine, time, music, irremote # Import pins/timing/buzzer/IR libraries
ir_rx = irremote.NEC_RX(18,8) # IR receiver on pin 18 (buffer size 8)
midi = music.MIDI(26) # Buzzer on pin 26
pwm2 = machine.PWM(machine.Pin(2)) # Red LED PWM on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Green LED PWM on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Blue LED PWM on pin 5
tc12 = machine.TouchPad(machine.Pin(12)) # Touch sensor on pin 12 (C)
tc13 = machine.TouchPad(machine.Pin(13)) # Touch sensor on pin 13 (D)
tc14 = machine.TouchPad(machine.Pin(14)) # Touch sensor on pin 14 (E)
mode = "Piano" # Default mode at start
recorded = [] # Storage for recorded notes
threshold = 300 # Touch threshold (classroom-calibrated)
print("Interactive Musical Instrument ready") # Serial start message for teachers/students
while True: # Main loop runs forever
if ir_rx.any(): # If an IR signal is available
code = ir_rx.code[0] # Read the first received code
if code == 0xA90: # Example code to set Piano mode
mode = "Piano" # Update current mode
print("Mode:", mode) # Print mode change
elif code == 0xA91: # Example code to set Drum mode
mode = "Drum" # Update current mode
print("Mode:", mode) # Print mode change
elif code == 0xA92: # Example code to set Record mode
mode = "Record" # Update current mode
print("Mode:", mode) # Print mode change
if mode == "Piano": # If Piano mode is selected
if tc12.read() < threshold: # If C pad is pressed
midi.pitch_time(261, 200) # Play C (261 Hz) for 200 ms
pwm2.duty(800); time.sleep(0.2); pwm2.duty(0) # Flash Red LED to confirm
print("Note C") # Log note
if tc13.read() < threshold: # If D pad is pressed
midi.pitch_time(293, 200) # Play D (293 Hz) for 200 ms
pwm4.duty(800); time.sleep(0.2); pwm4.duty(0) # Flash Green LED to confirm
print("Note D") # Log note
if tc14.read() < threshold: # If E pad is pressed
midi.pitch_time(329, 200) # Play E (329 Hz) for 200 ms
pwm5.duty(800); time.sleep(0.2); pwm5.duty(0) # Flash Blue LED to confirm
print("Note E") # Log note
elif mode == "Drum": # If Drum mode is selected
if tc12.read() < threshold: # If first pad is hit
midi.play(midi.DADADADUM) # Play drum effect pattern
print("Drum hit 1") # Log drum hit
if tc13.read() < threshold: # If second pad is hit
midi.pitch_time(100, 300) # Play low drum tone (100 Hz)
print("Drum hit 2") # Log drum hit
if tc14.read() < threshold: # If third pad is hit
midi.pitch_time(200, 150) # Play snare-like short tone (200 Hz)
print("Drum hit 3") # Log drum hit
elif mode == "Record": # If Record/Playback mode is selected
if tc12.read() < threshold: # If C is pressed
recorded.append(261) # Store C (261 Hz)
midi.pitch_time(261, 200) # Play C to confirm
print("Recorded C") # Log recording step
if tc13.read() < threshold: # If D is pressed
recorded.append(293) # Store D (293 Hz)
midi.pitch_time(293, 200) # Play D to confirm
print("Recorded D") # Log recording step
if tc14.read() < threshold: # If E is pressed
recorded.append(329) # Store E (329 Hz)
midi.pitch_time(329, 200) # Play E to confirm
print("Recorded E") # Log recording step
if len(recorded) >= 3: # If we have three notes recorded
print("Playback:", recorded) # Show what will be played
for note in recorded: # Iterate through stored notes
midi.pitch_time(note, 200) # Play each note
time.sleep(0.3) # Pause between notes
recorded = [] # Clear recording after playback
time.sleep(0.1) # Small delay to keep system stable
๐ External explanation
- What it teaches: Mode switching via IR, mapping touch inputs to notes/effects, feedback with LEDs, and simple recording with lists.
- Why it works: Each input (IR or touch) triggers a clear output (sound/light), and mode logic changes behavior without changing hardware.
- Key concept: Same sensors can do different jobs depending on the active mode.
โจ Story time
You step onto your mini stage. A button press turns your robot into a piano, another into a drum kit. Touch pads are your keys, LEDs dance with the music, and your recorded melody gets a proud replay. Encore!
๐ต๏ธ Debugging (2)
๐ Offโkey notes
- Symptom: Notes sound wrong or mismatched to labels.
- Cause: Frequencies not aligned with intended notes.
- Fix: Use correct values: C=261 Hz, D=293 Hz, E=329 Hz; verify typing accuracy in code.
๐ Modes do not change
- Symptom: Pressing remote buttons doesnโt switch modes.
- Cause: IR codes donโt match actual remote values.
- Fix: Run the IR Configuration microproject to print codes, then update
if code == ...to match your buttons.
โ Final checklist
- IR remote switches reliably between Piano, Drum, and Record modes.
- Touch pads trigger the correct notes/effects with consistent thresholds.
- LEDs flash as visual feedback for played notes.
- Recording stores notes and playback replays them clearly.
- Serial prints show mode changes and actions for easy classroom debugging.
๐ Extras
- Student tip: Add a โChordโ by pressing two pads quickly; experiment with timing for layered sounds.
- Instructor tip: Have learners design a themed concert (e.g., space sounds) using specific tones and LED colors.
- Glossary: IR code, mode, pitch (Hz), PWM duty, threshold, recording list.
- Mini tips: Calibrate touch thresholds; keep delays short; map LEDs to notes for instant recognition.