How to Play an MP3 File Using a NodeMCU (ESP8266) and DFPlayer Module

It only took about 12 hours of trial and error, but I finally got the NodeMCU to play an MP3 through the DFPlayer. It took 12 hours because I was reaching my tolerance when I went for a Hail Mary and swapped the Tx and Rx – and whaddayaknow – ABBA coming through loud and clear!

I don’t know if it’s a typo or what, but the GetStarted.ino helpfully describes the serial inputs in its code as:

SoftwareSerial softSerial(/rx =/4, /tx =/5);

Which corresponds with D2 and D1, respectively, on the NodeMCU:

However, as you can see from the diagram up above, the two are swapped, and D1 (BPIO5) should connect to Rx and D2 to Tx (GPIO4). OMFG!

The examples I’ve seen mostly use the Arduino UNO, so maybe the UNO has weird GPIO maps? Or maybe the knockoff DFPlayers sold on Amazon have their GPIO4/GPIO5 reversed (most likely scenario). I don’t know, but if you think you’ve wired your DFPlayer right, and your sketch looks good, then try swapping the Tx and Rx. It worked for me.

How to Do It, Step by Step

Select the NodeMCU board from the Tools > Board > ESP8266 Boards (3.1.2) > NodeMCU 0.9 (ESP 12 Module) menu.

If you don’t have the ESP8266 Boards installed, you need to do that first. I’m pretty new to the Arduino IDE, so I keep notes on how to set things up. For example:

  • Install Arduino IDE
  • Install Wemos driver EXE
  • Install ESP8266 boards to the IDE, if it isn’t already:
    File > Preferences > Additional Board Manager URLs: http://arduino.esp8266.com/stable/package_esp8266com_index.json
  • Click OK
  • Next, go to Tools > Board > Board Manager in your Arduino IDE.
  • Search for ESP8266 and install it.
  • Go to Tools > Board > ESP8266 Boards (3.1.2) > NodeMCU 0.9 (ESP 12 Module
  • Connect the board.
  • Go to Tools > Port and select the COM port.

While you’re at it, you might as well fire up the Serial Monitor in Tools > Serial Monitor. Set the Baud rate to 115200.

Wire up your boards like indicated at the top of this post. Note that I do NOT use a resistor that so many have recommended. It’s not necessary for this simple test.

Format your micro SD card for FAT32.

Choose a loud, obnoxious MP3 for your test, rename it to 0001.mp3, then copy it to the root directory. I used Waterloo by ABBA, because it has no intro; it starts shaking your booty right from the start. Yes – it will have just the one file and nothing else for this example.

This is for the simplest test, so I’m not going to go into how to add files, directories, etc.

Use the GetStarted.ino sketch. Here’s mine, but it’s exactly like the one on GitHub.

/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
 <https://www.dfrobot.com/product-1121.html>
 
 ***************************************************
 This example shows the basic function of library for DFPlayer.
 
 Created 2016-12-07
 By [Angelo qiao](Angelo.qiao@dfrobot.com)
 
 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/

/***********Notice and Trouble shooting***************
 1.Connection and Diagram can be found here
 <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
 ****************************************************/

#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"

#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))   // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/4, /*tx =*/5);
#define FPSerial softSerial
#else
#define FPSerial Serial1
#endif

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

void setup()
{
#if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  
  if (!myDFPlayer.begin(FPSerial, /*isACK = */true, /*doReset = */true)) {  //Use serial 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){
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  
  myDFPlayer.volume(20);  //Set volume value. From 0 to 30
  myDFPlayer.play(1);  //Play the first mp3
}

void loop()
{
  static unsigned long timer = millis();
  
  if (millis() - timer > 60000) {
    timer = millis();
    myDFPlayer.next();  //Play next mp3 every 3 second.
  }
  
  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
  
}

And the Serial Monitor displays:

I think that wraps it up. It took me so long for it to make sound that I’ve run out of steam for my actual project, which is to create a music player for babies or for old folks with Alzheimer’s Disease/Dementia or for playing soothing sleep sounds with giant buttons to hit while half asleep in the dark.

Leave a comment