Sensor Activated DFPlayer Mini Question

This is my first post, so I hope I'm doing this correctly!

I have some limited experience with arduino. I have appreciated all of the answers to other people's questions on this forum. Those answers have helped me learn and modify existing programs. Thank you!

My current project is a simple motion activated mp3 player with 20 short different mp3s.

I have used the following code from the following YouTube video: How to Make a Talking PIR Motion Security System - YouTube
Just posting the video to give the source credit. No need to watch.

The code is:


#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

#define SENSORPIN 9
#define PAUSETIME 5000

void setup() {
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  pinMode(SENSORPIN, INPUT);

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

  //Use softwareSerial to communicate with MP3
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    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);
  }
  Serial.println(F("DFPlayer Mini online."));

  //Set volume value (From 0 to 30)
  myDFPlayer.volume(30);
}

void sensorActivated() {
  int pirSensor = digitalRead(SENSORPIN);
  if(pirSensor == HIGH)
  {
    Serial.println("Sensor Activated");
    Serial.println("DFPlayer Working...");
    myDFPlayer.play(1);
  }
  return;
}

void loop() {
  sensorActivated();
  delay(PAUSETIME);
}

The SD card has nothing on it but 20 mp3s numbered from 0001 through 0020. They are not in a folder.

I have everything hooked up correctly and the code works fine with one exception. It will not go to the next mp3 on the SD card in the DFPlayer. It repeats file 0001 each time the sensor is triggered.

Can someone help me figure out how to make it play the next file each time it is triggered and then go back to 0001 once it plays the 20th file and continue playing the list until I turn the arduino off?

Any help would be appreciated!

Thanks in advance!

Yes. Posting in "project guidance" is perfect.

Not the best. Helpers usually don't want to spend time watching any long story. You better make a short story here.

Posting code, use code tags, </>. You posted text, a novell.

Modify Your post and know that all helpers are newbies regarding Your project. Tell us like we are babies.....

What do you think this line will do? It only plays track #1. If you want the next track, you should make that a variable that increments each time the sensor is activated and then rolls over to start again at track 1 when the last track plays.

You also do not want to start playing something if the sensor is activated, but when it becomes activated. Look at the State change detection example in the IDE to learn how to detect this properly (File->examples->02.digital->State Change Detection)

Thanks for the help @Railroader I just reformatted the text.

OK, so I appreciate @Railroader and @blh64 responses. I reformatted the above post to conform to the code standards.

I've also included an incremental variable to change the file being played and a for statement to check when the variable gets to 20.

Now I get a different issue. With the following code, it starts playing file 13 (instead of 1) then plays through 20 (sequentially) then goes back to 1 and plays through 3 then ends. It does not play files 4-12.

I can't figure out why it doesn't start with 1, play through 20 sequentially and then go back to 1.

What am I missing?

#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

#define SENSORPIN 9
#define PAUSETIME 7000

int soundCounter = 0;

void setup() {
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  pinMode(SENSORPIN, INPUT);

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

  //Use softwareSerial to communicate with MP3
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    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);
  }
  Serial.println(F("DFPlayer Mini online."));

  //Set volume value (From 0 to 30)
  myDFPlayer.volume(30);
}

void sensorActivated() {
  int pirSensor = digitalRead(SENSORPIN);
  if(pirSensor == HIGH)
  {
    Serial.println("Sensor Activated");
    Serial.println("DFPlayer Working...");
    myDFPlayer.play(soundCounter);
    for(int soundCounter; soundCounter < 20; soundCounter++);
  }
  return;
}

void loop() {
  sensorActivated();
  delay(PAUSETIME);
}

That doesn't work. Try soundCounter ++ %20;

That will make the counter go from 0 to 19 and then zero.

Thank you!

Just so I'm clear it should be

soundCounter ++ %20;

in place of the entire for statement?

I just tried that and it did not fix it.

That line does absolutely nothing (other than possibly waste some CPU cycles). You are declaring a completely new variable soundCounter insdie the for() loop with has nothing to do with the global variable of the same name. You might think they are the same, but the compiler does not.

It appears you may need to take some time and learn C/C++ just like we all did at some point.

You also need to take my advise in the previous post about state change detection, not just playing the next song if the PIR sensor is high. You somewhat get around that by having a massive delay() every time through loop, but that is not the best way since you are only checking the sensor once every 7 seconds which will make the program respond slowly. At the very least, only do the delay() if the PIR sensor has been activated.

#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

#define SENSORPIN 9
#define PAUSETIME 7000

int soundCounter = 1;

void setup() {
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  pinMode(SENSORPIN, INPUT);

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

  //Use softwareSerial to communicate with MP3
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    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);
  }
  Serial.println(F("DFPlayer Mini online."));

  //Set volume value (From 0 to 30)
  myDFPlayer.volume(30);
}

void sensorActivated() {
  int pirSensor = digitalRead(SENSORPIN);
  if(pirSensor == HIGH)
  {
    Serial.println("Sensor Activated");
    Serial.print("Playing track #");
    Serial.println(soundCounter);
    myDFPlayer.play(soundCounter);
    soundCounter++;   // increment track for next time
    if ( soundCounter > 20 ) {
      // wrap around if past last track
      soundCounter = 1;
    }
  delay(PAUSETIME);
  }
}

void loop() {
  sensorActivated();
}

@blh64 Thank you!

You are 100% correct, I just need to dig in and learn C/C++! That's now on my list.

After I uploaded the code, everything works...but it still starts from track 13 (even though it shows it is track 1) and it would cut out after either the 11th or 12th track it played. I found that when I increased the delay to 10 seconds, it kept going.

Could this be something happening in the processor of the arduino nano? That it doesn't finish computing and then just stops working? It even shows that the next track is playing on the serial monitor but no sound comes out. (I guess that means it's not the arduino?)

That would also mean the sensor is still sensing and sending the signal to the nano...

So I guess that could be that the DFPlayer may not be able to process within the 7 second delay?

I even changed out DFPlayers just to make sure I didn't get a bad one, but the same thing occurred. (I guess I could have gotten a bad batch?)

I also triggered the sensor 10 times in a row (with its 7 second delay), then waited 30 seconds to trigger it again and then waited between 7 and 20 seconds to trigger it each succeeding time. It kept working, so that's when I thought increasing the delay might solve the problem in the short term.

Any thoughts?

take a look at the FullFunction example that comes with the DFmini library. If all your files are in the /mp3 directory, you can play them using .playMp3Folder(fileno) command. If you just use the play() command, it takes the first file on the SD card (I believe) not necessarily 0001.mp3.

You can also read the state of the player to determine if the current file is still playing or has finished so you won't start a new file until after the current one is done.

Otherwise baffling file playing issues can sometimes be down to the sensitivity of the DFR module about the SD file structure. I'd recommend formatting it and recreating the requred content. A Quick Format is usually adequate but on several occasions in desperation I've done a full format and been rewarded.

I prepared 20 MP3s but couldn't get your code running. I successfully ran that from @blh64, but strangely always 16 files starting from track 5. It's late here so I'll have another look in the morning - and perhaps reformat my SD card. :slightly_smiling_face:

EDIT: Meant to add that I emulated your PIR with a wire manually switched between 0V and 5V (to A4 in my case).

Discovered why blh64's sketch was not playing the first 4 of 20 files. And file 0001 would probably not have been played anyway. See commented code below.

// Sketch now plays all 20 tracks then repeats
// Two reasons for previous failure here:
// - Some of my MP3s were very short, about 5 seconds
// - Delay is needed in setup to allow DFR module to 'catch up'.

#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

#define SENSORPIN A4 // Changed from D9 to suit my current UNO & breadboard

#define PAUSETIME 4000 // Reduced a bit for speed of testing

int soundCounter = 1;

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  pinMode(SENSORPIN, INPUT);

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

  //Use softwareSerial to communicate with MP3
  if (!myDFPlayer.begin(mySoftwareSerial, true, false))
  {
    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);
  }
  Serial.println(F("DFPlayer Mini online."));

  //Set volume value (From 0 to 30)
  myDFPlayer.volume(20);

  delay(2000); // Time for module to catch up
} // End setup

void sensorActivated()
{
  int pirSensor = digitalRead(SENSORPIN);
  if (pirSensor == HIGH)
  {
    //    Serial.println("Sensor Activated");


    myDFPlayer.play(soundCounter);

    Serial.print("Playing track #");
    Serial.println(soundCounter);
    soundCounter++;   // increment track for next time
    if ( soundCounter > 20 )
    {
      // wrap around if past last track
      soundCounter = 1;
    }
    delay(PAUSETIME);
  }
}

void loop()
{
  sensorActivated();
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.