Created a library for the MDFLY MP3 module (TDB380)

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.

Further checks reveal a software problem (surprise surprise). The sketch works OK when I have a pushbutton on pin 2 . The problem has occurred when I have used my newly acquired PIR detector and connected its signal pin in place of the pushbutton. I assumed it would behave exactly the the same. Obviously not … I need to write some sketches for the PIR to see how it works !

@DavidFMarks you might see some bouncing?

DID WONDER ABOUT THAT BUT THE SKETCH HAS AN ANTIBOUNCE BIT IN IT.

I have now got my mp3 player working nicely .. thanks for the help. I have now set up a servo operated jaw movement which I want to run concurrently with the playing of the mp3 file, but don’t seem to be able to do it. I thought that if I called play and then a few servo movements that the file would start to play and continue whilst the servo operates but it doesn’t. The servo starts to move then the file starts to play and is almost immediately interrupted by the next servo movements. Any suggestions would be appreciated.

The file stops playing when the servo moves? May be a timer conflict. Can I see your code?

Hi again, Here is the code (I am enclosing it in square brackets which I hope is correct (the help file is down at the moment)
[
#include <serMP3.h>
#include <Servo.h>
Servo VerticalEyes; // Define our Servo
Servo RightEyeHorizontal; // Define our Servo
Servo LeftEyeHorizontal; // Define our Servo
Servo Mouth; // Define our Servo

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); //instance of mp3 library

unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers

int n=1; // n defines the file number to be played

void setup()
{
VerticalEyes.attach(10); // servo connected to digital pin 10
RightEyeHorizontal.attach(9); // servo connected to digital pin 9
LeftEyeHorizontal.attach(8); // servo connected to digital pin 8
Mouth.attach(7);
pinMode(buttonPin, INPUT); //set pin 2 to input
MP3.begin(31);
Serial.begin(9600);
Serial.write(0xEF);
Serial.write(0xE0);
Mouth.write(100);
}

void loop()
{
int reading = digitalRead(buttonPin);
if (reading != lastButtonState)
{
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay)
{
buttonState = reading;
}
if (buttonState == HIGH) // if button press is genuine
{
n=14; // set number of file to be called

Playfile(n); // then call it

int hpos=90; // define position of horizontal eye servos
REye(hpos); // call Reye function and move servo to defined position
LEye(hpos); // call Leye function and move servo to defined position
int vpos=135; // define position of vertical eye servo
VertEyes(vpos); // call VertEyes function and move servo to defined position
}
lastButtonState = reading;
delay(150);
}
void Playfile(byte n) // define playfile functio
{

MP3.play(n);
delay(150);
Mouth.write(100);
delay(300);
Mouth.write (70);
delay(200);
Mouth.write(100);
Mouth.write(100);
delay(300);
Mouth.write (70);
delay(200);
Mouth.write(100);
Mouth.write (70);
delay(200);
Mouth.write(100);
Mouth.write(100);
delay(300);
Mouth.write (70);
delay(200);
Mouth.write(100);
}
int VertEyes(int vpos) // Define VertEyes function
{
VerticalEyes.write(vpos);
}
int REye(int hpos) //Define REye function
{
RightEyeHorizontal.write(hpos);
}

int LEye(int hpos) //Define LEye function
{
LeftEyeHorizontal.write(hpos);
}

]

It should be

[ code ] your code goes here [ /code ]

Without the spaces of course. Or just click on the # symbol at the start of your code and then again at the end.

Aha ! Thanks, sorry to clutter the place up !

I can't see anything in your code that would cause that behavior. I just checked my library and I am not using a timer (I coulldn't remember), so it's not that either. My guess would be that somehow it is reading your switch as changing states somehow. How are you pulling it up? Noise from the servos might be triggering it perhaps.

I do see a few pieces in your code you should look at. Nothing that would cause your issue, but thought I would mention them:

void setup()
{

  Serial.write(0xEF); // ********I assume you meant to send these to the MP3 module
  Serial.write(0xE0); //*********if so, they should be mp3.send(0xE0) (or MP3.stop())
 }
void Playfile(byte n)
{
  
  
  MP3.play(n);
  delay(150);
   Mouth.write(100);
   delay(300);
   Mouth.write (70);
   delay(200);
   Mouth.write(100);
   Mouth.write(100); //Did you really mean to call that twice?
   delay(300);
   Mouth.write (70);
   delay(200);
   Mouth.write(100); //I may be wrong, but I doubt you will see it do anything but move to 70
   Mouth.write (70);
   delay(200);
   Mouth.write(100);
    Mouth.write(100); //twice again
   delay(300);
    Mouth.write (70);
   delay(200);
   Mouth.write(100);  
}

In the instances were you call mouth.write(100) twice right away, I don't really understand why. Also, when you call 100 and 70 back to back, it probably is only going to move to 70 (unless I don't understand something about the servo library.)