Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
100% found this document useful (1 vote)
681 views

Engine RPM Measurement Using Timer 1 (Embedded C Programming and The Atmel Avr)

The document describes code used to measure engine and shaft RPM using timers and interrupts on an ATmega microcontroller. Timer 0 is used to record engine data like RPM, temperature etc at 1 second intervals. Timer 1's input capture is used to measure engine RPM by timing the period between pulses, with the value saved in an interrupt service routine. Shaft RPM is similarly measured using Timer 1 and INT0 interrupts to trigger capturing the timer value and calculating period and RPM.

Uploaded by

dinamik2t
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
681 views

Engine RPM Measurement Using Timer 1 (Embedded C Programming and The Atmel Avr)

The document describes code used to measure engine and shaft RPM using timers and interrupts on an ATmega microcontroller. Timer 0 is used to record engine data like RPM, temperature etc at 1 second intervals. Timer 1's input capture is used to measure engine RPM by timing the period between pulses, with the value saved in an interrupt service routine. Shaft RPM is similarly measured using Timer 1 and INT0 interrupts to trigger capturing the timer value and calculating period and RPM.

Uploaded by

dinamik2t
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 2

130

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;

/*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 of


the current temperature.
ENGINE RPM MEASUREMENT USING TIMER 1

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;

The A tmel RISC P rocessors

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*/

In this code, a global variable, previous_capture_time, is initialized to retain the


value from the previous capture. The ISR function reads the current capture time and uses
it, along with the previous captured time, to calculate the rpm. Notice the if statement that
checks for rollover; this is another method to allow for the case in which the 16-bit
timer/counter rolls over from 0xFFFF to 0x0000 during the elapsed period. The last statement 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 revolutions per pulse * 60 seconds per minute
Note that casting is used to ensure accuracy with the large numbers. Also, combining constants 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 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

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*/

You might also like