Arduino MP3 Player Using DF Player Module

Introduction

In this project, we are going to build a simple yet powerful DIY MP3 player using an Arduino and the DFPlayer Mini module. The DFPlayer Mini is a great choice for hobbyists because it is cheap, compact, and has a built-in power amplifier. Unlike other modules, it can be used with or without an Arduino, but by connecting it to a microcontroller, we can create custom controls like buttons, sensors, or even a remote control to play specific sounds.


📌Why use the DFPlayer Mini? 

There are several reasons why this module is better than using a standard SD card shield for audio:
Built-in DAC: It handles the audio processing internally, so the Arduino doesn't have to work hard.
Direct Speaker Support: You can connect a small speaker (up to 3W) directly to the pins without needing an external amplifier.
Format Support: It supports both MP3 and WAV files, which are common and easy to manage.


Preparing Your SD Card

Before you power on the circuit, you must prepare your Micro SD card correctly:
Format: Use a PC to format the card to FAT32.
Folders: Create a folder named mp3.
Naming Files: Name your songs 0001.mp3, 0002.mp3, etc. The module is very sensitive to naming conventions; if the names are random, the Arduino might fail to find the file.



Arduino MP3 Player Using DFPlayer Mini Module

If you want to build your own MP3 player with Arduino, the DFPlayer Mini module makes it simple and fun. This project lets your Arduino play MP3 files directly from a Micro-SD card and control playback with buttons, volume, and more.




🛠️ What You Need

To build this project, you will use:

Arduino UNO
16x2 LCD Display(With I2c Module Or Preset)
DFPlayer Mini MP3 Module
Micro-SD card with MP3 files
Speaker (8 Ω – 4 Ω)
Breadboard & jumper wires
Push Buttons
USB Port


Circuit Diagram

👉 Connect the speaker to SPK1 and SPK2 for sound output.




How the Circuit Works

The connection between the Arduino and the DFPlayer Mini uses Serial Communication. We use the SoftwareSerial library so that we can keep the main Hardware Serial (pins 0 and 1) free for uploading code.
Crucial Note: You must place a 1k Ohm resistor between the Arduino’s TX pin and the DFPlayer’s RX pin. This is because the DFPlayer Mini operates at 3.3V, while the Arduino provides 5V. Without this resistor, you will likely hear a loud "buzzing" or "popping" noise in the speaker, and it might eventually damage the module.


Understanding the Enhanced MP3 Player Code 

This updated version of the code does more than just play music; it adds a User Interface (UI) using a 16x2 LCD and implements advanced button controls. Below is a breakdown of how the logic works:

1. Custom Character Creation

To make the display look professional, the code uses uint8_t arrays to define custom icons for Play (0), Pause (1), Next (2), and Volume (4/5). These are loaded into the LCD's memory using the lcd.createChar() command during the setup() phase. This adds a visual element that standard text cannot provide.

2. Advanced Button Logic (Short vs. Long Press)

Instead of using simple digitalRead commands that can be unreliable, this code implements a "timer" logic using millis(). This allows a single button to perform two different tasks:

  • Short Press: Skips to the next or previous song.

  • Long Press: Adjusts the volume up or down. This is achieved by checking how long the button pin remains in the LOW state. If the duration exceeds longPressTimeL (250ms), the volume changes; otherwise, the track changes.

3. Communicating via Hexadecimal Commands

The code features a custom function called execute_CMD. This is a deep-level communication method that sends a 10-byte data packet to the DFPlayer Mini.

  • Start Byte (0x7E): Tells the module a command is coming.

  • Checksum: This is a mathematical calculation that ensures the data wasn't corrupted during transmission. Using this method instead of a basic library allows for faster response times and more control over features like specific volume levels (0-30).

4. User Feedback on LCD

Every time you interact with the player, the lcd.setCursor and lcd.print functions update the display. Whether you are pausing the music or cranking up the volume, the screen provides instant confirmation. We have included delay(500) and lcd.clear() sequences to ensure the text doesn't flicker and is easy for the user to read.

<LiquidCrystal_I2C.h> Library 👇

CODE

#include "SoftwareSerial.h"
#include "Wire.h"
#include "LiquidCrystal.h"
LiquidCrystal lcd(A5,A4,A3,A2,A1,A0);


uint8_t bPLAY[8] = {0x00, 0x00, 0x08, 0x0C, 0x0E, 0x0C, 0x08, 0x00};
uint8_t bPAUSE[8] = {0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00};
uint8_t bNEXT[8] = {0x00, 0x00, 0x11, 0x19, 0x1D, 0x19, 0x11, 0x00};
uint8_t bPREVIOUS[8] = {0x00, 0x00, 0x11, 0x13, 0x17, 0x13, 0x11, 0x00};
uint8_t bUPVOLUME[8] = {0x00, 0x00, 0x04, 0x04, 0x0E, 0x04, 0x04, 0x00};
uint8_t bDOWNVOLUME[8] = {0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00};

// Set the LCD address to 0x27 for a 16 chars and 2 line display


SoftwareSerial dfpSerial(10, 11);

/*************************
DF Player Serial Format:
  1. START_BYTE     0x7E
  2. VERSION        0xFF
  3. LENGTH         0x06
  4. COMMAND        CMD / operation
  5. FEEDBACK       1: with Feedback, 0: no feedback
  6. PARAMETER_1    Parameter of Command (High data byte)
  7. PARAMETER_2    Parameter of Command (Low data byte)
  8. CHECKSUM   
  9. CHECKSUM  
  10. END_BYTE      0xEF

*/
# define START_BYTE 0x7E
# define VERSION    0xFF
# define LENGTH     0x06
# define FEEDBACK   0x00
# define END_BYTE   0xEF


# define ACTIVATED LOW

const byte buttonPin = 5;

int buttonNext = 4;
int buttonPause = 3;
int buttonPrevious = 2;
boolean isPlaying = false;

unsigned long buttonTimerL = 0;
unsigned long longPressTimeL = 250;
boolean buttonActiveL = false;
boolean longPressActiveL = false;

unsigned long buttonTimerR = 0;
unsigned long longPressTimeR = 250;
boolean buttonActiveR = false;
boolean longPressActiveR = false;

byte currVolume = 25;

void setup () {
  lcd.begin(16,2);
  pinMode(buttonPause, INPUT_PULLUP);
  pinMode(buttonNext, INPUT_PULLUP);
  pinMode(buttonPrevious, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(9600);

  dfpSerial.begin (9600);
  delay(1000);
  //playFirst();
  isPlaying = false;

  setVolume(currVolume);
  delay(500);


  lcd.createChar(0, bPLAY);
  lcd.createChar(1, bPAUSE);
  lcd.createChar(2, bNEXT);
  lcd.createChar(3, bPREVIOUS);
  lcd.createChar(4, bUPVOLUME);
  lcd.createChar(5, bDOWNVOLUME);

  lcd.home();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");

  Serial.println("Setup Completed.");
}



// display all keycodes
void displayKeyCodes(void) {
  uint8_t i = 0;

 // while (1) {
    lcd.clear();
    lcd.print("Codes 0x");
    lcd.print(i, HEX);
    lcd.print("-0x");
    lcd.print(i + 16, HEX);
    lcd.setCursor(0, 1);

    for (int j = 0; j < 16; j++) {
      lcd.write(i + j);
    }
    i += 16;

    delay(4000);
 // }
}


void loop () { 
  // Button PREVIOUS / Volume DOWN
  if (digitalRead(buttonPrevious) == LOW) {
    if (buttonActiveL == false) {
      buttonActiveL = true;
      buttonTimerL = millis();
    }
    //if ((millis() - buttonTimerL > longPressTimeL) && (longPressActiveL == false)) {
    if (millis() - buttonTimerL > longPressTimeL) { // multiple long press
      longPressActiveL = true;
      volumeDown();
      Serial.println("Volume DOWN: ");
      Serial.println(currVolume);
    }
  } 
  else {
    if (buttonActiveL == true) {
      if (longPressActiveL == true) {
        longPressActiveL = false;
      } else {
        playPrevious();
        Serial.println("Playing PREVIOUS song");
       
      }
      buttonActiveL = false;
    }
  }

  // Button PLAY / PAUSE
  if (digitalRead(buttonPause) == ACTIVATED)
  {
    Serial.println("Button PLAY");
    if(isPlaying)
    {
      pause();
      isPlaying = false;
      Serial.println("Pause");
  
    }else
    {
      isPlaying = true;
      play();
      Serial.println("Play");
   
    }
  }

  // Button NEXT / Volume UP
  if (digitalRead(buttonNext) == LOW) {
    if (buttonActiveR == false) {
      buttonActiveR = true;
      buttonTimerR = millis();
    }

    //if ((millis() - buttonTimerR > longPressTimeR) && (longPressActiveR == false)) {
    if (millis() - buttonTimerR > longPressTimeR) { // Try multiple long press
      longPressActiveR = true;
      volumeUp();
      Serial.println("Volume UP: ");

      Serial.println(currVolume);
    }

  } 
  else {
    if (buttonActiveR == true) {
      if (longPressActiveR == true) {
        longPressActiveR = false;
      } else {
        playNext();
        Serial.println("Playing NEXT song");
   
      }
      buttonActiveR = false;
    }
  }
}


void play() {
  // Playback
  execute_CMD(0x0D,0,1); 
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(14, 1);
  lcd.setCursor(0, 1);
  lcd.print("Play");
  delay(1000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(6,1);
  lcd.print("Play");
  delay(500);
}

void pause() {
  execute_CMD(0x0E,0,0);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(14, 1);
  lcd.write(1);
  lcd.setCursor(0, 1);
  lcd.print("Pause");
  delay(1000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(5,1);
  lcd.print("Pause");
  delay(500);
}

void playNext() {
  // Next
  execute_CMD(0x01,0,1);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(14, 1);
  lcd.write(2);
  lcd.setCursor(0, 1);
  lcd.print("Next");
  delay(1000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(6,1);
  lcd.print("Play");
  delay(500);
}

void playPrevious() {
  // Previous
  execute_CMD(0x02,0,1);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(14, 1);
  lcd.write(3);
  lcd.setCursor(0, 1);
  lcd.print("Previous");
  delay(1000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("MP3 PLAYER");
  lcd.setCursor(6,1);
  lcd.print("Play");
  delay(500);
}

void volumeUp() {
  if (currVolume < 30) {
    currVolume++;
    setVolume(currVolume);
    lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("MP3 PLAYER");
    lcd.setCursor(14, 1);
    lcd.write(4);
    lcd.setCursor(0, 1);
    lcd.print("Vol-UP");
    delay(1000);
    lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("MP3 PLAYER");
    lcd.setCursor(6,1);
    lcd.print("Play");
    delay(500);
  }
}


void volumeDown() {
  if (currVolume > 0){
    currVolume--;
    setVolume(currVolume);
    lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("MP3 PLAYER");
    lcd.setCursor(14, 1);
    lcd.write(5);
    lcd.setCursor(0, 1);
    lcd.print("Vol-DOWN");
    delay(1000);
    lcd.clear();
    lcd.setCursor(3,0);
    lcd.print("MP3 PLAYER");
    lcd.setCursor(6,1);
    lcd.print("Play");
    delay(500);
  }
}

void setVolume(int volume) {
  execute_CMD(0x06, 0, volume); // Set the volume (0x00~0x30)
  delay(2000);
}

void execute_CMD(byte CMD, byte Par1, byte Par2) {
  // Excecute the command and parameters

  // Calculate the checksum (2 bytes)
  word checksum = -(VERSION + LENGTH + CMD + FEEDBACK + Par1 + Par2);

  // Build the command line
  byte Command_line[10] = { START_BYTE, VERSION, LENGTH, CMD, FEEDBACK,
                            Par1, Par2, highByte(checksum), lowByte(checksum), END_BYTE};

  //Send the command line to the module
  for (byte k = 0; k < 10; k++) {
    dfpSerial.write(Command_line[k]);
  }
}

⚠️Troubleshooting Common Issues 

If your project isn't making any sound, check the following: Power Supply: The DFPlayer Mini requires a stable 5V. If you are powering the Arduino via a laptop USB, it might not provide enough current for both the Arduino and the speaker. Wiring: Double-check that the TX of the Arduino goes to the RX of the DFPlayer (through a resistor). SD Card Slot: Ensure the card is pushed in all the way. Some cheap modules have loose SD slots.



إرسال تعليق

Post a Comment (0)

أحدث أقدم