Home Forums Sparkfun MP3 Shield Library Support Forum Triggering mp3 file over serial

Viewing 15 posts - 1 through 15 (of 16 total)
  • Author
  • #2351


    I have two arduinos, a mega 2560 with a touchscreen and a UNO with the Sparkfun MP3 Shield on it. I have connected the two arduinos using the TX/RX ports. I have the mega sending a three digit number over the serial port and I have tracks loaded on the MP3 SD card that follow the convention of track123.mp3

    I would like to be able to trigger the tracks on the shield using a three digit number (e.g. 123 to play track123.mp3) sent from the mega. I know the example files have a similar demo that uses the numbers 1-9 and I have had a stab at editing the code to play 3 digit track references. It all works, but the reliability of the playback is pretty hit and miss. Sometimes it plays the correct track, sometimes it looks like it misses a digit …. as an example:

    I transmit    –   123

    Playback plays – track123.mp3

    I transmit      –   123

    Playback doesn’t start

    I transmit     –   123

    Playback may trigger e.g. 121

    i.e. it didn’t get the last digit in the first request and therfore takes the two digits it did get “12” then the first digit that was in the second transmission “1”, making “121”.

    I may be wrong, but it’s hit and miss and sees to be doing something like the above.

    I think it must be somethig stupid tha I have done or overlooked! If someone could help me I would be really realy grateful.

    Code is below.





    Code …

    *  Example for Sparkfun MP3 Shield Library
    *      By: Bill Porter
    *      http://www.billporter.info
    *   Function:
    *      This sketch listens for commands from a serial terminal (like the Serial Monitor in
    *      the Arduino IDE). If it sees 1-9 it will try to play an MP3 file named track00x.mp3
    *      where x is a number from 1 to 9. For eaxmple, pressing 2 will play ‘track002.mp3’.
    *      A lowe case ‘s’ will stop playing the mp3.
    *      ‘f’ will play an MP3 by calling it by it’s filename as opposed to a track number.
    *      Sketch assumes you have MP3 files with filenames like
    *      “track001.mp3”, “track002.mp3″, etc on an SD card loaded into the shield.

    #include <SPI.h>

    //Add the SdFat Libraries
    #include <SdFat.h>
    #include <SdFatUtil.h>
    #include <stdlib.h>     // needed for [shighlight]atoi[/shighlight]

    //and the MP3 Shield Library
    #include <SFEMP3Shield.h>

    //create and name the library object
    SFEMP3Shield MP3player;

    char buffer[3];
    int received;
    byte result;

    int vol = 25;
    char title[30];
    char artist[30];
    char album[30];
    void setup() {


    received = 0;
    buffer[received] = ”;
    //boot up the MP3 Player Shield
    result = MP3player.begin();
    //check result, see readme for error codes.
    if(result != 0) {
    Serial.print(“Error code: “);
    Serial.println(” when trying to start MP3 player”);

    Serial.println(“Send a number 001-255 to play a track or s to stop playing”);


    void loop() {

    if (Serial.available())
    buffer[received++] = Serial.read();
    buffer[received] = ”;
    if (received >= (sizeof(buffer)-1))
    int myInt = atoi(buffer);
    received = 0;

    Serial.print(“Received command: “);
    Serial.println(” “);

    //if s, stop the current track
    if (myInt == 999) {

    else if (myInt >= 001 && myInt <= 800){
    //convert ascii numbers to real numbers
    // myInt = myInt – 48;
    Serial.print(“New myInt: “);
    //tell the MP3 Shield to play a track
    result = MP3player.playTrack(myInt);
    else if (myInt == 998){
    vol = vol-3;
    MP3player.SetVolume(vol, vol); // increase volume
    else if (myInt == 997){
    vol = vol+3;
    MP3player.SetVolume(vol, vol); // decrease volume

    //check result, see readme for error codes.
    if(result != 0) {
    Serial.print(“Error code: “);
    Serial.println(” when trying to play track”);


    //check result, see readme for error codes.
    if(result != 0) {
    Serial.print(“Error code: “);
    Serial.println(” when trying to play track”);







    Your pasted code has an error with buffer[received] = “; but that is likely do the the pasting and not actually in your code. Your issue is about the difference in real time versus slow input. Not sure what the problem is, looks reasonable. but being a realtime problem it needs extensive debugging. I do notice that you may want to employ a delimit, such as a carriage return. i.e. 123<cr>, as to denote the ending and flag for processing the received string. This helps with lining up the messages. There are plenty of discussions out there on adding common delimits and framing. Which is the problem here.

    Where as you can check out the example FilePlayer.ino. Which I created to allow larger serial messages or filenames. Per its notes.

    * This sketch behaves nearly identical to MP3Shield_Library_Demo.ino, but has

    * extra complicated loop() as to receive string of characters to create the

    * file index. As the Serial Monitor is typically default with no CR or LF, this

    * sketch uses inter character time out as to determine when a full string has

    * has been entered to be processed.

    This is basically what you are asking for, where as it is a bit more flexible and so being more sophisticated and complex. It uses Inter character Timeout as to delimit the requested bytes into a Frame. Or file name in this case. Allowing you to send the whole file name. Getting you longer list of files (infinite) you are able to play.




    Hi Michael,

    Thankyou ever so much for your reply. I have just downloaded the code you suggested and have uploaded it to my UNO with the Sparkfun MP3 shield connected.

    I tried using my own files but they weren’t working so I added the 2 demo files you had provide onto th SD card.  When I type “1! into the serial window and press enter, nothing happens. If I type “f track001.mp3” into the window, it starts to play the first second or so of the file but it seems to cut off. If I try playing track 2 using the same method, it still plays track 1 in the same manner a before. Similarly if I use any of the tracks I had previously recorded (e.g. track004.mp3), it still tries playing track 1. If I type just “1” or “2” nothing happens at all.

    I have copied the result from the serial window below that results from typing “f track002.mp3”. Curiously it seems to parse each letter but gives no output identifying the number element of the filename. If you could let me know if I’m doing something crazy I would really appreciate it.



    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: f
    Error code: 1 when trying to play track
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command:
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: t
    Warning Tests are not available.
    Un-Available while playing music or chip in reset.
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: r
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: a
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: c
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: k
    moving = -1000[milliseconds]
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: .
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: m
    Warning Tests are not available.
    Un-Available while playing music or chip in reset.
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: p
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command:

    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :



    Just a quick thought …. I’m still no further forward …. does the code in it’s default state work straight away with an UNO with Sparkfun MP3 shield, or did I need to adjust any of the code first?


    Jay 🙂


    (responding to jayceekey’s email)

    Fileplayer.ino that michael was referring too is in Michael’s branch of the code available here.


    Both MP3Shield_Library_Demo.ino and FilePlayer.ino work out of the box, straight from the download. Where FilePlayer.ino is nearly identical to the original MP3Shield_Library_Demo.ino, except with a more serial flexibility, that may help your desired goal.

    Are you indicating that MP3Shield_Library_Demo.ino works but FilePlayer.ino? doubt it. As above they work out of the box and with identical under structures.

    Your description of the symptoms are consistent with a DREQ interrupt problem. Please refer to the Troubleshooting . Specifically the subsection labeled “Why do I only hear 1 second of music, or less?” (sound familiar)

    You can verify a DREQ interrupt problem by not using interrupts. Change the SFEMP3ShieldConfig.h line 195 to

    #define USE_MP3_REFILL_MEANS USE_MP3_Polled

    rather than USE_MP3_INTx.


    Hi Guys,

    Thankyou ever so much for your help with this 🙂

    I will check out the interrupt change as suggested when I get home tonight.

    In the meantime I have just realised something that may or may not be the issue…..

    If you look at the serial window that I copied and pasted I’ve just realised something. The code consistently plays track001.mp3 and although it stops the track in less than a second, it never resumes from the last played position and any command always plays the first track and never any other that are requested.

    Looking at the serial window I pasted, it is actually parsing the command and acting on each character I type as an individual command rather than as a string i.e. it acts on “f” and gives error code 1 as it doesn’t wait for the remainder of the command (the file name) then each character until it gets to the numbers – which it doesn’t display in the serial window. It then resumes acting on “m”, “p” and “3”.

    It looks to me as if the issue is more in relation to the code  not treating the commands as continuous strings rather than individual letters?

    Sorry if I’m barking up the wrong tree and being dumb lol




    So you must not be using the Arduino’s built in Serial Monitor, as from the sounds of it. Where the IDE’s Serial Monitor does not send each character one at a time, but rather as a whole line.

    The original MP3Shield_Library_Demo.ino only accepts one character at a time and processes each character as individual commands when more than one is sent at once.

    FilePlayer.ino is different in that for numeric digits it delimits it serial input by Intercharacter Timeout, which is 500 ms as in the below line. Grouping the individual digits into a whole integer.

      } else if ((millis() – last_ms_char) > 500 && ( buffer_pos > 0 )) {

    So you are likely typing each character with more than 500ms between them. Causing the ICT to attempt to parse the serial buffer. You can increase the 500ms ICT. Or you can paste the whole command at once. More like the desired Serial.Print would.

    Where as it does not ICT for non digits. Where it still processes them individually.

    Looking at your trace it looks like you were typing: “track.mp3”. That is not the way FilePlayer.ino works.

    Rather you should run the “l” command to

    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    Received command: l
    Music Files found :
    00001: DING.wav
    00002: TRACK001.mp3
    00003: TRACK002.mp3
    Enter Index of File to play
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :

    Where you would enter 00003 to play “TRACK002.mp3”. You don’t type in “TRACK002.mp3”.

    So if you are sending “TRACK.MP3” I believe it is likely parsing each character as a unique command.

    Note also that “f” is a command to play “track001.mp3”.


    Hi Michael,

    Firstly can I say thankyou to you for your patience and advice. I have read your reply and am a little more confused ….

    I totally agree with your view that the code appears to be parsing the information I type rather than dealing with it as continuous string.

    What I don’t understand is how I could have done anything wrong!

    For testing purposes I am not using the second Arduino to send the commands, I am keeping it simple first and using the serial monitor screen. I don;t see how I could be using anything other than the standard USB serial monitor. I’m not running any other code at all.

    I am using a UNO that is loaded with the fileplayer.ino completely unaltered and simply sending commands from the same PC that I used to upload the code, using the serial monitor window set at the required baud rate via USB. I don’t see why it wouldn’t work.

    Incidentally, I tried using the 00003 command previously and I always type –

    f track002.mp3

    rather than 

    track002.mp3 or “track002.mp3”

    – when I have attempted to play a file using the whole file name. I did notice that you use upper case whereas I use lower case as per the files on the SD card. The code doesn’t require upper case file names and commands or something does it?

    Once again I’m so sorry for taking up your time as I know how frustrating it can be to try and talk someone through code remotely when you can’t see exactly what it is they’re doing – hence why I try and be as detailed as I can in my description of the problems.


    All the best,


    Jay 🙂


    ps …. just in case you thought I may have been doing something dumb like typing each character and pressing enter after each letter separately, the entire command is typed at once and sent as a string with only one carriage return.






    With the fileplayer.ino as is, one does not send “f track002.mp3”. Rather one sends a multi-digit enumeration of the filename as discovered by the List “l” command and the Inter-Character Timeout will delimit the command.

    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    [MPF, I sent “l” to List out directory]
    Received command: l
    Music Files found :
    00001: DING.wav
    00002: TRACK001.mp3
    00003: TRACK002.mp3
    Enter Index of File to play
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    [MPF, I sent “003”, to play #3 file from above]
    Index 00003: TRACK002.mp3
    Playing filename: TRACK002.mp3
    [MPF, I sent “s” to stop it]
    Received command: s
    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    [MPF, I sent 002 to play #2]
    Index 00002: TRACK001.mp3
    Playing filename: TRACK001.mp3
    [MPF, I sent 001 to play file #1]
    Index 00001: DING.wav
    Playing filename: DING.wav

    “f” will just simply play track001.mp3.



    Hey Michael,


    Sorry I thought I could trigger th file by typing

    f track001.mp3

    That makes sense then if you can only use th file index!

    Last question then I promise I will stop bugging you LOL ……

    How does the track index get assigned? Is there any way to get it to use e.g. track001 as 00001 and increasing as it goes in a logical way …. mine go up to 200 tracks and for some unknown reason the index jumps around a bit. Pasted then track indexs fter this message.



    00001: TRACK129.mp3
    00002: TRACK003.mp3
    00003: TRACK004.mp3
    00004: TRACK005.mp3
    00005: TRACK006.mp3
    00006: TRACK007.mp3
    00007: TRACK008.mp3
    00008: TRACK009.mp3
    00009: TRACK010.mp3
    00010: TRACK011.mp3
    00011: TRACK012.mp3
    00012: TRACK013.mp3
    00013: TRACK055.mp3
    00014: TRACK056.mp3
    00015: TRACK057.mp3
    00016: TRACK058.mp3
    00017: TRACK059.mp3
    00018: TRACK060.mp3
    00019: TRACK061.mp3
    00020: TRACK062.mp3
    00021: TRACK063.mp3
    00022: TRACK064.mp3
    00023: TRACK065.mp3
    00024: TRACK066.mp3
    00025: TRACK067.mp3
    00026: TRACK068.mp3
    00027: TRACK069.mp3
    00028: TRACK070.mp3
    00029: TRACK071.mp3
    00030: TRACK072.mp3
    00031: TRACK073.mp3
    00032: TRACK074.mp3
    00033: TRACK075.mp3
    00034: TRACK076.mp3
    00035: TRACK077.mp3
    00036: TRACK078.mp3
    00037: TRACK079.mp3
    00038: TRACK080.mp3
    00039: TRACK081.mp3
    00040: TRACK082.mp3
    00041: TRACK083.mp3
    00042: TRACK084.mp3
    00043: TRACK085.mp3
    00044: TRACK086.mp3
    00045: TRACK089.mp3
    00046: TRACK090.mp3
    00047: TRACK091.mp3
    00048: TRACK092.mp3
    00049: TRACK093.mp3
    00050: TRACK094.mp3
    00051: TRACK095.mp3
    00052: TRACK096.mp3
    00053: TRACK097.mp3
    00054: TRACK098.mp3
    00055: TRACK099.mp3
    00056: TRACK100.mp3
    00057: TRACK101.mp3
    00058: TRACK102.mp3
    00059: TRACK103.mp3
    00060: TRACK104.mp3
    00061: TRACK105.mp3
    00062: TRACK106.mp3
    00063: TRACK107.mp3
    00064: TRACK108.mp3
    00065: TRACK109.mp3
    00066: TRACK110.mp3
    00067: TRACK111.mp3
    00068: TRACK112.mp3
    00069: TRACK114.mp3
    00070: TRACK115.mp3
    00071: TRACK116.mp3
    00072: TRACK117.mp3
    00073: TRACK118.mp3
    00074: TRACK119.mp3
    00075: TRACK120.mp3
    00076: TRACK121.mp3
    00077: TRACK122.mp3
    00078: TRACK123.mp3
    00079: TRACK124.mp3
    00080: TRACK125.mp3
    00081: TRACK126.mp3
    00082: TRACK127.mp3
    00083: TRACK128.mp3
    00084: TRACK001.mp3
    00085: TRACK002.mp3
    00086: TRACK014.mp3
    00087: TRACK015.mp3
    00088: TRACK016.mp3
    00089: TRACK017.mp3
    00090: TRACK018.mp3
    00091: TRACK019.mp3
    00092: TRACK020.mp3
    00093: TRACK021.mp3
    00094: TRACK022.mp3
    00095: TRACK023.mp3
    00096: TRACK024.mp3
    00097: TRACK025.mp3
    00098: TRACK026.mp3
    00099: TRACK027.mp3
    00100: TRACK028.mp3
    00101: TRACK029.mp3
    00102: TRACK030.mp3
    00103: TRACK031.mp3
    00104: TRACK038.mp3
    00105: TRACK039.mp3
    00106: TRACK036.mp3
    00107: TRACK032.mp3
    00108: TRACK033.mp3
    00109: TRACK037.mp3
    00110: TRACK035.mp3
    00111: TRACK034.mp3
    00112: TRACK040.mp3
    00113: TRACK041.mp3
    00114: TRACK042.mp3
    00115: TRACK043.mp3
    00116: TRACK044.mp3
    00117: TRACK045.mp3
    00118: TRACK046.mp3
    00119: TRACK047.mp3
    00120: TRACK048.mp3
    00121: TRACK049.mp3
    00122: TRACK050.mp3
    00123: TRACK051.mp3
    00124: TRACK052.mp3
    00125: TRACK053.mp3





    The code is an example, meant to demonstrate features and was purposed to be as flexible as possible. Where my implementation wanted to be able to play and infinite list other files, beyond that of track0000.mp3. Hence the play and list feature simply sequence through the openNext of the SdCard, displaying all playable files with matching *.ext.

    fileplayer.ino Line 372:

    while (file.openNext(sd.vwd(),O_READ))
    if ( isFnMusic(filename) ) {
    SerialPrintPaddedNumber(count, 5 );
    Serial.print(F(“: “));

    I would expect the list and its corresponding enumerations should be consistent, as the openNext(), is sequencing through the SdCard’s FAT entries. Which should not change, unless you add files to it. Which won’t be something you do often, or on the fly at least. So I suspect you can manually list out the playable files with the “l” command and go with that list, until you change things. At which time you could check it again.

    That all said. There is nothing preventing you from changing the code (it is an example) to fit your own needs. where you can change the below section to your needs.

    fileplayer.ino Line 173:

    while (file.openNext(sd.vwd(),O_READ))
    if ( isFnMusic(filename) ) {

    if (count == fn_index) {
    Serial.print(F(“Index “));
    SerialPrintPaddedNumber(count, 5 );
    Serial.print(F(“: “));
    Serial.print(F(“Playing filename: “));
    int8_t result = MP3player.playMP3(filename);

    I recall your original problem is that you wanted to play a specific track, but not limited to 0-9 tracks. and were having problems with multi digit characters being sent and received. You can remove the above while (file.openNex… file.GetFilename and if( isFnMusic… and replace filename with a construction of your choice, similar to what happens at lines.

    The fileplayer.ino can help that. Where it was developed for a more general application. The features of ICT or delimiting can be re-used, by stream lining/hacking to better fit your needs.

    Ahh, screw it. I just made it and posted it here on GISTHUB  trackplayer-ino

    This should do what you want. Simply send in 1, 01, 001, 0001 or o0001 to play TRACK001.MP3. Same for 02 to play TRACK002.MP3 and so on. Where you need to make sure your sender has at least 500ms pause between numbers or commands.

    Diff TrackPlayer.ino and FilePlayer.ino to see the differences as mentioned above.

    If you don’t want the 500ms then, you can change the code to remove the ICT and use something like CR/LF as the delimit to queue parsing.


    Try FileNamePlayer.ino on my GISTHUB

    It should be just what you are looking for.

    Although take note that the Arduino IDE Serial Monitor sends out a few bytes of garbage, that may cause a little of confusion.

    This sketch listens for commands from a serial terminal which are TERMINATED with New Line Feeds (aka “\n” or 0xA). To use this sketch enable Serial Monitor to use NewLine’s.
    If the Serial message is 1 byte in length and terminated by LF, the byte will be processed as menu command.
    If the Serial Message is larger than 1 byte it will assumed a FileName and that file will be attempted to be played. Note the max length of string is 8.3 or 11 bytes long.

    So with this you can send the actual filename exactly as seen in the listing.

    Enter 1-9,f,F,s,d,+,-,i,>,<,p,r,R,t,m,M,g,k,h,O,o,D,S,V,l,01-65534 :
    [MPF: I sent “TRACK001.mp3” + LF using Serial Monitor]
    Received > “TRACK001.mp3”
    Playing = TRACK001.mp3

    You can still send commands such as “s” to stop but they too need to be “s”+<LF>


    Hi Michael,

    Thankyou ever so much for all your help – you are a total legend!

    I tried the trackplayer.ino code you kindly wrote and it works absolutely perfectly and does exactly what I wanted.

    I really appreciate the time you took to help me!


Viewing 15 posts - 1 through 15 (of 16 total)
  • You must be logged in to reply to this topic.