Site Tools


serialMP3 Module

The PageMac SerialMP3 module is an embedded MP3 and WAV player designed for robotics, home automation, and other hobbyist projects. Powered by an Atemega328P microcontroller, a VS1003B MP3 decoder and a 1.5W audio amp, the module only requires 5V power and a serial connection. You tell it what file to play over serial, and the module plays the file from an onboard microSD card. The module is 5cm x 5cm, so it's easy to include on a robot. The total cost of the serialMP3 module is about $20.

PageMac SerialMP3 module with wireless control module attached.

Idea and Early Prototypes

Prototype serialMP3

I had wanted a small module that could play sound files easily for quite some time. I wanted it to be simple - just provide track numbers over serial, play common file formats (OGG or MP3) with no crazy converfsions required, and an integrated audio amplifier. The last part proved to be difficult - I was unable to find any modules that met all of these requirements. There were plenty of MP3 modules, but I didn't want a headphone jack output - I wanted to connect it directly to a speaker. So I decided to build my own!

Most MP3 modules out there use the VLSI VS1053B. But this IC is expensive - $20 each! Ideally, I wanted my entire module to cost less than this. But while browsing SparkFun, I found the VS100D breakout board. The VS100D is a System-On-Chip, so it does more than just encoding and decoding. I bought the module with the hope that I could write my own software for the chip to play tracks and load files from an on-board flash memory chip. Unfortunately, after spending several weeks trying to get the damn thing to work, I gave up. Although I was able to get the module to play OGG files, and even load an example firmware that plays tracks over serial, I wasn't able to write my own code and get that to compile and load on the chip.

Frustrated, I searched the internet more for some more IC's to do that job for me, but I just kept coming back to the VS1053B. But eventually I found the VS1003. The VS1003 is an older MP3 decoding chip with less features than the VS1053, but all I needed it to do was decode MP3! Maybe this could work?

I bought the MP3 Player Shield and mono audio amp breakout. I was able to connect both of these to my Arduino Uno fairly easily, and since someone else has already writen a library to interface with the shield, I didn't have to write much code at all. The prototype worked!

But, the combined cost of all these breakout boards was about $70. I needed to make my own PCB to make it cheaper!

Hardware Design

I thought about using a PIC (my go-to microcontroller) to tie all this together, but then I'd have to spend hours implementing SD card and VS1053 code. So I opted to instead to just use a bare Atemega328p, put the Arduino bootloader on it and use all the libraries that have already been written.

Below is a block diagram of the SerialMP3 module:

The hardware design is basically a combination of an Arduino Pro, the SparkFun MP3 Player Shield and the mono audio amp. But I wasn't quite sure about a few things:

  • The VS1003 is very similar, but still slightly different from the VS1053. Fortunately, VLSI provides a migration guide (pdf) to transition from the VS1053 to the VS1003. I just used it to go backwards. The changes were minor - different voltage requirements and a few software register changes.
  • I wanted to run the system at 3.3V. My applications were using 3.3V serial, so I was able to avoid using a level translator since the SD card, VS1003 and Atemega328P could all run at 3.3V. However, this meant I had to clock the Atmega328P at 8 MHz instead of 16 MHz. I had no idea if this would cause a problem!

I probably should have made another prototype to verify that my design would work, but since it costs me about $15 for a batch of PCBs, I just went for it. Although I have thought of a few things I'd like to change on the board (such as putting 5V power on the serial control header so you can just use 1 cable), it is fully functional and there are no mistakes.

PCB Layout

  • The board requires 5V power. This can provided from a microUSB port (power only, no data) or through a header J6. The 5V power is used for the audio amp; everything else uses 3.3V and 2.7V from the on-board regulators.
  • Speaker output is through an RCA header (J5) or standard 0.1“ headers (J3). I used an RCA header because I have a lot of old computer speakers that use this connector, so I was able to plug these speakers directly in to the module. The headers are nice when you've got some bare-wire speakers.
  • Although the Atmega328P uses the Arduino bootloader, you need to use an FTDI breakout board to program the microcontroller via the the pins on J2 and the Arduino software.
  • Serial control is 3.3V I/O through header J4. That means you can't hook it up directly to an Arduino Uno or other dev board that uses 5V I/O without a level shifter. There's also one extra GPIO on J4 for extra stuff (for example, if you wanted to toggle a pin when a track is finished playing).
  • The VS1003 outputs stereo audio, but the audio is mixed to mono before being fed into the amp (as per the TDA2005 datasheet).
  • The amplifier can be turned on and off by the microcontroller. Originally I would turn it on before playing and off when the track finished, but there was sometimes a noticable “pop” before each track as the amplifier powered on. So now the amp is just powered all the time.
  • An LED controlled by the microcontroller indicates if a track is currently playing or not.

PCB Assembly and Production

I got the board fabricated at It's $10 + shipping for 10 boards.

Since the PCB has mostly surface mount components, I used solder paste with a microscope to assemble the board. You can read more about how I assemble PCB's here.


The firmware is relatively straight-forward. It listens for basic serial commands such as Play, Stop, Loop, Enqueue, Volume. The Enqueue command is for basic playlist functionality - you can queue up several tracks, and the module will play them sequentially. If you try to play a file when another file is currently being played, it will stop the current file.

This project uses two libraries: the Sparkfun MP3 Shield Arduino Library and sdfatlib. Both libraries were slightly modified to make this module work correctly. On the sdfatlib library, I increased the SPI speed since I was using an 8 MHz clock on the Atmega chip. (not really sure if this was required actually). On the SFEMP3 shield library, I had to make several changes to adapt it to work with the VS1003 chip instead of the VS1053. I also added functions to loop sound files.

Additionally, I changed the way it plays “tracks”. The existing code in the library can play a track, for example you call the function to play track 1, and it will load track001.mp3. I wanted to be able to retain more of the file name, so my code actually looks for a file called 001_whatever.mp3. This way I can look at all of the files on the SD card and still know what the files are.

The code doesn't currently play tracks by file name (you just tell it a track number instead), but it would be very easy to modify the code so that it played full tracks. The library already supports this.

Loading Firmware

I bought my ATmega328P IC's from DigiKey since it's more expensive to buy them pre-loaded with the Arduino bootloader. So before loading the firmware, the ATemega328p must be programmed with the bootloader.

I use the Pocket AVR Programmer. The easiest way to load the firmware is to just use the Arduino IDE.

  • Connect the AVR programmer to J1 on the serial MP3. Flip the switch to not provide power
  • Provide power to the serialMP3
  • In the Arduino IDE, change the board type to Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
  • Change the programmer to USBtinyISP.
  • Hit tools → Burn bootloader. It takes a couple of minutes.
  • After the bootloader is loaded, disconnect the AVR programmer
  • Connect an FTDI breakout board to J2
  • Change the programmer to AVRISP mkII
  • Upload the serialMP3 program

Alt method: Burn Bootloader with avrdude

I used to use avrdude to program new boards, but the Arduino IDE method described above is a little easier.

The bootloader hex is located here:


Open a command window in the same directory and use the following commands to set the fuses then program the hex file:

avrdude -b 19200 -c usbtiny -p m328p -v -e -U efuse:w:0x05:m -U hfuse:w:0xD6:m -U lfuse:w:0xFF:m
avrdude -b 19200 -c usbtiny -p m328p -v -e -U flash:w:optiboot_atmega328-Mini.hex -U lock:w:0x0F:m

Serial Commands

When I made this board, I had two usages in mind: my home security system and robots. In both cases, I would be controlling the SerialMP3 module from another microcontroller, and I only wanted to provide track numbers to play instead of a full file name. So, the current serial protocol reflects that. Commands are as follows:

PXX\r - Play track, where XX is the 2 hexit number of the track in hexadecimal. pXXX\r - Play track, where XXX is the 3 digit number of the track in decimal. LXX\r - Loop track, where XX is the 2 hexit number of the track in hexadecimal. EXX\r - Enqueue track, where XX is the 2 hexit number of the track in hexadecimal. VXX\r - Set volume of track, where XX is the 2 hexit number of the volume. (loudest is 00, quietest is FF) S\r - Stop all tracks

It works!

I love this board. I have successfully integrated it with my home security system. The audio is loud and clear, and I'm even able to loop WAV files without gaps! This was a huge bonus for me, as I have several alarm files that sound much better with gapless playback.

serialmp3_1.jpg serialmp3_2.jpg serialmp3_3.jpg


Project Downloads

projects/serialmp3.txt · Last modified: 2015-07-31 10:44 by daniel