[Solved] Trouble getting DFPlayer Mini to work correctly without the use of delay()

I've been trying to get my DFRobot DFPlayer Mini to work correctly with my Nano. For now, I'm trying to test a series of audio files to play in a sequence one after the other. I am checking the status of the BUSY pin to ascertain when playback of a file is complete. However, this plays the files randomly. It starts playing file #2 then skips to #5 and then stops randomly.

I've tried multiple SD cards. And WAV and MP3 formats but nothing seems to work correctly. Currently the files are on the root of the SD card and labelled as 0001.wav, 0002.wav, etc.

What am I missing?

EDIT1: Just tried delay() instead of polling the BUSY pin and that works.

Here is the code:

#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>

#define SERIAL_BAUD 9600
#define SOFTWARE_SERIAL_BAUD 9600
#define BUSY LOW

const byte BUSY_PIN = 9;  //DFR busy pin is on D9
const int SOFTWARE_SERIAL_RX = 13;
const int SOFTWARE_SERIAL_TX = 12;

SoftwareSerial mySoftwareSerial(SOFTWARE_SERIAL_RX, SOFTWARE_SERIAL_TX);  // RX, TX
DFRobotDFPlayerMini myDFPlayer;

// Play DFR audio and check for playback completion
void playAudio(DFRobotDFPlayerMini& player, int fileNumber) {
  player.play(fileNumber);
  while (digitalRead(BUSY_PIN) == BUSY) {
    ;  // This loop executes while the DFR BUSY pin is LOW indicating playback in progress.
  }
}

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }
  mySoftwareSerial.begin(9600);
  delay(10);

  pinMode(BUSY_PIN, INPUT);

  Serial.println("Initializing DFPlayer...");

  // Initialize the DFPlayer Mini
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    Serial.println("DFPlayer Mini not detected. Please check connections and if SD card is inserted.");
    while (true) {
      ;
    }
  }
  Serial.println("DFPlayer initialized!");

  myDFPlayer.setTimeOut(500);
  myDFPlayer.volume(10);
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
  playAudio(myDFPlayer, 1);
}

void loop()
{
  Serial.println("Playing file #1");
  playAudio(myDFPlayer, 1);

  Serial.println("Playing file #2");
  playAudio(myDFPlayer, 2);

  Serial.println("Playing file #3");
  playAudio(myDFPlayer, 3);

  Serial.println("Playing file #4");
  playAudio(myDFPlayer, 4);

  Serial.println("Playing file #5");
  playAudio(myDFPlayer, 5);

  Serial.println("Playing file #6");
  playAudio(myDFPlayer, 6);
}


Don't use this function. Use the .playMP3Folder() function and move all your MP3/WAV files into a folder called "MP3" on the SD card.

Thanks. I tried this just now. No joy :frowning:

What you described is a commonly reported problem. The fix I suggested normally works.

Please post the updated code, your schematic and some bright, clear photos of the circuit taken from above so that all the wires can be traced.

If the LED on top doesn't turn on then nothing is playing.
You're calling that playAudio function in rapid succession.
A delay() should be placed between - to give the track/s some time to play.

Put a print statement in your busy waiting loop to see if it gets there and stays busy:

  while (digitalRead(BUSY_PIN) == BUSY) {
    Serial.println("busy playing");
    ;  // This loop executes while the DFR BUSY pin is LOW indicating playback in progress.
  }

a7

Here is the updated code. Its not on a breadboard. I got a PCB made for it.

#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>

#define SERIAL_BAUD 9600
#define SOFTWARE_SERIAL_BAUD 9600
#define BUSY LOW

const byte BUSY_PIN = 9;  //DFR busy pin is on D9
const int SOFTWARE_SERIAL_RX = 13;
const int SOFTWARE_SERIAL_TX = 12;

SoftwareSerial mySoftwareSerial(SOFTWARE_SERIAL_RX, SOFTWARE_SERIAL_TX);  // RX, TX
DFRobotDFPlayerMini myDFPlayer;

// Play DFR audio and check for playback completion
void playAudio(int fileNumber) {
  myDFPlayer.playMp3Folder(fileNumber);
  delay(11000);
  // while (digitalRead(BUSY_PIN) == BUSY) {
  //   ;  // This loop executes while the DFR BUSY pin is LOW indicating playback in progress.
  // }
}


void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB
  }
  mySoftwareSerial.begin(9600);
  delay(10);

  pinMode(BUSY_PIN, INPUT);

  Serial.println("Initializing DFPlayer...");

  // Initialize the DFPlayer Mini
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    Serial.println("DFPlayer Mini not detected. Please check connections and if SD card is inserted.");
    while (true) {
      ;
    }
  }
  Serial.println("DFPlayer initialized!");

  // myDFPlayer.setTimeOut(500);
  myDFPlayer.volume(10);
  // myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  // myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
  // playAudio(1);
}

void loop() {
  Serial.println("Playing file #1");
  playAudio(1);

  Serial.println("Playing file #2");
  playAudio(2);

  Serial.println("Playing file #3");
  playAudio(3);

  Serial.println("Playing file #4");
  playAudio(4);

  Serial.println("Playing file #5");
  playAudio(5);

  Serial.println("Playing file #6");
  playAudio(6);

  Serial.println("");
}

The idea was to not use delay, hence the polling of the BUSY pin. With the delay it works.

I've not done this but in the loop you'll see a Serial line which prints to the screen which file is playing. It moves through the loop erratically randomly skipping files and then abruptly stops.

I'm thinking that I made my Reply before your first Edit of Post No.1
Trying to help you troubleshoot, so is alto777.
I believe there may be a slight delay between calling the playAudio() function, the track beginning to play and the Busy pin actually going Low.

The playAudio() function call is executed, it goes to that BUSY monitoring function where it doesn't see BUSY low right away - so it jumps out on that basis. The Arduino may go faster than the DFPlayer can keep up.

So - try to, at this point, introducing some delay (less than 11000) to accommodate, coordinate, take that into account.

Is your problem now resolved? And does your code now reflect that?

Post #9 appears to add some ambiguity?

@electrophile please post the current code and say whether it works or not.

Interesting. A slight delay before starting to look, or looking until it goes busy, then busy waiting while it stays busy, viz:

  while (digitalRead(BUSY_PIN) != BUSY) {
    ;  // This loop waits for the DFR player to get BUSY.
  }

  while (digitalRead(BUSY_PIN) == BUSY) {
    ;  // This loop executes while the DFR BUSY pin is LOW indicating playback in progress.
  }

@Terrypin do you know if there is this delay and if so how long it might be?

a7

Then you should have no problem posting the schematic as requested because it will have been drawn while designing the PCB.

Can I ask why you did not discover that checking the BUSY pin like this did not work on your prototype circuit?

Yes this looks like the reason. I did not want to use delays but I guess there is no choice.

Absolutely. The schematic is as shown below. In the prototyping, I never realized that I could use the BUSY pin. The schematic below reflects the BUSY pin connected to D9, but in the current PCB, I've soldered a wire between the two pins.

Yes, there is - at least one. I recall that there are two signals at end of playback. I'd have to look up old notes to be more precise.

If/when we get a clearer status report from @electrophile I'll try posting a working sketch using the BUSY pin.
EDIT: OK, we crossed in the ether, I see the schematic.

Like I said, it works when using delays (which I do not prefer to). It does not work while polling the BUSY pin. As @runaway_pancake pointed out, the Arduino might be running faster than the DFPlayer can action the BUSY pin.

Note that while the schematic shows the BUSY pin connected to D9 in the latest version, on the actual board right now I've soldered a wire between the two pins.

If the problem with the BUSY pin is that it does not go up until after some dust has settled, the solution I suggest in #12 above should fix that and might be tried.

I do not believe that using delay() cannot be avoided.

a7

Not sure I get that distinction.

More important, can we see the latest code (running with that schematic), and learn exactly what it is doing that you don't like?

Meanwhile, are you really using this serial pair?

const int SOFTWARE_SERIAL_RX = 13;
const int SOFTWARE_SERIAL_TX = 12;

Gives initialisation error here. I avoid 13 on principle, so my (working) pair is 10/11, not 13/12.