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. Arduino-projekti: hello mp3 player shield « tiko1102071

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.

    • RhysNo Gravatar says:

      Hey! fantastic library. newbie here and it sure made it easier for me to dive in. Can you tell me how the volume works though? I found that MP3player.setVolume(1,1) was the loudest, whereas I was expecting 255 to be the loudest.

      I am trying to simply connect a piezo speaker to the on-board connector (R and -) and the volume is very low. I know the speaker can get ear splittingly loud. please help?

      Regards and thanks,
      Rhys

    • […] illalla selaillessani testasin vielä tämän, ja totesin senkin toimivan moitteetta – ja jossakin määrin aloittelijalle on merkitystä […]

    • KeithNo Gravatar says:

      Fantastic library! Had me up and running in no time compared to the example sketches included on the sparkfun website.

      I am quite unfamiliar with the restrictions imposed by the hardware but is there a reason the filename must be in the 8.1 format? I would like to be able to open a filename that has more than 8 characters (most song titles are longer). I would also like to be able to open files that are inside a folder within root. Is this something that can be done easily?

      • KeithNo Gravatar says:

        After some digging I found that the SD libraries are strictly limited to the 8.3 format but folders can be opened.

        Another question though: Is it possible to call the “MP3Player.trackTitle()” function (as well as the other two similar functions) without going through the process of starting the song playing? I’ve found the parsing to be a quick process but opening the file to be rather slow.

        • BillNo Gravatar says:

          Keith, I sent you an email about your request.

        • Josh BarthNo Gravatar says:

          Keith,

          I too, had this issue, I have modded the library a bit to allow another file handle aside from the one used to open and parse the playing file. I then used this to grab the tag data and spit it out in a loop, in essence creating a method of displaying a Table of Contents.

          This is a needed addition to the library, because of the 8.3 restriction. I’m not the best at coding but, this library is the go to way to get this shield working so I think we need to persuade Bill to integrate these changes.

          Bill what do ya think? I can send my mess over if you wanna take a look. It really is fairly simple.

    • Al-GlitchNo Gravatar says:

      Excellent library Bill, however I have 1 suggested improvement:

      If you change the following lines:
      else if (temp >= ‘1’ && temp = ‘a’ && temp <= 'z'){
      temp = temp – 96;

      and change the 's' and 'f' commands to upper-case you can play 26 different files instead of just 9.

    • dimaNo Gravatar says:

      Consistently getting ERROR CODE 4 Decoder Mode Failure

      1 GB Flash FAT32

      I put the file together in Audacity 192kbps stereo mp3 (http://xfer.shiftingplanes.org/track001.mp3 just me singing into the mic… badly)

      Any suggestions much welcome at this point, kinda konfuzed as to what’s going on.

    • Thanks for the fantastic library Bill !

      I have had a good play with this today and just having a couple of strange things happen.

      I am just trying to hook up 2 switches to do a fade in and a fade out.

      I ended up using analogue inputs as switches as most of the digital pins seem to be busy.

      The following code more or less works but sometimes it just hangs.

      I think it may happen when between loops but I am not sure how to write the code better.

      Any suggestions would be very welcome.

      Thanks

      #include
      #include
      #include
      #include

      SFEMP3Shield MP3player;

      int loud = 0;
      int quiet = 150;

      //const int buttonPin = 10; // the number of the pushbutton pin
      int buttonState0 = 0; // variable for reading the pushbutton status
      int buttonState1 = 0; // variable for reading the pushbutton status

      void setup() {

      //start the shield
      MP3player.begin();

      //start playing track 1
      MP3player.playTrack(1);
      // MP3player.SetVolume(150, 150);

      }

      //do something else now
      void loop() {

      buttonState0 = analogRead(A0);
      buttonState1 = analogRead(A1);

      if (buttonState0 > 500) {
      fadeIn(5);
      }

      if (buttonState1 > 500) {
      fadeOut(5);
      }

      if (MP3player.isPlaying() == 0)
      {MP3player.playTrack(1);}

      }

      void fadeIn (int rate)
      {
      int vol = 0;

      for(vol = quiet; vol >= loud; vol -= 1)
      {
      MP3player.SetVolume(vol, vol);
      delay(rate);

      }
      }

      void fadeOut (int rate)
      {
      int vol = 0;

      for(vol = loud; vol < quiet; vol += 1)
      {
      MP3player.SetVolume(vol, vol);
      delay(rate);

      }
      }

      • BillNo Gravatar says:

        I’ll try to take a look at this in the next week or two and see if I can replicate the problem. In the mean time, it would help to put print statements everywhere and see where your code is hanging (The last print message will be just before the arduino hangs)

    • wayneNo Gravatar says:

      lib works great with mp3 shield, audio amp and 8ohm .5w speakers from sparkfun except i am recording voice with audacity and exporting 192b mp3 which also works ok but does anyone know how to increase the volume of the mp3 file ? an mp3 song plays nice and loud but recorded voice is soo low, it can barely be heard, thanks

    • CameronNo Gravatar says:

      Thanks man, this will make my life so so so much easier, i was starting to think i should have picked an easier first project 🙂

    • MNo Gravatar says:

      hey. I’m building an alarm system with automatic phone alert, and was thinking about using an MP3 shield to play a recorded audio message through the phone line. I’ve already got all the hardware, my only issue is programming. I have an UNO R3 board. Would you please tell me which pins I can’t call? I need 9 pins to make it work, 1 to activate a relay, 7 to generate the phone number and 1 to receive the alarm. I just don’t know where to fit the mp3 shield code

      • BillNo Gravatar says:

        The analog pins will give you 6 digital IOs, Digital pins 0 and 1 are free (assuming you are not using any Serial or USB in your sketch) and digital pin 5 can be used.

        D10 is not connected any looks tempting to use, but you can’t because it would mess up SPI comms.

        • MNo Gravatar says:

          Thanks for your reply, but that wont do. I need 8 output pins and only 1 Input pin. Analog pins only work as Input. Guess I have to get another board

          • BillNo Gravatar says:

            Analog pins most certainly can be used as digital output pins as well. They are exactly the same as pins 0-13 except they can also be used as analog input pins.

            • MNo Gravatar says:

              And thank you once again. Got Just the 9 pins I needed, wrote the code and now have a phone alarm system with voice alert running just as expected. If you ever come to Portugal ill buy you a beer

    • MNo Gravatar says:

      thank you for that awesome library by the way

    • AlexNo Gravatar says:

      Hi Bill, thanks for the great work here.
      I’m a beginner, hope this question is not too elementary.
      I’m working on the MP3 shield with a RTC (and some other stuff). Is it possible to use the SD card on the shield to do data logging (time stamp)?
      I’m in doubt as I believe that only 1 file can be open at a time in the SD card. Since the MP3 data is fetch in chucks is it possible to write to the card without interrupting the MP3 played?
      Any help will be great. Thanks a lot. Cheers…

      • BillNo Gravatar says:

        There’s not enough RAM in the Arduino to handle multiple file access on an SD card. You would have to wait to store data till a song ends by store the logged data somewhere else temporarily, (like EEPROM). Or look at adding external RAM. Though since external RAM would add to the SPI bus, you may run into a latency issue with multiple devices on the SPI bus.

    • GeoffNo Gravatar says:

      Hi,

      Thanks again for all your hard work on this. I have a super simple question (this is my first Arduino project ever). I want to run 4 lights off of this shield (each light controlled by a switch). I’ve looked through the comments (specifically the one from Wendy regarding the pin out diagram) and I’ve also looked on the shield itself to see what digital pins are free (I’m using the analog ones for various switches). So far the only pins that I can get LOW during playback are 5 and 10. Some other pins I can get to go LOW if there is no playback going on but I would like them to be independent. Is there any way I can get 2 more pins free?

      • BillNo Gravatar says:

        Don’t forget, any of the 6 analog pins can be used as digital pins, and they are all not used by the MP3 shield. So there’s your 4 right there.

        • GeoffNo Gravatar says:

          Thanks for the response. Right now I have all the analog pins used for switches. I could just have the led in line with the switch as a solution but I was hoping to have the leds do stuff on random events. I’m making a doll house for my daughter and I thought it would be fun to have a dance hall (hence the mp3 shield), and lights in all the rooms with switches. I also thought it would be neat to have it act like there was a thunderstorm every once in a while where the mp3 shield would play the audio and I would make the lights flicker. I guess I can shelve that idea if there are no more free pins.

          • PatrickDNo Gravatar says:

            Have you considered using a different model Arduino? The Arduino Mega 2560, for instance, has 54 digital I/O pins and 16 analog inputs where the Arduino Uno only has 28 and 14, respectively. I’ve used the shield with Bill’s library on an Arduino Mega 2560 with good success.

            • GeoffNo Gravatar says:

              Thanks for the suggestion. I think I am just going to go with having the LED’s in line with the switches. It will save me the cost of buying a new board.

              It leads me to one more (and hopefully my last) question. I’ve got everything up and running, stuff is playing using the awesome library and the MP3player.playTrack(); command. However, for some reason the MP3player.isPlaying(); command isn’t working. the MP3player shows up as orange but the isPlaying() part is black. I’ve tried a bunch of different commands and they all show up as orange, it is just this one that doesn’t seem to register. Am I doing something stupid here? I’ve even gone into the header file of the library to make sure that the command was there and it was. I’m sort of stumped on this one.

              Thanks

              Geoff

            • BillNo Gravatar says:

              The color of text has nothing to do with the compiler or how the code works. It’s just a nice thing the Ardino IDE does to make things pretty. If it’s not changing color, then I haven’t added it to the keywords.txt file. But that doesn’t effect the operation of the library.

    • Teddy FoxNo Gravatar says:

      Hi Bill,

      I tried to find out the answer on my question reading various forums but I didn’t succeed.

      I’m trying to use your library for Seedstudio Music Shield (http://seeedstudio.com/wiki/Music_Shield) on Arduino Mega 2560. Arduino pins are used there as follow: D10 – Used for SPI Chip Select; D11 – Used for SPI MOSI; D12 – Used for SPI MISO; D13 – Used for SPI SCK; D14(A0) – Used for Reset of VS1053; D15(A1) – Used for Data Require of VS1053; D16(A2) – Used for Data Select of VS1053; D17(A3) – Used for Chip Select of VS1053.

      So I made the changes in the SFEMP3Schield.h:

      //MP3 Player Shield pin mapping. See the schematic
      #define MP3_XCS 17 //Control Chip Select Pin (for accessing SPI Control/Status registers)
      #define MP3_XDCS 16 //Data Chip Select / BSYNC Pin
      #define MP3_DREQ 15 //Data Request Pin: Player asks for more data
      #define MP3_RESET 14 //Reset is active low
      #define SD_SEL 10 //select pin for SD card

      And with the code:

      #include
      #include
      #include
      #include
      SFEMP3Shield MP3player;
      void setup()
      { Serial.begin(9600);
      //start the shield
      MP3player.begin();
      switch (MP3player.begin())
      { case 1: Serial.println(“begin: SD Card Init Failure”); break;
      case 2: Serial.println(“begin: SD Card File System (FAT) Init Failure”); break;
      case 3: Serial.println(“begin: SD Card Root Directory Init Failure”); break;
      case 4: Serial.println(“begin: MP3 Decoder Mode Failure”); break;
      case 5: Serial.println(“begin: MP3 Decoder Speed Failure”); break;
      }
      MP3player.SetVolume(150,150);
      //start playing track 1
      MP3player.playTrack(1);
      switch (MP3player.playMP3(“001”))
      { case 1: Serial.println(“playMP3: Already playing track”); break;
      case 2: Serial.println(“playMP3: File not found”); break;
      }
      }
      void loop()
      { Serial.println(“I’m bored!”);
      delay(2000);
      }

      I got nothing: – Serial Monitor is empty (even “I’m bored!” is missed); – nothing in the earphones.

      What’s wrong?
      Thank you.

    • VinceNo Gravatar says:

      Hi Bill,

      great lib you did! With a few modifications to match my mp3 shield v10, it rocks!

      As I wish to add others SPI devices (RFM12B for the moment) I know I’ll have to share the SPI bus. I thought do this with some digitalWrite(xCS, HIGH or LOW) but I guess you have another solution with Shift Register (74HC595N certainly…). Would you please tell me more about the wiring and code please ?
      Cheers.
      Vince

      • BillNo Gravatar says:

        Vince, see the example code on this page. Any number of devices can share the SPI bus, you just have to make sure there are no collisions in traffic. That’s why there are pauseDataStream and resume function in my library.

    • JeffNo Gravatar says:

      Great Library and thanks!! Newbie getting started and trying to figure out how to make a 10k pot work the volume. I have a basic idea from what I read, but I am having trouble putting it together. Anyone have a script made for reading analog pin 4 (for example) and making it control the volume while the song is playing?
      Oh, does this have a randomize and repeat feature?
      Thanks!!

      • BillNo Gravatar says:

        It should be easy, just analogRead the pin, use the map() function (see how in the Arduino reference pages) to change it to the range for the SetVolume function.

        Randomize an repeat is something the end user would have to write a program for. Also something that should be easy. Let me know if you need further help.

Leave a Reply

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