ArduinoGeneral

DFPlayer mini + gets stuck in loop when it shouldnt.

userHead whispers007 2018-03-06 23:49:35 4956 Views3 Replies
Where can we go to get help or talk about the DFPlayer? This forum seems pretty dead lately.. and most posts have 0 replies. (DFPlayer posts are almost ALL 0 replies!) LOL

I have have a sketch that is really nothing more than a button (switch) state checker/listener..

button is pressed = play power on (002.wav) sound clip (one time)
if button is STILL pressed after power on clip is complete, immediately play the thrust (003.wav) sound clip, in a LOOP..
when pressed is released, play power down (004.wav) sound clip..

I have found that while trying to check when a clip has completed playback... just using myDFPlayer.play(#).. makes the isFinished function/listener (same as printDetail() function,.. but trimmed down) IMMEDIATELY say the song is finished, even though I can hear is still playing.

If I put a disableLoop() and/or enableLoop() before/after the play() command... this -SEEMS- to allow for the isFinished() listener to accurately report when the song is complete...

WHY?

does the myDFPlayer.play(#); action NOT work for trying to detect when a song is complete?

My main concern is that when trying to transition form a regular .play() command, to a .loop(#) command.. my power on sound clip will sometimes get stuck in a loop.. when only the thrust (003.wav) should EVER be in a loop

What is the correct/appropriate way to:

1.) Be able to detect when a song is complete (my results have shown I need to enableLoop() for that to work or be accurate)..

2.) Transition from a .play(#) to a .loop(#) action seamlessly.. without the .play(#) file being accidentally being looped?

Some combination of enableLoop() & disableLoop() and their placement HAS to be the key here?

Please try this demo code..

you only need a button/switch on A5/D19.. and a DFPlayer with 4 .wav files on it..
001.wav - boot sound, only plays once time when powered up
002.wav - plays when button is pressed (one time)
003.wav - loops for as long as button is pressed (after 002.wav is finished playing)
004.wav - plays when the button is released

Here is my demo code:
Code: Select all
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

const int buttonPin = 19;
int buttonState = 0;
int lastButtonState = 1;
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 5;    // the debounce time; increase if the output flickers

boolean doCompletionCheck = false;
int currentTrack = 0;

#define S_IDLE 1
#define S_POWERON 2
#define S_POWERDOWN 3
static int state = S_IDLE;

DFRobotDFPlayerMini myDFPlayer;
SoftwareSerial myDFPlayerSerialConn(7, 8);


void setup() {
  //debug (monitor)
  Serial.begin(115200);
  //talk to DFPlayer
  myDFPlayerSerialConn.begin(9600);
  
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  if (!myDFPlayer.begin(myDFPlayerSerialConn)) {
    Serial.println(F("Unable to begin:"));
    Serial.println(F(" - Please recheck the connection!"));
    Serial.println(F(" - Please insert the SD card!"));
    while (true);
  }
  Serial.println(F("DFPlayer Mini online."));
  myDFPlayer.setTimeOut(500);
  myDFPlayer.volume(7);
  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
    
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH);
  
  myDFPlayer.play(1);
  delay(2000);
}

void loop() {  
  switch (state) {
    case S_IDLE:
      buttonState = digitalRead(buttonPin);
      //if (buttonState != lastButtonState) {
      if ((buttonState != lastButtonState) && (millis() - lastDebounceTime > debounceDelay)) {
        lastDebounceTime = millis(); //update last time pressed/released
        
        if (buttonState == LOW) {  
          state = S_POWERON;
          
        }else {  
          state = S_POWERDOWN; 
          
        }    
      }else{        
        if(buttonState == LOW) {           
          if(currentTrack == 2 && doCompletionCheck == true){
            if(myDFPlayer.available()) {
              if(isFinished(myDFPlayer.readType(), myDFPlayer.read()) == 1){
              //if(isFinished(myDFPlayer.readType(), myDFPlayer.read()) == 1 && myDFPlayer.readState() != 513){
              //if(doCompletionCheck == true && currentTrack == 2 && myDFPlayer.readState() != 513 && isFinished(myDFPlayer.readType(), myDFPlayer.read()) == 1){
              //if(myDFPlayer.readState() != 513){
                Serial.println(F(">>> POWER ON PLAYBACK COMPLETE <<<"));                
                currentTrack = 3;
                doCompletionCheck = false;

                //myDFPlayer.stop();
                //myDFPlayer.disableLoop();
                //delay(10);//just a test!!!
                myDFPlayer.loop(3);
                //myDFPlayer.play(3);
                //myDFPlayer.next();
                //myDFPlayer.enableLoop();
              }              
            }
          }
                                      
        }else{                 
          if(currentTrack == 4 && doCompletionCheck == true){            
            if(myDFPlayer.available()) {                  
              if(isFinished(myDFPlayer.readType(), myDFPlayer.read()) == 1){                
                Serial.println(F(">>> POWER OFF PLAYBACK COMPLETE <<<"));                
                doCompletionCheck = false;                                 
              }              
            }
          }
        }       
      }
      lastButtonState = buttonState;
    break;

    

    case S_POWERON:
      Serial.println(F("[POWER UP]"));
      currentTrack = 2;      
      doCompletionCheck = true;
      //myDFPlayer.disableLoop();   
      myDFPlayer.play(2);
      //myDFPlayer.enableLoop();
      
      state = S_IDLE;
    break;

    

    case S_POWERDOWN:      
      Serial.println(F("[POWER DOWN]"));
      currentTrack = 4; 
      doCompletionCheck = true; 
      //myDFPlayer.disableLoop();
      myDFPlayer.play(4);
      //myDFPlayer.enableLoop();  //do not enable! 
      
      state = S_IDLE;    
    break;
  }

}

//used to check when a track is done playing
int isFinished(uint8_t type, int value) {
  switch (type) {   
    case DFPlayerPlayFinished:
      return 1;  
      break;
      
    //nothing            
    default:
      break;
  }
}
2018-05-30 14:14:43 Have you ever tried to just use one button to play one specific song, because there is no example about using a button to control a specific song by arduino code in the wiki(except for AD key mode), why don't you try 001.wav & 002.wav first. userHeadPic robert.chen
2018-05-25 04:47:11 ^bump (again)

Still on the look out for a TRIED -n- TRUE solution for reliably detecting when an audio clip is finished playing.

Especially with the example sketch above.

* press button -
* playing a clip using the .play(#) command... (clip #1)
* keep holding button down -
* sitting in a loop, constantly checking for this (clip #1) to be finished..
* Once playback complete is detected, start a .loop(#) command (clip #2)... that will loop until the button is released
* button release happens
* stops .loop(#) for clip #2
* automatically trigger .play(#) (clip #3)

...wait for button press/hold again..

Anyone show me proof where clip #1 doesnt randomly get stick in a LOOP! (that is only intended for clip #2 after clip #1 playback complete is detected)
userHeadPic whispers007
2018-03-17 02:15:23 ^bump userHeadPic whispers007