STM32 Digital Piano

ENGR 478 Embedded Systems Term Project

Digital piano on the STM32 NUCLEO-L476RG

A register-level embedded piano built with four push buttons, three speaker outputs, SysTick sound timing, EXTI button interrupts, and two ADC potentiometer controls.

GPIO EXTI SysTick ADC AD2 Tested

Real-time signal path

NUCLEO-L476RG
PC0-PC3
PA0
PA1
PA5
PA6
PA7

Buttons select chords. Potentiometers control volume and octave.

4 button inputs
3 speaker pins
2 ADC controls
20 kHz SysTick timing

Hardware Setup

Simple hardware, clear pin responsibilities

The hardware is intentionally small so the software behavior can be measured and explained clearly.

Push Buttons

PC0, PC1, PC2, and PC3 are inputs with pull-up resistors. Each press or release creates an EXTI interrupt.

Speaker Outputs

PA5, PA6, and PA7 are GPIO outputs. SysTick updates these pins to create the sound waveform.

Volume Knob

PA0 is an ADC input connected to a 10 kOhm potentiometer. It controls the duty time of the sound output.

Octave Knob

PA1 is an ADC input connected to a 10 kOhm potentiometer. It moves the selected note lower or higher.

Pin Direction Project Use
PA5OutputSpeaker output 1
PA6OutputSpeaker output 2
PA7OutputSpeaker output 3
PC0-PC3InputPush buttons through EXTI
PA0Analog inputVolume potentiometer
PA1Analog inputOctave potentiometer

Software Flow

Main logic and interrupts are separated

The program initializes GPIO, SysTick, EXTI, and ADC. After setup, the main loop waits with __WFI(). Button changes are handled by EXTI interrupts, while sound timing runs from the SysTick interrupt at 20 kHz.

  • Main loop reads ADC values every 20 ms.
  • EXTI interrupt updates the active button state.
  • SysTick interrupt drives PA5, PA6, and PA7.
  • Shared variables connect the button, ADC, and sound modules.
View detailed flowchart
Software flowchart for the STM32 digital piano

Design and Implementation

How the project was put together

The design was split into small parts so the project could be built, tested, and explained one step at a time. The buttons choose the chord, the ADC knobs adjust the sound, and SysTick creates the speaker waveforms.

01

Input Design

PC0-PC3 are button inputs. A released button reads HIGH and a pressed button reads LOW, so the EXTI interrupt can detect a press or release.

02

Control Design

The main loop wakes up, reads the two potentiometers every 20 ms, checks the active button, and sends the selected chord to the sound code.

03

Sound Design

SysTick runs at 20 kHz. Each speaker output has a counter, and the counter decides when PA5, PA6, or PA7 should change state.

04

Test Design

Analog Discovery 2 was used to check frequency, positive duty cycle, octave change, and button release behavior on the real output pins.

Chord Table

Each button selects a three-note chord

The software maps each button to a chord table, then the SysTick sound engine outputs the selected tones.

SW1 / PC0

C Major

C - E - G

SW2 / PC1

G Major

G - B - D

SW3 / PC2

A Minor

A - C - E

SW4 / PC3

F Major

F - A - C

Demo Video

Digital piano working on hardware

The video shows the project running on the NUCLEO-L476RG board with the buttons, speaker outputs, volume control, and octave control.

Demo Plan

What the demo verifies

The demo is organized around the main embedded concepts used in the project.

01

Button Response

Press each button and show that a different chord is selected.

02

Release Behavior

Release the button and show that the sound stops cleanly.

03

Volume Control

Turn the PA0 potentiometer and show the sound level changing.

04

Octave Control

Turn the PA1 potentiometer and show the pitch moving lower and higher.

Project outcomes and AD2 test results

Testing

Measured with Analog Discovery 2

The project was tested by checking the speaker output pins, button press and release behavior, ADC volume control, and ADC octave control. The measured values show that the generated tones closely match the expected musical frequencies.

FrequencyChord outputs verified on PA5, PA6, and PA7.
VolumeDuty timing changes when the PA0 knob moves.
OctavePA1 changes the selected note lower or higher.

AD2 Frequency Validation

Each button produced its own chord

The speaker pins were measured with Analog Discovery 2. These readings show that each push button selected a different three-note chord on PA5, PA6, and PA7.

Button Chord PA5 PA6 PA7
SW1 C major 263.85 Hz 334.36 Hz 385.60 Hz
SW2 G major 385.85 Hz 501.57 Hz 590.15 Hz
SW3 A minor 436.21 Hz 527.98 Hz 669.27 Hz
SW4 F major 346.02 Hz 435.85 Hz 528.05 Hz
Four Buttons Each button produced a different measured chord.
Three Outputs PA5, PA6, and PA7 each carried one chord tone.
AD2 Evidence The readings came from WaveForms frequency measurements.

AD2 Volume Validation

Volume knob changes the duty cycle

The PA0 potentiometer changes the positive duty cycle of the output waveform. This changes how loud the sound is while the note timing is still controlled by SysTick.

Volume Setting Button / Chord PA5 Frequency / Duty PA6 Frequency / Duty PA7 Frequency / Duty
High SW3 / A minor 436.09 Hz / 49.959% 527.85 Hz / 49.961% 668.71 Hz / 49.847%
Medium SW3 / A minor 435.97 Hz / 23.760% 527.98 Hz / 23.416% 669.09 Hz / 23.000%
Low C major capture 263.94 Hz / 1.2207% 334.36 Hz / 1.5603% 385.85 Hz / 1.7686%

AD2 Octave Validation

Octave knob shifts the chord frequency

The PA1 potentiometer changes the selected octave. The readings show the same chord moving lower and higher as the knob position changes.

Octave Setting PA5 PA6 PA7
Lower Octave 131.97 Hz 167.15 Hz 193.14 Hz
Middle Octave 263.94 Hz 334.26 Hz 385.85 Hz
Higher Octave 527.57 Hz 667.97 Hz 770.50 Hz
Highest Octave 1.0022 kHz 1.2530 kHz 1.4317 kHz

Firmware

How the code is organized

The project is split into small C files so each peripheral has a clear job and the full program is easy to explain.

main.c

Starts the board setup, reads the two ADC knobs, checks the active button, and calls the sound functions.

button.c

Sets PC0-PC3 as button inputs, uses EXTI interrupts, and debounces button press and release changes.

Systick_timer.c

Runs the 20 kHz sound timing, loads chord frequencies, changes volume duty time, and counts milliseconds.

ADC.c

Reads PA0 and PA1, smooths the knob values, and converts them into volume and octave settings.