Skip to main content
A L
Associate
April 11, 2018
Solved

RTC calibration (STM32L011G4)

  • April 11, 2018
  • 20 replies
  • 5979 views
Posted on April 11, 2018 at 22:27

Hi there! - After looking around for quite a while, I'm still not exactly sure how to calibrate the RTC on my STM32L011G4 board. - For our project, we are using an external LSE crystal (768 kHz) for the RTC. - Do I need to use the RTC_SmoothCalib method (example for other MCU types), or is there another way to adjust the RTC accuracy? I have an accurate 1s clock source from a GPS module hooked up and counting rising edges with EXTI interrupt... That works nicely. But how could the number of LSE clock ticks happening between the external 1s pulses be counted to adjust the calibration registers? (RTC_CALR)There are only 2 timers, and no 32-bit one on the STM32L.. - Any help / hints would be appreciated. I'm simply overwhelmed by all the cryptic options described in the docs...

#rtc #rtc-calibration #lse #calibration #stm32l011g4 #stm32l0x1

Note: this post was migrated and contained many threaded conversations, some content may be missing.
This topic has been closed for replies.
Best answer by henry.dick
Posted on April 12, 2018 at 01:19

It wouldn't work, as the lse is too coarse. Each count is 30ppm and you have to count sub cycle for this approach to be useful.

However you are almost on the right path: consider two clocks, one is slow : 1pps from the GPS, or 1pps from the rtc. And another high speed clock. The high speed clock doesn't need to be terribly accurate - it just need to be stable over the measurement period.

Write a code that counts the high speed clock being gated by the slow clock. 

First run the code using the 1pps from the GPS, write down the counts.

Then run the code using the 1pps from the rtc. Write down the counts .

The difference between the two counts, over the high speed clocks frequency, is the ppm error rate of the rtc.

Best of luck to your project.

20 replies

henry.dick
Associate II
April 11, 2018
Posted on April 11, 2018 at 23:12

Don't worry about how to implement the calibration. Instead, focus on the logic of your calibration. You have two oscillators, one with a known frequency (1pps from the GPS), and another unknown (the lse).

From that, how do you detect the frequency of the lse?

A L
A LAuthor
Associate
April 12, 2018
Posted on April 12, 2018 at 00:07

Thank you for the help! This is exactly what I'm struggling with... Somehow there must be a way to count the LSE clock ticks between the 1 second pulses from GPS module (1 pps). I'm trying to find a way to configure one of the timers (TIM2), so that it measures the number of LSE ticks instead of system clock ticks (with prescaler...). Is there a way to set up the internal MUX to let a timer have the LSE as a clock source?

Also, there's a quite suspicious option in STM32CubeMX I've discovered right before in the RTC panel (Pinout screen), to activate the calibration *output* of 1 Hz. I guess, this is to check the accuracy of the RTC after calibration on an external frequency counter... - But there's also an option called 'Reference clock detection'... hm... I'm still a bit lost there...

Tesla DeLorean
Guru
April 12, 2018
Posted on April 12, 2018 at 00:40

Select LSE as the clock source for LPTIM, read LPTIM_CNT in EXTI

Select LSE as the clock source for TIM21/22 and use the 1PPS to perform an Input Capture and interrupt subtract the last CCRx latched reading from the current.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Steve Melnikoff
Senior
April 12, 2018
Posted on April 12, 2018 at 10:42

If you're able to connect the 1PPS signal from the GPS to the RTC's timestamp input (RTC_TS), you can then gather timestamps from the RTC which you know to be precisely one second apart.

You can then adjust the RTC's calibration value such that the number of ticks between timestamps comes out to the frequency of ck_apre (which is output by the asynchronous prescaler).

By default, this is set to 256 Hz. However, if you to set the asynchronous predivider to zero, the synchronous one to 32759, and the initial calibration value to 0x100, following the instructions in the reference manual, it gives you much greater resolution, and hence better accuracy.

A L
A LAuthor
Associate
April 13, 2018
Posted on April 13, 2018 at 02:14

Thanks for the interesting hints Steve!

Just for the record: I was able to record time stamps by connecting the 1 PPS signal to RTC_TS (PA2 in my case). The HAL_RTCEx_TimeStampEventCallback() callback fires on every rising edge of the 1 PPS now, after enabling it with HAL_RTCEx_SetTimeStamp_IT().

Looking at the

http://www.st.com/resource/en/reference_manual/dm00108282.pdf

in the RTC section, I'm trying to understand how the RTC can actually be calibrated. I do see 2 important registers: RTC_CALR (which I initially though to be the main calibration register - only tested this once very briefly on another STM32 by writing extreme values into it), and RTC_PRER. I'm reading up on these now... /more on the insights later.
A L
A LAuthor
Associate
April 15, 2018
Posted on April 15, 2018 at 21:27

Ok. This has been quite bumpy a ride. But I think I've found a simple solution, a more general approach than trying to solve it with the limited ressource of the tiny L0.

So, here some notes for others to replicate this:

Since the

http://www.st.com/en/microcontrollers/stm32l011g4.html

does not include a 32-bit timer and since my test hardware has no accurate system clock source on the board (no HSE crystal, only LSE), and also has very limited amount of RAM/flash, I've decided to use another board for the calibration process that comes with those features. The

http://www.st.com/en/evaluation-tools/stm32f4discovery.html

in my case.

To make this work, both -- the accurate 1 PPS signal from the GPS module and the 1 Hz RTC calibration output from the target board (STM32L011) -- were connected to two channels of the TIM2 peripheral (32-bit timer) of the STM32F4, and configured in 'Input Capture direct mode' (PA1 -> TIM2_CH2 -> 1 PPS from GPS module / PA15 -> TIM2_CH1 -> RTC calibration output (1 Hz) from target board).

The short test program on the STM32F4 board first captures the number of internal clock ticks (at 25 MHz, driven by external 8 MHz crystal (HSE)) happening between the accurate 1 PPS (TIM2_CH2). After that, the program stops the Input Capture process on TIM2_CH2 and starts it on TIM2_CH1, to capture the clock ticks between the to-be-calibrated RTC 1 Hz output of the target board.

(While testing, I've noticed that quartz crystals are actually indeed much more stable/accurate RC oscillators; the measured clocks of an internal (16 MHz HSI) clock source were drifting around a lot. I think a stable/accurate high speed clock source is absolutely crucial for time calibration, it is almost impossible to calibrate the RTC on MCUs without a fast/stable clock as a reference...)

Currently the test output looks like that:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001603

001: captured ticks (1 PPS): 25001604

002: captured ticks (1 PPS): 25001597

003: captured ticks (1 PPS): 25001593

004: captured ticks (1 PPS): 25001593

005: captured ticks (1 PPS): 25001594

006: captured ticks (1 PPS): 25001595

007: captured ticks (1 PPS): 25001595

008: captured ticks (1 PPS): 25001595

009: captured ticks (1 PPS): 25001597

average: 25001596.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 24998275

001: captured ticks (RTC calib.): 24998278

002: captured ticks (RTC calib.): 24998277

003: captured ticks (RTC calib.): 24998279

004: captured ticks (RTC calib.): 24998281

005: captured ticks (RTC calib.): 24998275

006: captured ticks (RTC calib.): 24998281

007: captured ticks (RTC calib.): 24998284

008: captured ticks (RTC calib.): 24998281

009: captured ticks (RTC calib.): 24998283

average: 24998280.000000 ticks

capture process finished

RTC crystal runs too slow!

correction: 132.62033462524414062500 ppm

all done

------------------------------

Next up I have to calibrate the target board, and verify the result...

waclawek.jan
Super User
April 16, 2018
Posted on April 16, 2018 at 00:47

 ,

 ,

the measured clocks of an internal (16 MHz HSI) clock source was drifting around a lot. I think a stable/accurate high speed clock source is absolutely crucial for time calibration, so I think it is almost impossible to calibrate the RTC on MCUs without a fast/stable clock as a reference...

For a

https://community.st.com/0D70X000006SwQbSAK

with similar motivation I concocted a demo to measure internal oscillators against LSE, and the finding was, not surprisingly, similar.

132ppm deviation for a 32.768kHz crystal sounds a wee bit more than it should be - the poorest quality crystals should be up to 100ppm. Make sure the loading capacitors are properly calculated (see ), and that the crystal surroundings is as RF-quiet as possible (which includes but is not limited to very short leads to the crystal and capacitors and careful grounding arrangement).

JW

A L
A LAuthor
Associate
April 16, 2018
Posted on April 16, 2018 at 01:12

Thanks for the hint JW! Nice to read more on a similar topic in the other thread, I have a lot to learn about how to use the STM32 peripherals properly...

waclawek.jan wrote:

132ppm deviation for a 32.768kHz crystal sounds a wee bit more than it should be - the poorest quality crystals should be up to 100ppm. Make sure the loading capacitors are properly calculated (see ), and that the crystal surroundings is as RF-quiet as possible (which includes but is not limited to very short leads to the crystal and capacitors and careful grounding arrangement).

Interesting, yes, I actually had problems with those RTC 32.768 kHz crystals before... On another project (using an STM32F7x) I needed to replace the loading capacitors multiple times to get the oscillator running. I also tried to tweak things with STM32CubeMX in the RCC settings (LSE_Drive_Capability, LSE Startup Timout Value), but it only started to resonate with very 'unusual' caps of 2 x 2.7 pF, a

https://abracon.com/Resonators/ABS07-120-32.768kHz-T.pdf

by Abracon was used in both projects. The MCU didn't even want to start executing code when wrong caps were installed, even the LSE wasn't used... Strange. - I do not understand this in great detail, tried to read more on how to calculate trace widths, caps etc. But I still needed to do things by trial'n'error at the end... ;p

Edit: IIRC there's quite a lot of useful info on this topic in this app note:

http://www.st.com/content/ccc/resource/technical/document/application_note/c6/eb/5e/11/e3/69/43/eb/CD00221665.pdf/files/CD00221665.pdf/jcr:content/translations/en.CD00221665.pdf

A L
A LAuthor
Associate
April 15, 2018
Posted on April 16, 2018 at 00:41

Alright, it finally seems to work. Now I just need to let it run for a longer time (hours/days) to see how accurate the calibration is... Thanks for the initial hints, it helped quite a bit.

Before the calibration it looks like this: it measures both clock sources for 32 seconds (+ ignored 5 seconds at the beginning of each measurement), compares the results, and calculates the correction value to be used in the Smooth Calibration register:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001590

001: captured ticks (1 PPS): 25001591

002: captured ticks (1 PPS): 25001580

003: captured ticks (1 PPS): 25001580

004: captured ticks (1 PPS): 25001580

005: captured ticks (1 PPS): 25001581

006: captured ticks (1 PPS): 25001581

007: captured ticks (1 PPS): 25001582

008: captured ticks (1 PPS): 25001583

009: captured ticks (1 PPS): 25001583

010: captured ticks (1 PPS): 25001583

011: captured ticks (1 PPS): 25001584

012: captured ticks (1 PPS): 25001585

013: captured ticks (1 PPS): 25001586

014: captured ticks (1 PPS): 25001586

015: captured ticks (1 PPS): 25001587

016: captured ticks (1 PPS): 25001587

017: captured ticks (1 PPS): 25001588

018: captured ticks (1 PPS): 25001589

019: captured ticks (1 PPS): 25001589

020: captured ticks (1 PPS): 25001590

021: captured ticks (1 PPS): 25001591

022: captured ticks (1 PPS): 25001590

023: captured ticks (1 PPS): 25001579

024: captured ticks (1 PPS): 25001580

025: captured ticks (1 PPS): 25001581

026: captured ticks (1 PPS): 25001582

027: captured ticks (1 PPS): 25001582

028: captured ticks (1 PPS): 25001582

029: captured ticks (1 PPS): 25001584

030: captured ticks (1 PPS): 25001584

031: captured ticks (1 PPS): 25001585

average: 25001584.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 24998260

001: captured ticks (RTC calib.): 24998259

002: captured ticks (RTC calib.): 24998259

003: captured ticks (RTC calib.): 24998261

004: captured ticks (RTC calib.): 24998262

005: captured ticks (RTC calib.): 24998262

006: captured ticks (RTC calib.): 24998249

007: captured ticks (RTC calib.): 24998251

008: captured ticks (RTC calib.): 24998252

009: captured ticks (RTC calib.): 24998251

010: captured ticks (RTC calib.): 24998253

011: captured ticks (RTC calib.): 24998252

012: captured ticks (RTC calib.): 24998256

013: captured ticks (RTC calib.): 24998255

014: captured ticks (RTC calib.): 24998255

015: captured ticks (RTC calib.): 24998256

016: captured ticks (RTC calib.): 24998257

017: captured ticks (RTC calib.): 24998258

018: captured ticks (RTC calib.): 24998259

019: captured ticks (RTC calib.): 24998259

020: captured ticks (RTC calib.): 24998258

021: captured ticks (RTC calib.): 24998260

022: captured ticks (RTC calib.): 24998260

023: captured ticks (RTC calib.): 24998261

024: captured ticks (RTC calib.): 24998263

025: captured ticks (RTC calib.): 24998263

026: captured ticks (RTC calib.): 24998252

027: captured ticks (RTC calib.): 24998252

028: captured ticks (RTC calib.): 24998256

029: captured ticks (RTC calib.): 24998248

030: captured ticks (RTC calib.): 24998254

031: captured ticks (RTC calib.): 24998254

average: 24998256.000000 ticks

capture process finished

correction factor:

24998256.000000 / 25001584.000000 =

0.99986690282821655273

RTC crystal runs too slow!

correction: -133.09716796875000000000 ppm

correction value (ticks +/- 32 s interval):

MINUS 140

use this on the target:

HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_32SEC, RTC_SMOOTHCALIB_PLUSPULSES_RESET, 140);

all done

------------------------------

And after the calibration:

------------------------------

starting capturing process

starting to capture 1 PPS signal (GPS module)

000: captured ticks (1 PPS): 25001590

001: captured ticks (1 PPS): 25001590

002: captured ticks (1 PPS): 25001588

003: captured ticks (1 PPS): 25001579

004: captured ticks (1 PPS): 25001581

005: captured ticks (1 PPS): 25001581

006: captured ticks (1 PPS): 25001581

007: captured ticks (1 PPS): 25001582

008: captured ticks (1 PPS): 25001582

009: captured ticks (1 PPS): 25001583

010: captured ticks (1 PPS): 25001584

011: captured ticks (1 PPS): 25001584

012: captured ticks (1 PPS): 25001585

013: captured ticks (1 PPS): 25001586

014: captured ticks (1 PPS): 25001586

015: captured ticks (1 PPS): 25001587

016: captured ticks (1 PPS): 25001588

017: captured ticks (1 PPS): 25001588

018: captured ticks (1 PPS): 25001588

019: captured ticks (1 PPS): 25001589

020: captured ticks (1 PPS): 25001590

021: captured ticks (1 PPS): 25001590

022: captured ticks (1 PPS): 25001587

023: captured ticks (1 PPS): 25001578

024: captured ticks (1 PPS): 25001580

025: captured ticks (1 PPS): 25001580

026: captured ticks (1 PPS): 25001580

027: captured ticks (1 PPS): 25001581

028: captured ticks (1 PPS): 25001582

029: captured ticks (1 PPS): 25001582

030: captured ticks (1 PPS): 25001583

031: captured ticks (1 PPS): 25001583

average: 25001584.000000 ticks

starting to capture 1 Hz RTC calibration output (target)

000: captured ticks (RTC calib.): 25001310

001: captured ticks (RTC calib.): 25002073

002: captured ticks (RTC calib.): 25001310

003: captured ticks (RTC calib.): 25002074

004: captured ticks (RTC calib.): 25001311

005: captured ticks (RTC calib.): 25001313

006: captured ticks (RTC calib.): 25001312

007: captured ticks (RTC calib.): 25002076

008: captured ticks (RTC calib.): 25001301

009: captured ticks (RTC calib.): 25002065

010: captured ticks (RTC calib.): 25001302

011: captured ticks (RTC calib.): 25002066

012: captured ticks (RTC calib.): 25001304

013: captured ticks (RTC calib.): 25001304

014: captured ticks (RTC calib.): 25001306

015: captured ticks (RTC calib.): 25002069

016: captured ticks (RTC calib.): 25001306

017: captured ticks (RTC calib.): 25002070

018: captured ticks (RTC calib.): 25001309

019: captured ticks (RTC calib.): 25002071

020: captured ticks (RTC calib.): 25001309

021: captured ticks (RTC calib.): 25001310

022: captured ticks (RTC calib.): 25001310

023: captured ticks (RTC calib.): 25002074

024: captured ticks (RTC calib.): 25001312

025: captured ticks (RTC calib.): 25002075

026: captured ticks (RTC calib.): 25001312

027: captured ticks (RTC calib.): 25002078

028: captured ticks (RTC calib.): 25001303

029: captured ticks (RTC calib.): 25001302

030: captured ticks (RTC calib.): 25001304

031: captured ticks (RTC calib.): 25002065

average: 25001594.000000 ticks

capture process finished

correction factor:

25001594.000000 / 25001584.000000 =

1.00000035762786865234

RTC crystal runs too fast!

correction: -0.35762786865234375000 ppm

calibration complete! NO FURTHER CORRECTION REQUIRED

all done

------------------------------

TODO: Update RTC Smooth Calibration parameters on the fly, while the microcontroller is running, with the same technique...