2024-07-31 02:32 AM
Hello,
I am currently trying to setup a timer to measure time in between two pulses. I have managed to get it working with the code below but the issue is that I get very imprecise readings on the frequency. I get an error that is hovering around 1-1.5%, what can I do to minimize this error or is it not possible to get less then 1% error in this type of reading?
(The setting in values is done within the init function. I just dont want to send the whole code base)
Regards,
Björn
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
{
if (Is_First_Captured==0) // if the first rising edge is not captured
{
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3); // read the first value
Is_First_Captured = 1; // set the first captured as true
}
else // If the first rising edge is captured, now we will capture the second edge
{
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3); // read second value
if (IC_Val2 > IC_Val1)
{
Difference = IC_Val2-IC_Val1;
}
else if (IC_Val1 > IC_Val2)
{
Difference = (0xffff - IC_Val1) + IC_Val2;
}
float refClock = TIMCLOCK/(PRESCALAR);
frequency = refClock/Difference;
__HAL_TIM_SET_COUNTER(htim, 0); // reset the counter
Is_First_Captured = 0; // set it back to false
}
}
}
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
int Is_First_Captured = 0;
/* Measure Frequency */
float frequency = 0;
#define TIMCLOCK 270000000
#define PRESCALAR 1375
htim23.Instance = TIM23;
htim23.Init.Prescaler = 1374;
htim23.Init.CounterMode = TIM_COUNTERMODE_UP;
htim23.Init.Period = 4294967295;
htim23.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim23.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
2024-07-31 06:02 AM
Accuracy will be limited by the tick rate of the timer and the accuracy of the clock source. HSE will be more accurate than using HSI. Using a lower prescaler will give you better resolution. Use a prescaler that is low but also doesn't overflow before the slowest pulse is complete.
2024-07-31 06:53 AM - edited 2024-07-31 06:57 AM
These are all things we have thought about, we are using HSE and we have a rather slow period in between pulses so we want some prescaler. My original question might be better asked as "is there any hard percentage of inaccuracy with the clocks that you cant go below with the cpu, due to hardware interrupts and alike?"
Björn
2024-07-31 07:39 AM
No, there's no limit. Since the timer is in input capture mode, it will be accurate to the exact tick rate of the timer. Doesn't matter if the interrupt is delayed, as long as you read it before it changes again.
Do you see jitter or do you see a constant +1% bias?
How are you determining error exactly, by which i mean how do you "know" the frequency of the signal is what you think it is? Can you use a logic analyzer to view the signal on the actual pins?
2024-07-31 11:37 PM - edited 2024-07-31 11:38 PM
We see a varying error that is hover around 1% below the actual frequency. We are using a picoscope to double check the signal that we are generating with the help of a function generator. We are not using a logic analyzer to see the signal on the actual pins though.
2024-08-01 03:23 AM
> We see a varying error that is hover around 1% below the actual frequency.
This sounds like a systematic error, maybe some missing +1 in some timer setting?
Concerning TIM23:
- Are you sure that it accepts an input clock of 270 MHz ? (just found it, it's okay)
- Why "Difference = (0xffff - IC_Val1) + IC_Val2;" It's 32 bit timer, so better subtract from 0xFFFFFFFF. (I think you don't need that at all with unsigned integer)
- Why that strange prescaler value, giving an actual timer frequency of 270 M / 1375 = 196.343 k ?
=> maybe it's a floating point resolution error, I recently had that and it drove me crazy before I found that out.
2024-08-01 03:53 AM
The timer value we have changed as we found that the frequency on the timer was 137 500 000 not 270MHz, and we also found the subtraction error and changed it to 0xFFFFFFFF. We are still seeing the error however...
2024-08-01 04:25 AM
Have you checked the integer capture values and differences?
For a constant and jitter free input signal (what's the frequency by the way?), these should not vary by more than +-1 counter tick.
Then think about input signal frequency compared to timer resolution - maybe you cannot get better than the 1% ?
2024-08-01 04:30 AM
Given that we have pulses that vary between 1/60 hz and 1 hz at the absolute most we should be able to get more than 1%.
2024-08-01 06:21 AM
Generate an output PWM from your microcontroller and measure it to verify its clock is consistent with your measurement tools.
> and we also found the subtraction error and changed it to 0xFFFFFFFF.
This still has an error. If it's a 32-bit timer, the difference with full range is (IC_Val2 - IC_Val1) always.
Perhaps add some more detail into the exact values you're getting.