Micros rollover in ISR

Hi. I have a situation with a non-working button in my sketch. From debugging print I think this is related to micros rollover, but I don't know how to change/fix this.

When running the sketch, buttons work ok at start. Debugging info shows that variable last_micros increases after each button push, as it should. But after running for 71(?) minutes the micros() rollover, and that value is now lower than last_micros. And no button push is recognized.

I am using: Mega2560, IDE 1.0.2. When I search this forum, I have only found statements that supports the existing code. (But it don't work, at least for me.)

Copy of some of the code:

volatile int push[2] = {0,0};        // Variable to pass button press back to main loop
long debouncing_time = 40;           // Debouncing Time in Milliseconds
volatile unsigned long last_micros;  // Variable to keep time while debounce
ISR(PCINT0_vect) // handle pin change interrupt for PCINT0 to PCINT7 here, pin D53-D50 and D10-D13
{
  static uint8_t btn = _BV(PB5) | _BV(PB6);
  uint8_t t = PINB;  // read port status

  // check if buttons are pushed
  t &= _BV(PB6) | _BV(PB5); // D11 D12
  if (t != btn) {  // activity on pins, we're only interested in high to low transitions
    if((long)(micros() - last_micros) >= debouncing_time * 1000) {  
      push[0] |= !(t & _BV(PB5));
      push[1] |= !(t & _BV(PB6));
      btn = t;
      last_micros = micros();  // start/restart bounce guard timer (covers make and break)
    }
 }  
}
void loop() {
.
.
.
  // do data logging if it is time for it
  if(millis() - logTime>LOG_DELAY) {
    logTime += LOG_DELAY;
    Serial.print("brewController loop, do dataLogger");
    Serial.print(" micros:");
    Serial.print(micros());
    Serial.print(" last_micros:");
    Serial.print(last_micros);
    dataLogger();
  }
}

The debugging print is in a loop that is activated every 2.nd second.

Why are you casting your micros calculation to long? You want to keep it as unsigned long so it works properly.

volatile int push[2] = {0,0};        // Variable to pass button press back to main loop
...
      push[0] |= !(t & _BV(PB5));
      push[1] |= !(t & _BV(PB6));

When does push ever get un-set?

@majenko:
I copied this part of the code. Can you explain how removing (long) would make a difference?

@Nick:
Push variable is reset in the main loop. It is used together with the MENWIZ library. Sorry if this was confusing.

void loop() {
.
.
  if ( push [0] > 0 ) { // confirm
    virtualButton = 6;
    push[0] = 0;
  }
  if ( push [1] > 0 ) { // escape
    virtualButton = 5;
    push[1] = 0;
  }
.
.
  // do data logging if it is time for it
  if(millis() - logTime>LOG_DELAY) {
    logTime += LOG_DELAY;
    Serial.print("brewController loop, do dataLogger");
    Serial.print(" micros:");
    Serial.print(micros());
    Serial.print(" last_micros:");
    Serial.print(last_micros);
    dataLogger();
  }
}

Take the following snippet:

    unsigned long a, b;

    a = 1000304UL;
    b = 1008UL;

    printf("%lu\n", b - a);
    printf("%ld\n", (long)(b - a));

b - a gives 4293968000, which is greater than whatever threshold you like - say 1000. That deals with your rollover nicely.
Cast that to a signed long, and you get: -999296 - that's not going to be above your threshold. Rollover broken.

It works! Thank you!