Sketch stops working after ~40 minutes. Overflow? I have this simple sketch I use on Arduino Micro:

int fan = 3;
int led = 13;
int ledState = HIGH;         //all'inizio gira
//unsigned long time;
unsigned long prevMicros = 0;        // will store last time LED was updated  +
unsigned long interval =  7000000;           // lunghezza della pausa in secondi
unsigned long intervalON =  1000000;           // lunghezza del ON in secondi

void setup() {    
 pinMode(fan, OUTPUT);   
 pinMode(led, OUTPUT);  
 prevMicros = micros();
}

void loop() {
  unsigned long currMicros = micros();

  // manage overflow? BOH
   if (ledState == HIGH &amp;&amp; (((unsigned long)(currMicros  - prevMicros)) &gt;= intervalON)){
     prevMicros = currMicros;
      ledState = LOW;
    }
    else if (ledState == LOW &amp;&amp; (((unsigned long)(currMicros - prevMicros)) &gt;= interval)){
      ledState = HIGH;//riparte
      prevMicros = currMicros;     
    }

    digitalWrite(led, ledState);
    digitalWrite(fan, ledState);
}


I could use millis() instead of micro(), but I decided to keep this to shorten the overflow rate (should be 72 minutes). I shall go back to millis() once my issue is fixed.

The sketch works as expected, turning on the LED for a second every 7, but the sketch hangs after 40 minutes. Can you tell me why, and how to manage overflow properly? Why is it hanging after 40 and not 72 minutes? Thanks
When comparing time intervals, use unsigned long instead of long.

if ( ... (((unsigned long)(currMicros - prevMicros)) &gt;= intervalON) )


The time counter overflows at some point -- micros() overflows after 70 minutes, milis() overflows after nearly a month -- but these are unsigned values.

When an unsigned value is interpreted as a signed value -- (long) instead of (unsigned long) -- then half of the values are interpreted as negative numbers. So after 40 minutes, the micros() value looks like a negative number, and the (curr-prev) >= interval comparison returns false. After 70 minutes, the micros() overflows back to 0, and the signed comparisons work as expected.

The solution is to use unsigned long for all delta-time comparisons.

This is easier to see if you consider a smaller, 3-bit number: there are 8 values for a 3-bit number. If the 3-bit number is unsigned, then the values are 0, 1, 2, 3, 4, 5, 6, 7. But if the 3-bit number is signed, then those same binary code numbers are interpreted as 0, 1, 2, 3, -4, -3, -2, -1. Same principle for int and long values, just a larger range of values.

EDIT: 

Based on your comment below, I did some testing on my own hardware (Sparkfun "red board" Arduino UNO R3 clone), and added some code to help make it more testable. Some highlights:


Added a diagnostic LED on Arduino pin 9, to indicate when the timer overflow has happened (i.e. new time is less than previous time).
Added a mask to force the timer overflow to happen sooner, so I don't have to wait an hour to verify whether the code had any effect.
Calculated timeSinceLastChange and applied mask, to handle overflow.
Added TIMER_DATATYPE based on jippie's comment


The complete code:

//--- based on comment from jippie about using C++ standard width integer types
// #define TIMER_DATATYPE unsigned long
#define TIMER_DATATYPE uint32_t

//--- MarkU: diagnostic LED to indicate that timer overflow happened.
// Comment out this line for normal operation.
#define DIAGNOSTIC_LED_TIME_OVERFLOW 9
//---

//--- MarkU: diagnostic: force timer overflow to happen sooner.
// This must be significantly longer than the intervals being measured.
// Must be a binary all-1's bitmask.
// 0x3FFFFFF overflow after approximately 1 minute
// 0xFFFFFFF overflow after approximately 5 minutes
// 0xFFFFFFFF overflow after approximately 70 minutes
#define DIAGNOSTIC_TIMER_OVERFLOW_MASK 0x3FFFFFF
//---

int fan = 3;
int led = 13;
int ledState = HIGH;         //all'inizio gira
//unsigned long time;
TIMER_DATATYPE prevMicros = 0;        // will store last time LED was updated  +
TIMER_DATATYPE interval =  7000000;           // lunghezza della pausa in secondi
TIMER_DATATYPE intervalON =  1000000;           // lunghezza del ON in secondi

void setup() {
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);

  //--- MarkU: diagnostic LED indicate that timer overflow happened
#if DIAGNOSTIC_LED_TIME_OVERFLOW
  pinMode(DIAGNOSTIC_LED_TIME_OVERFLOW, OUTPUT);
  digitalWrite(DIAGNOSTIC_LED_TIME_OVERFLOW, LOW);
#endif // DIAGNOSTIC_LED_TIME_OVERFLOW
  //---

  prevMicros = micros();
}

void loop() {
  TIMER_DATATYPE currMicros = micros();

  //--- MarkU: diagnostic: force timer overflow to happen sooner
#if DIAGNOSTIC_TIMER_OVERFLOW_MASK
  currMicros = (TIMER_DATATYPE)(currMicros &amp; ((TIMER_DATATYPE)DIAGNOSTIC_TIMER_OVERFLOW_MASK));
#endif // DIAGNOSTIC_TIMER_OVERFLOW_MASK

  //--- MarkU: consolidate time delta calculation
  TIMER_DATATYPE timeSinceLastChange;
  if (currMicros &lt; prevMicros) {
    //--- MarkU: handle timer overflow
#if DIAGNOSTIC_LED_TIME_OVERFLOW
    digitalWrite(DIAGNOSTIC_LED_TIME_OVERFLOW, HIGH);
#endif // DIAGNOSTIC_LED_TIME_OVERFLOW
#if DIAGNOSTIC_TIMER_OVERFLOW_MASK
    timeSinceLastChange = (currMicros - prevMicros) &amp; DIAGNOSTIC_TIMER_OVERFLOW_MASK;
#else // DIAGNOSTIC_TIMER_OVERFLOW_MASK
    timeSinceLastChange = (currMicros - prevMicros) &amp; 0xFFFFFFFF;
#endif // DIAGNOSTIC_TIMER_OVERFLOW_MASK
  } else {
    timeSinceLastChange = currMicros - prevMicros;
  }
  //---

  // manage overflow? BOH
  if (ledState == HIGH &amp;&amp; (timeSinceLastChange &gt;= intervalON)) {
    prevMicros = currMicros;
    ledState = LOW;
  }
  else if (ledState == LOW &amp;&amp; (timeSinceLastChange &gt;= interval)) {
    ledState = HIGH;//riparte
    prevMicros = currMicros;
  }

  digitalWrite(led, ledState);
  digitalWrite(fan, ledState);
}