Simple timed loop using interrupts

Hello, I'm trying to setup Timer 2 in Arduino UNO to get a timed while loop. The code is easy as follows:

volatile int Ts = 0;
volatile uint8_t resetFlag = 0;

int itcounter = 0;

void setup() {
  Serial.begin(9600);

  // Fast PWM mode
  TCCR2A &= B00001100;
  TCCR2A |= B00000011;

  // Prescaler 32
  TCCR2B &= B11110000;
  TCCR2B |= B00000011;

  // OvF Interrupt
  TIMSK2 &= B11111000;
  TIMSK2 |= B11111001;
}

void loop() {
  // put your main code here, to run repeatedly:
  Ts = 0;
  int tt = 0;
  
  while(1){
    tt = Ts;
    if(tt > 400){
      Serial.println(tt);
      break;
    }
  }
  
  itcounter++;

  if(itcounter == 20){
    itcounter = 0;
    delay(1000);
  }

}

ISR(TIMER2_OVF_vect){
  Ts++;
}

My problem is the timed output appears to be unreliable. Every now and then it breaks the while loop when Ts = 511, like a glitch. I can't figure out why and I cannot make it repeatable.

This is an output example:

401
401
401
401
401
401
401
401
401
401
401
511
401
401
401
401
401
401
511
401

Try this slightly modified program.

I'll leave it as an exercise for the reader as to why it seems to work better.

volatile long Ts = 0;
volatile uint8_t resetFlag = 0;

int itcounter = 0;

void setup() {
  Serial.begin(115200);

  // Fast PWM mode
  TCCR2A &= B00001100;
  TCCR2A |= B00000011;

  // Prescaler 32
  TCCR2B &= B11110000;
  TCCR2B |= B00000011;

  // OvF Interrupt
  TIMSK2 &= B11111000;
  TIMSK2 |= B11111001;
}

void loop() {
  // put your main code here, to run repeatedly:

  int tt = 0;
  
  while(1){
    if (Ts) {
      tt++;
      Ts = 0;
    }

    if(tt > 400){
      Serial.println(tt);
      break;
    }
  }
  
  itcounter++;

  if(itcounter == 200){
    itcounter = 0;
    delay(1000);
  }

}

ISR(TIMER2_OVF_vect){
  Ts++;
}

At first I thought Ts was too short and the rollover was happening to glitch you but it wasn't. The glitch was oddly odd. Baud rate I thought also.

Then I recalled the constant advice to "set a flag in the interrupt and do something in the main code" and changed Ts to act like a flag.

I had it count to 200 looking for a pattern (no pattern), it looks fine w/ 20 now again.

HTH

a7

Try disabling interrupts while copying Ts:

    noInterrupts();
    tt = Ts;
    interrupts();

Thank you very much. Still I don't get why my way wasn't working properly.

Correct me if I am wrong please: your way increments tt inside the while loop based on the value of Ts

if (Ts) {
      tt++;
      Ts = 0;
    }

This way you will never realize if the glitch still happened because for example the increment will happen for any Ts != 0. So for example if something happened which cause a delay and the computation of two increments for the interrupt counter (Ts = 2 or more) your code will count for just one, so how do you garantee that the glitch didn't happen?

Try disabling interrupts while copying Ts:

That's what I did as well when testing your code, and get stable results. You are reading a two byte value while it is changing.

cli();
tt = Ts;
sei();

Thank you very much. You made my day. This is the simple explanation I was looking for.

Thank you again.

anacleto86:
Thank you very much. Still I don't get why my way wasn't working properly.

Correct me if I am wrong please: your way increments tt inside the while loop based on the value of Ts

if (Ts) {

tt++;
      Ts = 0;
    }




This way you will never realize if the glitch still happened because for example the increment will happen for any Ts != 0. So for example if something happened which cause a delay and the computation of two increments for the interrupt counter (Ts = 2 or more) your code will count for just one, so how do you garantee that the glitch didn't happen?

So you could just add Ts to tt, then zero Ts incase you think Ts might advance by more than one by the time you get to looking at it.

[edit] but you'd want to ignore interrupts whilst doing, haha.

a7