For an index to all my stories click this text.
Portable MP3 players where once THE thing to have. Now they are getting obsolete because (almost) everyone has a handheld computer (called a smartphone) that is perfectly capable of doing the job. However, sometimes you want a simple music player that does the job. And that's exactly what we are going to build.
DFRobot DFPlayer
DFRobot is an US brand that makes some neat gadgets. And the most well-known is the DFRobot DFPlayer. It is a small MP3 player that has an amplifier on board so you can attach a loudspeker for direct results. The MP3 files are stored on a SD card and therefore there is an SD card reader on board.
The board has an original price of about 5 USD but clones (which are 100% copies) can be bought from our Chinese friends for about 1.50 USD.
In 2019 I wrote a small story on how to use this MP3 player with just two buttons. The functionality was limited. Pressing the first button took you to the next song. The other button switched to the previous song. You can find that story here:
https://lucstechblog.blogspot.com/2019/05/mp3-player-stand-alone.html
In 2022 I revisited the DFRobot MP3 player and wrote a story on how you could control it from a website. That sory attached an ESP8266 or ESP32 to the DFRobot MP3 player. It had however the same limited functionality as the story with the manual control. You can read that story here:
https://lucstechblog.blogspot.com/2019/10/web-controlled-mp3-player.html
More control.
The previous two stories used the DFRobot MP3 player's IO pins to control the player. And they only offer next song, previous song functionality. There are however a lot more possibilities.
To use these extra functions you need to send commands over a serial interface (UART). And that is a lot easier as you think.
There is a nice MicroPython library that makes it possible to control almost all functions of this player. You can find that library here:
https://github.com/lavron/micropython-dfplayermini
If you do not know how to install MicroPython libraries please consider buying one of my books describing the use of Micropython with the Raspberry Pi Pico. You can find them here:

Click here to open a link on Amazon to buy my books
This library offers the following controls:
music.play(x) plays track x from the SD card
music.play('next') play the next track. If the just played track was the last
on the SD card the player will play the first track.
music.play('prev') Play the previous track. If there is no previous track
then the player will play the last track on the SD card.
music.stop() stops playing music
music.volume(x) sets the volume to x where x is a value fom 0 to 40
music.pause() stops playing
music.resume() starts playing where pause left
music.loop_track( store a track number
music.loop() keeps repeating the stored track
music.loop_disable() stops repeating the track
music.fadeout(fadeout_ms) slowly turns the volume down and stops playing
All these commands must be given over the UART lines.
The DFRobot MP3 player's pins.
The DFRobot MP3 player is a small module with 16 pins. It is breadboard friendly. Let us have a look at the pins we are going to use in this project.
Obviously this is the power line. The module needs 3.2 till 5V. I supply the power through a separate 5V USB wall plug. The 5V is connected to the module but NOT to the Raspberry Pi Pico.
GND
This is the GND line and is connected to the wall plug and the Pico.
RX
This is the UART receive line and will get connected to the Pico's TX line
TX
This is the UART transmit line and will get connected to the Pico's RX line
SPK_1 and SPK_2
Attach a speaker to these lines for playing the audio. The lines give a mono signal.
The DFRobot Mp3 player has a build-in amplifier and can run a speaker up to 3 Watt.
DAC_R and DAC_L
The DFRobot MP3 player has a build in DAC. We can attach these lines to the left and right entrances of an amplifier.
BUSY
The DFRobot mini MP3 player has a build-in led. That led is on while a sound track is playing. At the same time the BUSY pin gives a low signal. When the sound track finishes the player stops and the line gets high.
The importance of the BUSY line.
If you give the command to play a song (track) then the DFRobot puts the BUSY pin in a LOW state. Then the song finishes and the player stops. The BUSY line will get HIGH. And nothing happens further.
This is often not what we would like to happen. Most of the time we want the player to automatic play the next song.
So what we have to do is to test if the BUSY line gets HIGH and if so send the command music.play('next')
But beware !!!
If you add a stop button and give the command music.stop() the player will stop playing but the BUSY line will get HIGH. So if you do not take care of that the software will immediately send the command music.play("next') and the next track will start playing.
If you intentionally will skip to the next song (track) just press the music.play('next") button.
The same goes for a button that pauses the player. When at pause the Busy line will get HIGH and the software will automatically go on to play the next song. So take care of that in the software if you have a pause and resume button.
The breadboard setup.
I have used two half breadboards but things could easily be build on a full breadboard.
At the top there is a USB plug. In earlier projects I used a breadboard USB adapter to connect a USB power plug to my breadboard. Nowadays I use my own printed USB connector for this. That is not because they are a lot cheaper but because I always seem to miss the breadboard connectors when I need them. The VCC is connected to the DFRobot VCC line but NOT to the Pico. The GND line is connected to the DFRobot GND line and to the Pico's GND line. Here is the link to the story about this and the STL files if you want to print some yourself:
https://lucstechblog.blogspot.com/2025/03/print-your-own-usb-connector.html
Please make sure you do NOT connect the VSS line of the Pico to the VCC of the USB connector. If you do and you power your Pico from your computer you might damage the Pico and your computer beyond repair.
To the left at the top there is a speaker. It is just a speaker so not a computer speaker which has an amplifier in it. You can use earplugs or an headphone if you do not have a speaker at hand.
The speaker is connected to the SPK_1 and SPK_2 pins. So it is a mono signal.
The TX line of the DFRobot mini player is connected to pin GP1 of the Pico which is UART0 pin RX. The RX line of the DFRobot mini player is connected to pin GP0 of the Pico which is UART0 TX. So TX and RX are crossed.
The VCC line of the DFRobot is connected to the USB connector VCC and the GND.
Next there are 5 buttons at the bottom breadboard. Each button has a pull-up resistor of 10K and the first 4 buttons are connected to the Pico's pins 18,19,20 and 21. These are the buttons that choose next song, previous song, volume up and volume down.
The fifth button is connected to the Pico's pin 30 which is the reset button.
Beware of the pins
When I started testing I tought my Pico was broken. I had connected the next song and previous song buttons to the Pico pins 16 and 17. And the most strange things happened. The player would play random songs.
Then it occured to me that those pins are also used as UART0 pins.
So whenever I pushed a button I also gave a pulse on the UART pin of the DFRobot player !!
So when using UART0 you can not use pins GP16, GP17 but also not GP12 and GP13.
You can attach the DFRobot player to UART1 (GP4 and GP5) but then you can not use GP8 and GP9. To do so however you would need to alter the library which I do not recommend.
The MicroPython program
from dfplayermini import Player from time import sleep import machine vol = 20 butnext = machine.Pin(18, machine.Pin.IN) butprev = machine.Pin(19, machine.Pin.IN) butvolup = machine.Pin(20, machine.Pin.IN) butvoldwn = machine.Pin(21, machine.Pin.IN) busypin = machine.Pin(22, machine.Pin.IN) txpin = machine.Pin(0) rxpin = machine.Pin(1, machine.Pin.IN) music = Player(pin_TX=txpin, pin_RX=rxpin) sleep(.2) music.stop() sleep(.2) music.volume(vol) sleep(.2) music.play(1) sleep(2) while True: if busypin.value() == 1: music.play('next') sleep(.2) if (butnext.value()==0): music.stop() sleep(.2) print ("next number") music.play('next') sleep(.2) if (butprev.value()==0): music.stop() sleep(.2) print ("previous number") music.play('prev') sleep(.2) if (butvolup.value()==0): vol = vol + 1 print ("Volume : ",vol) music.volume(vol) sleep(.2) if (butvoldwn.value()==0): vol = vol - 1 print ("Volume : ",vol) music.volume(vol) sleep(.2)
After all the explanation above I do not think this program needs any more explanation.
Not all commands are available. You can add buttons and alter the program to your whishes with the commands described above.
Just one thing:
At the beginning of the program the volume is set to 20. This is a moderate setting. It is set at such a volume that you will not damage your ears when using earphones or a headphone. You can always adjust the volume later with the volume buttons.
Till next time
Have fun
Luc Volders