Skip to main content
Version: ACS CC

Piano Trainer

A wireless piano learning assistant with falling notes, physical keys, and real-time scoring.

info

Author: Adela-Mihaela Băieșiu
GitHub Project Link: https://github.com/UPB-PMRust-Students/acs-project-2026-Adela717.git

Description

Piano Trainer is an embedded piano learning system built around a wireless keyboard unit and a main display unit.

The project is inspired by piano tutorial videos where colored notes fall toward the piano keys. The user has a 12-key piano keyboard covering one chromatic octave. The keyboard unit detects key presses and sends them wirelessly using Bluetooth.

The main unit, built around the STM32 Nucleo-U545RE-Q development board, receives the key events, displays the falling notes on a TFT screen, generates audio feedback using a passive buzzer, and computes gameplay statistics.

The device includes a menu system for choosing predefined songs, a gameplay screen with falling notes, a listening mode for visualizing song notes without scoring, a results screen, and a best scores screen.

Motivation

I chose this project because I learned piano using online videos where colored notes move toward the keys and show when and for how long each note should be played. I wanted to recreate this learning method as a physical embedded device.

Architecture

  • Piano input module: reads the 12 physical piano keys corresponding to one chromatic octave.
  • Menu input module: reads the control buttons used for navigating the interface: UP, DOWN, SELECT, and BACK.
  • Display module: renders the start menu, song selection screen, gameplay screen, falling notes, results screen, listening mode screen, and best scores screen.
  • Song engine: stores each song as a sequence of note events. Each event contains the note, the expected start time, and the note duration.
  • Audio module: generates musical tones using a passive buzzer controlled through PWM.
  • Scoring module: compares the expected notes with the user input and computes the final score, accuracy, number of correct notes, missed notes, and maximum combo.
  • Best scores module: keeps track of the best scores achieved during the current runtime session.
  • Application state machine: controls the transitions between the main menu, song selection, listening mode, gameplay, results, and best scores screens.
  • Wireless keyboard module: reads the physical piano keys and menu buttons on a separate keyboard unit.
  • Bluetooth communication module: sends key press, key release, and menu button events from the keyboard unit to the main display unit.
  • Listening mode module: allows the user to visualize the notes of a selected song without scoring, useful for learning the melody before playing it. Architecture diagram

Log

Week 5 - 11 May

  • Settled on the project idea and shaped it into a small piano trainer with physical keys, audio feedback, a display, song selection, and scoring.
  • Split the system into two parts: a wireless keyboard side and a main unit that handles sound, display, and game logic.
  • Picked the main components and put together the first version of the hardware plan and bill of materials.

Week 12 - 18 May

  • Built the first working prototype and wired the keyboard side to the main unit.
  • Got the 12 piano keys and menu buttons working, then configured the Bluetooth link between the two boards.
  • Added the first STM32-side logic so the received key events could trigger piano sounds.
  • Brought up a basic version of the TFT screen to confirm that the display integration was working.

Week 19 - 25 May

  • Reworked the display UI into a more complete menu-based interface.
  • Added the screens for song selection, listening mode, gameplay, statistics, and navigation.
  • Integrated the scoring and gameplay flow with the keyboard input and audio feedback.

Hardware

The project is built as two separate hardware units: a wireless keyboard unit and a main display unit.

The wireless keyboard unit contains the physical piano keys and the menu control buttons. It is responsible for detecting user input and sending key events to the main unit through Bluetooth. The keyboard contains 12 physical keys, covering a chromatic octave.

The main display unit contains the STM32 Nucleo-U545RE-Q development board, the TFT display, and the passive buzzer. It receives input events from the wireless keyboard unit, updates the game state, displays the falling notes, generates sound, and computes the final statistics.

Schematics

Schematics

Bill of Materials

DeviceUsagePrice
STM32 Nucleo-U545RE-QMain microcontroller board used to run the Rust firmware, receive keyboard events, control the TFT display, and generate audio through PWMProvided
Raspberry Pi Pico HSecondary microcontroller used in the wireless keyboard unit to read the piano keys and menu buttons through the MCP23017 and forward events to the Bluetooth UART module41.14 RON
HC-05 Bluetooth UART ModuleBluetooth master module used on the Pico keyboard unit to transmit key and menu events wirelessly30.25 RON
HC-06 Bluetooth UART ModuleBluetooth slave module used on the STM32 main unit to receive key and menu events wirelessly30.4 RON
TFT SPI Display ST7789V 2.8 inch 240x320Used to display the main menu, song selection screen, listening mode, falling notes, results, and best scores58.99 RON
MCP23017 I/O ExpanderUsed by the wireless keyboard unit to read most of the piano keys through I2C, reducing the number of GPIO pins required7.77 RON
12x12mm Tactile Push Buttons x16Used as 12 physical piano keys and 4 menu control buttons1.52 RON
Passive Buzzer Module 3.3V-5VUsed to generate musical tones through PWM6.44 RON
BreadboardsUsed as the prototyping area for connecting the modules, buttons, power rails, and peripherals12.89 RON
10 Male-Male Jumper Wires x4Used for breadboard connections between components10.30 RON
10 Female-Male Jumper Wires x4Used for connecting modules with pins to the breadboard or Nucleo board8.66 RON
10 Female-Female Jumper Wires x4Used for direct connections between modules with male header pins6.54 RON

Software

LibraryDescriptionUsage
embassy-rsAsync embedded framework for RustUsed as the main runtime for the STM32 firmware
embassy-stm32STM32 hardware abstraction layer for EmbassyUsed for UART, SPI, DMA, GPIO, timers, PWM, and clock configuration on the main unit
embassy-futuresAsync utilities for Embassy-based applicationsUsed for coordinating asynchronous tasks and handling concurrent input/display logic
embedded-io-asyncAsync I/O traits for embedded systemsUsed for reading UART data asynchronously from the Bluetooth module
embedded-halCommon embedded hardware abstraction traitsUsed for shared embedded traits such as PWM control
defmt + defmt-rttLightweight embedded logging frameworkUsed for debugging and runtime logs through probe-rs
panic-probePanic handler for embedded Rust programsUsed to report firmware panics during debugging
Custom ST7789V display driverMinimal SPI display driver implemented in RustUsed to initialize the TFT display and draw the menu, gameplay, and results UI
heaplessFixed-capacity data structures for embedded systemsUsed for storing songs, notes, menu items, and scoring data without dynamic allocation
rp2040-hal / rp-picoHardware abstraction layer and board support package for Raspberry Pi Pico HUsed for GPIO, I2C, UART, and timing on the wireless keyboard unit
UART-based Bluetooth communicationSerial communication over HC-05/HC-06 Bluetooth modulesUsed for sending key press, key release, and menu events from the keyboard unit to the main display unit