DFPlayer Mini begin() always fails with "Busy" error, but works standalone via IO_1/GND short

I'm building a simple soundboard: pressing an arcade button should play a random track (1 of 100) from folder "01" on the SD card. Board is a DFRduino Nano V4 (Arduino Nano clone, paired with a generic DFPlayer Mini module.

Wiring:

  • Nano +5V → DFPlayer VCC
  • Nano GND → DFPlayer GND
  • Nano GND → GND rail on breadboard
  • Nano D12 → 1kΩ resistor → DFPlayer RX
  • Nano D9 → DFPlayer TX
  • DFPlayer SPK_1 → speaker (−)
  • DFPlayer SPK_2 → speaker (+)
  • Button COM → GND
  • Button NO → Nano D2

SD card: FAT32, folder "01" in root, files named 001.mp3 through 100.mp3.


Code:

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

SoftwareSerial mySerial(9, 12);
DFRobotDFPlayerMini myDFPlayer;

const int buttonPin = 2;
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200;

void setup() {
  Serial.begin(115200);
  mySerial.begin(9600);

  pinMode(buttonPin, INPUT_PULLUP);
  randomSeed(analogRead(A0));

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

  if (!myDFPlayer.begin(mySerial, true, true)) {
    Serial.println("Error: DFPlayer not responding.");
    while (true) {
      delay(1000);
    }
  }

  myDFPlayer.volume(15);
  Serial.println("DFPlayer ready");
}

void loop() {
  bool buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState == LOW) {
        int track = random(1, 101); //random audio drom 1 to 100

        Serial.print("Playing track: ");
        Serial.println(track);

        // folder "01", files 001.mp3 - 100.mp3
        myDFPlayer.playFolder(1, track);
      }
      lastDebounceTime = millis();
      lastButtonState = buttonState;
    }
  }
}

Symptom: myDFPlayer.begin() always returns false. Using a diagnostic snippet that reads readType()/read() right after a failed begin(), I consistently get error type DFPlayerError with error code Busy (1) — on every attempt, even with retries and delays in between.

What I've already ruled out:

  • Shorting the DFPlayer's IO_1 pin directly to GND plays a track through the speaker just fine, so the SD card, file indexing, amplifier, and speaker all work correctly.
  • Checked continuity of every UART and power connection with a multimeter - all read close to 0Ω, no opens.

My board:

Use other pins. Pin 9 seems to have troubles with other libraries because of a TIMER in the hardware. Try 2, 4 or 4, 6.

Use the example to discover the error. DFRobotDFPlayerMini/examples/GetStarted/GetStarted.ino at master · DFRobot/DFRobotDFPlayerMini · GitHub

Datasheet for ref: Dreamer Nano V4.1 - Compact & Versatile Microcontroller | DFRobot Wiki

Try this with only one (or a few) files.

I switched to pins 4 and 6, wired everything correctly, but it's still not working properly.

However, I found something interesting: when I power the device on (via USB or the battery) and press the button, nothing happens - but if I unplug and reinsert the SD card while the device is powered on, it suddenly starts working.

I also wired up a 4x AA battery holder (6V) with an on/off switch, thinking the issue might be related to USB voltage, but that changed nothing - the SD card re-insertion trick is still what makes it work.

Any ideas what could be causing this?

That sounds like an initialization issue.

Adding some reset call might help.

@bartekpawlak181

Your sketch works fine here after making one change in setup(). That pair RX,Tx (9,12) looked odd to me so I changed it to my usual pair (10,11). That then runs correctly. Changing it back to (9,12) caused initialisation errors. So change

SoftwareSerial mySerial(9, 12);
to
SoftwareSerial mySerial(10, 11);

I think you'll find other pairs like
SoftwareSerial mySerial(5, 6);

and others will also be OK.

Is this MP3 player a clone or real DFPlayer?

I wonder if a clone player uses the "not inserted" indication to flag "no media" and stop the sketch from working rather than blindly amplifying nothing.

@Terrypin thanks for the suggestion.
I changed the pins to 10 and 11 and also modified the sketch to add some debugging output.

Now D10 (Nano RX) goes to DFPlayer TX, and D11 (Nano TX) goes to DFplayer RX through the 1K resistor.
Unfortunately, the behaviour is still the same.

Here is the updated code:

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

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

const int buttonPin = 2; // Button on D2
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200; // ms

void setup() {
  Serial.begin(115200);
  mySoftwareSerial.begin(9600);

  pinMode(buttonPin, INPUT_PULLUP);
  randomSeed(analogRead(A0));

  bool ok = myDFPlayer.begin(mySoftwareSerial, true, true);

  if (!ok) {
    Serial.println(F("Unsuccessful first try, resetting..."));
    for (int i = 0; i < 3 && !ok; i++) {
      myDFPlayer.reset();
      delay(1000);
      ok = myDFPlayer.begin(mySoftwareSerial, false, true);
      Serial.print(F("Reset try"));
      Serial.print(i + 1);
      Serial.println(ok ? F(": success") : F(": still failed"));
    }
  }

  if (!ok) {
    Serial.println(F("No change after resetting"));
  } else {
    Serial.println(F("Connected"));
    delay(1000);
  }

  myDFPlayer.volume(18);

  Serial.println(F("Ready to play"));
}

void loop() {
  bool buttonState = digitalRead(buttonPin);

  // Detect button push with debouncing
  if (buttonState != lastButtonState) {
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState == LOW) {
        int track = random(1, 101); // Random number between 1 and 100

        Serial.print(F("Button pressed, playing track: "));
        Serial.println(track);

        myDFPlayer.playFolder(1, track); // folder "01", files 001.mp3 - 100.mp3
      }
      lastDebounceTime = millis();
      lastButtonState = buttonState;
    }
  }

  // Listening for dfplayer diagnostic
  if (myDFPlayer.available()) {
    uint8_t type = myDFPlayer.readType();
    int value = myDFPlayer.read();
    Serial.print(F("DFPlayer -> Type: ")); Serial.print(type);
    Serial.print(F(", Value: ")); Serial.println(value);
  }
}

And this is the complete output from the Serial Monitor after powering the device on:

Unsuccessful first try, resetting...

Reset try1: success

Connected

Ready to play

DFPlayer -> Type: 6, Value: 1

At this point I press the button, but no sound is played:

Button pressed, playing track: 86

DFPlayer -> Type: 6, Value: 1

Then I unplug the SD card:

DFPlayer -> Type: 3, Value: 2

I plug the SD card back in:

DFPlayer -> Type: 2, Value: 2

And then I press the button again - this time it works and the sound plays:

Button pressed, playing track: 23

Initially, after powering on the device and after each button press, the DFPlayer reports a BUSY state. However, after I unplug an plug the SD card back in, the BUSY state disappears.

@xfpd Regarding the clone question: I bought the DFPlayer from a Polish electronics/robotics store, Botland:

I don't think it's a clone.

Try a 1000ms delay after each of these commands.

Sorry for the "picture" of this... See the part about 1.5 to 3 seconds of initialization... relating to file numbers (number of files it must read through)...

I tried that as well, even with delays of 5000 ms, but unfortunately it still doesn't work, the same errors appear.

Not that a free enterprise version couldn't put the DFROBOT label on the IC, but here's a real one vs one of the many workalikes available for 1/10 the price of the real thing.

I've got an original one, 100%

Puzzling, as all went well here. I uploaded your sketch to a UNO. Had an initial failure, which I suspect was due to my touching one of the breadboard dupont connectors. Probably the most frequent causes of intermittent failure and frustration for me. But I've been playing snippets of some of my favourite MP3s with no problem. Every button press plays the reported track.

The only change I made was to avoid thinking about folders. It obviously has no bearing on the cause of your problem.

// myDFPlayer.playFolder(1, track); // folder "01", files 001.mp3 - 100.mp3
myDFPlayer.play(track); // plays a random track within the range set, currently 1-60

Do you have another DFR player you can try? Another mSD/Nano or Uno/breadboard? Confident about robustness of wiring?

Most of my DFR players are clones. I've found that trial/error is often needed in choosing delays. But for these tests on your sketch I tried three different modules with the sketch and all gave same good behaviour.

I connected my Nano (CLONE) to my DFPlayerMini (CLONE) according to the sketch in Post #7, pins (10, 11), and it "worked"... I do not have 100 files (only two), so no audio was output.

I powered-up WITHOUT an SDcard, and this was the report in the Serial Monitor...

Unsuccessful first try, resetting...

I then inserted an SDcard and this was the report in the Serial Monitor...

Reset try1: success
Connected
Ready to play
Button pressed, playing track: 77
Button pressed, playing track: 64
Button pressed, playing track: 8
Button pressed, playing track: 24
Button pressed, playing track: 36
Button pressed, playing track: 80
Button pressed, playing track: 78

These are the contacts that show the SDcard is inserted.

I would say your DFPlayerMini is giving false indications.
Or... remove many of your files (keep only three).

I left only 3 audio files, and modified the sketch to shuffle between just 3, but the same problem still remains. I do not have another player on hand,

Then I suggest you get another one or two , they're quite inexpensive.

And my other questions?

Post your sketch so we can use what you are using. Also, make a drawing of your current wiring. ** the last sketch you posted is picking from 100 files.

[edit]
This is my Serial Monitor output:

Unsuccessful first try, resetting...
Reset try1: success
Connected
Ready to play
Button pressed, playing track: 75
Button pressed, playing track: 56

This is your Serial Monitor output (your output has extra line feeds that I removed)

Unsuccessful first try, resetting...
Reset try1: success
Connected
Ready to play
DFPlayer -> Type: 6, Value: 1

The "DFPlayer -> Type, Value: 1" is an error your DFPlayer is reporting.

I finally got my DFPlayerMini to "fail" by wiggling the TX and RX pins... but a off/on made everything work again.

Button pressed, playing track: 62
Button pressed, playing track: 62
DFPlayer -> Type: 0, Value: 0
Button pressed, playing track: 21
DFPlayer -> Type: 0, Value: 0
Button pressed, playing track: 54
DFPlayer -> Type: 0, Value: 0
Button pressed, playing track: 44
DFPlayer -> Type: 0, Value: 0

So... I now suspect (1) wiring/jumpers and (2) solderless breadboard

  • Both your Nano and your DFPlayerMini are NOT pressed into the breadboard.
  • The pins should not be visible.
  • Your connections are not being "made."


Thanks both for the input.

@xfpd I checked the DFRobotDFPlayerMini source ( DFRobotDFPlayerMini/DFRobotDFPlayerMini.h at master · DFRobot/DFRobotDFPlayerMini · GitHub ), and I think our errors are actually different:

  • Mine: Type: 6, Value: 1 = DFPlayerError / Busy. The DFPlayer is responding, but says it's busy, possibly while initializing/scanning the SD card.

  • Yours: Type: 0, Value: 0 = TimeOut. The Arduino gets no response at all, which fits with your TX/RX wiggle test.

So yours looks like a connection issue, while mine seems more related to the DFPlayer/SD card state.

@Terrypin the wiring is definitely fine on my end. I tested every possible connection with a multimeter and everything checks out. I think I'll just order some replacement parts and try swapping them out.

I'll post my current sketch and wiring diagram below (sorry it's a little bit messy, I'm new to this).

My current sketch:

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

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

const int buttonPin = 2; // Button on D2
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200; // ms

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println(F("Begin mySoftSerial 9600"));
  mySoftwareSerial.begin(9600);
  delay(1000);

  pinMode(buttonPin, INPUT_PULLUP);
  randomSeed(analogRead(A0));

  bool ok = myDFPlayer.begin(mySoftwareSerial, true, true);

  if (!ok) {
    Serial.println(F("Unsuccessful first try, resetting..."));
    for (int i = 0; i < 3 && !ok; i++) {
      myDFPlayer.reset();
      delay(1000);
      ok = myDFPlayer.begin(mySoftwareSerial, false, true);
      Serial.print(F("Reset try"));
      Serial.print(i + 1);
      Serial.println(ok ? F(": success") : F(": still failed"));
    }
  }

  if (!ok) {
    Serial.println(F("No change after resetting"));
  } else {
    Serial.println(F("Connected"));
    delay(1000);
  }

  myDFPlayer.volume(18);

  Serial.println(F("Ready to play"));
}

void loop() {
  bool buttonState = digitalRead(buttonPin);

  // Detect button push with debouncing
  if (buttonState != lastButtonState) {
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState == LOW) {
        int track = random(1, 4); // Random number between 1 and 3

        Serial.print(F("Button pressed, playing track: "));
        Serial.println(track);

        myDFPlayer.playFolder(1, track); // folder "01", files 001.mp3 - 003.mp3
      }
      lastDebounceTime = millis();
      lastButtonState = buttonState;
    }
  }

  // Listening for dfplayer diagnostic
  if (myDFPlayer.available()) {
    uint8_t type = myDFPlayer.readType();
    int value = myDFPlayer.read();
    Serial.print(F("DFPlayer -> Type: ")); Serial.print(type);
    Serial.print(F(", Value: ")); Serial.println(value);
  }
}


@bartekpawlak181 -
Your Uno/Nano and DFPlayerMini are NOT inserted into the breadboard.

The wiring in the first photo I posted is outdated. I'm now using female-to-female Dupont wires to connect everything directly like this, since I couldn't properly fit the gold pins into my breadboard.

I know it's not the conventional way to wire it, but I find it easier to work with. And as I mentioned earlier, I don't think the wiring is the problem here - I tested all the connections and everything checks out.

The pink stuff is conductive. You are shorting all those pins.

It is not good practice to change multiple things. One at a time, then test.

Yes, you can. You did not do it. These pins and breadboard are made for each other. Laying the pins on the breadboard caused poor connection at best.

Your most recent code is questionable... I am trying to figure out why...

What does your SDcard file structure (directory tree) look like? An example...

PS C:\> cd '.\Program Files\Wireshark\profiles\'
PS C:\Program Files\Wireshark\profiles> tree
Folder PATH listing for volume Windows-SSD
Volume serial number is EA09-8130
C:.
├───Bluetooth
├───Classic
└───No Reassembly
PS C:\Program Files\Wireshark\profiles>