Availability of Timer2?

Following on from some threads that want to do timed things (like feeding fish, or blinking lights) with very high accuracy, I have been looking at ways of getting timer information in an interrupt.

As I understand it, the Atmega328 has three timers (Timer0, Timer1, and Timer2) plus a watchdog timer. The watchdog timer is basically for getting you out of trouble, and is lower accuracy than the other timers.

The way I read wiring.c, Timer0 is used for the millis() timer. It is also used for micros().

If my arithmetic is correct, the Timer0 interrupt will be called roughly every 1.024 ms, however the incrementing of the millis timer variable compensates for the fact that the interrupt is not called exactly every 1 ms.

Also, as far as I can make out, micros() works by grabbing the current timer data from Timer0 and adding in the number of times it overflowed in the interrupt routine, suitably scaled.

So far so good. Now my question really is, "are Timer1 and Timer2 available?".

The comments in wiring.c say:

timers 1 and 2 are used for phase-correct hardware pwm

So I am guessing that Timer1 and Timer2 are at least partially involved in PWM (eg. for motors, or for generating sound).

So what are the disadvantages, if any, of using (say) Timer2 to flash lights or feed fish? Some test code:

#include <avr/interrupt.h>  
#include <avr/io.h>

ISR(TIMER2_OVF_vect) 
{
  digitalWrite(13, !digitalRead (13));
};  

void setup() {
  pinMode (13,OUTPUT);

  //Timer2 Settings: Timer Prescaler /1024, WGM mode 0
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1 << CS20;

  //Timer2 Overflow Interrupt Enable  
  TIMSK2 = 1<<TOIE2;

  //reset timer
  TCNT2 = 0;

} //end of setup

void loop() {}

Testing indicates that the LED toggles every 16.4ms, with a frequency of 30.46 Hz (that being two toggles). This sounds right, being the system clock in microseconds, scaled by 1024, and overflowing every 256 ticks (1/16000000 * 1024 * 256 == 0.01638).

So is there a flaw in this plan? This interrupt (scaled down a bit more) could be used to flash lights every second or two.

I think you're right about the timer usage.

Given that every second question here is along the lines of "How do I take action on X when I'm doing Y" I reckon there has to be an opening for a bright young lad to knock up a pseudo dual-tasking arrangement using timers and interrupts.

Whether or not this would get beginners into more trouble I'm not sure, but if packaged well maybe not. Maybe something like

loop() {
   // this runs all the time
}

loop1() {
   // this happens every X mS
}

The WDT is an easy choice here because it's never used by anything else, the only catch is the resolution, the fastest you can have is ~16mS, OTOH that's about perfect for switch debouncing.


Rob

Yes, well I was thinking about something like flashing LEDs. If the timer interrupt fires off every 16ms or so, and you take action every 16 or so times through the ISR, then you could have an LED flash every 1/4 of a second. Then all the rest of the program has to do is set a boolean saying if you want the LED to flash, or not.

For this example then I would say the WDT is a perfect match, and it doesn't screw with PWM.

I'd like to do something more generic but just don't have the time.


Rob

The timers are used to drive PWM pins thusly: Timer0 controls pins 5&6, timer1 controls 9&10, timer2 controls 11&3. So as long as you don't need PWM on those pins, the timers are swell. The disadvantage to using them for your fish is that the corresponding pins can't be PWM'd anymore.

The WDT is swell as long as you're happy with only 9 possible durations from 16ms to 8sec (I think).

9 possible durations from 16ms to 8sec (I think).

Correct, well 10 durations but who's counting :slight_smile:


Rob

That's what I get for doing it from memory, not looking at a data sheet :). 0-9. That's 10 positions...

As far as I remember, Newsoftserial (and softwareserial) and the servo library use timer 2