cancel
Showing results for 
Search instead for 
Did you mean: 

STM32h735 imprecise timings

BjornLindholm
Associate II

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;

12 REPLIES 12
TDK
Guru

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.

 

If you feel a post has answered your question, please click "Accept as Solution".

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

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?

If you feel a post has answered your question, please click "Accept as Solution".

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.

LCE
Principal

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.

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...

LCE
Principal

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% ?

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%. 

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.

If you feel a post has answered your question, please click "Accept as Solution".