Created a library for the MDFLY MP3 module (TDB380)

Thanks for sharing,

Some minor remarks on the lib

void serMP3::begin(uint8_t vol)
{
	delay(3);  // is this really needed??????
	setVol(vol);
	delay(5);
	stop();
}
bool serMP3::busy()    // just busy 'reads/sounds' better in an if or while statement if (!busy()) or while(busy())
{
	return (digitalRead(_bsyPin) == HIGH);
}

further you could consider making small functions inline (directly in the .h file) to reduce the footprint of sketches.
(send must be public ?)

	inline void stop() { send(239) };
	inline void pause() { send(234) };
	inline void volUP() { send(232) };
	inline void volDN() { send(233) };

Great suggestions. The delay was needed at least on mine. It takes a moment for the module to respond. Before I added it, the volume was not getting changed. Someone may experiment with removing it and see if works for them.

I will make the other changes that you suggested. Especially the inline functions. I hadn't known how to do that before. Very useful.

Yep, Gnd was connected to module and arduino. Think its time to go back to the real serial and see if it still works with that or if I've done something really daft !

Tried using pin 1 to tx and 2 as busy with the following sketch to test the module
[const int busyPin = 2; // the number of the Busy pin

void setup() {
// initialize the serial communication:
Serial.begin(4800); //Set to 4800 bps
Serial.write(0xEF); // Reset board
delay(2000);
pinMode(busyPin, INPUT);
}

void loop(){
if (digitalRead(busyPin) ==LOW) {
//device busy
}
else {
Serial.write(0); // Play Random file
delay(5000);
}
}]
The result was to play one of the files at full volume. when I recompile and run it plays the same file at greatly reduced volume and if I change the file number it plays the same file again at reduced volume. Whilst I don't expect people to spend too much time on my problem If there is an obvious error here I would like to know what it is !

Nearly there ! The main problem appears to be the volume. The data sheet seems to be wrong. The +volume pin is shown as pin 9 when it seem to be grounding pin 10 that increases the volume. I now have to sort out how to get the files in the right order and then how to call them from within my sketch rather than via the serial monitor ! still at least we seem to be winning. Thanks for your patience and help.

As for the volume, I found that the module does not start up at full volume. That is why I put the volume setting in my .begin method so that you can set it at intialization. If you are looking at the MDFly datasheet, it is missing some of the commands.

You set the volume by writing C8-E7 (200-231). 231 being full volume. So in your setup() put Serial.write(231) to start up with full volume.

EF is not technically a reset. It is STOP. I put that in my code because the module sometimes starts up randomly playing an MP3. Using 0 to play a random file was silly in my opinion.

So, try this:

void setup(){
   Serial.begin(9600);
   Serial.write(0xEF); //Stop playing
   Serial.write(0xE0); //Set the volume just below full volume
}

It seems like your module is either just playing a random file at startup and your loop isn't working because the busy signal is active, or it only sees one file on the card for some reason.

I don't see anything wrong with your code (assuming you are changing the number from 0 for the file you want to play). BTW, you could snag the serial parsing part of my example code and just replace the calls with Serial.write commands if you wanted to try out all the features.

void loop(){
  byte sc = 0;
  unsigned long number = 0;
  byte n =0;
  
  if(Serial.available()){
    sc = Serial.read();   
  }
  
  if(sc == 'p' || sc == 'P'){ //Play (001-199)
    number=Serial.parseInt();
    n = byte(number);
    if(n > 0 && n < 200){
     MP3.play(n);
    }

    else {
      Serial.println("Error: Use a value 1 - 199);
    }
  }

  if(sc == 's' || sc == 'S'){ //Stop Playing
    Serial.write(0xEF);
  }

  if(sc == '+'){ //Voume Up
    Serial.write(0xE8);
  }

  if(sc == '-'){ //Volume Down
    Serial.write(0xE9);
  }

  if(sc == 'v' || sc == 'V'){ //Set Volume (01-31)
    number=Serial.parseInt();
    n = byte(number);
    n = n + 200;
    if(n >= 0 && n < 32){
    Serial.write(n);
    }
    else {
      Serial.println("Error: Use a value 0 - 31);
    }
  }

  if(sc == 'f' || sc == 'F'){ //Change Directory (01-15) 01 is root
    number=Serial.parseInt();
    n = byte(number);
    n = n + 240;
    if(n > 240 && n < 256){
    Serial.write(n);
    }
    else{
      Serial.println("Error: Use a value 1 - 15);
    }
  }

  if(sc == '*'){ //Play a random file (will switch back to the root folder! Only plays from root folder)
   Serial.write(0x00);
  }

  if(sc == '/'){ //Pause/Resume
   Serial.write(0xEB);
  }
}

No promises that there isn't a typo in there.

If it is working with the serial port, it should be working with my library. The only thing my library is doing mainly is emulating the Tx portion of a standard serial port at 4800 baud. I used code directly from the SoftwareSerial library to do that part.

Everything else is just formatting numbers to make it easier to understand, and doing some error checking.

Nothing wild going on with it.

Everything seems to be working ok now. (My grumpy scarecrow is grumbling away nicely now !) Only two things puzzle me.
Using the code below I am surprised that after the function Playfile is executed that it does not return to the main loop and then repeat.
Also when I upload the program it initially plays the file (n)which was set previously. Only when I run for the second time does it use the new value of (n).
Any comments would be appreciated.

You forgot to post your code.

Oh dear, Matron isn't going to let me out soon. Here's the code !
#include <serMP3.h>

serMP3 MP3(11,10);
const byte n=1;
void setup(){

MP3.begin(31);
Serial.begin(9600);
Serial.write(0xEF);
Serial.write(0xE0);

}

void loop(){
Playfile(n);
}

void Playfile(byte n)
{
MP3.play(n);
}

DavidFMarks:
Oh dear, Matron isn't going to let me out soon. Here's the code !
#include <serMP3.h>

serMP3 MP3(11,10);
const byte n=1;
void setup(){

MP3.begin(31);
Serial.begin(9600);
Serial.write(0xEF);
Serial.write(0xE0);

}

void loop(){
Playfile(n);
}

void Playfile(byte n)
{
MP3.play(n);
}

I'm not sure if this is your entire code, but you do realize that you are telling it to constantly and continually attempt to play the MP3 over and over regardless of whether it is already playing, right? Perhaps the reason it is not working is because you are flooding the serial buffer. Loop will run repeatedly executing that Playfile(n) over and over again every couple of microseconds.

What is it that you are trying to accomplish here and I can help adjust your code?

BTW, working on a hardware mod to this module that will allow me to access the SD card directly so that I can read other files from the card (but not while an MP3 is playing of course.) I am seriously condiering designing my own module which handles all the FAT stuff, the MP3 stuff, etc... while allowing direct access to files. Similar to the way the VMUSIC2 module works, but letting me use microSD cards instead.

It seems that every MP3 module I find out there just doesn't do what we really need it to do. Which, for me anyway, is to play specific MP3s without any real overhead to the microcontroller, allow FAT access without any overhead to the micro, and allow me to access other files on the card. Again, the VMUSIC2 does do all this, but it only works for USB sticks. I want something that uses SD or microSD.

I have been playing around with directly controlling an SD card and MP3 chip with the arduino, but it requires so many of the pins, so much of the resources, all the RAM, and such huge code size, that you can't really do anything else BUT make an MP3 player out of it.

If someone knows of a module that exists that does all of that already and doesn't cost a bazillion dollars, I would love to hear about it!

Yes, that is all of the code ! I rather thought I might be in a continuous loop (As you can see I am in the early stages programming the arduino and am still struggling with some basic concepts .. like how top break out of the continuous loop !) What I am trying to achieve is a routine that I can call from within a program which is , for example controlling servo motors.
I am trying therefore to learn how to set up a function which I can call from the body of the program which will play a specified file and then return to the program.For instance if I write a piece of code that runs a servo to turn my scarecrow's eyes to the right, it can make an appropriate comment or if the PIR detector I have just obtained detects someone the program can again call an appropriate (or perhaps even a innapropriate !) remark. The main problem is that despite reading books/articles etc. my aged brain has somehow not grasped this concept of a continuously looping program and how to make it stop or jump out of it after executing one operation , all of which I am sure must be very simple !

@DavidFMarks

If you put Playfile(n); in the set-up it will only be called once during set-up. I took your sketch and did just that. I then used the Debounce example to add a button that calls Playfile(n) when the button is HIGH. You could make it call Playfile(n+1) if you wanted to advance the player to the next MP3.

I hope this is helpful, this code is untested and may need some adjustments to fit your needs.

/* 
 Debounce
 
 Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 a minimum delay between toggles to debounce the circuit (i.e. to ignore
 noise).  
 
 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached from pin 2 to +5V
 * 10K resistor attached from pin 2 to ground
 
 * Note: On most Arduino boards, there is already an LED on the board
 connected to pin 13, so you don't need any extra components for this example.
 
 
 created 21 November 2006
 by David A. Mellis
 modified 30 Aug 2011
 by Limor Fried
 
 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Debounce
 */
////// set pin numbers:////////////////////////
const int buttonPin = 2;     // the number of the pushbutton pin 
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

serMP3 MP3(11,10);

/////////////////////variables////////////////////
// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

const byte n=1;

void setup(){
  pinMode(buttonPin, INPUT);
  MP3.begin(31);
  Serial.begin(9600);
  Serial.write(0xEF);
  Serial.write(0xE0);
  Playfile(n); /// set-up gets called one time, this will be called only once
}

void loop(){
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState)
  {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 

  if ((millis() - lastDebounceTime) > debounceDelay) 
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }

  // Call Playfile(n) using the state of the button:
  if (buttonState == HIGH)
  {
    Playfile(n);
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;   
}

void Playfile(byte n)
{
  MP3.play(n);
}

Thanks for that. I think I'm beginning to see some daylight. More tinkering required tomorrow !

DavidFMarks:
Yes, that is all of the code ! I rather thought I might be in a continuous loop (As you can see I am in the early stages programming the arduino and am still struggling with some basic concepts .. like how top break out of the continuous loop !) What I am trying to achieve is a routine that I can call from within a program which is , for example controlling servo motors.
I am trying therefore to learn how to set up a function which I can call from the body of the program which will play a specified file and then return to the program.For instance if I write a piece of code that runs a servo to turn my scarecrow's eyes to the right, it can make an appropriate comment or if the PIR detector I have just obtained detects someone the program can again call an appropriate (or perhaps even a innapropriate !) remark. The main problem is that despite reading books/articles etc. my aged brain has somehow not grasped this concept of a continuously looping program and how to make it stop or jump out of it after executing one operation , all of which I am sure must be very simple !

With a microcontroller, all code is run sequentially, step by step. The only exception to that rule are interrupts. So your main loop would consist of checking things, testing things, etc.. Your separate functions for different stuff you want to do upon a events would be outside of the loop. So, in your example... your main loop would keep checking the ultrasonic sensor and when it meets whatever conditions you set, you call the functions you want to run. When the function is done, it returns to the loop. If you look in my example code, the loop is checking for serial commands. When it gets something, it pases it by figuring out exactly what was entered. Then on a match, it calls the different functions. If there are no serial commands, it just loops until there is.

No success so for with the mod. I have attached pictures. I am not really sure why it isn't working. I will take another stab at it soon.

Bascially I just removed the network resistors going to pins 1-4 and wired up a 74HC244 buffer between those pins and the SD card socket. Right now I have the OE signal tied to ground, but if I can get it working, I will break that out so I can tri-state the buffer so that it doesn't interfere with the module when I am not accessing the card with the arduino.

Almost working now! I can nominate a file (set value of n) within the program and it plays the appropriate file (after I have used drivesort to get them in the right order). Trouble now is that when the file plays, sometimes it plays in full (about 4 seconds) and sometimes it cuts short. I thought perhaps the trick would be to use checkBsy() in the sketch but every attempt to use it tells me that it has not been declared. I thought that the play command would cause a file to play to the end. Is this not the case ?>

Yes. I have never experienced that issue. Is it possible that your MP3 is corrupted? What's especially odd is nearly every behavior you have described just keeps coming back to a GND not connected between the Arduino and the module. Unless you are 100% certain, I would suggest measuring this connection to make sure it is not broken.

The not being declared part. Are you spelling it correctly?

BTW, this is the only thing that checkBsy is doing. No reason you couldn't do the same thing in your code without calling the function. The only real reason I have it in there was for my library to use it. Not really any advantage to using it in your code versus just using digitalRead(bsyPin);

But anyway, that shouldn't have anything to do with why your MP3 is stopping short. The only reasons I can think of for that to happen is if the file is corrupt and the module crashes out of playback or it received (or thought it did) an overriding command. A GND issue would make things really unstable and cause the module to hiccup. I had all the issues you have described happen to me whenever I forgot to connect the grounds together.