Reusing Timer4 on Zumo 32u4 doesn't yield expected timing results

I need a timer to generate interrupts every 10 ms, so I can implement a simple RTOS on the Zumo 32u4.

I already looked at the Zumo 32U4 Robot User’s Guide 8 “AVR Timers” section and decided I could live without the buzzer, so picked Timer-4 for my purpose.

Using the ATmega32U4 datasheet and other resources, I came up with the following code:

#define BSP_TICKS_PER_SEC  100

ISR(TIMER4_COMPA_vect) {
    OS_ProcessTick(0); // process time events for tick rate 0
}

void onStartup() 
{
    TCCR4A = 0U;
    // Prescale by 1/1024
    TCCR4B = (1U << CS43 ) | (0U << CS42) | (1U << CS41) | (1U << CS40);
    // Enable TIMER compare Interrupt for OCR4A
    TIMSK4 = (1U << OCIE4A);
    // Count up until you get the equivalent of BSP_TICKS_PER_SEC.
    // This is just a convenient way to say later if I want
    OCR4A  = (F_CPU / BSP_TICKS_PER_SEC / 1024U) - 1;
    // Timer/Counter 4 Interrupt(s) initialization
    TIMSK4 = (0<<OCIE4D) | (1<<OCIE4A) | (0<<OCIE4B) | (0<<TOIE4);
    TCNT4  = 0U;
}

I am driving an LED (using ledRed() function) in ProcessTick(). I switching on the LED for what I think should be one second (100 ticks), then switching off for one second (100 ticks). The frequency that I observe with the LED is actually about 1.5 seconds. Where am I making the error?

Thanks!

Hello.

I moved your post to our “Robots” subforum, which seems more appropriate.

Can you post your full code? It is difficult to help you troubleshoot without seeing the part of your code that controls the LED’s state.

- Amanda

Hi Amanda, I could post the code that switches LED on/off, but I’m not sure that would be useful as the code is autogenerated from a HSM modeling tool called QM. That generated code does not touch the timer or processor; it simply calls ledRed(HIGH) and ledRed(LOW).

As I suspected, the problem was in the code that sets up the timer. I made two changes to make it work:

  1. Explicitly set TCCR4C/D/E to zero.
  2. Set OCR4C to the same value as OCR4A.

Not doing any of the above results in incorrect operation (either the wrong interrupt frequency, or no interrupts).

To verify the timing is correct, I display elapsed milliseconds on the zumo LCD and verified that the number of milliseconds is between 999 and 1001.

Full code for the Blinky example is available here: https://github.com/nagarkar/pololuzumo32u4

1 Like

Cool; I’m glad you were able to figure out and fix the problem. Thanks for letting us know and sharing your code!

- Amanda