engine rpm measurement using timer 1 (embedded c programming and the atmel avr)

3
 130  The following code is placed above main() as the interrupt service routine for the Timer 0 overow: 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-inc remented as a part of the storing of the current temperature. ENGINE RPM MEASUREMENT USING TIMER 1  The input capture featur e 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 t his system, so using a prescaler of 8 will pro vide clock pu lses of 1 MHz with a convenient period of 1 microsec ond. These clock pulses drive Timer 1, and the input capture register (ICR1) will be used to capture the Timer 1 count each time a falli ng edge occur s on the ICP of the ATMega16. When this occur s, an interrup t will be genera ted. In the interrup t service routin e, the curr ent captur ed count is compa red 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;     E     X     A     M     P     L     E

Upload: dinamik2t

Post on 03-Nov-2015

49 views

Category:

Documents


0 download

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