DFPlayer Mini auto repeats?

Hallo

Have a few questions about this module in connection with Particle World.

I am using the below sketch to try to play a file timed to begin using the BulldogLowell Time Alarms - I find that the MP3 repeats itself over and over again - is this normal? Do I need to either find and exploit a ‘repeat=off’ flag or send a pause/stop at the exact end duration of my MP3?

Thanks!

    /* MP3 PLAYER PROJECT
    From project: http://educ8s.tv/arduino-mp3-player/
    Modified for "Particle world" by @FiDel
    */

    # define Start_Byte 0x7E
    # define Version_Byte 0xFF
    # define Command_Length 0x06
    # define End_Byte 0xEF
    # define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]

    # define ACTIVATED LOW

    int buttonNext = D2;
    int buttonPause = D3;
    int buttonPrevious = D4;
    boolean isPlaying = false;



    void setup ()
    {
      pinMode(buttonPause, INPUT_PULLUP);
      digitalWrite(buttonPause,HIGH);
      pinMode(buttonNext, INPUT_PULLUP);
      digitalWrite(buttonNext,HIGH);
      pinMode(buttonPrevious, INPUT_PULLUP);
      digitalWrite(buttonPrevious,HIGH);

      Serial1.begin(9600);
      delay(1000);
      playFirst();
      isPlaying = true;
    }



    void loop ()
    { 
     if (digitalRead(buttonPause) == ACTIVATED)
      {
        if(isPlaying)
        {
          pause();
          isPlaying = false;
        }else
        {
          isPlaying = true;
          play();
        }
      }


     if (digitalRead(buttonNext) == ACTIVATED)
      {
        if(isPlaying)
        {
          playNext();
        }
      }

       if (digitalRead(buttonPrevious) == ACTIVATED)
      {
        if(isPlaying)
        {
          playPrevious();
        }
      }
    }


    void playFirst()
    {
      execute_CMD(0x3F, 0, 0);
      delay(500);
      setVolume(20);
      delay(500);
      execute_CMD(0x11,0,1); 
      delay(500);
    }


    void pause()
    {
      execute_CMD(0x0E,0,0);
      delay(500);
    }


    void play()
    {
      execute_CMD(0x0D,0,1); 
      delay(500);
    }


    void playNext()
    {
      execute_CMD(0x01,0,1);
      delay(500);
    }


    void playPrevious()
    {
      execute_CMD(0x02,0,1);
      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)
     int16_t checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);

     // Build the command line
     byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, checksum >> 8, checksum & 0xFF, End_Byte};

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

DFPlayer documentation leaves a lot to be desired:

  • 0x11 turns repeat on.
  • 0x0D performs the “resume” function … not the “play” as documented. Just send as (0x0D,0,0).
  • 0x3F queries the DFPlayer … returns the type of media attached: 1 = USB key, 2 = SD card, 3 = both.

To play tracks based on file name, the tracks must be stored in folders.

  • Standards folders can be named 01-99, and can hold up to 255 tracks each. Standard track names must have a 3-digit numeric prefix … like “003 Beans In My Ears.mp3”
  • Huge folders can be named 01-15, and can hold up to ~3000 tracks each, and file names must have a 4-digit prefix … like “0004 Tennessee Bird Walk.wav”.
  • 0x0F will play a track stored in a standard folder (0x0F,1,5) will play a file 005.mp3 stored in folder 01.
  • 0x14 will play a track stored in a huge folder (0x14,0x10,0x06) will play file 0006.mp3 stored in folder 01. Note that the first hex digit in the MSB identifies the folder. The second hex digit in the MSB combines with the LSB digits to identify the track.
  • 0x12 will play a track stored in a special Huge folder named “mp3”, 0x12,0x00,0x07) would play 0007.mp3. In this case, both MSB and LSB can be combined into a single uint16_t that identifies the track number.

If you issue a play command and you want to know “is the track playing?”, you can use 0x42 to query DFPlayer for the status … it will return a 0x42 frame, where:

  • MSB identifies the active media: 1 = USB key, 2 = SD card, 16(0x10) = sleep)
  • LSB provides device status: 0 = idle, 1 = playing, 2 = paused

It is best to wait about 200ms before checking status after you issue a play command. I’ve seen the DFPlayer return play status > 2 while a track is playing, so I code “if (not idle) …” rather than "“if (playing) …”.

If you simply want to know when a track stops playing … watch for DFPlayer to return 0x3C, 0x3D, or 0x3E frames. These frames are automatically sent to announce “end of play”. DFPlayer often sends duplicate frames at “end of play”, so you’ll probably want to ignore a frame if it is identical to the previous “end of play” frame.

You have long delays between commands. I’d recommend that you remove them, and put something like the following logic in your execute_CMD function. In my testing, a 30ms delay is adequate for most commands, but it may be necessary to insert more delay in front of queries if a recent change has been made.

uint32_t submitGap = (millis() - lastSubmitMillis);
if (submitGap < 30) delay(30 - submitGap);
lastSubmitMillis = millis();

Note lastSubmitMillis would be defined as uint32_t global variable.

1 Like

Thanks so much for this! I am going to have another pop at it tonight and see how far I get. I have been puzzled by why the song just repeats continually with the above FiDel code. I will experiment. :slight_smile:

By the way, adding DFPlayer prefixes is a pain. If you have Windows folders with music files, you can copy them to another folder or another device using this script that will add a three (or four) digit prefix to each file it copies.

rem	DFPlayerRename.cmd
rem	This script
rem		- reads tracks (.mp3 and .wav files) from from the "copyFromPath".
rem		- prepends a three-digit or four-digit number to each file name.
rem		- writes the track with the new file name to the "copyToPath".
rem		For example: The script might read "Tennessee Bird Walk.mp3" and write "015Tennessee Bird Walk.mp3"

rem TO USE THIS SCRIPT
rem		1.  Configure the NUM copyFromPath, and copyToPath below
rem		2.  Save this file to your hard-drive
rem		3.  If copyToPath points to a folder that does not yet exist ... create it. 
rem		4.  Double-click the script to perform the copy/rename operation.


rem	Script Configuration  --------------------------------------------------------------------------------------------------------

rem		Standard DFPlayer folders must be named 01-99, and must contain track names prefixed with 001-255
rem 	Huge DFPlayer folders must be named 01-15, and must contain tracks prefixed with 0001-2999 (or more with a performance penalty)
rem			If you are creating a standard folder, set NUM to 1000.
rem			If you are creating a huge folder, set NUM to 10000.

rem		Set "copyFromPath" to the folder name where the tracks ( currently exist.
rem		Set "copyToPath" to the folder name where the tracks will be written.
rem		Examples: 
rem			set copyFromPath=t:\MusicLib\Jazz\MP3
rem			set copyToPath=c:\DFPlayer

rem --------------------------------------------------------------------------------------- START of Script
SETLOCAL ENABLEDELAYEDEXPANSION

set /a NUM = 1000

set copyFromPath=t:\MusicLib\Jazz\MP3

set copyToPath=c:\DFPlayer

cd /d "%copyFromPath%"
for %%a in (*.mp3 *.wav) do (
	set /a NUM=!NUM! + 1
	set "filename=!NUM:~1!%%a"
	copy "%%a" "%copyToPath%\!filename!"
)
rem ----------------------------------------------------------------------------------------- END of Script


rem	Script Details --------------------------------------------------------------------------------------------------------------

rem		SETLOCAL ENABLEDELAYEDEXPANSION <-- enables us to reference the incremented value of NUM and the modified filename in the 
rem											"for loop". Note they are referenced as !NUM! and !filename! within the loop
rem		cd /d "%copyFromPath%"	<-- makes the copyFromPath the current directory
rem		for %%a in (*.mp3 *.wav) do ( <-- executes the following block of code for every .mp3 and every .wav file in the directory
rem			set /a NUM=!NUM! + 1 <-- increments NUM
rem			set "filename=!NUM:~1!%%a" <-- sets filename to NUM with the first digit stripped off, plus the original file name %%a
rem			copy "%%a" "%copyToPath%\!filename!" <-- copies the original file to specified folder and the new file name
rem		)

Quick one - did you ever experience that sometimes the audio through the DFPlayer was distorted or ‘throaty’? I am experiencing this problem and I don’t know what’s causing it. It’s only sometimes. I’m not using any resistors or filters. Maybe I should.

Thanks so much for your help.

DAC or Speaker???

I have a 470uf electrolytic cap in series with my speaker. I have not noticed any distortion, but I have low expectations give the tiny speaker that I have connected.

At one point, I wired up a jack and tested through an amp, and I was pleased with the sound quality. Based on my notes, I ran each DAC channel through a 4.7K resistor and a 1uf cap on the way to the jack. I also grounded the wire that ran from the cap to the jack through a 10k bleeder resistor.

I am doing a similar project and I also have the repetition problem how can I be correcting this?