Can't get tutorial from Rachel De Barrios to work for DFPlayer MP3Player project

For the wiring diagram, step-by-step video, code explanation and more
motion-activated soundUse code tags to format code for the forum effects projects with Arduino, visit:

*/

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> // download this library from Arduino IDE "Manage Libraries"

int pirPin = 12; // Arduino pin the PIR sensor is connected to
int rxPin = 2; // Arduino pin the TX pin of mp3 player is connected to
int txPin = 3; // Arduino pin the RX pin of mp3 player is connected to

int motionStatus = 0; // variable to store the PIR's current reading (high or low)
int pirState = 0; // variable to store the PIR's state change

SoftwareSerial fxSerial (rxPin, txPin); // Software Serial object
DFRobotDFPlayerMini fxPlayer;

void setup() {
pinMode(pirPin, INPUT); // set Arduino pin that PIR is connected to as an INPUT
pinMode(rxPin, INPUT); // set Arduino pin that mp3 player TX is connected to as an INPUT
pinMode(txPin, OUTPUT); // set Arduino pin that mp3 player RX is connected to as an OUTPUT

Serial.begin(9600); // initialize Serial Monitor (for looking at PIR readings)
fxSerial.begin(9600); // initialize Serial communication for mp3 player
fxPlayer.begin(fxSerial); // tells mp3 player to use fxSerial for communication
fxPlayer.volume(20); // mp3 player volume (pick a value 10-30)

delay(10000); // allow 30-60 secs for PIR sensor to calibrate before proceeding with sketch
}

void loop() {
motionStatus = digitalRead(pirPin); // read the PIR pin's current output (is it HIGH or LOW?)
Serial.println(motionStatus);
// if PIR pin output is HIGH:
if (motionStatus == HIGH) {

if (pirState == LOW) {
  Serial.println("Motion Detected"); // print result to the serial monitor
  pirState = HIGH; // update the previous PIR state to HIGH
  
  fxPlayer.play(random(1,2)); // play a random track from 1 to 5 from micro SD card
  
  delay(20000); // length in microseconds of longest track
}
}

// or else if PIR pin output is LOW:
else {

if (pirState == HIGH) {
  Serial.println ("Motion Ended"); //print result to the serial monitor
  pirState = LOW; // update the previous PIR state to LOW
}
}
}

I’m not sure if my PIR sensor is working as intended. It will go off seemingly by itself. I’m not sure what is triggering it but it doesn't go off even when I hit it, but it will just go off by itself. Can someone also tell me the significance of the delays and if they matter? I know that it says to put a delay for the longest audio file’s length, but I have 2 second files, as well as 3 minute songs.

That is the timeout, adjusted using one of the (orange?) potentiometers. After sensing an object and turning on, the preset timeout turns the PIR off.

The PIR is not a touch-sensing device.

You can time each song and use the measured value "delay(measuredMilliSeconds)" for each song.

Two seconds in microseconds is 2000. Twenty seconds in microseconds is 20000 (20 * 1000). Three minutes in microseconds is 180000 (3* 60 * 1000).

How can I just make it so that my audio files will play all the way through and don't have to use the delay() function? I am also experiencing a popping sound as I use my audio files.

Use the BUSY output pin. Just be aware of its limitations (including not asserting instantly due to serial communication buffering and other factors).

Not an uncommon occurrence with some players. IIRC on the real DFPlayer Mini there is a zero ohm resistor on the bottom of the board you can move to another spot to squelch the audio amp when the track stops playing.

I am having trouble visualizing this. Do you have any pictures or videos?

Is the sketch in post 25 exactly the one we are now discussing? And what is the latest sketch, if it differs in any way from Rachel’s?

It’s late here but given your replies to the above I’ll try to address both of your outstanding issues tomorrow, Wednesday.

In the time since then, I have made some adjustments. I have been adding in custom wait times for each audio track, but I am trying to find a way in which I don’t have to do so.

The new sketch: 

/*This Arduino sketch plays a random track from a DFRobot PlayerMini
mp3 player module when motion is detected by a PIR sensor.

For the wiring diagram, step-by-step video, code explanation and more
motion-activated sound effects projects with Arduino, visit:

*/

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> // download this library from Arduino IDE "Manage Libraries"

int pirPin = 12; // Arduino pin the PIR sensor is connected to
int rxPin = 3; // Arduino pin the TX pin of mp3 player is connected to
int txPin = 2; // Arduino pin the RX pin of mp3 player is connected to
int track = 1;
int delayTime = 5000;

int motionStatus = 0; // variable to store the PIR's current reading (high or low)
int pirState = 0; // variable to store the PIR's state change

SoftwareSerial fxSerial (rxPin, txPin); // Software Serial object
DFRobotDFPlayerMini fxPlayer;

void setup() {
pinMode(pirPin, INPUT); // set Arduino pin that PIR is connected to as an INPUT
pinMode(rxPin, INPUT); // set Arduino pin that mp3 player TX is connected to as an INPUT
pinMode(txPin, OUTPUT); // set Arduino pin that mp3 player RX is connected to as an OUTPUT

Serial.begin(9600); // initialize Serial Monitor (for looking at PIR readings)
fxSerial.begin(9600); // initialize Serial communication for mp3 player
fxPlayer.begin(fxSerial); // tells mp3 player to use fxSerial for communication
fxPlayer.volume(30); // mp3 player volume (pick a value 10-30)

delay(10000); // allow 30-60 secs for PIR sensor to calibrate before proceeding with sketch
}

void loop() {
motionStatus = digitalRead(pirPin); // read the PIR pin's current output (is it HIGH or LOW?)

// if PIR pin output is HIGH:
if (motionStatus == HIGH) {

if (pirState == LOW) {
  Serial.println("Motion Detected"); // print result to the serial monitor
  pirState = HIGH; // update the previous PIR state to HIGH
  track = random(1,28);
  fxPlayer.play(track); // play a random track from 1 to 5 from micro SD card
   
 
    
  if(track == 1){
   delayTime = 16000;
  }
  if(track == 2){
   delayTime = 3000;
  }
  if(track == 3){
   delayTime = 2000;
  }
  if(track == 4){
   delayTime = 4000;
  }
  if(track == 5){
   delayTime = 221000;
  }
   if(track == 6){
   delayTime = 153000;
  }
  if(track == 7){
   delayTime = 153000;
  }
  if(track == 8){
   delayTime = 113000;
  }
  if(track == 9){
   delayTime = 27000;
  }
  if(track == 10){
   delayTime = 5000;
  }
  }
  delay(delayTime); // length in microseconds of longest track
}

// or else if PIR pin output is LOW:
else {

if (pirState == HIGH) {
  Serial.println ("Motion Ended"); //print result to the serial monitor
  pirState = LOW; // update the previous PIR state to LOW
}

}
}

try this.

URL shortener?

I'm studying your latest sketch this morning.

Let's fix the easiest one of your problems first. That annoying popping noise can be removed with additional player initialisation parameters.
Change this line
fxPlayer.begin(fxSerial); // tells mp3 player to use fxSerial for communication
to this
fxPlayer.begin(fxSerial, true, false); // tells mp3 player to use fxSerial for communication

Obviously I cannot test your sketch as it stands because your SD is populated with tracks of widely varying durations. But make that one change and let me know if the noise has gone. Like several aspects of this module's behaviour, it may not work on all clones, but I'm optimistic.

Your second outstanding issue, allowing full play of each track, is a bit harder. There are several approaches, the most popular being to connect the module's BUSY pin to an extra pin of the Arduino so that you can detect when a track has finished. It's also arguably the simplest to code, but (on some clones at least) is occasionally quirky in its behaviour. If I get time today I'll post more thoughts. Meanwhile, further searching of your own within the forum will turn up several examples of using the BUSY pin, including my own, so you may be able to complete the project yourself. More satisfying, yes?

EDIT: Wed 13 Nov 2024 11:05
Your sketch above does not even compile here. It's missing a curly bracket at the end Did you compile and run it before posting?

Updated sketch:

/*This Arduino sketch plays a random track from a DFRobot PlayerMini
mp3 player module when motion is detected by a PIR sensor.

For the wiring diagram, step-by-step video, code explanation and more
motion-activated sound effects projects with Arduino, visit:

*/

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> // download this library from Arduino IDE "Manage Libraries"

int pirPin = 12; // Arduino pin the PIR sensor is connected to
int rxPin = 3; // Arduino pin the TX pin of mp3 player is connected to
int txPin = 2; // Arduino pin the RX pin of mp3 player is connected to
int track = 1;
int delayTime = 5000;

int motionStatus = 0; // variable to store the PIR's current reading (high or low)
int pirState = 0; // variable to store the PIR's state change

SoftwareSerial fxSerial (rxPin, txPin); // Software Serial object
DFRobotDFPlayerMini fxPlayer;

void setup() {
  pinMode(pirPin, INPUT); // set Arduino pin that PIR is connected to as an INPUT
  pinMode(rxPin, INPUT); // set Arduino pin that mp3 player TX is connected to as an INPUT
  pinMode(txPin, OUTPUT); // set Arduino pin that mp3 player RX is connected to as an OUTPUT
  
  Serial.begin(9600); // initialize Serial Monitor (for looking at PIR readings)
  fxSerial.begin(9600); // initialize Serial communication for mp3 player
  fxPlayer.begin(fxSerial, true, false); // tells mp3 player to use fxSerial for communication
  fxPlayer.volume(30); // mp3 player volume (pick a value 10-30)
  
  delay(10000); // allow 30-60 secs for PIR sensor to calibrate before proceeding with sketch
}

void loop() {
  motionStatus = digitalRead(pirPin); // read the PIR pin's current output (is it HIGH or LOW?)  
  
  // if PIR pin output is HIGH:
  if (motionStatus == HIGH) {
    
    if (pirState == LOW) {
      Serial.println("Motion Detected"); // print result to the serial monitor
      pirState = HIGH; // update the previous PIR state to HIGH
      track = random(12,12);
      fxPlayer.play(track); // play a random track from 1 to 5 from micro SD card
       
     
        
      if(track == 1){
       delayTime = 16000;
      }
      if(track == 2){
       delayTime = 3000;
      }
      if(track == 3){
       delayTime = 2000;
      }
      if(track == 4){
       delayTime = 4000;
      }
      if(track == 5){
       delayTime = 221000;
      }
       if(track == 6){
       delayTime = 153000;
      }
      if(track == 7){
       delayTime = 153000;
      }
      if(track == 8){
       delayTime = 113000;
      }
      if(track == 9){
       delayTime = 27000;
      }
      if(track == 10){
       delayTime = 5000;
      }
      if(track == 11){
       delayTime = 6000;
      }
      }
      delay(delayTime); // length in microseconds of longest track
    }
  
    
  // or else if PIR pin output is LOW:
  else {
      
    if (pirState == HIGH) {
      Serial.println ("Motion Ended"); //print result to the serial monitor
      pirState = LOW; // update the previous PIR state to LOW
    }
  }
  }

The popping sound persists.

As usual, that sort of feedback is unhelpful. Exactly when does this 'popping' occur? Based on your mistakes so far my best guess would be that it's down to you. One likely candidate is your power supply. I've just ploughed through the posts and still cannot see a schematic of your circuit. Not a copy of part of Rachel's project.

One last contribution from me: reduce the player volume from 30 to 15.

Good luck.

I can look past the popping sound (which only happens when an audio file plays). I now want to know if there is some sort of bias that the Arduino has when choosing a random number. I've tried out my sketch a few times, and my Arduino keeps playing the same 5 files and not playing anything else. These are my 3rd, 6th, 8th, 9th, and 20th tracks.

The newest sketch:

/*This Arduino sketch plays a random track from a DFRobot PlayerMini
mp3 player module when motion is detected by a PIR sensor.

For the wiring diagram, step-by-step video, code explanation and more
motion-activated sound effects projects with Arduino, visit:

*/

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> // download this library from Arduino IDE "Manage Libraries"

int pirPin = 12; // Arduino pin the PIR sensor is connected to
int rxPin = 3; // Arduino pin the TX pin of mp3 player is connected to
int txPin = 2; // Arduino pin the RX pin of mp3 player is connected to
int track = 1;
int delayTime = 5000;

int motionStatus = 0; // variable to store the PIR's current reading (high or low)
int pirState = 0; // variable to store the PIR's state change

SoftwareSerial fxSerial (rxPin, txPin); // Software Serial object
DFRobotDFPlayerMini fxPlayer;

void setup() {
  pinMode(pirPin, INPUT); // set Arduino pin that PIR is connected to as an INPUT
  pinMode(rxPin, INPUT); // set Arduino pin that mp3 player TX is connected to as an INPUT
  pinMode(txPin, OUTPUT); // set Arduino pin that mp3 player RX is connected to as an OUTPUT
  
  Serial.begin(9600); // initialize Serial Monitor (for looking at PIR readings)
  fxSerial.begin(9600); // initialize Serial communication for mp3 player
  fxPlayer.begin(fxSerial); // tells mp3 player to use fxSerial for communication
  fxPlayer.volume(30); // mp3 player volume (pick a value 10-30)
  
  delay(10000); // allow 30-60 secs for PIR sensor to calibrate before proceeding with sketch
}

void loop() {
  motionStatus = digitalRead(pirPin); // read the PIR pin's current output (is it HIGH or LOW?)  
  
  // if PIR pin output is HIGH:
  if (motionStatus == HIGH) {
    
    if (pirState == LOW) {
      Serial.println("Motion Detected"); // print result to the serial monitor
      pirState = HIGH; // update the previous PIR state to HIGH
      track = random(1,31);
      Serial.println(track);
      fxPlayer.play(track); // play a random track from 1 to 5 from micro SD card
       
     
        
      if(track == 1){
       delayTime = 16000;
      }
      if(track == 2){
       delayTime = 3000;
      }
      if(track == 3){
       delayTime = 1000;
      }
      if(track == 4){
       delayTime = 4000;
      }
      if(track == 5){
       delayTime = 221000;
      }
       if(track == 6){
       delayTime = 153000;
      }
      if(track == 7){
       delayTime = 153000;
      }
      if(track == 8){
       delayTime = 53000;
      }
      if(track == 9){
       delayTime = 27000;
      }
      if(track == 10){
       delayTime = 5000;
      }
      if(track == 11){
       delayTime = 6000;
      }
      if(track == 12){
       delayTime = 216000;
      }
       if(track == 13){
       delayTime = 3000;
      }
      if(track == 14){
       delayTime = 30000;
      }
      if(track == 15){
       delayTime = 1000;
      }
      if(track == 16){
       delayTime = 57000;
      }
      if(track == 17){
       delayTime = 6000;
      }
      if(track == 18){
       delayTime = 2500;
      }
      if(track == 19){
       delayTime = 65000;
      }
      if(track == 20){
       delayTime = 2000;
      }
      if(track == 21){
       delayTime = 11000;
      }
      if(track == 22){
       delayTime = 166000;
      }
      if(track == 23){
       delayTime = 29000;
      }
      if(track == 24){
       delayTime = 6000;
      }
      if(track == 25){
       delayTime = 3000;
      }
      if(track == 26){
       delayTime = 150000;
      }
      if(track == 27){
       delayTime = 2000;
      }
      if(track == 28){
       delayTime = 2000;
      }
      if(track == 29){
       delayTime = 1500;
      }
      if(track == 30){
       delayTime = 500;
      }
      if(track == 31){
       delayTime = 3200;
      }
      }
      delay(delayTime); // length in microseconds of longest track
    }
  
    
  // or else if PIR pin output is LOW:
  else {
      
    if (pirState == HIGH) {
      Serial.println ("Motion Ended"); //print result to the serial monitor
      pirState = LOW; // update the previous PIR state to LOW
      
    }
  }
  }

My previous contribution was intended to be my last. But in the hope that you might learn something, I can't resist pointing out that, once again, you've ignored advice. I said:
"One last contribution from me: reduce the player volume from 30 to 15."

Do you begin to understand why successive respondents, initially trying to help, have stopped wasting their time?

I had already tried that previously. The popping sound had remained at the same volume, it just made it harder to hear the audio.

Sorry if I wasted your time.