Arduino nano stop executing code after few hours

Hello,

I’m working on a project and after few hours my arduino nano is still ON but he seem stuck. When i turn off and turn on everything become ok for few hours.

My project is a chicken door with :

=> 1 arduino nano
=> 2 relay
=> 2 contactor
=> 1 rtc

I think it’s a code problem ( out of memory or somthing ).

My code :

#include <LowPower.h>
#include <DS3232RTC.h>        // https://github.com/JChristensen/DS3232RTC
#include <Streaming.h>        // http://arduiniana.org/libraries/streaming/
#include <Wire.h>
 
const int wakeupPin = 2 ;
const bool PRINTENV = false;
volatile int woken = 0 ;
 
void
wakeUp()
{
    woken = 1 ;
}
 
void
setup()
{
    pinMode(wakeupPin, INPUT_PULLUP) ;
    pinMode(LED_BUILTIN, OUTPUT) ;
     //relay
    pinMode(6,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
    pinMode(7,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
    //Contactor
    pinMode(8,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
    pinMode(9,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
    
    Serial.begin(115200) ;
    delay(50) ;
    Serial.println(F("WAKING UP...")) ;
    Wire.setClock(400000) ;
 
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() != timeSet)
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time");

    Serial.println() ;
    delay(50) ;
 
    // initialize the alarms to known values, 
    // clear the alarm flags, clear the alarm interrupt flags
    // ALARM_1 will trigger at 30 seconds into each minute
    // ALARM_2 will trigger every minute, at 0 seconds.
    RTC.setAlarm(ALM1_MATCH_SECONDS, 30, 0, 0, 0);
    RTC.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0);
 
     
    // clear both alarm flags
    RTC.alarm(ALARM_1); RTC.alarm(ALARM_2);
 
    // We are going to output the alarm by going low onto the 
    // SQW output, which should be wired to wakeupPin
    RTC.squareWave(SQWAVE_NONE);
 
    // Both alarms should generate an interrupt
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.alarmInterrupt(ALARM_2, true);
}
 
void
loop()
{
  
    boolean isOpen=digitalRead(8);// et on l’affecte à la variable "a"
    boolean isClosed=digitalRead(9);// et on l’affecte à la variable "a"

    time_t t = RTC.get();
    if(hour(t) > 8  && hour(t) < 21 && isOpen == 0){
      //so we are on a day and it's closed so we open the gate
      printenv( isClosed, isOpen, "Open the gate", t);
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);
    }else if(hour(t) >= 21 && isClosed == 0){
     //so we are on a night and it's open so we open the gate
      printenv( isClosed, isOpen, "Close the gate", t);
      digitalWrite(6, LOW);
      digitalWrite(7, HIGH);
    }else{
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      // The INT/SQW pin from the DS3231 is wired to the wakeup pin, and
      // will go low when the alarm is triggered.  We are going to trigger
      // on the falling edge of that pulse.
      attachInterrupt(digitalPinToInterrupt(wakeupPin), wakeUp, FALLING) ;
   
      // Go into powerdown mode, waiting to be woken up by INT pin...
      LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF) ;
   
      // For now, let's just ignore transitions on this pin...
      detachInterrupt(digitalPinToInterrupt(wakeupPin)) ;
      // We have to clear the alarm condition to make the pin go back to
      // the high state.   I'm clearing both of them, because we are 
      // triggering every 30 seconds (in this example)
      RTC.alarm(ALARM_1) ; RTC.alarm(ALARM_2) ; 
      printenv( isClosed, isOpen, "Wait now", t);
    }

   delay(500) ;
}

void
printenv(bool isClosed,bool isOpen, const String& action, time_t t)
{
  if(PRINTENV){
      Serial.print(action);
      Serial.print(" => ");
      Serial.print("isClosed : ");
      Serial.print(isClosed);
      Serial.print(" - isOpen :");
      Serial.print(isOpen);
      Serial.print(" -  Time:");  
      Serial.print(hour(t));   
      Serial.print(" : "); 
      Serial.print(minute(t));   
      Serial.println("");
  }
}

Thanks !

Try using a char array instead of a String object in the printenv() function. String objects don't work too well in on RAM-restricted systems like microprocessors. They're usually fine at first but they fragment the microprocessor's memory and lead to crashes after a while.

Thanks, i’m gonna try that.

I think yesterday i tried a new version without logs and i had the same problem.

Agree, avoid Strings and make sure that your power supply is well filtered. Voltage spikes from the relay/contactor can reset or damage the Arduino.

Also, it is generally a bad idea to continuously attach/detach interrupts, and in this case, there is absolutely no need to do so. Attach once in setup() and you are done.

      attachInterrupt(digitalPinToInterrupt(wakeupPin), wakeUp, FALLING) ;
   
      // Go into powerdown mode, waiting to be woken up by INT pin...
      LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF) ;
   
      // For now, let's just ignore transitions on this pin...
      detachInterrupt(digitalPinToInterrupt(wakeupPin)) ;

Oh thanks i'm gonna try that.

My current battery is :

-> 2x 18650 : 4pcs meco 3.7v 4000mah protected rechargeable 18650 li-ion battery Sale - Banggood.com

-> 1 x Dual usb 5v 1a 2.1a mobile power bank 18650 battery charger pcb module board Sale - Banggood.com

(This is directly connected to my arduino nano with usb)

But i'm a bit lost on this point, can my setup do the job ?

I updated my code and alimentation but i have still my problem after 2 hours of execution.

Actually i use a ELEGOO nano, it can be my problem ?

Thx

Please post the latest code, using code tags, and a hand drawn wiring diagram, with all pins labeled and components identified. Also, please post links to the product pages or data sheets for the various devices.

Tell us exactly what happens when the system fails.

No, a Nano from any manufacturer has the same avr atmega328 chip which runs your code.

Unless... Does the chip say "WAVGAT" on it?

jremington:
Agree, avoid Strings and make sure that your power supply is well filtered. Voltage spikes from the relay/contactor can reset or damage the Arduino.

Also, it is generally a bad idea to continuously attach/detach interrupts, and in this case, there is absolutely no need to do so. Attach once in setup() and you are done.

I don't think it's unusual to attach() prior to going to sleep and detach() after waking up.

OP, can you try your code with the contactors disconnected? Maybe just replace them with LEDs to indicate activity...

How are the contactor coils connected to the Arduino? How is the power done?

I don’t think it’s unusual to attach() prior to going to sleep and detach() after waking up.

True, lots of people have bad habits that they picked up somewhere. There is no point in doing what you describe, when it is completely unnecessary (as in the above case) or in the unlikely event that it is necessary, and there are simpler and faster approaches.

jremington:
True, lots of people have bad habits that they picked up somewhere.

+1 for that synopsis! :sunglasses:

HI,

This is my code :

#include <LowPower.h>
#include <DS3232RTC.h>        // https://github.com/JChristensen/DS3232RTC
#include <Streaming.h>        // http://arduiniana.org/libraries/streaming/
#include <Wire.h>

const int wakeupPin = 2 ;
volatile int woken = 0 ;

void
wakeUp()
{
   woken = 1 ;
}

void
setup()
{
   pinMode(wakeupPin, INPUT_PULLUP) ;
   pinMode(LED_BUILTIN, OUTPUT) ;
    //relay
   pinMode(6,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
   pinMode(7,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
   //Contactor
   pinMode(8,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)
   pinMode(9,OUTPUT); //On indique à l’Arduino le mode du pin (entrée)

   Serial.begin(115200) ;
   delay(50) ;
   Serial.println(F("WAKING UP...")) ;
   Wire.setClock(400000) ;

   setSyncProvider(RTC.get);   // the function to get the time from the RTC
   delay(50) ;

   // initialize the alarms to known values,
   // clear the alarm flags, clear the alarm interrupt flags
   // ALARM_1 will trigger at 30 seconds into each minute
   // ALARM_2 will trigger every minute, at 0 seconds.
   RTC.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0);


   // clear both alarm flags
   RTC.alarm(ALARM_2);

   // We are going to output the alarm by going low onto the
   // SQW output, which should be wired to wakeupPin
   RTC.squareWave(SQWAVE_NONE);

   // Both alarms should generate an interrupt
   RTC.alarmInterrupt(ALARM_2, true);
   attachInterrupt(digitalPinToInterrupt(wakeupPin), wakeUp, FALLING) ;
}

void
loop()
{

   boolean isOpen=digitalRead(8);
   boolean isClosed=digitalRead(9);

   time_t t = RTC.get();
   if(hour(t) > 8  && hour(t) < 18 && isOpen == 0){
     //so we are on a day and it's closed so we open the gate
     digitalWrite(6, HIGH);
     digitalWrite(7, LOW);
   }else if(hour(t) >= 18 && isClosed == 0){
    //so we are on a night and it's open so we open the gate
     digitalWrite(6, LOW);
     digitalWrite(7, HIGH);
   }else{
     digitalWrite(6, LOW);
     digitalWrite(7, LOW);

     // Go into powerdown mode, waiting to be woken up by INT pin...
     LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF) ;

     // We have to clear the alarm condition to make the pin go back to
     // the high state.   I'm clearing both of them, because we are
     // triggering every 30 seconds (in this example)
     RTC.alarm(ALARM_2) ;

   }

  delay(500) ;
}

I tried to power it without a battery but i have the same problem ( after 1h30 approximatly).

My hardware :

→ arduino : (https://www.amazon.fr/gp/product/B0722YYBSS/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)

→ 1 Rtc : ( https://www.amazon.fr/AZDelivery-RTC-gratuite-Raspberry-microcontrôleur/dp/B01M2B7HQB/ref=pd_ybh_a_10?_encoding=UTF8&psc=1&refRID=Z7XPW7RCDAGB2CXXT7HV )

→ 2 relay ( https://www.amazon.fr/gp/product/B07BVXT1ZK/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1 ) used for open and close gate

→ 1 motor ( Mini moteur à engrenage métallique N20, 3V, 6V, 12V cc, 15, 30, 50 tr/min, 100, 200, 300, 500, 1000 tr/min | AliExpress )

→ 2 contactor

Hi,
Does the "stop" in your code correspond with a contactor operation?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can I suggest you add the "Blink without delay" LED code to your sketch, to make the onboard LED flash, if your code locks up the LED will stop operating, this is usually termed a "Heartbeat LED".

Thanks.. Tom... :slight_smile:

I don't see any obvious problems with the code, but there are some minor ones:

  1. volatile int woken = 0 ; Make this a byte. Accessing multibyte variables requires protection against corruption by an interrupt, during the access.

  2. It seems pointless to have two sets of alarms, just to determine what hour it is. Do you care if the door closes 30 seconds too early or late?

  3. Why do you include Streaming.h?

I too suspect electrical noise from the relays/contactors/motors. Post a complete wiring diagram.

Yes i have two contactor from an old coffee machine like that :

Heartbeat LED is a good idea.

I'm gonna write a schema and take a picture of my circuit today.

Thanks !

PaulRB:
No, a Nano from any manufacturer has the same avr atmega328 chip which runs your code.

Unless... Does the chip say "WAVGAT" on it?

A paradigm shift occurred in the universe.
New NANOs came out.SAMD21 processor
IDE PRO in Alpha.
MicroChip released 328pb

And many are googling these developments as you read this