Interrupt stops working after some 10s of minutes

Hello, I wrote this code:

int sw1Pin=2;
int sw2Pin=3;

int jmpr1Pin=5;
int jmpr2Pin=8;

int add1Pin=4;
int add2Pin=7;

int add01Pin=6;
int add02Pin=9;

int lightPin=11;

int offDelay=15000;
int ledState=0;
int ledDim=0;

volatile int offCount=0;

volatile bool swState;
bool prevSwState=0;
bool fadeFlag=0;

               
int myDelay2 = 5;   // Wait this many millis()


int lastTime = 0;              // The clock time in millis()
int deltaT;                         // A calculated value


int lastTime2=0;
int deltaT2;


void setup() {

  pinMode(lightPin,OUTPUT);
  pinMode(add01Pin,OUTPUT);
  pinMode(add02Pin,OUTPUT);
  pinMode(add1Pin,OUTPUT);
  pinMode(add2Pin,OUTPUT);
  pinMode(13,OUTPUT);

  digitalWrite(add01Pin, LOW);
  digitalWrite(add02Pin, LOW);

  digitalWrite(add1Pin, HIGH);
  digitalWrite(add2Pin, HIGH);

  
  
  pinMode(sw1Pin,INPUT_PULLUP);
  pinMode(sw2Pin,INPUT_PULLUP);
  
  pinMode(jmpr1Pin,INPUT);
  pinMode(jmpr2Pin,INPUT);

  if(digitalRead(jmpr1Pin)==HIGH)offDelay+=15000;
  if(digitalRead(jmpr2Pin)==HIGH)offDelay+=30000;
  
  
  //Serial.begin(9600);
  
  attachInterrupt(digitalPinToInterrupt(sw1Pin),doorAction,CHANGE); 
  attachInterrupt(digitalPinToInterrupt(sw2Pin),doorAction,CHANGE); 


}

void loop() {
 
  
  //Serial.print(swState);
  //Serial.print("    ");
  //Serial.print((offCount>0)&&(swState==0));
  //Serial.println();
  if ((swState==1)&&(ledState==0))fade();
  else{
    if((swState==0)&&(ledState==1)){
      while((offCount>0)&&(swState==0)){
        deltaT2=millis()-lastTime2;
        if(deltaT2>=1){
          offCount--;
          //if(((offCount%500)<=25)&&(offCount>1))digitalWrite(13,HIGH);
          //else digitalWrite(13,LOW);
          lastTime2=millis();
          }
        }
      if((swState==0)&&(ledState==1))fade();
      }
    }  
  }
    

  
 
  
void doorAction(){
  swState=(digitalRead(sw1Pin))||(digitalRead(sw2Pin));
  //digitalWrite(13,swState);
  //Serial.println(swState);
  if(swState==0)offCount=offDelay;
    }
  


void fade (){
  if(ledState==1)
    {   while(ledDim>0){   
          deltaT = millis() - lastTime;
          if ( deltaT >= myDelay2 ) {
              ledDim--;
              analogWrite(lightPin,ledDim);
              lastTime = millis();
              
           }
    }
        
      ledState=0;
      
      
      }
  else
     {   while(ledDim<255){   
          deltaT = millis() - lastTime;
          if ( deltaT >= myDelay2 ) {
              ledDim++;
              analogWrite(lightPin,ledDim);
              lastTime = millis();
              
           }
    }
        
      ledState=1;
      
      
      }
      
      
  
  }

It's purpose is to detect the state of 2 doors and turn on (fade in/out) LED strip using an N-MOSFET.

  • I need the LED strip to turn on(linear fade on) when one or both doors open
  • While door(s) is (are) open, the LED strip should stay lit
  • When both doors are closed, a countdown of 15s(or more, defined by additional jumpers) should start and if during the countdown both of the doors stay closed, the LED strip should turn off (linear fade off)

The circuit works normally when I restart the Nano and try to open and close the door a few times.

The problem is, when I leave both doors closed for some time, like 10 minutes or more, the Arduino freezes and doesn't turn on the LED strip anymore.

attached below is a rough schematic of the circuit.

Please ignore unused variables as I'm used to Eclipse so I forgot to remove them

Any help would be appreciated

Likely your main problem:

        deltaT2 = millis() - lastTime2;

Your 'int lastTime2;' can only hold values up to 32767. After 32.767 seconds it will overtflow and your calculation will produce unexpected results. Use 'unsigned long lastTime2;'.

Another problem:

int offDelay = 15000;


void setup()
{
  pinMode(jmpr1Pin, INPUT);
  pinMode(jmpr2Pin, INPUT);


  if (digitalRead(jmpr1Pin) == HIGH)
    offDelay += 15000;
    
  if (digitalRead(jmpr2Pin) == HIGH)
    offDelay += 30000;  // OVERFLOW!  15000+30000 = 45000.  On an UNO, 'int' only goes up to 32767.
}

Thank you, I completely forgot about int limitations since my C programming course, so I have completely overseen these issues.
:slight_smile:
I will correct them now and load the new corrected code.

After that, I'll catch you up if that did indeed solve the problem.

You should also consider the fact that the use of interrupts is completely unnecessary in this application. Polling and a simple State Machine would do very nicely.

Additionally, as implemented, the interrupts are likely to cause undefined behavior. Access to a 16-bit variable (like "offCount") is non-atomic on an 8-bit AVR processor. Yet, you are accessing it in your non-interrupt code without the protection of a noInterrupts() / interrupts() critical section.

Thank you for your reply. For now it is working correctly, we'll see in the morning if it keeps running that way.

Nonetheless, I'd like to do the coding properly, so I'm eager to create a state machine for it, but I'm currently without an idea because the last time I was making a state machine, it was in VHDL on an FPGA.

Would you bother to help me rewrite the code in your proposed, optimised way?

The concept in code is similar. One or more variables holds the "state" of the machine and the loop() function runs continuously (no blocking code). On every iteration, it makes decisions on which code to execute, what I/O to perform, and when to change "state" (i.e whether or not to update the state variable).

Every iteration of loop should be very quick. Either do nothing or some small part of a larger task. Then exit and let the loop run again.

Here's a tutorial:
https://www.gammon.com.au/statemachine

This one is more in-depth:

It starts here:

I'll try and get the hang of it once again soon.

Thank you for your help and suggestions, I really appreciate it and I think there should be more communities like this one, especially in EE topics.