Sparkfun MP3 Shield Arduino Library

Posted in Arduino Libraries by Bill
28 Jan 2012

The Sparkfun MP3 Player Shield for Arduino is a inexpensive and easy way to add MP3 playback capability to your Arduino project. But it was lacking an easy to use Arduino Library to go along, so I fixed that. Introducing the SFEMP3Shield library just for this shield. Now playing an MP3 files is as easy as MP3player.playTrack(5); and all the work is done behind the scenes.

Most of this library comes from the existing example code, with the major new feature of being interrupt driven. So no need to worry about feeding the MP3 chip, whenever it’s ready for more the library will be ready to feed it. This allows the Arduino to perform other tasks while music is playing. The most basic use of the library is as follows:

 

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SdFat sd;
SFEMP3Shield MP3player;

void setup() {

  Serial.begin(9600);

  //start the shield
  sd.begin(SD_SEL, SPI_HALF_SPEED);
  MP3player.begin();

  //start playing track 1
  MP3player.playTrack(1);
}

//do something else now
void loop() {

  Serial.println("I'm bored!");
  delay(2000);

}

That’s all it takes to get your Arduino to play an MP3 file using the shield.  How easy is that?

The library does have more functions and even error reporting. All of which can be found in the ReadMe file or in the Example Sketch included with the Library.

Source Code available on GitHub project pages: Sparkfun MP3 Player Shield Arduino Library

Or Direct Download here.

Using the SPI bus for something else as well?

I added some functions to make sure there will be no data collisions on the SPI bus caused by the MP3 decoder asking for more data at the wrong time. You need to wrap any SPI code you add to your project with these two functions. Here’s an example from my project that also has a shift register on the SPI bus:

  //disable interrupts to avoid collisions on the SPI bus between this code //and the MP3player library
  MP3player.pauseDataStream();

  //shift data
  tempIO = SPI.transfer(HIBYTE(output));
  tempIO<<8; 
  tempIO = SPI.transfer(LOBYTE(output));

  //latch output on shift registers
  digitalWrite(OUTLATCH,LOW);
  digitalWrite(OUTLATCH,HIGH);
  digitalWrite(OUTLATCH,LOW);

  //enable interrupts
  MP3player.resumeDataStream();

But you can’t stop the data stream to the MP3 Shield for too long before it runs out of data so be careful and try not to do too much stuff in between the functions.

 

Wanna be your own DJ?

New features! Requested in the comments below, there are now functions to skip around a playing track. You could fast forward, rewind, create loops, etc.

Here’s an example that will just open a file, jump to the 30 second mark (measured in milliseconds, 30 seconds = 30000 ms), and loop the song back every 750 ms:

MP3player.playTrack(1);

for(;;) {
MP3player.skipTo(30000);
delay(750);
}

If you want to know where you are in the current playback, do this:

time = MP3player.currentPosition();
Serial.println(time);

Both functions are not super accurate and depend on the bitrate of the file. The library should auto-detect the bitrate of the file but may fail on some MP3 files. If that happens, you have to set the bitrate manually like this:

MP3player.playTrack(1);
MP3player.setBitRate(192);

I can already see the cool DIY DJ equipment that could be made with this. Let me know if you have problems, and comment below if you ever make something cool with the library.

Troubleshooting

Pulled from the GitHub Project Page

The below is a list of basic questions to ask when attempting to determine the problem.

  • Did it initially PRINT the available RAM and Full Help Menu?
    • The MP3Shield_Library_Demo.ino example should initially provide a opening print indicating the amount of available SRAM and full menu help. If you don’t see this the problem is between your Target and IDE. And likely not this library
    • Is Serial Monitor set to the correct tty or com port and 115200 baud rate? Did you change the baud rate?
    • Reset the Arduino after Serial Monitor is open or send any key. It may have printed these prior to the Serial Monitor being started.
  • WHAT is the Error reported?
    • Is the Error Code is indicating a file problem.
    • Are the filenames 8.3 format? See below warning.
    • See also Error Codes
  • Did the SdCard LOAD?
    • Try reseating your SdCard.
  • Is it FAT(FAT16 or FAT32)?
    • If the Error Code is indicating problems with the INIT, VOLUME or Track not being successful. It is recommend to use SdFat Example Library’s QuickStart.ino as to see if it can access the card. Additionaly, SdInfo.ino may indicate if it can mount the card. Which may then need to formatted in FAT16 or FAT32. Where SdFormatter.ino can do this for you.
  • Are the needed files on the root?
    • Remember to put patch and audio track files on the SdCard after formatting.
    • Are the filenames 8.3 format? See below warning.
  • "Error code: 1 when \b trying to play track"
    • See the above Limitations. about Non-Blocking.
    • Remember to check your audio cables and volume.
  • Why do I only hear1 second of music, or less?
    • This symptom is typical of the interrupt not triggering the SFEMP3Shield::refill(). I bet repeatidly sendnig a track number will advance the play about one second at a time, then stop.
    • What board is it? Check Hardware Limitations. about Interrupts.
    • Are you trying the SFE provided test files ? Or some homemade mp3 files? The SFE test files are nice as they are Immediately LOUD.
    • Interrupt problems may cause mp3 files that have a quiet lead in (or ramp up of volume) to be falsely diagnosed as not playing at all. Where the first 1 second may not be loud enough to be heard.
  • Free RAM = 1090 Should be a base line of 1094
    • As a courtesy and good practice the provided example MP3Shield_Library_Demo.ino prints out the available remaining RAM, not statically allocated. And the actual available amount may depend on specific processor, IDE version, libraries and or other factors. A Uno built with IDE version 1.0.2 should have approximately 1094 bytes available from the example as is. And a Mega using a 2560 may show 6713, as it has more RAM.

Note

This library makes extensive use of SdFat Library as to retrieve the stream of audio data from the SdCard. Notably this is where most failures occur. Where some SdCard types and manufacturers are not supported by SdFat. Though SdFat Lib is at this time, supporting most known cards.

 

Warning

SdFatLib only supports 8.3 filenames. Long file names will not work. Use the 'd' menu command to display directory contents of the SdCard. "longfilename.mp3" will be converted to "longfi~1.mp3" . Where one can not predict the value of the 1. The DOS command of "dir \c /x" will list a cross reference, so that you know exactly, what is what.

Still Need Help?

Use the support forum to look for a solution or ask for help. Please don’t use the comments below to ask for help.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Share

Trackbacks / Pingbacks

  1. door welcome music « dynamicboost
  2. Your theme song greets you at the front door - Hack a Day

Warning: count(): Parameter must be an array or an object that implements Countable in /homepages/46/d285670699/htdocs/bill/wp-includes/comment.php on line 879
  1. 590 Comments.

    • Josh BarthNo Gravatar says:

      Thank you.

      I’m just tinkering, built a portable mp3 loudspeaker consisting of an Arduino Mega, Sparkfun MP3 Shield and STA540 Audio Amp kit. I really appreciate the ease of use of your library. I of course want to take it a step further and I’m a networking guy.

      So I want to pick your brain, there is a project-

      http://maniacbug.wordpress.com/2011/12/30/arduino-on-ice-internet-radio-via-shoutcast/

      It uses a VS1053 as well to fetch an internet radio stream and it feeds the encoded stream directly to the chip.

      I’ve poked around a bit between the Shield Library and the VS1053 library from the mentioned project. I am not confident I have what it takes but, I’m hoping you might take interest in adding a feature to allow the handoff of a data stream such as HTTP streaming radio rather than just file.

      • BillNo Gravatar says:

        Hey Josh,

        I wrote this library for that particular shield. To add features like HTTP connection streaming goes outside its original scope. But it seems like that guy has already done exactly what you want, so what trouble are you having?

        And yes, I have wanted to try to stream audio in a setup like his, but don’t have the time to play with that right now.

        • BillNo Gravatar says:

          That might come off sounding harsh. I don’t mean it to be. Yes, I’d like to try streaming some day. But I’m too busy at the moment to play with it.

        • Josh BarthNo Gravatar says:

          Oh I understand, it came off just fine. I can sound a bit rough around the edges at times too. No harm no foul.

          Maybe I should elaborate. I don’t want you to stray and do anything not shield oriented with the library.

          My point is though, that this shield (and especially the earlier ones without SD) are capable of playing from sources other than from SD. Currently the “refill()” function is pretty much bound to fetch from SD.

          If there were a way to manipulate the functionality when you initialize the shield that would be awesome, ideally you should be able to create a single instance of the MP3Player and switch it’s source on the fly. Take for example a networked PA system, it should be able to play ambient audio from a local SD and then at any point cut out for an over the air announcement.

          I will certainly help with what I can, but honestly I am an amateur when it comes to code….it takes a bunch of time pondering for me to come up with a bit of code with elegance and perfect functionality.

          ….sorry gotta roll, work calls.

    • DanielNo Gravatar says:

      Hi Bill

      Your library looks interesting. Is there a possibility to use the encoding-capabilities of the chip as well?

      Thank you very much,

      Dani

    • DanBNo Gravatar says:

      Hi!

      Thanks for this awesome library.
      Somehow I can’t get it to work!
      No clue why, the simple example code seems to run fine, according to print. Reformatted the card, tried a couple of different mp3 files, (all 192 kbps) Even tried another board.

      Any tips on where I should start to look for bugs / faults?

      Thanks ‘n cheers!

    • DanBNo Gravatar says:

      wow, ur fast!
      nope, only prints the “i’m bored”

      The only feedback I get is the funky stuff during upload…

    • DanBNo Gravatar says:

      i meant, funky sounds

    • DanBNo Gravatar says:

      How silly of me, I’ve only looked at the SdFat examples.

      It gives me:
      Error code: 2 when trying to play track

      So, it can’t find the file right?

    • DanBNo Gravatar says:

      ouch, I’m having a hard time to admit this: the track was named track01.mp3
      jeez…what a moron I am.

      thanks bigtime for helping me out!

      I’ll buy you a beer via paypal!

      cheers!

    • KJNo Gravatar says:

      Want to use the code for another music shield. The fez music shield (www.ghielectronics.com/catalog/product/289) also uses the VS1053 architecture. would at least some of the code work?

      • DanielNo Gravatar says:

        Oh, that’s interesting, since that board seems to have connected the mic-IN-pins! Dani

      • BillNo Gravatar says:

        Hmm, This board is going to be trouble. They connected the chip’s DREQ line to digital pin 4, which means using external interrupts to feed in music data won’t work. The end user would have to poll the pin constantly. Or I could hijack an internal interrupt to poll the pin so the end user does’t have to worry about it. Other then that it all you would have to do is change the pin definitions. I’m interested in tackling this problem so I may release an official update that would run this.

        In the mean time, you could jumper Digital pin 4 and 2 and change (in SFEMP3Shield.h )

        #define MP3_XCS 6
        #define MP3_XDCS 7

        to

        #define MP3_XCS A5
        #define MP3_XDCS A4

        And change #define SD_SEL 9 to whatever pin your SD card CS pin is connected to and the library should work.

        It’s also a shame they didn’t add an SD card slot. That would have made this shield more capable then the Sparkfun version.

    • DanielNo Gravatar says:

      They have an SD card slot on their mainboard, thats probably why they didn’t include one in the shield.

    • OJNo Gravatar says:

      Hi there and thanks for this amazing library – made the job of integrating sound effects into my project a breeze!
      I do run into a bit of an issue though, and I guess this might not be strictly due to your library, but that’s at least where I get the symptoms.

      I’m trying to play a nearly 3 minute long (192bps) MP3, which I restart if finished, using : if (!MP3player.isPlaying()) playSound(“Alive.mp3”); in the loop().

      Trouble is, it plays fine, but the playSound function never returns, meaning the program hangs here, playing the song to the end and then does nothing.

      My setup is a bit weird – it’s a Peggy 2.0 board (Evil Mad Scientist) that shares power with a Diavolino (Duemilanove 328 clone) with the MP3 shield attached. The Peggy 2.0 and Diavolino are connected to the same 5V power and talks to each other using I2C.

      Top-off-my-head ideas: RAM? (I don’t quite know how much extra your library eats while playing), I2C conflict? (unlikely I guess), voltage? (unlikely, as the 5V wallwart can do 1500mA). At my wits’ end here. Any ideas?

      • BillNo Gravatar says:

        Hmm, that’s odd. Can you put print statements in playMP3() function in the .cpp file of the library so we can find where in the function it is hanging? For example, add to the end of the function:

        Serial.print(“0”);
        //gotta start feeding that hungry mp3 chip
        refill();

        Serial.print(“1”);

        //attach refill interrupt off DREQ line, pin 2
        attachInterrupt(0, refill, RISING);

        Serial.print(“2”);

        return 0;

        Save the file and then re-upload and watch the output on the serial monitor so we can see if it’s one of those calls that is locking up the main thread.

        • OJNo Gravatar says:

          Errr, I did as you suggested and now I think I’m slightly losing my mind 😉

          After end of track the system hangs, and upon a reset the MP3 Player Shield refuses to initialize. It only manages to print half the Serial.printl() that reports errors before coming to a halt, so I cannot see the error code (it gets to “Err” before hanging). A couple of seconds’ power off seems to clear it, but all serial communication stops after the MP3 Shield is activated. It plays the song to completion, but the animation I have running on the Peggy 2.0 display to check that we’re alive (streamed from the Diavolino with the MP3 shield) hangs after a few seconds, and as serial dies when initializing the shield, I get no status messages. It seems almost as if playing the MP3 file sucks up all the RAM, but I’m too green on Arduino to trust my own judgement here (as a UNIX guy, that’d be my guess, but I think I’m looking at it from the wrong angle).

          I suspect that I am possibly wasting your time, as it might be that there are other issues with code or hardware, and the MP3 library is not at fault. I guess my best option trying to debug this would be to try to strip out parts of the code to I get down to something that works and rebuild until it doesn’t. That would at least help if it really is RAM that’s the issue.

          I’ve tried three different suggestions for checking free RAM, but it seems they all give highly diverging and erratic results, so I think I’ll just strip and then start adding code until it acts up again.

    • dyynamicNo Gravatar says:

      thanks bill again for that smooth working library. one noob question though: is it possible to still use one or both of the digital pin interrupts? i am triggering the mp3 tracks via a hall sensor and use a push button to stop playing, which both would be better as interrupts i suppose. however, the shield itself seems to already use pin 2 and 3. do you have any ideas how to work around that?

      • BillNo Gravatar says:

        You can’t use pin 2, as that needs to be exclusively used for the shield. But if you aren’t using MIDI (my guess is no if you are using my library) then you can cut the trace in-between the two gold pads on the shield next to pin 3 so you can use pin 3 for something else.

        But it looks like you already finished your project, looks good!

        • dyynamicNo Gravatar says:

          yeah thought so… won’t do the cutting as the code is running without interrupt for now. i wish though arduino would have more interrupt pins… thanks for your reply.

    • […] awesome work of bill porter and bill greimann I can use their smooth libraries for this project: sparkfun mp3 player shield library and sdfat library. apart from that, the coding is pretty straight forward. whenever the magnet is […]

    • Hi ! First of all, thanks a lot for your library. As soon as I can get my mp3 shield to work, it will make my life infinitely more happy !!

      So, I have downloaded the libraries, installed them inside my Arduino app (osx -> content:ressources/java/libraries/).

      The MP3_Shield_Library_Demo compile well but then return a” Error code: 1 when trying to start MP3 player” on the serial monitor.

      Any idea that can cause such an error ?
      Does the “Sd2PinMap.h” file have to be modified ?

      • BillNo Gravatar says:

        If you read the ‘ReadME.txt’ file you see that error 1 is “SD Card Init Failure” which is an error generated by the SDFat library. I can’t help you much with that other then to follow the Sparkfun guide for formatting the SD card correctly.

        You could also run the “SdInfo” example in the SDFat library to see what error it gives when it tries accessing the card. You have to change

        const uint8_t SdChipSelect = SS_PIN;

        to

        const uint8_t SdChipSelect = 9;

        in that example sketch. Let me know what it says and maybe we can figure this out. Also, did you try another SD card?

    • To complete my previous message :

      MP3_Shield_Example.pde -> gives nothing but silence
      MP3_Player_Example.pde –>
      MP3 Testing
      Error: Card init
      Error: Volume ini
      Error: Opening root

      The SD card is FAT16

      Any idea ? Thanks again 🙂

    • […] slot, and audio jack for the powered speakers. [Sebastian] grabbed a copy of [Bill Porter's] mp3 shield library to get the project up and running […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.