Musical Keyboard
Northwestern CE 346, Fall 2024
View code on GitHub ↗︎- Embedded Systems
- Sensor Integration
- Audio Systems
- State Machines
- 3D Printing

The problem
Build a piano keyboard with two modes: (1) Free Play, a normal playable keyboard, and (2) Simon Says, a memory game where the keyboard plays a growing note sequence via LEDs and audio and the user has to repeat it back.
System architecture
The keyboard is built around the following components:
- micro:bit
- 8 force sensors
- 2 external ADS1015 4-channel ADCs
- 8 LEDs
- Speaker
A push button controls power, and a switch lets the user choose between two modes. The 3D-printed keys and housing were designed in OnShape.
Modes
Free Play — continuously polls the ADC values from the force sensors to control volume. Pressing a key plays its corresponding note, synthesized in software and output through PWM, and chords can be played by pressing multiple keys at once.
Simon Says — a memory game that plays a growing sequence of notes and lights, then waits for the user to repeat it. A correct repeat extends the sequence by one note; a wrong keypress or timeout ends the game, and completing all 30 notes wins.
Because both modes read from the same 8 force sensors and drive the same speaker, only one mode's logic runs at a time, selected by the position of the mode switch.

Design constraints and requirements
The micro:bit provided only 3 analog inputs, while the design required 8 for the keys plus 1 for volume. This meant we had to use two external 4-channel ADCs over I2C. We also pivoted from the initial choice of capacitive touch to force sensors because we were uncertain about capacitive sensing through the 3D-printed keys. Each force sensor ultimately provided both key-press detection and pressure-based input, replacing the original capacitive touch and potentiometer approach.
Firmware
Notes are synthesized in software using a precomputed 500-sample sine lookup table. A phase accumulator steps through the table based on the desired frequency, producing a 16 kHz audio waveform. For chords, sine waves from multiple pressed keys are summed and scaled by the average force reading, so harder presses produce louder sound. The resulting waveform is output through the MCU's PWM peripheral.
Simon Says runs as a 5-state machine that handles sequence playback, user input, and win, lose, or continue outcomes. I implemented the win, loss, and end-of-game states, including LED and audio feedback. The game resets when the mode switch changes from Free Play back to Simon Says.
I also handled sensor bring-up by reading both ADCs over I2C and retrieving the force-sensor data used in both modes.
Verification
Our verification checked two things:
- Each key produced the correct pitch for each force sensor's intended note.
- During Simon Says, firmware checks user input against the expected sequence, so a correct key press advanced the game and a wrong one triggered the losing state.
Results
The physical keyboard was fully assembled and wired with all 8 keys, the mode switch, the external ADC stage, and the speaker. A video demo is included below: