Engine RPM Measurement Using Timer 1 (Embedded C Programming and The Atmel Avr)
Engine RPM Measurement Using Timer 1 (Embedded C Programming and The Atmel Avr)
The following code is placed above main() as the interrupt service routine for the Timer 0
overflow:
E X A M P L E
int time_cntr = 0;
The input capture feature is used to capture the period of the engine rpm pulses. The period
is used to calculate the rpm. Note that one pulse occurs for every two engine revolutions in
a 4-cycle engine such as this one.
The system clock is 8 MHz in this system, so using a prescaler of 8 will provide clock pulses
of 1 MHz with a convenient period of 1 microsecond. These clock pulses drive Timer 1, and
the input capture register (ICR1) will be used to capture the Timer 1 count each time a
falling edge occurs on the ICP of the ATMega16. When this occurs, an interrupt will be
generated. In the interrupt service routine, the current captured count is compared to the
previously captured time to determine the period of the pulses, which is used to calculate the
engine rpm.
The following code is placed in main() to initialize Timer 1 to capture the time on the
falling edge:
/* Timer(s)/Counter(s) Interrupt(s) initialization*/
TIMSK=0x21;
/* timer0 overflow, ICP interrupts enabled*/
/* Timer/Counter 1 initialization*/
TCCR1A=0x00;
TCCR1B=0x02;
/*prescaler = 8, capture on falling edge*/
TCNT1H=0x00;
/*start at 0*/
TCNT1L=0x00;
131
And the following code makes up the ISR for the capture event:
unsigned int previous_capture_time;
This measurement gets a little bit more involved, because there is not a second capture register in the Mega16 and the shaft rpm signal is connected to INT0. You can create your own
capture register within the INT0 ISR by reading the Timer 1 count when the interrupt occurs. Then the rest of the function works very much like the one above for the engine rpm:
unsigned int previous_shaft_capture_time; /*saved time from previous*/
/*capture*/
/* External Interrupt 0 service routine*/
interrupt [EXT_INT0] void ext_int0_isr(void)
{
E X A M P L E