For a project I'm doing I've used an ESP8266/12e, a RTC Module DS3231 and a DFplayerMini
Basically it's a caller for birds and it has to play a 12-minute long MP3. The MP3 file should be played for 2 hours at the sunrise and 2 hours before the sunset, so each time it should be played 10 times (10 × 12 = 120 minutes (2 hours))
The code I wrote so far (some parts are omitted for brevity):
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Wire.h>
#include <RtcDS3231.h>
#define DELAY_ONPLAY 1000
#define DELAY_ONPAUSE 20000
// RTC Library (I2C)
RtcDS3231<TwoWire> rtcObject(Wire);
// MP3 Serial communication
SoftwareSerial mySoftwareSerial(14, 12);
DFRobotDFPlayerMini myDFPlayer;
// Variables
int volume, mth, day, h, m;
// State of the playback
int playbackCount = 0;
bool isPlaying = false;
RtcDateTime currentTime;
void setup() {
mySoftwareSerial.begin(9600);
// Start serial connection
Serial.begin(115200);
// Start I2C
rtcObject.Begin();
if (!myDFPlayer.begin(mySoftwareSerial)) {
while(true){
delay(10);
}
}
/* Get the value of potentiometer in the range of [3..30] and
* set the volume
*/
setVolume();
}
void loop() {
setVolume();
currentTime = rtcObject.GetDateTime(); //get the time from the RTC
mth = currentTime.Month();
day = currentTime.Day();
h = currentTime.Hour();
m = currentTime.Minute();
/* The caller is not playing: check if date and time should
* start the playback
*/
if (isPlaying == false) {
if (startSunrise() || startSunset()) {
isPlaying = true;
}
else {
// Nothing to do for the next 20 seconds
delay(DELAY_ONPAUSE);
}
}
else {
// Currently playing
if (playbackCount < 10) {
if (/* MP3mini_is_idle */) {
myDFPlayer.play(1);
playbackCount = playbackCount + 1;
}
}
else {
playbackCount = 0;
isPlaying = false;
Serial.print("End of playback");
}
delay(DELAY_ONPLAY);
}
}
void setVolume() {
// Get the value of potentiometer in the range of [3..30]
volume = map(analogRead(A0), 0, 1023, 2, 30);
volume = constrain(volume, 3, 30);
// Set the player volume
myDFPlayer.volume(volume);
Serial.println(String(volume));
}
bool startSunrise() {
/* at the sunrise the call has to be played for 2 hours */
if (mth == 2) {
if ((day == 20 && h == 7 && m == 8) ||
(day == 21 && h == 7 && m == 6) ||
...
(day == 28 && h == 6 && m == 54) ||
(day == 29 && h == 6 && m == 52)) { return true; }
}
if (mth == 3) {
if ((day == 1 && h == 6 && m >= 49) ||
(day == 2 && h == 6 && m >= 47) ||
(day == 3 && h == 6 && m >= 45 ) ||
(day == 4 && h == 6 && m >= 43) ||
...
(day == 27 && h == 6 && m >= 0) ||
(day == 28 && h == 5 && m >= 58)) { return true; }
}
return false;
}
bool startSunset() {
/* 2 hours before sunset the call has to be played for 2 hours */
if (mth == 2) {
if ((day == 20 && h == 15 && m >= 41) ||
(day == 21 && h == 15 && m >= 42) ||
...
(day == 28 && h == 15 && m >= 52) ||
(day == 29 && h == 15 && m >= 54)) { return true; }
}
if (mth == 3) {
if ((day == 1 && h == 15 && m >= 56) ||
(day == 2 && h == 15 && m >= 58) ||
(day == 3 && h == 15 && m >= 59) ||
(day == 4 && h == 16 && m >= 1) ||
...
(day == 27 && h == 16 && m >= 31) ||
(day == 28 && h == 16 && m >= 33)) { return true; }
}
return false;
}
The part I'm stuck on is
if (playbackCount < 10) {
if (/* MP3mini_is_idle */) {
myDFPlayer.play(1);
playbackCount = playbackCount + 1;
}
}
How do I detect in the if
condition if the MP3 is actually playing before play it again?
I think a 12-minute delay()
is not the right approach.
In the image below the DFPlayerMini pinout: I noticed It has a BUSY
pin but I haven't found examples so far that uses this pin to detect the playback state.
Thanks for any suggestion.