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. Repairing and Upgrading Laser Spirograph « The Mind of Bill Porter

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.

    • ChrisNo Gravatar says:

      Good timing. Just picked one of these up today. Nice to see how you added the extra functionality on top of an already good library.

    • MattNo Gravatar says:

      hmmm, looks good. i might have to try this do you know if it would be possible to add a “go-to timecode x in track y and play” type function? Or is there a way to jump around within a track to make “loops”? (Like groove~ in maxmsp if you are familiar with that.)

      thanks for the lib.

    • AndyNo Gravatar says:

      Hey Bill, nice job! I’ve been playing with my newly acquired MP3 Player Shield recently, and for the life of me I can’t figure out how to add an external volume control. Could you help me, or at least point me in the right direction?

      • BillNo Gravatar says:

        My library lets you set the volume control on the mp3 chip, so you could hook up a potentiometer to an analog pin, read it and set the value in the MP3 chip. Is that what you are going for?

        • AndyNo Gravatar says:

          Exactly! But what would the code look like? Would you do a digitalWrite to SPI_VOL?

          • BillNo Gravatar says:

            You didn’t read the Readme.txt file did you? Shame one you! 😛 Here’s a line from it:
            void SetVolume(byte Left, byte Right) Sets volume in MP3 player, starts off at 40 for both.

            So use MP3player.SetVolume(50,50); to go louder, or a number lower then 40 to go lower. I don’t know what the outer limits are, though I will look them up when I get a chance and add it to the ReadMe.

    • BillNo Gravatar says:

      Hey guys, can you up-vote my comment on Sparkfun so it gets to the top, and more people see the link to the library? Thanks

    • Jupiter MollNo Gravatar says:

      Is it possible to controll this shield with an rfid reader without conflict?

      • BillNo Gravatar says:

        Depends how the RFID reader is connected to the Arduino. This shield uses pins 2-13 basically, but can share the SPI port (pins 11,12,13) with something else if codded right.

    • hans caluwaertsNo Gravatar says:

      You did a wonderful job, thank you so much.
      Is there any chance to make this work together with a (Wiznet) ethershield on a mega 2560.
      I found out already I’ll have to re-route
      Shield 11 — Arduino Mega 2560 51 (MOSI)
      Shield 12 — Arduino Mega 2560 50 (MISO)
      Shield 13 — Arduino Mega 2560 52 (SCK).
      Would the ethershield and mp3 shield SPI communication interfere ? The idea behind this question is that I would like to play pre-recorded messages with the MP3 shield that are triggered by events on other arduinos on my LAN (e.g. “heating in bathroom activated” sounds in the living room if the arduino controlled bathroom thermostat switches on).
      I have about 30 events I would like to announce automatically triggered by 5 networked arduinos that control about everything in the house.
      Hope you can help.

      • BillNo Gravatar says:

        Hmm, I just looked through the source code for the ethernet library, and I don’t think they should interfere, as long as you wrap any function call related to the ethernet library with the pauseDataStream() and resumeDataStream() functions from my library. This will make sure the Arduino ignores any requests for data from the MP3 decoder until the function in between (related to the ethernet library) has finished with the SPI bus for now. Though I don’t know know long calls to the ethernet library take. If they take longer then 100ms, the buffer in the MP3 decoder might run out of data, and cause the sound to come out with gaps.

        You could also just never call an ethernet library function while a MP3 file was playing, if that’s acceptable in your application. If there’s no MP3 file playing, then the MP3 shield sits idle on the SPI bus and doesn’t care what else is going on. A function in my library (isPlaying()) will tell you if a files is currently playing.

        • hansNo Gravatar says:

          I can’t get the MEGA 2560 r2 or r3 to play an MP3. Changed the MOSI MISO SCK and compiled for the mega but no success. Tried API23 and 1 but same result. Plays a fraction (just a glitch, hardly enough to be able to recognize the song, I’d say 50 ms, and then eternal silence).
          I have no idea what else might have to be updated to make it work on a mega 2560. Did you try your SFEMP3Shield lib on a MEGA 2560 ? No ethershield installed yet, just the mega with the mp3 shield and 11 to 51, 12 to 50 and 13 to 52.
          Hope you can help.

          • BillNo Gravatar says:

            I did not try on a mega. How do you have the shield situated on the mega? is the DREQ pin from the shield still contacted to pin 2 on the Arduino? Do you have a regular Arduino around to test the SD card and shield on?

      • riza karaNo Gravatar says:

        Yes .i play Arduino Mega.But you dont forget
        Shield 9 — Arduino Mega 2560 53 SD_CS .

    • hansNo Gravatar says:

      It works fine on a UNO and on a Duamilenove (2009). I stored some more mp3’s on the 2 GB FAT 16 micro SD card and can play all of them on both boards. So far so good.I then cut pins 11,12,13 of the pin header on the mp3 shield and installed it on a MEGA2560, all pins connected through the pin headers except 11/12/13 which are routed to 51/50/52.
      Hope this helps you to see what I’m doing (wrong ?)

      • hansNo Gravatar says:

        Sorry for clicking on the wrong reply button and starting a new topic. I took a look at the UNO and MEGA schematic and found out that on the UNO pin 2 is INT0(PD2) but on the MEGA pin 2 is (OC3B/INT4)PE4. As far as I understand it looks to me that pin 2 of the MP3 shield is connected to another interrupt line, which might be the problem.

        • BillNo Gravatar says:

          That’s what I’m thinking, but when I research the interrupt parts of the Arduino API for the Mega, I get conflicting results. Did you try changing the library to use interrupt 4 instead of 0?

          • hansNo Gravatar says:

            Didn’t change anything in the lib so far, I’ve never done that before and I don’t want to screw things …

            • BillNo Gravatar says:

              It’s not too bad. The worst you can do is mess something up, and just delete it and download it again.

              If you open SFEMP3Shield.cpp in a text editor like notepad or wordpad, look for ‘attachInterrupt(0, refill, RISING);’ in three (3) different places. change the 0 inside the () to a 4. Then look for ‘detachInterrupt(0);’ in four (4) different places, and change it from 0 to 4 as well.

            • hansNo Gravatar says:

              changing the lib didn’t fix it for the MEGA, I’ve been measuring on pin2 with my scope but don’t see any level change.
              I did notice on the working UNO setup that pins 7 and 9 are triggered, is this also controlled in the lib and could it be that those also must be changed to be compatible with the MEGA ??

            • BillNo Gravatar says:

              Hans, I sent you an email so we can figure this out. I’m tempted to go buy a mega just to test this for you.

            • BillNo Gravatar says:

              Ok hans, I went and bought a Mega to figure this out, and I did. Download the library again, make sure you have the SPI port jumped to the right pins on the Mega and it will work.

    • PerryNo Gravatar says:

      Just want to say thanks, this makes working with mp3 shield a lot easier. 🙂

      • BillNo Gravatar says:

        You’re welcome Perry! If you document your project, let me know. I love seeing what people do with my Arduino libraries.

        • PerryNo Gravatar says:

          I already added a Sparkfun Serial enabled lcd for playback info (trackname and time (taken out of a sketch for turning the lcd into a clock)) too bad you can not the read mp3 tag info, to display on the screen.
          Have you by any chance figured out to set treble and bass? it should be possible according to the datasheet but i could not figure out how to change te settings.

          • BillNo Gravatar says:

            You could read the track info, if you wrote code to read and parse the binary ID3 tag info. I warn you, it’s a mess. If I ever get bored, I might try it. But I’m too busy right now. The library does scan and parse the MP3 frame header just to extract out the bitrate and nothing else.

            Treble and bass should be easy. I’ll look into that today.

            • PerryNo Gravatar says:

              This is the info about reading mp3 id3 tags
              if it is possible to read the last 128 bytes of the mp3 file all data is stored there.

              the layout is
              ID3v1 identification -> 3 characters (the word “TAG”)
              Song Title -> 30 characters
              Artist -> 30 characters
              Album -> 30 characters
              Year -> 4 characters
              Comment -> 30 characters
              Genre -> 1 byte

              Maybe if you could give me some pointers about how to read those 128 bytes i could try to create a function extarct the correct data.

            • BillNo Gravatar says:

              Wow, that’s simple enough. What I had read about ID3 was a variable length tag at the beginning of the file that would be a pain to parse. A static length at the end of the file should be no problem. I’ll work on that tonight.

            • BillNo Gravatar says:

              Ok, functions for reading the MP3 track title,artist,album have been added. Download the newest version and look at the example.

            • PerryNo Gravatar says:

              WOW you are fast, i am at work right now so i will look at it tonight.
              This library is getting better all the time 🙂

            • PerryNo Gravatar says:

              The id3 tag info works like a charm, and saves me a lot of tinkering time…

          • BillNo Gravatar says:

            I followed the spec sheet in setting treble and bass and got random results. I’ll have to play with it later to see of I can get it to work.

        • CrunchyNo Gravatar says:

          Bill, thank you again for this very very useful librarie !

          With it, in just 2 hour i’ve made an Arduino based gift box for the 90th birthday of my grandma!
          When she open it, the box play an random message between 90 recorded souvenirs of my childhood with her…
          I think, it would have been difficult to do that in time without this librarie. (I’ve start the project only 2 days before his birthday).

          Crunchy

        • CrunchyNo Gravatar says:

          Bill, thank you again for this very very useful librarie !

          With it, in just 2 hour i’ve made an Arduino based gift box for the 90th birthday of my grandma!
          When she open it, the box play an random message between 90 recorded souvenirs of my childhood with her…
          I think, it would have been difficult to do that in time without this librarie. (I’ve start the project only 2 days before her birthday).

          Crunchy

    • TomNo Gravatar says:

      Very good library and easy to understand – great work, Bill! I’m playing with the Motor Shield R3 on top of the mp3-shield, but as soon as I do the MP3player.begin()-command I cannot communicate with the Motor Shield anymore. Could you tell me how to reset the mp3-shield to the state before I did the begin-command? I’ve tried it with stop.track() but that didn’t work… Would be also nice to have an example-sketch of that SPI-Bus stuff you were writing about. Sorry for my noobish post, but I am still a beginner. Would be very cool if you could help me! Thanks in advance.

      • BillNo Gravatar says:

        Hi Tom,

        Sorry to be the bearer of bad news, but the problem is the Arduino Motor Shield and Sparkfun MP3 Shield are not hardware compatible. The MP3 Shield needs to use the SPI bus, pins 10-13, pins 6-9 for control, and pin 2 for the interrupt. The motor shield needs to use pins 3,8,9,11,12,13 to drive the two H-bridges. There’s no way to make these to work along side each other on the same Arduino, without major hardware and software modifications.

        The only feasible options to to use a second Arduino to run the MP3 shield, and exchange commands between them over serial.

    • MattNo Gravatar says:

      Oh, another question, not necessarily particular to this library – can the shield “mix” two mp3 files? or play a mp3 and a midi note at the same time?

      Thanks!

      • BillNo Gravatar says:

        No, the decoder can only handle one MP3 stream or midi stream at once. You’d have to pre-process the MP3 files an do the mixing before sending it to the decoder, which is something the Arduino might not have enough horsepower to do.

    • PhilipNo Gravatar says:

      All I can say is “thank goodness” for your library. Just got an MP3 Player Shield today and the example code just wasn’t working. As soon as I added your library and uploaded your example code, BINGO! I guess that’s the beauty of open source – the manufactures make the things and the people actually make it work. ;p Thanks again for this, you rock.

    • TreyNo Gravatar says:

      Hi Bill,
      I have just received the Arduino Uno-R3, as well as the mp3 shield to attach to it. I have downloaded all drivers and software, but cannot get any sound to play. I have tried both your way of changing (!card.init(SPI_FULL_SPEED, 9)), and sparkfun’s way by changing the sdfatlib pin to 9. Neither are getting results though. Also with your basic library you wrote, arduino software does not recognize “SFEMP3Shield MP3player” (it is not orange). Any idea? I have gotten LED light examples to perform, so I know the UNO-R3 is communicating right. I named the SD file track001.mp3, and it is 192kbps. I am very new at this, is there anything you could recommend or that i may be overlooking for the mp3 shield??

      Any help/comments are greatly appreciated!

      Thanks!

      • BillNo Gravatar says:

        “arduino software does not recognize “SFEMP3Shield MP3player” (it is not orange).”

        Trey, that means you did not unzip and copy the library into the Arduino libraries folder correctly. The path of the .h file should be My Documents\Arduino\libraries\SFEMP3Shield\SFEMP3Shield.h anythinf else and it won’t see it.

        You can also verify it’s not copied correctly by opening up a black sketch, and trying to import the library by clicking Sketch -> Import library. If it’s not listed, it isn’t seeing the library.

        • TreyNo Gravatar says:

          Thank you. That solved it and it is working perfectly! Great code. Unfortunately, I am attaching a CAN shield to the UNO-R3 as well, and the mp3 board is not liking that at all. My overall goal is to receive CAN input to the CAN shield, and depending on the speed of the car, play a different pitch sound from 0-20mph through the mp3 player! Any thoughts/suggestions/starter-tips for me? Thanks!

          • BillNo Gravatar says:

            You have the same problem as Tom, the shields are not compatible. But in this case it’s a little more feasible to make them compatible.

            You’d have to re-route (here’s an easy way to do that) pin 2 on the CAN shield to pin 3 on the arduino, and edit any library for the CAN shield to use interrupt 1 instead of 0.

            You would have to not connect pins 7-8 of the CAN shield to the arduino and lose the function of those LEDs on the CAN shield, whatever they do.

            Last you would have to re-route pin 10 on the CAN shield to pin 5 on the Arduino and edit any library for the CAN shield to use pin 5 for the CAN controller’s CS(chip select) pin instead of pin 10.

            The last thing is you would (might) have to edit the CAN shield library to add the ‘pauseDataStream’ functions around any SPI transfers to make sure the two shields don’t interfere on the SPI bus.

            That was what I came up with when I glanced at the two spec sheets. The easier thing to do is to have two separate Arduinos talking to each other over serial. One handle CAN communications, the other handles MP3 playing.

            • TreyNo Gravatar says:

              Ok great. I’m glad to know it is at least feasible to do using the go-between shield which I luckily had ordered just in case, and is on the way! That’s crazy you can tell me all of that just by glancing at the spec sheets. That would have taken my 3 hours!

              Also, do you know if it is possible to integrate a gas pedal (like in video games) to the arduino? Or any other components I would need? I am using artificial CAN from a “USB-to-CAN” devise from ixxat.com, and am trying to simulate driving speeds from this artificial CAN, so I thought it would be cool to incorporate a pedal. And if you know, could you describe the general layout/order of how everything in the system would communicate?

              Thanks again so much for all your (very fast) help!

            • BillNo Gravatar says:

              Trey, I have very little experience with CAN so I’m not a good person to ask about that.

    • hgsNo Gravatar says:

      Nice work! I made my own MP3 shield with the VS1003B, does this lib works with this chip? what changes do I have to do to make it work?

      thank you.

    • […] museum to see if they wanted that option. I figured an old computer (or better yet, an Arduino and MP3 Shield could ‘playback’ scanning signals for logos) could be used to generate signals for logos […]

    • FRiCNo Gravatar says:

      Hi, thanks for making this great library. I have the older Sparkfun MP3 Shield (http://www.sparkfun.com/products/9736) without the SD card. In case anyone else is still using this older shield, the library can be modifed to work with this shield by just changing a few lines.

      Of course, since the older shield doesn’t have SD, you’ll have to modify SD_SEL according to the SD interface. I use the SD card on the Ethernet shield so it’s 4 for me.

      In SFEMP3Shield.h
      #define MP3_XCS 9 //Control Chip Select Pin (for accessing SPI Control/Status registers)
      #define MP3_XDCS 2 //Data Chip Select / BSYNC Pin
      #define MP3_DREQ 3 //Data Request Pin: Player asks for more data
      #define SD_SEL 4 //select pin for SD card

      And in SFEMP3Shield.cpp, all the lines with attachInterrupt and detachInterrupt should be changed from 0 to 1.

Leave a Reply

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