Skip to main content
Version: ACS CC

Smart Light Piano

Digital piano project built on a Raspberry Pi Pico 2W, featuring auto-light detection, multi-mode play and optional Wi-Fi integration.

info

Author: Andrei-Alexandru Ciucan
GitHub Project Link: source code

Description

Smart Light Piano is a mini digital piano based on a Raspberry Pi Pico 2W.
It allows the player to interact with eight physical keys, triggering musical notes generated via PWM on a 5V passive buzzer.
The system integrates three LEDs for dynamic visual feedback:

  • Red LED:
    • Connected to the photoresistor (LDR).
    • Behavior: As the environment gets darker, the red LED brightens proportionally; as ambient light increases, the red LED dims progressively.
  • Yellow LED:
    • Triggered when a button located at an even position (2, 4, 6, 8) is pressed.
    • Purpose: Highlights even-positioned key presses.
  • Green LED:
    • Triggered when a button located at an odd position (1, 3, 5, 7) is pressed.
    • Purpose: Highlights odd-positioned key presses.

The piano offers three operating modes, selected through two dedicated buttons:

Mode TriggerMode NameDescription
Button A pressedNote Guess ModeA random note is played and the player must identify it by pressing the corresponding key. Each correct guess is stored and the sequence of correct notes is replayed as a melody after the first mistake.
Button B pressedEffects ModeApplies real-time audio effects (such as vibrato, tremolo, or frequency shifts) to the notes for a more dynamic sound experience.
Both Button A and Button B pressedPressure-Controlled Pitch Mode (optional)An advanced mode where note pitch varies according to air pressure measurements from the BMP280 sensor, allowing players to modify sounds by moving the device up or down. This mode is optional and intended to enrich the overall interaction.

If, during testing, the BMP280 pressure readings do not provide a clear-enough delta when I move the piano up or down, the pitch‑modulation logic will seamlessly fall back to temperature‑based mapping from the same sensor.

Optional: In a future update, Wi-Fi connectivity may be added to:

  • Display the current ambient temperature remotely
  • Transmit or record the sequence of played notes through a network connection

Motivation

This project combines my passion for embedded systems, music and real-time hardware interaction.
It involves reading analog and digital inputs, communicating with sensors over I²C, generating real-time audio signals and coordinating everything through asynchronous Rust programming.
The result is a responsive system that seamlessly blends low-level hardware control with modern approaches to embedded software development.

Architecture

The project has the following architecture:

  • Raspberry Pi Pico 2W: Handles the main logic of the project - reading piano key inputs, controlling the buzzer through PWM to generate musical notes, adjusting LED brightness based on the photoresistor (LDR) reading, handling mode selection through buttons and communicating with the BMP280 sensor over I²C.
  • Raspberry Pi Pico 2W (Debugger Controller): Dedicated to debugging and monitoring the operation of the first Pico.
  • Passive 5V Buzzer (via transistor): Controlled via PWM from the first Pico. Generates audible musical notes corresponding to key presses, with real-time modulation depending on the selected mode.
  • Piano Buttons (8 Buttons): Connected to the main Pico's GPIO pins. Each button corresponds to a musical note; pressing a button triggers sound generation.
  • Mode Selection Buttons (2 Buttons): Connected to separate GPIO pins.
    • Pressing Button A selects Note Guess Mode.
    • Pressing Button B selects Effects Mode.
    • Pressing both simultaneously activates Pressure-Controlled Pitch Mode.
  • Photoresistor (LDR) with Voltage Divider: Provides analog light measurements read by the ADC module of the main Pico. Controls the brightness behavior of the red LED depending on the ambient light level.
  • LED Indicators (Red, Yellow, Green):
    • The red LED adjusts its brightness dynamically based on the ambient light measured by the LDR — brighter in darkness, dimmer in strong light.
    • The yellow LED lights up when a piano key at an even position is pressed.
    • The green LED lights up when a piano key at an odd position is pressed.
  • BMP280 Sensor: Connected to the main Pico via I²C. Provides real-time pressure and temperature data, used in Pressure-Controlled Pitch Mode to adjust the buzzer sound dynamically.
  • Power Source: Provides USB power to the primary Raspberry Pi Pico 2W, which in turn supplies power to the second Pico used for debugging, along with all the connected peripherals.
  • Breadboard: Used to build and run the entire project without soldering. All components are connected directly using jumper wires for flexibility and ease of assembly.
  • Prototype Board (Optional): May be used later to solder the final version of the circuit for improved durability and long-term use.

Architecture Diagram

Log

Week 23 - 30 April

I started working on the project documentation and set up the GitLab repository to manage the documentation separately. I created the first version of the system block diagram using diagrams.net, drafted the initial list of hardware and software components and began designing the hardware schematic in KiCad, covering the main modules. I also outlined the structure for the final index.md file.

Week 5 - 11 May

Week 12 - 18 May

Week 19 - 25 May

Hardware

I am using two Raspberry Pi Pico 2W boards in this setup. The main Pico handles all piano functionalities (PWM audio output, button reading, LED brightness control via ADC and BMP280 communication over I²C), while the second Pico acts as a debug interface through UART.

Hardware DevicePurposeUsage
Raspberry Pi Pico 2W (Main Controller)Main microcontrollerHandles piano note generation, button input, LED control, LDR reading and BMP280 data acquisition
Raspberry Pi Pico 2W (Debugger)DebuggingMonitors the main controller's state via UART during development
Passive 5V Buzzer (controlled via transistor)Sound outputEmits musical notes generated by PWM signals
Switching Transistor (for Buzzer)PWM signal controlEnsures safe driving of the 5V passive buzzer without overloading GPIO pins
8 Piano ButtonsUser inputTriggers different musical notes corresponding to each button
2 Mode ButtonsMode switchingSelects the operating mode (Note Guess Mode, Effects Mode, Pressure-Controlled Mode)
Red, Yellow and Green LEDsVisual feedbackIndicates light intensity or button presses (even/odd keypresses)
Light Dependent Resistor (LDR)Ambient light sensorMeasures light intensity
Fixed Resistor for LDR (10kΩ)Voltage dividerForms a divider circuit with the LDR for ADC reading
BMP280 SensorPressure and temperature measurementConnected over I²C
Current-Limiting Resistors (220Ω–470Ω)LED protectionLimits current through each LED to safe values
Breadboard (830 pts)Project assemblyUsed to build and connect all components without soldering
Prototype PCB 10x15cm (Optional)Permanent wiringCan be used to solder the final circuit for improved robustness
USB Power SupplyPower sourceSupplies 5V via USB directly to the debugger Pico 2W

Schematics

KiCad

Photos

Prototype

Software

The project firmware is written entirely in Rust, using an asynchronous multitasking model with Embassy libraries, running on a Raspberry Pi Pico 2W.
Four independent asynchronous tasks manage real-time behavior:

  • A mode control task that monitors the two mode selection buttons and configures the piano behavior accordingly.
  • A piano task that plays musical notes based on key presses, dynamically adapting to the active mode (Note Guess, Effects, Pressure-Controlled Pitch).
  • An LDR task that adjusts the brightness of the red LED depending on ambient light measured by the photoresistor.
  • A BMP280 task that reads environmental data asynchronously via I²C, supporting optional dynamic pitch adjustment based on pressure.

Detailed Design

The main software modules are:

ModuleFunctionality
Mode Control TaskContinuously monitors the two mode buttons. Depending on which button(s) are pressed, it updates a shared state variable that configures how the piano task operates: random note guessing, sound effects, or pressure-based pitch shifting.
Piano TaskReads the 8 piano buttons. Generates different behaviors based on the current selected mode: normal tone playing, sound effects applied, or pitch dynamically influenced by atmospheric pressure.
LDR TaskReads the photoresistor (LDR) values using ADC and adjusts the PWM duty cycle to smoothly control the brightness of the red LED.
BMP280 TaskCommunicates with the BMP280 sensor over I²C to acquire temperature and pressure readings every second. Pressure values are used optionally to influence musical note characteristics when in Pressure-Controlled Mode.
PWM and GPIO HandlingPWM is used for buzzer sound modulation and LED brightness control. GPIO pins are used for button inputs with pull-up configurations and non-blocking reads.
Task SynchronizationEmbassy's async framework ensures cooperative multitasking and real-time responsiveness without requiring threads or RTOS features.

Functional Diagram

Functional Diagram

Bill of Materials

Hardware

DeviceUsagePrice
Raspberry Pi Pico 2WMain microcontroller running piano, LDR, BMP28042 RON
Raspberry Pi Pico 2WDebugger42 RON
BMP280 Sensor ModuleAir pressure and temperature readings9 RON
LDR SensorMeasures ambient light intensity2 RON
Passive Buzzer 5VAudio output for piano notes (with PWM)1.5 RON
2N2222 NPN TransistorAmplifies PWM signal to drive 5V buzzer0.2 RON
Resistor 1kΩ 0.25WBase resistor for transistor0.1 RON
Resistor 10kΩ 0.25WVoltage divider with LDR0.1 RON
Red LED 5mmShows brightness level (PWM-controlled)0.4 RON
Green LED 5mmLights up for odd keys pressed0.4 RON
Yellow LED 5mmLights up for even keys pressed0.4 RON
Resistor 220Ω 0.25WCurrent limiting resistors for LEDs0.2 RON (each) ×3
Tactile Push-Button 6x6mmPiano keys (8x) + Mode selection (2x)0.4 RON × 10
Breadboard Jumper Wires SetConnections8.5 RON
Colored 40p 2.54 mm Pitch Male Pin HeaderSoldered on Pico 2W for connection1 RON x 5
Breadboard 830 ptsAssembly platform for the entire project10 RON x 2
20p Female Pin Header 2.54 mm(Optional)Socket for Pico W on PCB4.3 RON x 4
Prototype PCB 10x15cm(Optional)For soldering permanent project7.4 RON

Total: 161 RON

Software

LibraryDescriptionUsage
embassy-rpEmbassy Hardware Abstraction Layer (HAL) for Raspberry Pi RP2040 microcontrollers.Handles GPIO, PWM, ADC and I2C peripherals.
embassy-timeTimekeeping utilities for no-std embedded systems.Timing delays and periodic tasks using async/await.
embassy-executorAsync executor for embedded environments.Runs multiple async tasks concurrently.
embedded-hal-asyncAsync traits for embedded devices (I2C, SPI, etc.).Provides async I2C operations (write, write_read) for BMP280 communication.
defmtLightweight logging framework for embedded systems.Debugging and runtime information output.
panic-probeMinimal panic handler using defmt.Captures panics and outputs debug info through RTT.
  1. RP2350 (Raspberry Pi Pico 2) – Datasheet & Pinout
  2. Using PWM on RP2350
  3. Embedded‑HAL async (embassy) – Quick Start
  4. Driving a 5 V Passive Buzzer with an NPN Transistor
  5. LDR Voltage Divider Explained
  6. BMP280 Pressure & Temperature Sensor – Application Notes
  7. LED Current‑Limiting Resistor Calculator
  8. Breadboard Wiring Best Practices
  9. Prototype PCB Soldering Tips (Perfboard)