How to reset arduino nano after program cycle

I have put together a piece of code through suggestions on this forum that I finally go to work perfectly. When a button is pressed a relay opens then four different dfplayers play simultaneously. When one designated player (4) finishes the relay is closed and the hardware waits for another input. The only issue I found is that after a week or so the arduino freezes and you have to turn it off then back on again. I assumed that this would be easily fixable via software but I can't figure out how to do it. Every attempt I have tried to implement creates an endless loop of cycling through the restarting of the dfplayers. I don't really care if it resets after every cycle or after a certain number of cycles....It just doesn't seem to work at all for me. All I tried was the software reset. I understand that there is a way to use a jumper wire from the reset pin but I didn't know how to mesh that code with my own. I got suggestions from here but couldn't make it work. - How to Reset Arduino Programmatically

Here is my initial code:

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

// Start 4 serial ports
SoftwareSerial mySerial1(3, 4);   // RX, TX dfplayer 1
SoftwareSerial mySerial2(5, 6);   // RX, TX dfplayer 2
SoftwareSerial mySerial3(7, 8);   // RX, TX dfplayer 3
SoftwareSerial mySerial4(9, 10);  // RX, TX dfplayer 4

// We declare variables for the 4 dfplayer
DFRobotDFPlayerMini DFPlayer1;
DFRobotDFPlayerMini DFPlayer2;
DFRobotDFPlayerMini DFPlayer3;
DFRobotDFPlayerMini DFPlayer4;

const int relayPin = 13;   // Pin connected to the relay module
const int busyPin = 11;    // Pin connected to the Busy pin of DFPlayer4

void setup() {
  pinMode(relayPin, OUTPUT);   // Set the relay pin as OUTPUT
  pinMode(busyPin, INPUT);     // Set the Busy pin as INPUT

  // Definition of the button connected to pin 2 and GND
  pinMode(2, INPUT_PULLUP);

  // We initialize the 4 serial channels
  mySerial1.begin(9600);
  mySerial2.begin(9600);
  mySerial3.begin(9600);
  mySerial4.begin(9600);

  // Initialize the 4 players
  DFPlayer1.begin(mySerial1);
  DFPlayer2.begin(mySerial2);
  DFPlayer3.begin(mySerial3);
  DFPlayer4.begin(mySerial4);

  // set volume for dfplayers
  DFPlayer1.volume(25);   // Set volume value (0~30).
  DFPlayer2.volume(25);   // Set volume value (0~30).
  DFPlayer3.volume(25);   // Set volume value (0~30).
  DFPlayer4.volume(10);   // Set volume value (0~30).
}

void loop() {
  if (digitalRead(2) == LOW) {
    DFPlayer1.play(1);
    DFPlayer2.play(1);
    DFPlayer3.play(1);
    DFPlayer4.play(1);
    digitalWrite(relayPin, HIGH);   // Turn on the relay module
  }

  delay(250);   // Small delay for the players to start playing

  // Check if DFPlayer4 is still playing
  while (digitalRead(busyPin) == LOW) {
    // Code stopped here until DFPlayer4 finishes playing.
  }

  digitalWrite(relayPin, LOW);   // Turn off the relay module
}


1 Like

The best way for your situation would be probably to set up the watchdog let say for 4 seconds.
It have to be "renewed" within this time otherwise it will cause a reset, so if the programs hangs up the watchdog will reset the Nano.

that sounds awesome...but can you give me some pointers on how to implement that?

I modified the code to add a watchdog. Great suggestion. Clearly, I did something wrong. What it does now is start playing, then 8 seconds into the audio clip it starts a loud clicking which I would assume is the nano resetting but it doesn't stop playing.

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <avr/wdt.h>  // Include the Watchdog Timer library

// Start 4 serial ports
SoftwareSerial mySerial1(3, 4);   // RX, TX dfplayer 1
SoftwareSerial mySerial2(5, 6);   // RX, TX dfplayer 2
SoftwareSerial mySerial3(7, 8);   // RX, TX dfplayer 3
SoftwareSerial mySerial4(9, 10);  // RX, TX dfplayer 4

// We declare variables for the 4 dfplayer
DFRobotDFPlayerMini DFPlayer1;
DFRobotDFPlayerMini DFPlayer2;
DFRobotDFPlayerMini DFPlayer3;
DFRobotDFPlayerMini DFPlayer4;

const int relayPin = 13;   // Pin connected to the relay module
const int busyPin = 11;    // Pin connected to the Busy pin of DFPlayer4

void setup() {
  pinMode(relayPin, OUTPUT);   // Set the relay pin as OUTPUT
  pinMode(busyPin, INPUT);     // Set the Busy pin as INPUT

  // Definition of the button connected to pin 2 and GND
  pinMode(2, INPUT_PULLUP);

  // We initialize the 4 serial channels
  mySerial1.begin(9600);
  mySerial2.begin(9600);
  mySerial3.begin(9600);
  mySerial4.begin(9600);

  // Initialize the 4 players
  DFPlayer1.begin(mySerial1);
  DFPlayer2.begin(mySerial2);
  DFPlayer3.begin(mySerial3);
  DFPlayer4.begin(mySerial4);

  // set volume for dfplayers
  DFPlayer1.volume(25);   // Set volume value (0~30).
  DFPlayer2.volume(25);   // Set volume value (0~30).
  DFPlayer3.volume(25);   // Set volume value (0~30).
  DFPlayer4.volume(10);   // Set volume value (0~30).

  wdt_enable(WDTO_8S);  // Enable Watchdog Timer with an 8-second timeout
}

void loop() {
  if (digitalRead(2) == LOW) {
    DFPlayer1.play(1);
    DFPlayer2.play(1);
    DFPlayer3.play(1);
    DFPlayer4.play(1);
    digitalWrite(relayPin, HIGH);   // Turn on the relay module
  }

  delay(250);   // Small delay for the players to start playing

  // Check if DFPlayer4 is still playing
  while (digitalRead(busyPin) == LOW) {
    // Code stopped here until DFPlayer4 finishes playing.
  }

  digitalWrite(relayPin, LOW);   // Turn off the relay module

  wdt_reset();  // Reset the Watchdog Timer to prevent reset

  // Insert other code here as needed
}

In your loop function you have this while loop. If that while loop takes more than 8 seconds then the watchdog will time out. You can either keep resetting the watchdog in there or you can rewrite this so that it doesn't need to block there.

void loop() {

  // Check if DFPlayer4 is still playing
  if (digitalRead(busyPin) == LOW) {
    // Code does nothing because DF player is playing
    //  But DOES NOT stop running.  
  } else {

    digitalWrite(relayPin, LOW);  // Turn off the relay module

    if (digitalRead(2) == LOW) {
      DFPlayer1.play(1);
      DFPlayer2.play(1);
      DFPlayer3.play(1);
      DFPlayer4.play(1);
      digitalWrite(relayPin, HIGH);  // Turn on the relay module
      delay(250); // if you really need this...
    }
  }

  wdt_reset();  // Reset the Watchdog Timer to prevent reset

  // Insert other code here as needed
}

is there an 8 second limit? I tried just changing that to the audio track length and I get an error.

how do you test something like this to see that it is working?

byte idx = 0;

void(* resetFunc) (void) = 0; // create a standard reset function

void setup() 
{
  Serial.begin(19200);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  delay(2000);
  Serial.print("\r\n\r\n");
  Serial.println(idx);
}

void loop() 
{
  digitalWrite(13, HIGH);
  idx ++;
  Serial.println(idx);
  delay(5000); 
  resetFunc();
}

thank you. I am confused as to where to put this code in my own.

That will let you reset from code. But you were describing code that is locked up. If the code is freezing up then it won't be able to execute that statement. But the watchdog will still reset the board.

Most of it just proves the thing out.
The essential lines are --

void (* resetFunc) (void) = 0;
and
resetFunc();

Place void (* resetFunc) (void) = 0;
before setup() ("as per" the example).
The function call gets placed as appropriate (some criterion is met / not met and the function is called).
It's not clear, to me, why a software reset is necessary.

It's not. His board is freezing. Needs hardware to do it. If the code freezes how will this function get called?

It could be called before the Big Freeze?
It works "perfectly", by accounts, however, it 'freezes' - the two propositions are contradictory.

If you know when the freeze is coming. It sounds like the OP doesn't.

Look I'm just saying how it could be done. If it were my project I'd find out why it was freezing. I wouldn't just stick the watchdog in and hope. I'd be afraid that it meant something more.

I'm surprised that the code works at all. Most people have troubles with just two instances of SoftwareSerial, and you have four.

This is a project for a Mega, with four hardware serial ports.

@Delta_G - I agree.

I had a quick look at the DFPlayer Mini MP3 Player - DFRobot manual and deep in there they mention that if the device hangs up then you need to disconnect and reconnect power.

I also looked that their library and samples. The challenge therefore is whether the arduino has hung or the other hardware on the end of the serial ports has hung and then what can you do about it?

There is a timeout parameter in the DFRobot library so maybe look into that. Some means of controlling the power to the other devices may be needed (i.e. another relay to control the power to them) and code to see if they are responding is needed (as per the samples for the library) and if not then cut their power, wait a few seconds and then see if they come alive.

Good luck. Be patient. These kinds of problems are very difficult to isolate and fix.

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