Pages: 1 [2] 3 4   Go Down
Author Topic: Created a library for the MDFLY MP3 module (TDB380)  (Read 6927 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:

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.


Code:
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.
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You forgot to post your code.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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);
  }


Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 !
Logged

Greenville, IL
Offline Offline
Edison Member
*
Karma: 15
Posts: 1328
Warning Novice on board! 0 to 1 chance of errors!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@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.

Code:
/*
 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);
}
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


* MP3 hack 004.jpg (172.2 KB, 612x816 - viewed 54 times.)

* MP3 hack 003.jpg (1501.46 KB, 3264x2448 - viewed 44 times.)
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?>
Logged

Offline Offline
God Member
*****
Karma: 27
Posts: 829
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Pages: 1 [2] 3 4   Go Up
Jump to: