An open-source, USB-powered audio player that brings physical objects to life.
- Components
- Wiring Diagram
- Firmware Details
- DFPlayer Mini & SD Card Setup
- LED Status Indicators
- How to Use
- How to Build
- Support Me
- Third-Party Code and License
- RP2040 (Zero)
- DFPlayer Mini
- RC522 NFC reader
- USB Connector
- WS2812 (NeoPixel LED)
- 2 Speaker 3 Ohm
- Micro SD Card
- Perfboard (5x7cm)
- Connectors / Cables
- Enclosure / Box
Figure 1: Wiring diagram on the perfboard
The firmware is written in MicroPython and utilizes a modified version of the penguintutor/dfplayermini-pico library.
The DFPlayer Mini requires the SD card to be formatted to FAT16 or FAT32.
The module requires a specific file naming convention to function reliably:
- Folder naming: Use a folder named
01in the root directory. - File naming: Files should be prefixed with a three-digit number (e.g.,
001.mp3).
The WS2812 LED (internal on PIN 16 and (optional) extenal on PIN 28) provides visual feedback on the system's state:
- White: System is initializing.
- Green: Ready and waiting for NFC tag.
- Blue: Valid tag and playing
- Cyan: Finished playing on tag
- Red:: Error: No SD card or invalid tag
Copy music or audio stories onto an SD card. Write tags as plain text on NFC tags — you can use your smartphone for that. On the tag, write the numbers of the files you want to play, separated by commas, for example: 1,2,5 will play files 1, 2, and 5 in that order. You can also use ranges with a minus sign, like 12-20 (plays files 12 through 20), or just a single file like 33.
Unfortunately, I can only read about 15 bytes from Ultralight NFC tags, so the list can't be too long — in that case you can use the range format instead, for example 102-139.
If you remove the same tag and hold it up again later, playback resumes from where it stopped. If you hold up a different tag, playback starts from the beginning. You can also just take the tag away to pause playback. Use the buttons to skip to the next or previous track with a short press, and adjust the volume with a long press.
You can glue the tags onto figures or other objects later. Have fun with your music box :)
For initial testing, it is recommended to build the circuit on a breadboard first as shown in the wiring diagram.
- Install Thonny IDE on your computer.
- Flash the MicroPython firmware to the RP2040.
Firmware download: MicroPython for RP2040
- Copy all files from the
firmwarefolder to the RP2040.
- Do not connect an external USB power source to the additional USB port while the RP2040 is connected to your computer via USB.
- Once the RP2040 is disconnected from the computer, the external USB port can be used to power all components. But for testing purpose you can use the USB Port of the RP2040.
- The external USB port will later be integrated into the enclosure.
Solder the components and wires onto the perfboard as shown in Figure 1. Once the assembly is complete, perform an initial functional test before mounting the board into the enclosure.
Drill the necessary holes for the cable glands and connectors, then insert them and secure with hot glue if necessary. The status LED was also routed through the lid for better visibility.
If you find this project helpful and would like to support my work, I would be very grateful for a contribution via GitHub Sponsors or in Bitcoin (BTC) / Litecoin (LTC). Every bit of support helps me to keep creating and sharing new projects. Thank you!
ltc1qx2yf4cndqr2zf3vfd7l2ywm5hylvhm0a8jrxry
bc1q5yga8eluxk7cn4pc7k36lwee06mwt5gtre8nrm
bitcoincash:qp4gapsmpt75nh7clp64dhae2myhl9h8tg2f77w652
This project contains modified code from the penguintutor/dfplayermini-pico repository.
- Original Author: @PenguinTutor
- Original Repository License: GNU General Public License v3.0 (GPL-3.0) – see full text in the original repository's
LICENSEfile. - Modifications by: (@simonbln)
- Date of modifications: March 2026
- Nature of modifications:
- Updated
command.to_bytes(1)tocommand.to_bytes(1, 'big')for compatibility with newer Python versions. - Fixed the return value parsing for the reset command to correctly handle the module's response.
- Updated
This modified version is distributed under the same license terms (GPL-3.0). The complete license text is included in this repository as LICENSE.



