DFMiniMp3 random playback, but only one time

Hello,

I would like to use one button (sw1) that will playback if button is pressed only one time mp3 file, but in random selection in folder.

I used fonction mp3.playRandomTrackFromAll();

if(digitalRead(sw1))
  {    
      mp3.playRandomTrackFromAll(); // random of all folders on sd
       delay(1000);

But it play non stop all files.

Please can you help me?

Here is the code:

/*
 TANK VITRINE PROJECT
*/

#include <SoftwareSerial.h>
#include <DFMiniMp3.h>


int sw1 = 3; // Push Button n°1 (pin3) // Random files playing
int sw2 = 4; // Push Button n°2 (pin4)
int sw3 = 5; // Push Button n°1 (pin5)
int sw4 = 6; // Push Button n°1 (pin6)


class Mp3Notify
{
public:

static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action)
 {
   if (source & DfMp3_PlaySources_Sd) 
   {
       Serial.print("SD Card, ");
   }
   if (source & DfMp3_PlaySources_Usb) 
   {
       Serial.print("USB Disk, ");
   }
   if (source & DfMp3_PlaySources_Flash) 
   {
       Serial.print("Flash, ");
   }
   Serial.println(action);
 }
 
 static void OnError(uint16_t errorCode) // DA
 {
   // see DfMp3_Error for code meaning
   Serial.println();
   Serial.print("Com Error ");
   Serial.println(errorCode);
 }

 //static void OnPlayFinished(uint16_t globalTrack)
 static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) // DA
 {
   Serial.println();
   Serial.print("Play finished for #");
   //Serial.println(globalTrack);
   Serial.println(track);     
}
 static void OnPlaySourceOnline(DfMp3_PlaySources source) // DA
 {
   PrintlnSourceAction(source, "online");
 }
 static void OnPlaySourceInserted(DfMp3_PlaySources source) // DA
 {
   PrintlnSourceAction(source, "inserted");
 }
 static void OnPlaySourceRemoved(DfMp3_PlaySources source) // DA
 {
   PrintlnSourceAction(source, "removed");
 }

 static void OnCardOnline(uint16_t code) // DA
 {
   Serial.println();
   Serial.print("Card online ");
   Serial.println(code);     
 }

 static void OnCardInserted(uint16_t code) // DA
 {
   Serial.println();
   Serial.print("Card inserted ");
   Serial.println(code); 
 }

 static void OnCardRemoved(uint16_t code)
 {
   Serial.println();
   Serial.print("Card removed ");
   Serial.println(code);  
 }
};

// instance a DFMiniMp3 object, 
// defined with the above notification class and the hardware serial class
//
DFMiniMp3<HardwareSerial, Mp3Notify> mp3(Serial);
// Some arduino boards only have one hardware serial port, so a software serial port is needed instead.
// comment out the above definition and uncomment these lines
//SoftwareSerial secondarySerial(10, 11); // RX, TX
//DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(secondarySerial);




void setup() 
{
 //4 push buttons with pulldown
 pinMode(sw1,INPUT);
 pinMode(sw2,INPUT);
 pinMode(sw3,INPUT);
 pinMode(sw4,INPUT);
 
 Serial.begin(115200);
 Serial.println("initializing...");  
 
 mp3.begin();
 
 // show some properties and set the volume
 uint16_t volume = mp3.getVolume();
 Serial.print("volume ");
 Serial.println(volume);
 mp3.setVolume(30);  
 uint16_t count = mp3.getTotalTrackCount(DfMp3_PlaySource_Sd);
 Serial.print("files ");
 Serial.println(count);

/*
 // ???
 uint16_t mode = mp3.getPlaybackMode();
 Serial.print("playback mode ");
 Serial.println(mode);
 
 Serial.println("starting...");
 // ??
 */
}





void waitMilliseconds(uint16_t msWait)
{
 uint32_t start = millis();
 
 while ((millis() - start) < msWait)
 {
   // calling mp3.loop() periodically allows for notifications 
   // to be handled without interrupts
   mp3.loop(); 
   delay(1);
 }
}

void loop() 
{

  if(digitalRead(sw1))
 {    
     mp3.playRandomTrackFromAll(); // random of all folders on sd
      delay(1000); 
 }
 
 if(digitalRead(sw2))
 {    
     mp3.playMp3FolderTrack(2);  // Play track 0002
     delay(1000); 
 }
 
 if(digitalRead(sw3))
 {    
     mp3.playMp3FolderTrack(3);  // Play track 0003
     delay(1000); 
 }
}//end of void

Are your buttons properly wired up with pull-down resistors? Your code expects that.

You are connected to the MP3 player with the hardware serial port but you are printing debug statements to the hardware serial port. You can't do both unless you are using a Mega and then use the second hardware port for the MP3. If you are using a Uno/Nano, then you need to use the SoftwareSerial version.

Once you start playing a song, you con't use delay() because that blocks. That is why the library has the waitMilliseconds() function since it calls mp3.loop() once in a while. If you did that, you would get the notification of when the track is done playing and then react to it however you want.

Hi, Thanks for help.

blh64: Are your buttons properly wired up with pull-down resistors? Your code expects that.

Yes, and yes, i'am using a NANO/

blh64: You are connected to the MP3 player with the hardware serial port but you are printing debug statements to the hardware serial port. You can't do both unless you are using a Mega and then use the second hardware port for the MP3.

OK, i will just delate printing codes.

blh64: Once you start playing a song, you con't use delay() because that blocks. That is why the library has the waitMilliseconds() function since it calls mp3.loop() once in a while. If you did that, you would get the notification of when the track is done playing and then react to it however you want.

So, I have to delate all delay() ?

Nothing changes.

Kayumba I would ditch the current library you are using and use PowerBroker’s Mini Fast Library, available here:

It might be downloadable now from Libraries in the IDE menu. I would highly recommend it, it cuts out all the unnecessary lines in the program. For reference, here is a Halloween Prop program I built that fires a solenoid relay as the DF Mini MP3 player plays a random track off the player.

#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
int buttonPin = 4;
int relay1 = 2;
SoftwareSerial mySerial(10, 11); // RX, TX
DFPlayerMini_Fast myMP3;

void setup()
{
  pinMode(4, INPUT_PULLUP);  // pushbutton pin
  pinMode(relay1, OUTPUT);  //relay 1 on solenoid
  Serial.begin(115200);
  mySerial.begin(9600);

  myMP3.begin(mySerial);
  
  Serial.println("Setting volume to max");
  myMP3.volume(30);
  delay(20);
  
  
}

void loop(){
  // put your main code here, to run repeatedly:
if (digitalRead(buttonPin) == LOW){
  delay(100);
 
  myMP3.playNext();  //Play the first mp3
  Serial.println("1st MP3 playing");
  digitalWrite(relay1, LOW);
  Serial.println("Solenoid Relay ON");
  delay(12000); // Give the DFPlayer some time
}
 else {
   myMP3.sleep ();  //mp3 player off 
   Serial.println("MP3 player off");
   digitalWrite(relay1,HIGH);


  //do nothing
}
}

As you can see, I still use the DELAY function, but its such a simple prop there was no need to do anything else. You may need to use the millis() function referenced above. Check out the State Case example to guide you in the IDE. Hope that helps.

halloweenrick: Kayumba I would ditch the current library you are using and use PowerBroker's Mini Fast Library, available here: https://github.com/PowerBroker2/DFPlayerMini_Fast

It might be downloadable now from Libraries in the IDE menu.

:) :) :) :)

Yes, you can install it via the Arduino IDE's Libraries Manager.

Also note that DFPlayerMini_Fast.h allows the call of ‘.randomAll();’. I do think, however, that it will only play one song per call. That being said, you can constantly poll ‘.isPlaying();’ and if it ever returns false, you can call ‘.randomAll()’ again to play another random track.

That will fix your problem for sure!

Ok, I will try to do something with DFPlayerMini_Fast.h library.

I'am very novice with Arduino codes. Car somebody give me with exemple code for DFPlayerMini_Fast.h That makes two push buttons plays random files in different folders if button pushed. Example button1 plays once file randomly in folder "sounds1", button2 plays once randomly in folder "sounds2".

Thank you very much.

Power_Broker:
Also note that DFPlayerMini_Fast.h allows the call of ‘.randomAll();’. I do think, however, that it will only play one song per call. That being said, you can constantly poll ‘.isPlaying();’ and if it ever returns false, you can call ‘.randomAll()’ again to play another random track. T

That will fix your problem for sure!

Here is what I done.

But it’s still playing non stop.

#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>


SoftwareSerial mySerial(10, 11); // RX, TX
DFPlayerMini_Fast myMP3;

int sw1 = 3; // Push Button n°1 (pin3) // Random plaing
int sw2 = 4; // Push Button n°2 (pin4)
int sw3 = 5; // Push Button n°1 (pin5)
//int sw4 = 6; // Push Button n°1 (pin6)


void setup() 
{
 //4 push buttons with pulldown
 pinMode(sw1,INPUT); // Random play button
 pinMode(sw2,INPUT);
 pinMode(sw3,INPUT);
 //pinMode(sw4,INPUT);
 
 Serial.begin(115200);
 mySerial.begin(9600);

 myMP3.begin(mySerial);
 
 Serial.println("Setting volume to max");
 myMP3.volume(5);
 delay(20);
 
 Serial.println("Playing track 1 for 5 sec");
 myMP3.play(1);
 delay(5000);

}

 
void loop() 
{

  if(digitalRead(sw1))
 {    
 
 Serial.println("Playing track 1 for 5 sec");
 myMP3.play(3);
 delay(5000);
     
}
if(digitalRead(sw2))
 {    
 
 Serial.println("Playing Random sounds");
 myMP3.randomAll();

}

What will be a code for sw2 to stop playing at the end of track?

if(digitalRead(sw2))
 {    
 
 Serial.println("Playing Random sounds");
 myMP3.randomAll();

}

Kayumba: Here is what I done.

But it's still playing non stop.

I thought that's what you wanted. I think we're misunderstanding each other. Keep in mind that without a video of your setup, I have no idea what your project is doing nor of what you want it to do, so you have to be VERY detailed in your descriptions of both.

1.) What EXACTLY do you want your project to do? Use as much detail as you can to make it clear. Do you want it to play all files in random order? How do you know what folder to play the files out of? etc.

2.) What EXACTLY is your project currently doing?

The answers to this question will help us answer your original question and fix your project.

Power_Broker:
I thought that’s what you wanted. I think we’re misunderstanding each other. Keep in mind that without a video of your setup, I have no idea what your project is doing nor of what you want it to do, so you have to be VERY detailed in your descriptions of both.

1.) What EXACTLY do you want your project to do? Use as much detail as you can to make it clear. Do you want it to play all files in random order? How do you know what folder to play the files out of? etc.

2.) What EXACTLY is your project currently doing?

The answers to this question will help us answer your original question and fix your project.

Sorry, it’s most be my bad English.
I will try to be clear.

Project :
Make a box with 3 buttons that plays sounds.
Every button plays randomly and separately mp3 audio files.
For each button one folder.
Exemple: Button1 = folder1_mp3, Button2 = folder2_mp3, Button3 = folder3_mp3

Fonctions:

When Button1 are pressed = play only once, one mp3 file in random selection from “folder1_mp3”.
When playback of audio file is finish = waiting for another push.

When Button2 are pressed = play only once, one mp3 file in random selection from “folder2_mp3”.
When playback of audio file is finish = waiting for another push.

Etc.

Stuff:
3 push buttons
1 Arduino NANO
1 DFPlayer mini mp3
1 Speaker
1 amplification

Ok, now I understand how you want it to work. What is it doing incorrectly now? What exactly is your project doing incorrectly?

Power_Broker: Ok, now I understand how you want it to work. What is it doing incorrectly now? What exactly is your project doing incorrectly?

if(digitalRead(sw2))
{    

Serial.println("Playing Random sounds");
myMP3.randomAll();

}

Its plays non stop all files. But I want that it plays only once.

Ok, so what you’ll have to do is use the random() function to come up with a random track to play every time a button is pressed. Then feed that random number to ‘.playFolder(uint8_t folderNum, uint8_t trackNum)’ to play the random track from a specific folder.

Like that ?

int randomInt = 0;

With void loop:

void loop() 
{

// Create random number of file
randomInt = random(1,10);

   if(digitalRead(sw1))
  {    
  
  Serial.println("Playing track 1 for 5 sec");
  myMP3.play(3);
  delay(5000);
      
}
 if(digitalRead(sw2))
  {    
  
  Serial.println("Playing Random sounds");
  myMP3.randomAll(randomInt);

  }

}

No, like this:

#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>


SoftwareSerial mySerial(10, 11); // RX, TX
DFPlayerMini_Fast myMP3;


int randomInt;
int sw1 = 3; // Push Button n°1 (pin3) // Random plaing
int sw2 = 4; // Push Button n°2 (pin4)
int sw3 = 5; // Push Button n°1 (pin5)
//int sw4 = 6; // Push Button n°1 (pin6)


void setup()
{
  //4 push buttons with pulldown
  pinMode(sw1, INPUT); // Random play button
  pinMode(sw2, INPUT);
  pinMode(sw3, INPUT);
  //pinMode(sw4,INPUT);

  Serial.begin(115200);
  mySerial.begin(9600);

  myMP3.begin(mySerial);

  Serial.println("Setting volume to max");
  myMP3.volume(5);
  delay(20);

  Serial.println("Playing track 1 for 5 sec");
  myMP3.play(1);
  delay(5000);
}


void loop()
{
  if (digitalRead(sw1))
  {
    Serial.println("Playing track 1 for 5 sec");
    myMP3.play(3);
    delay(5000);
  }
  
  if (digitalRead(sw2))
  {
    randomInt = random(1, 10);
    Serial.println("Playing Random sounds");
    myMP3.playFolder(1, randomInt);
  }
}

OK, thank you.

Now it plays the same file at every push of button "sw2"

On my card I have folder named mp3 inside I have 6 files .mp3 0001.mp3 0002.mp3 0003.mp3 0004.mp3 0005.mp3 0006.mp3

So I changed to:

if (digitalRead(sw2))
  {
    randomInt = random(1, 7);
    Serial.println("Playing Random sounds");
    myMP3.playFolder(1, randomInt);
  }

I'am using Mac OS, it's may causing the problem when I delate files from card etc

This might sound really dumb, but did you name the file: 0001.mp3

because you just need to name it 0001. If you do a deep dive into your files you'll see that the sd card adds ANOTHER .mp3 extension- which means you've actually got a file name of: 0001.mp3.mp3

And that's why your player keeps playing the one file over and over, as it can't find the file its looking for.

And yes, it took me an hour to figure that out the first time too.

If all your files are in "mp3", use 'myMP3.play(randomInt);'. I had you use 'myMP3.playFolder(1, randomInt);' because you said you wanted folders for mp3 files for each button.

Please read the documentation here and here.

:)

Allright, Thank you very much.