Home › Forums › Sparkfun MP3 Shield Library Support Forum › Triggering mp3 file over serial
- This topic has 15 replies, 3 voices, and was last updated 11 years, 5 months ago by Michael P. Flaga.
-
AuthorPosts
-
April 2, 2013 at 2:03 pm #2351AnonymousInactive
Hi,
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.
Thanks
Jay
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() {Serial.begin(9600);
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.print(result);
Serial.println(” when trying to start MP3 player”);
}Serial.println(“Hello”);
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))
{
Serial.print(buffer);
int myInt = atoi(buffer);
received = 0;Serial.print(“Received command: “);
Serial.write(myInt);
Serial.println(” “);//if s, stop the current track
if (myInt == 999) {
MP3player.stopTrack();
}else if (myInt >= 001 && myInt <= 800){
//convert ascii numbers to real numbers
// myInt = myInt – 48;
Serial.print(“New myInt: “);
Serial.print(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.print(result);
Serial.println(” when trying to play track”);
}}
//check result, see readme for error codes.
if(result != 0) {
Serial.print(“Error code: “);
Serial.print(result);
Serial.println(” when trying to play track”);
}
}}
delay(10);
}
April 2, 2013 at 3:43 pm #2352Michael P. FlagaMemberYour 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.
April 4, 2013 at 2:17 pm #2358AnonymousInactiveHi 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.
Cheers,
Jay
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
Pausing
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 :
April 7, 2013 at 3:43 am #2369AnonymousInactiveJust 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?
Cheers,
Jay 🙂
April 8, 2013 at 4:37 pm #2374BillMember(responding to jayceekey’s email)
Fileplayer.ino that michael was referring too is in Michael’s branch of the code available here.
April 8, 2013 at 9:34 pm #2375Michael P. FlagaMemberBoth 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.
April 9, 2013 at 12:43 am #2380AnonymousInactiveHi 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
jay
April 9, 2013 at 12:46 pm #2383Michael P. FlagaMemberSo 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”.
April 9, 2013 at 1:44 pm #2384AnonymousInactiveHi 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 🙂
April 9, 2013 at 1:47 pm #2385AnonymousInactiveps …. 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.
Cheers,
Jay
April 9, 2013 at 3:20 pm #2386Michael P. FlagaMemberWith 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
by:
Album:
[MPF, I sent “s” to stop it]
Received command: s
Stopping
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
by:
Album:
[MPF, I sent 001 to play file #1]
Index 00001: DING.wav
Playing filename: DING.wav“f” will just simply play track001.mp3.
April 9, 2013 at 3:31 pm #2387AnonymousInactiveHey 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.
Cheers,
J
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.mp3April 9, 2013 at 6:13 pm #2388Michael P. FlagaMemberThe 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))
{
file.getFilename(filename);
if ( isFnMusic(filename) ) {
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(“: “));
Serial.println(filename);
count++;
}
file.close();
}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))
{
file.getFilename(filename);
if ( isFnMusic(filename) ) {if (count == fn_index) {
Serial.print(F(“Index “));
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(“: “));
Serial.println(filename);
Serial.print(F(“Playing filename: “));
Serial.println(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.
April 9, 2013 at 8:40 pm #2389Michael P. FlagaMemberTry 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.mp3You can still send commands such as “s” to stop but they too need to be “s”+<LF>
April 11, 2013 at 3:40 am #2390AnonymousInactiveHi 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!
Jay
-
AuthorPosts
- You must be logged in to reply to this topic.