#include <avr/interrupt.h>
#include <avr/io.h>
#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT
int ledPin = 13;
int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
long starttime = 0;
// Aruino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000
ISR(TIMER2_OVF_vect) {
RESET_TIMER2;
int_counter += 1;
if (int_counter == 1000) {
second+=1;
int_counter = 0;
}
};
void setup() {
Serial.begin(9600);
Serial.println("Initializing timerinterrupt");
//Timer2 Settings: Timer Prescaler /64,
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
// Use normal mode
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
// Use internal clock - external clock not used in Arduino
ASSR |= (0<<AS2);
//Timer2 Overflow Interrupt Enable
TIMSK |= (1<<TOIE2) | (0<<OCIE2);
RESET_TIMER2;
sei();
starttime = millis();
}
void loop() {
if (oldSecond != second) {
Serial.print(second);
Serial.print(". ->");
Serial.print(millis() - starttime);
Serial.println(".");
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
oldSecond = second;
}
}
it states:
In function 'void setup()':
error: 'TCCR2' was not declared in this scope
when I try to compile... shouldn't it be working as I included interrupt.h?
I have a very limited knowledge of C, so I'm not very sure how all this stuff works.
Any help would be appreciated!
Your current problem has nothing to do with C or interrupts: you are referring to a register (TCCR2) that doesn't exist. Your options are TCCR2A, TCCR2B, or TCCR2C. Look at the mega168 datasheet (the timer2 registers section) to see what they do and which one to use (hint: I think you want to replace TCCR2 with TCCR2B).
Thanks for the advise, I have a lot to learn from this little datasheet.
I replaced a couple of variables in this example, and got to make it work. I had to change 1000 to 495 overflows per second to get something around 999-1000ms per cycle.
Here's the revised code:
#include <avr/interrupt.h>
#include <avr/io.h>
#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT
int ledPin = 13;
volatile int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
long starttime = 0;
// Aruino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000
// Corrected to 495 instead of 1000
ISR(TIMER2_OVF_vect) {
RESET_TIMER2;
int_counter += 1;
if (int_counter == 495) {
second+=1;
int_counter = 0;
}
};
void setup() {
Serial.begin(9600);
Serial.println("Initializing timerinterrupt");
//Timer2 Settings: Timer Prescaler /64,
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
// Use normal mode
TCCR2B &= ~((1<<WGM21) | (1<<WGM20));
// Use internal clock - external clock not used in Arduino
ASSR |= (0<<AS2);
//Timer2 Overflow Interrupt Enable
TIMSK2 |= (1<<TOIE2) | (0<<OCIE2B);
RESET_TIMER2;
sei();
starttime = millis();
}
void loop() {
if (oldSecond != second) {
Serial.print(second);
Serial.print(". ->");
Serial.print(millis() - starttime);
Serial.println(".");
digitalWrite(ledPin, HIGH);
//delay(100);
digitalWrite(ledPin, LOW);
oldSecond = second;
}
}
and I'm using the script below to generate a frequency of 1Hz:
16,000,000 / 64 / (256 - 6) / 1000 = 1
crystal/prescale/(timer - resetting preload)/count variable
Unfortunately, what I get is nothing close to 1000ms/cycle. I get around 2018ms/cycle.
First, why the 18ms delay; and second, why is the period double of what It should be?
I have tried other prescalers, like 32 and 128, and what I got is a proportional delay (respectively 9ms and 36ms), with the period still double of what it should (mathematically) be.
Now, I tried to change the Counter resetting preload to different values. Setting TCNT2 to values from 0 (not touching it at all) to 255 (1 tick away from reset...) gave me the following weird results:
at 0 preload, the period is 2040ms.
at 255 preload, the period is 1024ms.
using other preload values produced a linear transition from 1024ms to 2040ms... as if there was another counter running behind the scenes and going through a full cycle before my timer is activated...
is it the TCCR2A running behind the TCCR2B ?.. Now, I'm getting a bit confused
The Arduino software preconfigures timer2 to generate a phase-correct PWM before your setup() routine is called. In phase-correct mode, the timer counts up to its maximum value and then back down to zero, at which point it overflows. What this means is that phase-correct PWMs have approximately double the frequency of fast PWMs (fast PWMs are generated by having the timer count up to the max value and then overflow back to zero).
Try reconfiguring the timer to generate a fast PWM and you should get the results you're expecting. You can do this by setting bits WGM21 and WGM20 of TCCR2A:
Thanks Ben! I was wondering how TCCR2A and TCCR2B were related. I begin to understand the structure of the ATMEGA a bit better now.
I'm planning to use the timer to cook-up my own drum module... tried to use millis before but the 500Hz precision wasn't good enough to get decent amplitude recognition algorithms to work.