cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_Delay() inaccuracy

bns
Associate II

Hi folks,

I recently started my STM32 journey using a STM32WLE5JCxx (the LoRa-E5). After fighting with the SubGHz for a while, I managed to write a decent application, but I'm not completely familiar with all of the essentials yet.

Currently, I am using the `HAL_Delay()` function, but after some testing found that it is highly inaccurate. My code snippet:

 

  int i = 0;
  while(1) {
	  printf("%d\n", i++);
	  HAL_Delay(100000);
  }

 

The output I get (with the actual difference in milliseconds calculated afterwards):

 

13:26:41.925 > 0 
13:28:22.323 > 1 (+398)
13:30:02.318 > 2 (-5)
13:31:42.309 > 3 (-9)
13:33:22.290 > 4 (-19)
13:35:02.236 > 5 (-54)
13:36:42.118 > 6 (-118)
13:38:21.961 > 7 (-157)
13:40:01.796 > 8 (-165)
13:41:41.623 > 9 (-173)
13:43:21.431 > 10 (-192)

 

This means that on every 100 seconds, the clock drifts anywhere from -200ms to +400ms. A fixed value drift might've been OK, but this is quite unworkable.

I did read that `HAL_Delay()` might not be the most accurate clock source, but I am unsure how to implement a 'simple' delay-function. If someone could help me with a snippet or point to a place where I can find explanation on how to make an accurate delay myself, that would be very much appreciated.

Cheers!

15 REPLIES 15
bns
Associate II

@MM..1 while I do agree that printf is not the definitive solution to measuring clock accuracy, it says enough about clock drift. Especially when running for an extended period - see below using the MSI:

15:47:15.448 > 0
15:48:55.236 > 1
15:50:34.951 > 2
15:52:14.621 > 3
15:53:54.291 > 4
15:55:33.984 > 5
15:57:13.677 > 6
15:58:53.392 > 7
16:00:33.139 > 8
16:02:12.908 > 9
16:03:52.692 > 10
16:05:32.499 > 11
16:07:12.316 > 12
16:08:52.153 > 13
16:10:32.005 > 14
16:12:11.860 > 15
16:13:51.716 > 16
16:15:31.602 > 17
16:17:11.511 > 18
16:18:51.422 > 19
16:20:31.340 > 20
16:22:11.266 > 21
16:23:51.165 > 22
16:25:31.087 > 23
16:27:11.029 > 24
16:28:50.966 > 25
16:30:30.903 > 26
16:32:10.832 > 27
16:33:50.767 > 28
16:35:30.702 > 29
16:37:10.635 > 30
16:38:50.571 > 31
16:40:30.506 > 32
16:42:10.443 > 33
16:43:50.374 > 34

That's about five seconds over the course of roughly an hour.
I will further investigate the use of the TXCO that is available on the LoRa-E5 and see if I can improve this. Thanks for the help @SofLit !

For normal human calc use delay 120000 and as you see in tables clock as MSI or any other internal is stable, but not precise , error is around 10% based on temp and Vcc after calibrating around 1%. Then In hour = 60min you can arive 6min error or calib 36sec...

LCE
Principal

Yeah, using the internal RC oscillator for timing measurements is like using an old mechanical wrist watch for a 100 m sprint... ;)

I think your clock source has offset. If you can use the TCXO that would likely be a lot tighter/consistent

I'd free run the counter, not continually reset it.

At that point the time line becomes more consistent and more impervious to other stuff going on, like UART output.

I'd delta the time measurement, and advance the start / check-point reference

int i = 0;
uint32_t delay = 100000;
uint32_t start = TIM2->CNT;
while(1) {
  printf("%d\n", i++);
  while((TIM2->CNT - start) < delay);
  start += delay;
}

.  

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Together with a document I received from a colleague, I managed to get the TCXO going!
Drift is pretty much gone now: I only got 16ms drift over the course of 3600s.

 

18:57:14.177 > 0
18:58:54.176 > 1
19:00:34.176 > 2
19:02:14.176 > 3
19:03:54.175 > 4
19:05:34.175 > 5
19:07:14.175 > 6
19:08:54.174 > 7
19:10:34.174 > 8
19:12:14.173 > 9
19:13:54.172 > 10
19:15:34.172 > 11
19:17:14.172 > 12
19:18:54.171 > 13
19:20:34.171 > 14
19:22:14.170 > 15
19:23:54.170 > 16
19:25:34.170 > 17
19:27:14.169 > 18
19:28:54.169 > 19
19:30:34.167 > 20
19:32:14.167 > 21
19:33:54.168 > 22
19:35:34.167 > 23
19:37:14.166 > 24
19:38:54.166 > 25
19:40:34.165 > 26
19:42:14.165 > 27
19:43:54.165 > 28
19:45:34.164 > 29
19:47:14.164 > 30
19:48:54.164 > 31
19:50:34.163 > 32
19:52:14.162 > 33
19:53:54.162 > 34
19:55:34.161 > 35
19:57:14.161 > 36

 

I will try and see if the logic proposed by @Tesla DeLorean makes it more stable - 16ms on 3600s is ~44ppm drift, ideally I'd get to half of it. But this is definitely usable!! Thanks everyone!

For anyone ending up here - see the attachment chapter 7.5 for the HSE/TCXO settings, and see my Clock configuration in the next image.

bns_0-1729016287448.png

 

bns
Associate II

Correction: 16ms on 60m is 4.5ppm, not 44.5ppm so this definitely ticks all the boxes as I hoped for <10ppm. Yay :)