DFPlayer detect when song is done playing

I'm using the DFRobotDFPlayerMini lib to drive my board.
and i'm trying to detect when a song is done playing, to start a new song or action.

I've tried myDFPlayer.readState() and myDFPlayer.readType() != DFPlayerPlayFinished
but the first pass will run okey but then it goes wrong

this is the code i have at the moment:

bool playSong(int song){
myDFPlayer.play(song + 1); //Play the first mp3
myDFPlayer.start();
delay(50);
myDFPlayer.available();
delay(50);
Serial.print("state[START]: ");Serial.println(myDFPlayer.readState());
// Wait untill file is done playing
Serial.print("Waiting");

//while( myDFPlayer.readType() != DFPlayerPlayFinished ){
while( myDFPlayer.readState() > 500 ){
Serial.print(".");
//printDetail(myDFPlayer.readType(), myDFPlayer.read());
Serial.print("**.state: ");Serial.println(myDFPlayer.readState());
myDFPlayer.available();
delay(100);
}
Serial.println(" ");
delay(100);
Serial.print("state[DONE]: ");Serial.println(myDFPlayer.readState());
Serial.println(F("Song is done playing"));
//myDFPlayer.pause();
Serial.print("state[PAUSE]: ");Serial.println(myDFPlayer.readState());
return true;
}

After 24hours of trying i have to call i some help...
Can someone please help me.
I'm probably doing something stupidly wrong or going about it in a totally wrong way.

When posting code we need to see it all not just little bits. We also want it in code tags, that is the </> icon top left.

Was there ever any resolution on this?

I too am looking for a rock solid/stable way to detect

I'm not clear if using readState() or readType() or some mixture of both and a track# is best? But I either cant get it to work at all... or if it 'does' register the track is complete and starts to loop the next track.. it seems to be erroneous as the first track is cut short, and the never audio (loop) starts.

Summary of what I'm attempting.

Upon power on..
play a boot up sound (001.wav)
waits/listens for button press/state
when the button is pressed down, it plays 002.wav file..
*** if by the time 002.wav file is done playing.. and the button is STILL pressed, .. automatically start to loop 003.wav file.***
when the button is released play 004.wav file.

Maybe its my implementation?

//import needed libraries
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"


//project vars
const int buttonPin = 19; //Pin (A5) the pin that the pushbutton is attached to
int buttonState = 0; // current state of the button
int lastButtonState = 1; // previous state of the button
boolean doCompletionCheck = false;

//FSM state control/vars
#define S_IDLE 1
#define S_POWERON 2
#define S_POWERDOWN 3

//FSM init vars
static int state = S_IDLE; // initial state is 1, the "idle" state.

//instantiate class instances
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX (DFPlayer connections)
DFRobotDFPlayerMini myDFPlayer;

void setup() {

  //debug (monitor)
  Serial.begin(115200);

  //talk to DFPlayer
  mySoftwareSerial.begin(9600);

  //declare pin & state
  pinMode(buttonPin, INPUT); // initialize the button pin as a input
  digitalWrite(buttonPin, HIGH); //use interal pull up resistors

  //check on DFPlayer state (ready for use?)
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true); //keep checking,...repeat
  }
  Serial.println(F("DFPlayer Mini online."));

  //why?
  myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms

  //----Set volume----
  myDFPlayer.volume(9);  //Set volume value (0~30).
  Serial.print(F("CURRENT VOLUME: ")); //read current volume
  Serial.println(myDFPlayer.readVolume()); //read current volume

  //----Set different EQ----//
  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);

  //----Set source device, we use SD as default----//
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);

  //play boot sound on power-up
  myDFPlayer.play(1);

  Serial.print(F("INTIT STATE: "));
  Serial.println(state);

  //delay to let boot sound play and start 'listening' for interaction
  delay(3000);
}

void loop() {

  //FSM state listener
  switch (state) {
    case S_IDLE:

      //check main button state
      buttonState = digitalRead(buttonPin);

      //** button state HAS changed (compare) **//
      if (buttonState != lastButtonState) {
       
        //-- button state changed and is: pressed (ie: down) --//
        if (buttonState == LOW) {
         
         //any time button is pressed down, trigger power on sound
          state = S_POWERON;

         
        //-- button state changed and is: not pressed (ie: up) --//
        }else {       
             
          //any time button is released, trigger power down sound     
          state = S_POWERDOWN;
                         
        }       

      //** button state has NOT changed  **//     
      }else{
               
        //check if -still- pressed
        if(buttonState == LOW) {
                   
         if(doCompletionCheck == true){     
            Serial.println(F("watching audio file for completion"));     
           
            //dedicated function attempt for checking track completion
            trackComplete(2, 3, 'l');             
           
            /*
            if(myDFPlayer.readType()==DFPlayerPlayFinished && myDFPlayer.readCurrentFileNumber()==2) { 
              Serial.println(F("audio finished..."));
             
              myDFPlayer.loop(3);
              doCompletionCheck = false;
            }
            */
          }

                                   
        }else{
          //Serial.println(F("BUTTON STILL -NOT- PRESSED........ "));   
        }
      }

      //update/save the current button state for next loop/cycle
      lastButtonState = buttonState;
    break;

    case S_POWERON:
      //play power up     
      myDFPlayer.play(2);     
      doCompletionCheck = true;     
     
      //return to button checking
      state = S_IDLE;
    break;

    case S_POWERDOWN:     
      myDFPlayer.play(4);
     
      //return to button checking
      state = S_IDLE;   
    break;
  }

}

//playMode options: p = play or l = loop
void trackComplete(int currTrack, int newTrack, uint8_t playMode) {  
  if(myDFPlayer.readType() == DFPlayerPlayFinished && myDFPlayer.readCurrentFileNumber() == currTrack) {
  //if(myDFPlayer.readState() != 513) {   
    //stop calling this function in IDLE loop
	doCompletionCheck = false;

    switch (playMode) {
      case 'p':
        myDFPlayer.play(newTrack);
      break;

      case 'l':
        delay(800);
        myDFPlayer.loop(newTrack);
      break;     
    } 
     
  }
  //back to button checking
  state = S_IDLE;
}

This and the loud speaker POP upon power on/off are the last two obstacles for me here...

Any advice is appreciated.

Thanks!

Just to the last point (pop upon on/off):
DFPlayer MP3 module - high quiescent power consumption and clicks when power applied and removed - FIX!

@uxomm

Nice link.

Thanks.. (too bad it doesnt have any pics!)..

Have you done this mod yourself?

Wondering if something else can be done instead of directly mod'ing each board. :frowning:

Still going to check it out though! (thanks again)

@xl97
No, I have not done this mod myself yet.
I have been using DFPlayers for some projects in the past ("audio objects" for exhibitions). The pop upon on/off has never been a real problem so far. But I kept this link on my list "DFPlayer useful hints". Maybe some day...
I's a pitty that there are no pictures.
If you check it out, please let us (the forum) know the results.
Would be happy to add a new line to the list. :slight_smile:

^ SPAM. (bot).... and has no bearing on the OP..

(Moderator removed spam)

Just an update: while look like similar post/thread.. the comment(s) hold some more info.

Im not clear though.. do you still need to move the resistor or not? remove anything (must have missed this previously?)

  • so basically remove the 0R resistor from side and put it on the other? (thats it?) hmm...

eqsone said:
Dude, you rock! The white noise on 'pause' was about to drive me crazy. I found that Pin1 and 'Busy' can simply be connected by just shorting the two open solder-pads on the other side next to the 8002. The removed resistor will fit straight in, a drop of solder will do too. Thank you so much for this point out!
Side note:

I got a second batch of DFPlayers in... must be knock offs..

The led are RED this time..original batch had blue leds.... they also DO NOT work with my current sketch. (I'm not sure what part yet.. but I think its the disableLoop() and enableLoop() functions.. that 'kill it'..

it will boot, and it will play the initial 'boot sound'.. but it will NOT play anything upon button press.. (havent dug any deeper into these new ones yet)..

Anyone know HOW to check the current version/firmware? And more so.. how to update it?

another fun update:

So even the pics of the items on ebay show it with 0R resistor in the correct place!!

But neither of the batches I have purchased have them in the correct spot!!!! (and some dont even look to have the most current firmware!!)

This some INSANE quality control! LOL

In the German-speaking part of the forum, a guy discovered more noise after the modification (this thread). though no more pops... :o

Thanks.. I posted there as well.. hoping to get a video of this 'noise' it introduced.

I'm not clear HOW though?

From what I understand.. that resistor mod (swapping to the other side of the amp to the open pads).. is how it is/was SUPPOSED to come/be assembled?

Some of the ebay pics even show it on the left side (after mod side).. while the boards you actually receive show it on the right? (has anyone ever gotten one with it on the left from the factory I wonder?)

I will try it on one of the extra I have this weekend... (cant hurt.. been all over the board with these things already)

  • cant get an accurate reading of a file if using .play(#)
  • cant play a single once, and switch to a loop(#) command without sometimes getting the initial file caught in a 'loop' (like the boards internal file pointer is not fast enough or gets messed up)
  • cant use Neopixels - even if you write non-blocking code (Neopixels disable interrupts that serial comm needs)
  • one batch of boards has some OLD firmware (or something) that will NOT work with the latest DFRobot DFPlayer library!!!!
  • all boards have a loud POP/CRACK when powered on/powered off.. (0R amp resistor apparently placed on the wrong side of things.

xl97:
[/i]Side note:

I got a second batch of DFPlayers in... must be knock offs..

The led are RED this time..original batch had blue leds.... they also DO NOT work with my current sketch. (I'm not sure what part yet.. but I think its the disableLoop() and enableLoop() functions.. that 'kill it'..

it will boot, and it will play the initial 'boot sound'.. but it will NOT play anything upon button press.. (havent dug any deeper into these new ones yet)..

I'm experiencing exactly the same issue with these modules. They are definitely two different kinds.

The good "blues" use this chip : YX5200-24SS
The bad "reds" use this one : AA1746CJ1U6H1-94

Looks like the reds are a knock off using a cheaper main chip. I couldn't find any data on it where as the YX5200 data sheet is available.

I also found it's the loop functions that do not work correctly. It may be a timing issue or even a different command set, but without a data sheet for the knockoff device it's impossible to tell.

The only clue to tell which one you're ordering seems to be to look closely at the picture of the device. The "blues" (good) have "MP3-TF-16P" written on the top and screen printed white squares around the components, while the "reds" (bad) have "DFPlayer Mini" written on the top and no screen print around the components.

As I had 50 bad ones in a batch I've had to modify my code to get around the loop issue (not nice) so as not to waste them.

Stay away from the red devices people!

Nice find on the bogus chip name.

I can confirm all of the 'tell-tale' signs you noted:

  • red led

  • lack of silkscreen around components

  • on my particular batch, they had the numbers on the chip etched off.

I had even asked about this and they 'assured' me they have great quality control and all chips and genuine.

(lies)..

I already got my money back.

Did your boards have the bogus chip name still intact? (or how did you know the fake chip model?)

Oh - different chipsets :o
Interesting!
So I had luck so far. Always had those boards with the blue LED - so far.

@uxomm -

Did you get any updates about the loud speaker 'pop' upon power on/off has been addressed (using the stock DFRobot library at least)..

I posted/updated a few threads about a tip one of the other members mentioned. (There is an extra reset call in the begin() method in the library)..

I have both led kinds.. :frowning: (limited to quick playback features only,...although I believe the regular .loop() command -is- working on mine, but no queries to chip/responses, or enabled/disableLoop() methods....)

The chip name on the fakes are as I posted above mate, it was on the chips. Faint, but took a pic and enhanced it with photoshop filters until I could see the number. Just call me Columbo :wink:

I can use the fake ones for other projects that don't need a loop feature so at least they won't go to waste, but it's bloody annoying!

Totally agree.

Mine had the number etched off.. (so I couldnt not grab any identifying marks/numbers)

Its a shame... I only find the clones/fakes for $1.75.. and not the real ones. :frowning:

xl97:
@uxomm -
Did you get any updates about the loud speaker 'pop' upon power on/off has been addressed (using the stock DFRobot library at least).

No updates yet.
I should get updates from several threads regarding dfplayer. But everything is quiet (except for this thread). :slight_smile:

I had/have updated a few threads on it..

Just wanted to make sure you knew this 'speaker pop' issue stems from the DFRobot default library..

At this point.. if you get a LEGIT DFPlayer board:

  • Blue led
  • YX5200 chip set
  • silkscreen around the components on PCB

the only 'item' left to address is, how to accurately and consistently (via code, but using the BUSY PIN).. detect when a song has finished playing.

  • internally it must have a pointer (or something) to know when the song has finished.. so it can start it over again during a 'loop' command.

  • but I dont think it works or works correctly when just using a one time play back command like: .play(#)..

  • if I was better/more advanced at high level C++ coding.. and had more time.. I might try and take a look at the library again...