Using Random, Pause and Resume with a DF Mini MP3 player

Using PowerBroker's DF Mini Fast Library: GitHub - PowerBroker2/DFPlayerMini_Fast: Fast and easy to understand Arduino library to use the DFPlayer Mini MP3 module from DFRobot.com. This is a huge improvement (both in terms of execution speed and simplicity) to the standard library provided by DFRobot.com.

I would like to use an Arduino UNO, DF Mini Mp3 player, LED, and PIR sensor to make a startle noise prop for the Trick or Treaters. What I would like is to have an ambient soundtrack playing, namely Disney's Haunted Mansion soundtrack playing as they enter the yard. I would like that saved in Folder 0 of the MP3 player.

Once a Trick or Treater sets off the PIR, I would then like to play a random yell or scream from Folder 1. After that short scream, I would like to resume playing the soundtrack in Folder 0 from where it left off when the PIR triggered Folder 1 to go off. What I'm trying to avoid is guests and my own self having to hear "Welcome Foolish Mortals" (the start of the soundtrack) 1000 times Halloween night.

So I see this in this thread where PowerBroker references this function:

randomSeed(analogRead(0));
  randNumber = random(10);

But I have been unsuccessful in adapting that in my sketch.

Here it is. This does compile, but does not function. If I call a specific file, it does work. But I'm trying to use this with random in Folder 0, (maybe even in Folder 1) and Pausing the ambient soundtrack in Folder 1 and resuming it after the interruption by the PIR.

/* PIR sensor tester
/*/
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
SoftwareSerial mySerial(10, 11); // RX, TX
DFPlayerMini_Fast myMP3;
int ledPin = 7; // choose the pin for the LED
int inputPin = 9; // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0; // variable for reading the pin status

void setup() {
Serial.begin(115200);
mySerial.begin(9600);
myMP3.begin(mySerial);




Serial.println("Setting volume to max");
myMP3.volume(10);
delay(20);
pinMode(ledPin, OUTPUT); // declare LED as output
pinMode(inputPin, INPUT); // declare sensor as input

Serial.begin(9600);
Serial.println("Playing track 5");
myMP3.playFolder(0,1);
delay(5000);
}

void loop(){
val = digitalRead(inputPin); // read input value
if (val == HIGH) { // check if the input is HIGH
digitalWrite(ledPin, HIGH); // turn LED ON
if (pirState == LOW) {
// we have just turned on
Serial.println("Motion detected!");
// We only want to print on the output change, not state
pirState = HIGH;
myMP3.playFolder(1,1);
}
} else {
digitalWrite(ledPin, LOW); // turn LED OFF
if (pirState == HIGH){
// we have just turned off
Serial.println("Motion ended!");
// We only want to print on the output change, not state
pirState = LOW;
myMP3.playFolder(0,1);
}
}
}

I am unsure if I need to time or poll the player (isPlaying) to make this work. Thank you for your help in advance.

Formatted sketch:

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


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


int ledPin = 7;     // choose the pin for the LED
int inputPin = 9;   // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0;        // variable for reading the pin status


void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myMP3.begin(mySerial);
  
  myMP3.volume(10);
  delay(20);
  
  pinMode(ledPin, OUTPUT);
  pinMode(inputPin, INPUT);
  
  myMP3.playFolder(0, 1);
  delay(5000);
}


void loop()
{
  val = digitalRead(inputPin);
  
  if (val == HIGH)
  {
    digitalWrite(ledPin, HIGH);
    
    if (pirState == LOW)
    {
      Serial.println("Motion detected!");
      pirState = HIGH;
      myMP3.playFolder(1, 1);
    }
  }
  else
  {
    digitalWrite(ledPin, LOW);
    
    if (pirState == HIGH)
    {
      Serial.println("Motion ended!");
      pirState = LOW;
      myMP3.playFolder(0, 1);
    }
  }
}

You might need to use myMP3.playAdvertisement(trackNum); in order to "insert" a scream without restarting the track.

Thank you PowerBroker! However, the playAdvertisement function does not stop in the middle of the track, but causes the original ambient Haunted Mansion music to start again from the top.
Playing with PAUSE and RESUME however, does stop the Haunted Mansion music dead in its tracks, and picks it up where it stopped. Is there anyway you know of to combine those functions? I tried the Advertisement function with the DFRobotDFPlayerMini.h library as well, but its does the same thing. Here my code adapted from yours.

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


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


int ledPin = 7;     // choose the pin for the LED
int inputPin = 9;   // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0;        // variable for reading the pin status


void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myMP3.begin(mySerial);
 
  myMP3.volume(10);
  delay(20);
 
  pinMode(ledPin, OUTPUT);
  pinMode(inputPin, INPUT);
 
  myMP3.playFromMP3Folder(1);
  delay(5000);
}


void loop()
{
  val = digitalRead(inputPin);
 
  if (val == HIGH)
  {
    digitalWrite(ledPin, HIGH);
   
    if (pirState == LOW)
    {
      Serial.println("Motion detected!");
      pirState = HIGH;
      myMP3.playAdvertisement(3);
    }
  }
  else
  {
    digitalWrite(ledPin, LOW);
   
    if (pirState == HIGH)
    {
      Serial.println("Motion ended!");
      pirState = LOW;
      myMP3.playFromMP3Folder(1);
    }
  }
}

Also, I was not able to get the randnumber function working in the advertisement or other folders. For anyone following along, I also added an additional 1k resistor to the RX line, which eliminated the thumping sound by playing such a long music file. So both the TX and RX now have the 1k resistor in them.

Annndddd... as always, if you read the documentation, you can usually find what your are looking for.
From DFRobot's .doc file:

So, knowing that we can use Advertise to insert and have the track stop, I investigated further and realized that DFRobotDFPlayerMini has a stopAdvertise function. I hit Advertise, put in a 7 second delay, and the after hit stopAdvertise, the track plays exactly where it left off.

#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>
#include "Arduino.h"


SoftwareSerial mySerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;


int ledPin = 7;     // choose the pin for the LED
int inputPin = 9;   // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0;        // variable for reading the pin status


void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myDFPlayer.begin(mySerial);
 
  myDFPlayer.volume(10);
  delay(20);
 
  pinMode(ledPin, OUTPUT);
  pinMode(inputPin, INPUT);
  
  myDFPlayer.playMp3Folder(1);
  delay(5000);
}


void loop()
{
  val = digitalRead(inputPin);
 
  if (val == HIGH)
  {
    digitalWrite(ledPin, HIGH);
   
    if (pirState == LOW)
    {
      Serial.println("Motion detected!");
      pirState = HIGH;
      delay(100);
      myDFPlayer.advertise(3);
      delay(7000);
      myDFPlayer.stopAdvertise();
    }
  }
  else
  {
    digitalWrite(ledPin, LOW);
   
    if (pirState == HIGH)
    {
      Serial.println("Motion ended!");
      pirState = LOW;
     
    }
  }
}

Success! I may still investigate the random function for the screams, but I'm happy enough with the ambient Haunted Mansion music not restarting everytime the scream/advertisement goes off I may just stick with this. Thank you again PowerBroker!

Oooh, that's interesting! I'll take a look into the documentation and then add that functionality into my library when I get a chance.

Thank you!

I added the ability to stop an "advertisement" in release 1.1.3. Now you can use DFPlayerMini_Fast.h again instead of having to use the P.O.S. DFRobotDFPlayerMini.h

Thanks again!