1

The task is: after five clicks on OK, the built-in LED starts flashing with a frequency of 5Hz using an interrupt. After the eighth click on OK, the flashing (and glowing) should stop.Why is flashing not working

bool ledState = false;
volatile bool ledOn = true;

void setup(){
TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0;
  TCNT2 = 0;
  OCR2A = 77;
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 |= (1 << OCIE2A);
 pinMode(13, OUTPUT);
}

void loop(){
 if(button5.buttonPressedCount >= 5 && button5.buttonPressedCount < 8){
    ledState = true;
  }

  if(button5.buttonPressedCount > 7){
    ledState = false;
  }
}

ISR(TIMER2_COMPA_vect){
  if(ledState){
  digitalWrite(13, ledOn);
  ledOn = !ledOn;
  }
}
10
  • Why OCR2A = 77;? May 11 at 12:49
  • The value for obtaining a frequency of 5 Hz with a divider of 1024
    – Good York
    May 11 at 12:50
  • Could you please explain, within the question, how you go from “f = 5 Hz” to OCR2A = 77;? May 11 at 12:51
  • timer will run at a frequency of 16 MHz / 1024 = 15.625 kHz, so desired interrupt frequency = (77 + 1) * 15.625 kHz / 1024 = 5 Hz
    – Good York
    May 11 at 12:54
  • 1
    This calculation is wrong. May 11 at 12:57

1 Answer 1

2

On the Uno (ATmega328P microcontroller), timers 0 and 2 are 8-bit only: they cannot count beyond 255. Timer 1, on the other hand, is 16-bits. This is the most convenient timer for generating low frequencies.

Speaking of frequencies... One LED period involves two toggles (turn on, then turn off). Thus, if you want the LED to blink at 5 Hz, the toggle action should happen at 10 Hz. Given that the CPU is clocked at 16 MHz, this means you have to toggle the LED every 1,600,000 CPU cycles.

If you set the prescaler to 1,024, you then you have to count 1,600,000/1,024 = 1,562.5 timer cycles. You cannot count a non-integer number of cycles, but you probably do not care about such accuracy. If you do care, set the prescaler to 256 and count 1,600,000/256 = 6,250 timer cycles by setting the compare match register to 6,249.

One last issue: keep in mind that, in normal counting mode, the timer counts up to its maximum value (65,535, or 255 on an 8-bit timer) and then restarts at zero. If you want it to count only up the value set in the compare match register, you should choose the appropriate waveform generation mode: the fast PWM mode that lets you control the TOP value with OCR1A.

3
  • then it should look like this? TCCR1A = 0; TCCR1B = 0; TIMSK1 = 0; TCNT1 = 0; OCR1A = 6249; // Set compare match value for prescaler 256 TCCR1B |= (1 << CS12); // Set prescaler to 256 TIMSK1 |= (1 << OCIE1A); // Enable interrupt on compare match A
    – Good York
    May 11 at 13:51
  • @GoodYork: Read the datasheet and see how to set the appropriate waveform generation mode. May 11 at 13:57
  • like this: TCCR1A = (1 << WGM11) | (1 << COM1A0); TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS12); TIMSK1 = (1 << OCIE1A); OCR1A = 6250;
    – Good York
    May 11 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.