Hello,
I assume that you are currently using the TIM module to generate the periodic interrupts. However, the input capture mode of the TIM provides hardware that is specifically suited to period measurement, with only a single interrupt required per measurement cycle. This would be the method that I would advocate, and should give simpler code than you currently have.
If you were to use a wheel sensor that gave 8 pulses per revolution, I would estimate that the distance covered between pulses might lie within the range 200-250 mm. For the upper limit of this range, and assuming 10 kph is the minimum measured speed that is required, this would give 90 ms between successive pulses. At 160 kph the period between successive pulses would be 5.6 ms.
With a bus frequency of 7.3728 MHz, and a prescale division of 16, the overflow period for the TIM would be 142.2 ms. So input capture mode should work well for the periods you are attempting to measure. If you were to reduce the number of pulses per revolution, the prescale value should be increased accordingly, but the measurement update period for very low speeds might then be considered too long.
The following code example should illustrate the requirements of the input capture method -
#define KPH_CAL 829425L // Assumes 250mm distance per pulse
// with TIM clock rate 460.8 kHz (prescale 16)
// Global variables:
word tcount;
word tprev;
word kph = 0;
byte flag = 0;
/**************************************************************************/
void main( void)
{
/* Initialisation stuff */
EnableInterrupts;
for ( ; ; ) { // Main polling loop
__RESET_WATCHDOG();
if (flag) { // Test for new reading
if (2 == flag) // Overflow occurred
kph = 0;
else { // Normal operation
kph = (word)(KPH_CAL / tcount); // Result is kph * 2
kph = (kph + 1) / 2; // Rounding adjustment
}
flag = 0;
/* Update KPH display */
}
} // Loop always
}
/**************************************************************************/
// Input capture operation for TIM channel 0 (wheel sensor signal)
interrupt void capture_ISR( void)
{
tcount = TCH0 - tprev; // Measured pulse period
tprev = TCH0;
TCH1 = TCH0 - 1; // Next compare slightly less than O/F period
flag = 1; // Flag new reading
TSC0_CH0F = 0; // Clear interrupt flag for capture channel
}
/******************************************************************************/
// Output compare operation for TIM channel 1 (overflow detect)
interrupt void compare_ISR( void)
{
flag = 2; // Flag period overflow
TSC1_CH1F = 0; // Clear interrupt flag for compare channel
}
The KPH calculation may take about 0.5 ms to complete, but this is still much less than the minimum period between readings. A rounding adjustment has been applied to the calculation.
It would be possible, and not too complex, to also apply a moving average algorithm to the readings, particularly for higher speeds, to smooth out fluctuations of the individual readings. You might need to reduce the sample size at lower speeds, to improve the response.
Regards,
Mac
Message Edited by bigmac on
2008-06-18 06:58 PM