Hi
So having a nightmare with this DFplayer (mainly because one is working fine and the other is acting up).
To summarize the set up - I've two phones - each has an arduino R4 wifi.
They are connected to each other using software serial on pins 8 and 9.
This communication is working fine.
Both arduino are connected to a DFplayer mini on pins 0 and 1. This is working fine with one player and not with the other.
Both also connect to a HBridge on pins 3 and 4 to ring the phones bell - this works fine.
One phone acts as the parent and triggers the second - they both ring if the hooks are down on both - if the hooks are not neither ring - if either phone is lifted while ringing they both stop and the lifted phone plays an mp3. If either phone is lifted outside the ring cycle they play a different track.
I have a number of switches in the code to turn off the bell, audio, serial logging, and remote logging.
Because I cannot use the serial monitor when connecting to the dfplayer I have been sending messages to the 2nd arduino where i can read them in the serial monitor.
As I said - one phone is fine the other is not.
I desoldered the dfplayer from the board and tested it with a simple circuit and it did work so theDFplayer is working.
When I put it back in my circuit it stops working.
I've checked and there are no shorts across any of the pins and so it seems like the arduino/serial/something else is causing the problem.
The code is below - but as I said it seems not to matter as the code works on the other phone
#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
#include "SoftwareSerial.h"
bool logging = true; /////////////////////////////////// enable to print serial values
bool remoteLog = false; //send log messages via arduinoSerial.
bool verbose = false; //////// enable for full printing to serial
bool audio = true; /////////////////////////////////// enable to use DF player
bool bell = false; //// enable to activagte bell
//// serial stuff that I don't understand fully
#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266)) // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/4, /*tx =*/5);
#define FPSerial softSerial
#else
#define FPSerial Serial1
#endif
///////// Variables for hardware connections
uint8_t hookPin = 2; // connection to phone hook
uint8_t Ha_pin = 3; // ConnectionA to HBridge
uint8_t Hb_pin = 4; // ConnectionB to HBridge
uint8_t commsRX = 8; // RX from Arduino2 TX
uint8_t commsTX = 9; // TX to Arduino2 RX
///////////////////////////////// DFplayer
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
////////////////////////////////////////// Variables for Arduino<->Arduino Communication
const byte numChars = 3; //arduinoComms data size
char receivedChars[numChars];
boolean newData = false; //serial data received`
SoftwareSerial arduinoSerial(commsRX, commsTX); // RX, TX for arduino comms
///////////////////////////////// Variables for ringer cycle
const uint32_t HALF_WAVE_PERIOD = 25; // 25mS = 20Hz
uint32_t lastHalfWaveAtMs;
uint32_t cycleStart;
bool toggle = false;
bool isSwitchOn;
uint32_t switchStateChangeAtMs;
volatile uint32_t pinChangeInterruptAtMs;
///////////////////////////////////////////// control variables
///////////////////////////////////////////// control variables
int ringDuration = 10 * 1000; // match to other arduino
int timerGap = 1 * 30 * 1000;
bool localHook = false;
bool localHook_prev = false;
bool ringTrigger = false;
bool remoteHook = false;
int triggerTimerStart;
bool timerTrigger = false;
int ringTimerStart;
bool ringTimerActive = false;
bool audioTrigger = false;
bool bellTrigger = false;
int audioTrack = 2;
//SETUP/////SETUP////SETUP/////SETUP//////SETUP//////SETUP/////SETUP///////
///////SETUP/////SETUP////SETUP/////SETUP//////SETUP//////SETUP/////SETUP//
//SETUP/////SETUP////SETUP/////SETUP//////SETUP//////SETUP/////SETUP//////
void setup() {
#if (defined ESP32)
FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
FPSerial.begin(9600);
#endif
Serial.begin(9600);
if (logging) {
logSerial("Setup Initialised - Arduino1");
logSerial("Logging enabled");
}
// delay(100);
arduinoSerial.begin(9600); //enable serial for arduinoCOmms
arduinoSerial.println("<Arduino1 has connected>");
logSerial("DFSerial & arduinoSerial enabled");
if (remoteLog) sendChars("LL"); // send LL for end of setup
// delay(100);
if (audio) initDFPlayer(); //initalise DFplayer routing if audio has been enabled
else logSerial("Sending:initDFPlayer()");
pinMode(hookPin, INPUT);
pinMode(Ha_pin, OUTPUT); //set pins for HBridge
pinMode(Hb_pin, OUTPUT);
uint32_t ms = millis(); // set initial values for finger cycle
lastHalfWaveAtMs = ms;
cycleStart = ms;
isSwitchOn = false;
switchStateChangeAtMs = ms;
pinChangeInterruptAtMs = ms;
delay(ringDuration); //delay to wait for initial ring cycle
sendLocalValues(); //send intial states
alignAudio(); // send at startup to ensure both phones on same track
receivedChars[0] == 'B';
logSerial("Setup Complete");
if (remoteLog) {
sendChars("L1"); // send L1 for end of setup
}
}
///////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP
//MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP/////
///////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP////MAIN LOOP
void loop() {
unsigned long currentTime = millis();
// if (remoteLog) sendChars("M1"); // send A1 for playing audio
//////// Conditions
localHook = digitalRead(hookPin); // localHook = 1 = TRUE - Phone is ON the Hook
recvWithStartEndMarkers(); //// Arduino Comms Receive
parseRemote(); /// update local variables based on remote conditions
showNewData(); /// Arduino Comms to Serial
sendLocalValues(); //// send local values to remote
/// timer to see if trigger ringing
if (currentTime - triggerTimerStart > timerGap) {
timerTrigger = true;
triggerTimerStart = currentTime;
}
// if (remoteLog) sendChars("M7"); // send A1 for playing audio
/// timer to see if ring timeer is within ring lenght
if (currentTime - ringTimerStart < ringDuration) {
ringTimerActive = true;
}
// if (remoteLog) sendChars("M8"); // send A1 for playing audio
////// actions
if (timerTrigger) { //// time to make call
if (localHook) { /// check if local phone is avaialble to take call
if (remoteHook) { /// check if remote phone is avaialble to take call
ringTimerStart = currentTime;
sendTrigger(); /// send trigger to phone 2
incrementAudio();
logSerial("Starting Ring Timer");
// if (remoteLog) sendChars("L3"); ///send L3 for starting ring Timer
} else logSerial("timertrigger - remote hook is up");
} else logSerial("timertrigger - local hook is up");
}
// if (remoteLog) sendChars("M9"); // send A1 for playing audio
if (ringTimerActive) { /// ring timer is active ring bell
if (!localHook) { /// check if local phone has been picked up
/// trigger local audio
if (audio) {
myDFPlayer.play(audioTrack);
if (remoteLog) sendChars("A1");
} else {
logSerial("Trigger Audio Track");
logSerial(String(audioTrack));
}
ringTimerStart = 0; //if picked up cancel ring timer
bellTrigger = false; //reset bell trigger
} else if (!remoteHook) { /// check if remote phone has been picked up
ringTimerStart = 0; /// if picked up cancel ring timer
bellTrigger = false; //reset bell trigger
} else {
if (bell) ringCycle();
logSerial("BellRinging");
}
} else {
if (!localHook) {
if (localHook != localHook_prev) /// check if local phone has been picked up
if (audio) myDFPlayer.play(1);
if (remoteLog) sendChars("A2");
else logSerial("Trigger Wrong Dial");
}
}
// if (remoteLog) sendChars("N1"); // send A1 for playing audio
if (audio) { // stop any audio if phone is on hook
if (localHook) {
if (localHook != localHook_prev) {
if (remoteLog) sendChars("Y7"); // send Y7 for marker here
myDFPlayer.stop();
// delay(100);
// logSerial("Stopping Audio");
}
}
}
// if (remoteLog) sendChars("N2"); // send A1 for playing audio
ringTimerActive = false; //resetRingTimer trigger
audioTrigger = false; //reset audio trigger
timerTrigger = false; //reset timer trigger
localHook_prev = localHook;
}
///END LOOP////END LOOP////END LOOP////END LOOP////END LOOP////END LOOP/////////
////////END LOOP////END LOOP////END LOOP////END LOOP////END LOOP////END LOOP////
///END LOOP////END LOOP////END LOOP////END LOOP////END LOOP////END LOOP/////////
void parseRemote() {
if (receivedChars[0] == 'R') {
// if (verbose) logSerial("remote hook is down - ready to receive - ring phone");
remoteHook = true; /// if remote hook is down
} else if (receivedChars[0] == 'B') {
// if (verbose) logSerial("remote hook is up - Busy - do nothing");
remoteHook = false; /// if remote hook is up
} else if (receivedChars[0] == 'Q') {
audioTrack = 2;
logSerial("audioTrack = 2");
}
}
void sendTrigger() {
logSerial("sendingTrigger to remote");
arduinoSerial.print("<");
arduinoSerial.print("T");
arduinoSerial.println(">");
}
void sendChars(char myMsg[]) {
arduinoSerial.print("<");
arduinoSerial.print(myMsg);
arduinoSerial.println(">");
}
void incrementAudio() {
if (audioTrack < 17) {
audioTrack++;
} else {
audioTrack = 2;
alignAudio();
}
}
void alignAudio() {
logSerial("sendingTrigger to remote");
arduinoSerial.print("<");
arduinoSerial.print("Q");
arduinoSerial.println(">");
}
void sendLocalValues() {
if (localHook != localHook_prev) {
logSerial("hook Changed State");
arduinoSerial.print("<");
arduinoSerial.print("C");
arduinoSerial.println(">");
if (localHook) {
///// hook is down ready to ring or receive calls.
///// hook is down = hook is true
arduinoSerial.print("<");
arduinoSerial.print("R");
arduinoSerial.println(">");
} else {
/////// hook is up - phone is busy
/////// hook is false
arduinoSerial.print("<");
arduinoSerial.print("B");
arduinoSerial.println(">");
}
}
}
void printDetail(uint8_t type, int value) {
switch (type) {
case TimeOut:
logSerial("Time Out!");
break;
case WrongStack:
logSerial("Stack Wrong!");
break;
case DFPlayerCardInserted:
logSerial("Card Inserted!");
break;
case DFPlayerCardRemoved:
logSerial("Card Removed!");
break;
case DFPlayerCardOnline:
logSerial("Card Online!");
break;
case DFPlayerUSBInserted:
logSerial("USB Inserted!");
break;
case DFPlayerUSBRemoved:
logSerial("USB Removed!");
break;
case DFPlayerPlayFinished:
logSerial("Number:");
logSerial(String(value));
logSerial(" Play Finished!");
break;
case DFPlayerError:
logSerial("DFPlayerError:");
switch (value) {
case Busy:
logSerial("Card not found");
break;
case Sleeping:
logSerial("Sleeping");
break;
case SerialWrongStack:
logSerial("Get Wrong Stack");
break;
case CheckSumNotMatch:
logSerial("Check Sum Not Match");
break;
case FileIndexOut:
logSerial("File Index Out of Bound");
break;
case FileMismatch:
logSerial("Cannot Find File");
break;
case Advertise:
logSerial("In Advertise");
break;
default:
break;
}
break;
default:
break;
}
}
void initDFPlayer() {
sendChars("X"); // send X for initDFplayer
logSerial("DFRobot DFPlayer Mini Demo");
logSerial("Initializing DFPlayer ... (May take 3~5 seconds)");
if (!myDFPlayer.begin(FPSerial, /*isACK = */ true, /*doReset = */ true)) { //Use serial to communicate with mp3.
logSerial("Unable to begin:");
logSerial("1.Please recheck the connection!");
logSerial("2.Please insert the SD card!");
sendChars("X1"); // send X1 for unable to init DFPlayer
while (true) {
delay(0); // Code to compatible with ESP8266 watch dog.
}
}
// myDFPlayer.begin(Serial,true,true);
logSerial("DFPlayer Mini online.");
sendChars("L2"); // send L2 for DFplayers Initialised
myDFPlayer.volume(15); //Set volume value. From 0 to 30
}
void ringCycle() {
uint32_t ms = millis();
if (!bellTrigger) cycleStart = ms; // prevent retrigger of cycle
bellTrigger = true;
// cycle is 500 ms off, 700mS on, 300mS off, 700ms on, 3300mS off
uint32_t msIntoCycle = ms - cycleStart;
if (verbose) logSerial(String(msIntoCycle));
bool inRingBurst = (msIntoCycle > 300 && msIntoCycle < 1200) || (msIntoCycle > 1600 && msIntoCycle < 2500);
if (msIntoCycle > 2500) cycleStart = ms;
// alternate and enable/disable H-Bridge
if (inRingBurst) {
if (verbose) logSerial("In ring burst");
if (ms - lastHalfWaveAtMs > HALF_WAVE_PERIOD) {
toggle = !toggle;
digitalWrite(Ha_pin, toggle);
digitalWrite(Hb_pin, !toggle);
lastHalfWaveAtMs = ms;
}
}
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (arduinoSerial.available() > 0 && newData == false) {
rc = arduinoSerial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
} else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
logSerial("AR2: ");
logSerial(receivedChars);
newData = false;
}
}
void logSerial(String message) {
// Handled overhere so logging to serial can easily be switched to send to other device.
if (logging) Serial.println(message);
return;
}