A music toy for little kids (about 3–6) built on the Adafruit Macropad RP2040. Twelve glowing keys, one dial, a tiny screen, and a speaker, with four games that sneak in a little STEM: pitch, sequences, patterns, and loops.
It's designed for kids who can't read yet. The screen shows pictures, never words, and nothing ever plays a "you lost" sound.
How to play
The controls are the same in every game:
- Press the dial to go to the next game. A little jingle plays and the picture changes.
- Turn the dial to change the game's one setting. The big picture on the screen shows the current choice, and the dots under it show where you are.
| Game | Screen picture | What you do | Dial changes | The STEM idea |
|---|---|---|---|---|
| Rainbow Piano | piano | Every key plays a note. Low notes start at the top-left, high notes end at the bottom-right. The scale is pentatonic, so any keys together sound nice. | Instrument: flute, bell, robot, guitar | Pitch: higher notes are faster vibrations |
| Follow the Lights | glowing key | One key lights up. Press it to play the next note of a song. Finish the song for a rainbow party. | Song: twinkle star, little lamb, Old MacDonald's cow, birthday cake, rowing boat | A song is a sequence of steps |
| Echo | speaker | The toy plays a pattern, then you play it back. It starts with one note and grows by one each time you get it right, up to 8. A miss just replays the pattern. | How many keys are in the game: 4, 6, or all 12 | Memory and patterns |
| Beat Loop | drum | A 4-step drum machine. Each row is a step and each column is a drum (kick, snare, shaker). Tap keys to turn drums on or off while the loop plays. | Tempo, from turtle to rabbit | Loops, like a for loop in code |
After 10 minutes with no button presses, the lights, screen, and sound turn off. Press any key or the dial to wake it up. That press only wakes the toy; it won't play a note.
Setup
You need a Macropad RP2040 and a USB-C data cable. The Macropad has no battery, so use a USB power bank to take it off your desk.
-
Install CircuitPython 10.x. Download the UF2 from circuitpython.org/board/adafruit_macropad_rp2040. Hold the dial down while pressing the reset button (left side) to get an
RPI-RP2drive, then copy the UF2 onto it. The board restarts as aCIRCUITPYdrive. -
Install
boot.py(once). Copycircuitpy/boot.pyto theCIRCUITPYdrive, then unplug the Macropad and plug it back in. From then on the drive stays hidden and the board writes its own files (see below for why). -
Copy the toy over. With uv installed, run:
uv run scripts/deploy.pyThis sends
circuitpy/to the board over USB serial, with theneopixellibrary from the Adafruit bundle (fetched with circup). It only sends files that changed and checks each one after writing, then restarts the board.
Why the drive is hidden
macOS's FAT driver delays writes to small drives like CIRCUITPY, which makes writes fail and can corrupt the drive (circuitpython#8449). That happened while building this. So by default boot.py hides the drive and lets the board write its own files, and deploy.py sends files over serial using mpremote's transport. Bonus: unplugging mid-play can't corrupt anything.
To see the drive, hold the top-left key while plugging the Macropad in. Hide it again by replugging without the key.
Parent settings
Edit circuitpy/settings.toml and run uv run scripts/deploy.py, or show the drive (above) and edit settings.toml on it.
VOLUME: 0–100, default 100 (the speaker is tiny)BRIGHTNESS: key lights, 0–100, default 30SLEEP_MINUTES: idle time before the toy turns off, default 10
Fixing a corrupted CIRCUITPY drive
If the drive won't mount or files come back empty, open the serial console (scripts/console.sh), press Ctrl-C, and enter import storage; storage.erase_filesystem(). That wipes and reformats CIRCUITPY and restarts the board. Then repeat steps 2 and 3.
Development
The layout of circuitpy/ matches the CIRCUITPY drive exactly. The game logic doesn't touch the hardware: modes ask an io object to play notes and light keys. On the board that object is hardware.py; in tests it's a fake that records what was asked for, so the games can be tested on a laptop.
uvx pytest # tests
uvx ruff check . # lint
uvx ruff format . # format
uv run scripts/deploy.py # copy to the board
scripts/console.sh # serial console: prints, tracebacks, REPL
CircuitPython is a subset of Python. Modules like dataclasses, enum, typing, and functools don't exist on the board, so the lint config bans them.
Screen pictures are 16×16 text art in icons.py (# is a lit pixel), so there are no image files to manage. Songs are note names in songs.py, and a test checks that every note has a key.
Ideas for later
- Animal sounds bank (WAV files)
- Record a tune and play it back
- "Shake for drums" with an accelerometer on the STEMMA QT port
Prior art and credits
No existing Macropad project aimed at toddlers turned up, but these showed the way:
- Adafruit's MacroPad Tone guide: key-to-note with rainbow colors
- Adafruit's synthio guide and todbot/macropadsynthplug: non-blocking, polyphonic synthesis on the Macropad
- deckerego/Macropad_4chord_MIDI: designing so you can't play a wrong note
- Adafruit's Simon game for Circuit Playground: the classic echo game
- analogsketchbook/Macropad-Sequencer: step-sequencer layout ideas (no code borrowed)
- Adafruit's Dragon Drop: a game loop with OLED graphics
