engine rpm measurement using timer 1 (embedded c programming and the atmel avr)
DESCRIPTION
Engine Rpm Measurement Using Timer 1 (Embedded c Programming and the Atmel Avr)TRANSCRIPT
-
130
The following code is placed above main() as the interrupt service routine for the Timer 0overflow:int time_cntr = 0; /*global variable for number of Timer 0*/
/*overflows*/
/* Timer 0 overflow interrupt service routine*/interrupt [TIM0_OVF] void timer0_ovf_isr(void){
TCNT0 = 6; /*reload timer 0 for next period*/if (time_cntr++ == 500) /*check for one second, increment counter*/ {
if (data_set_cntr < 120) /*record data if less than 120 sets*/{
e_rpm[data_set_cntr] = current_e_rpm; /*record engine rpm*/s_rpm[data_set_cntr] = current_s_rpm; /*record shaft rpm*/temp[data_set_cntr++] = current_temp; /*record engine temp*/
}time_cntr = 0; /*reset counter for next 1 second interval */
} }Notice that the data_set_cntr variable is post-incremented as a part of the storing ofthe current temperature.
ENGINE RPM MEASUREMENT USING TIMER 1
The input capture feature is used to capture the period of the engine rpm pulses. The periodis used to calculate the rpm. Note that one pulse occurs for every two engine revolutions ina 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 pulsesof 1 MHz with a convenient period of 1 microsecond. These clock pulses drive Timer 1, andthe input capture register (ICR1) will be used to capture the Timer 1 count each time afalling edge occurs on the ICP of the ATMega16. When this occurs, an interrupt will begenerated. In the interrupt service routine, the current captured count is compared to thepreviously captured time to determine the period of the pulses, which is used to calculate theengine rpm.
The following code is placed in main() to initialize Timer 1 to capture the time on thefalling 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;
EX
AM
PL
E
39594_02_ch02_p087-170.qxd 3/24/06 05:40 PM Page 130
-
The Atmel RISC P roce s sor s 131
And the following code makes up the ISR for the capture event:
unsigned int previous_capture_time; /*saved time from previous*//*capture*/
/* Timer 1 input capture interrupt service routine*/interrupt [TIM1_CAPT] void timer1_capt_isr(void){
unsigned int current_capture_time, period; /*current time and*//*period*/
current_capture_time = (256* ICR1H) + ICR1L; /*get captured time*/if (current_capture_time > previous_capture_time) /*check rollover*/
period = current_capture_time - previous_capture_time;else
period = 0xFFFF - current_capture_time + previous_capture_time;current_e_rpm = (unsigned long)120E6 / (unsigned long)period;previous_capture_time = current_capture_time; /*save for next*/
/*calculation*/}
In this code, a global variable, previous_capture_time, is initialized to retain thevalue from the previous capture. The ISR function reads the current capture time and usesit, along with the previous captured time, to calculate the rpm. Notice the if statement thatchecks for rollover; this is another method to allow for the case in which the 16-bittimer/counter rolls over from 0xFFFF to 0x0000 during the elapsed period. The last state-ment in the ISR saves the current_capture_time for use as the previous_capture_time the next time a pulse occurs.
The rpm is being calculated as follows:
RPM = 1E6 micro-seconds/second * 1 pulse / period in micro-seconds * 2 revolu-tions per pulse * 60 seconds per minute
Note that casting is used to ensure accuracy with the large numbers. Also, combining con-stants shortens the calculation formula.
DRIVE SHAFT RPM MEASUREMENT USING TIMER 1
This measurement gets a little bit more involved, because there is not a second capture reg-ister in the Mega16 and the shaft rpm signal is connected to INT0. You can create your owncapture register within the INT0 ISR by reading the Timer 1 count when the interrupt oc-curs. 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){
EX
AM
PL
E
39594_02_ch02_p087-170.qxd 3/24/06 05:40 PM Page 131