2018-04-11 01:27 PM
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.Solved! Go to Solution.
2018-04-12 01:11 AM
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.
Or simply count for 30 seconds (the finest calibration step is just below one ppm).
JW
2018-04-12 01:42 AM
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.
2018-04-12 07:14 PM
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.2018-04-13 08:22 AM
I'm still a bit confused, and don't understand all the options to use/calibrate the RTC peripheral in the STM32 yet.
So, to keep things simple for now: I simply accumulated the number of LSE cycles in the 1 PPS interrupt callback function for 32 seconds in total. And then I took the difference between the sum of the captured values and the expected number of LSE ticks (32 * 32768). - With my current test hardware, I get a 'cumulative error' of about -16 ticks. - This is less than a 30 ppm error, i.e. less than 1 LSE clock tick per second.
After that, I've tried to adjust the RTC with the 'Smooth Digital Calibration' method (RTC_CALR), by using this HAL function: HAL_RTCEx_SetSmoothCalib().
But For some reason I cannot see any difference, even when I use the calibration with maximum correction parameters like this (still -16 ticks):
HAL_RTCEx_SetSmoothCalib(&hrtc, RTC_SMOOTHCALIB_PERIOD_8SEC, RTC_SMOOTHCALIB_PLUSPULSES_SET, 0x000001FF);
However, after letting the board run for a couple of hours the RTC's error becomes visible like expected after using HAL_RTCEx_SetSmoothCalib() with maximum parameter. - I assume that the adjustments made by the 'smooth calibration block' are not visible yet after measuring for a such a short time...
Please correct me if I'm on the wrong track. - I plan to use a high frequency clock source later on.
Any hints to make the most simple calibration method work would be appreciated.
As a sidenote: This STM32L011 RTC test board is just a personal side-project of mine to learn more about the RTC and low-power modes of the STM32, later on. But I don't have a very accurate frequency counter at hand, for checking... - And I have only only basic understanding of all the peripherals.
2018-04-13 09:07 AM
You may want to read the data sheet and Hal user manual. The calibration registers is set to work over 20 bits (32 second) so it should kick in after 32 second. On the next 32 second measurement, the measurement should be more accurate and the error ticks should go down.
No idea what the right functions are to use for Hal.
2018-04-14 11:13 AM
Some more tests have been done...
When I understand you correctly, then you suggested that it is actually possible to use the SubSeconds field for calibration, because the two prescalers/dividers applied to the RTC clock source (that divide the 768 kHz in my case down to 1 second pulses for the calendar) are also used to update the sub second register (RTC_SSR). As described in the
/external-link.jspa?url=http%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Freference_manual%2Fdm00108pdf
(section 4.3 Clock and prescalers), the 'asynchronous prescaler' (ck_apre) generates the clock signal used by the SubSeconds counter, hence it increases in resolution by making that prescaler smaller (full input clock speed when equal to 1), and the synchronous prescaler (applied after first clock division by the asynchronous prescaler) larger, while making sure that the resulting 1 second interval for the actual RTC calender keeps exactly 1 second long.To do this with HAL level code / STM32CubeMX, I will try to use the RTC initialization structure's AsynchPrediv / SynchPrediv fields for this:
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24; hrtc.Init.AsynchPrediv = 127; // change this hrtc.Init.SynchPrediv = 255; // change this hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; if (HAL_RTC_Init(&hrtc) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }Please correct me if I'm wrong.
After setting up the RTC time stamp capturing (with HAL_RTCEx_SetTimeStamp_IT() / HAL_RTCEx_TimeStampEventCallback()), the SubSecond field of the captured RTC time stamps can be used to measure the deviation of the LSE clock from the accurate 1 PPS signal.
I'm trying to do this right now...
Another observation made: I can only capture timestamps (with interrupts), after an RTC alarm has been triggered (HAL_RTC_SetAlarm_IT() / HAL_RTC_AlarmAEventCallback()). When I do not enable the alarm at all, no RTC timestamps are captured...
2018-04-15 12:27 PM
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. Thehttp://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 processstarting to capture 1 PPS signal (GPS module)000: captured ticks (1 PPS): 25001603001: captured ticks (1 PPS): 25001604002: captured ticks (1 PPS): 25001597003: captured ticks (1 PPS): 25001593004: captured ticks (1 PPS): 25001593005: captured ticks (1 PPS): 25001594006: captured ticks (1 PPS): 25001595007: captured ticks (1 PPS): 25001595008: captured ticks (1 PPS): 25001595009: captured ticks (1 PPS): 25001597average: 25001596.000000 ticksstarting to capture 1 Hz RTC calibration output (target)000: captured ticks (RTC calib.): 24998275001: captured ticks (RTC calib.): 24998278002: captured ticks (RTC calib.): 24998277003: captured ticks (RTC calib.): 24998279004: captured ticks (RTC calib.): 24998281005: captured ticks (RTC calib.): 24998275006: captured ticks (RTC calib.): 24998281007: captured ticks (RTC calib.): 24998284008: captured ticks (RTC calib.): 24998281009: captured ticks (RTC calib.): 24998283average: 24998280.000000 tickscapture process finishedRTC crystal runs too slow!correction: 132.62033462524414062500 ppmall done------------------------------Next up I have to calibrate the target board, and verify the result...
2018-04-15 03:41 PM
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 processstarting to capture 1 PPS signal (GPS module)000: captured ticks (1 PPS): 25001590001: captured ticks (1 PPS): 25001591002: captured ticks (1 PPS): 25001580003: captured ticks (1 PPS): 25001580004: captured ticks (1 PPS): 25001580005: captured ticks (1 PPS): 25001581006: captured ticks (1 PPS): 25001581007: captured ticks (1 PPS): 25001582008: captured ticks (1 PPS): 25001583009: captured ticks (1 PPS): 25001583010: captured ticks (1 PPS): 25001583011: captured ticks (1 PPS): 25001584012: captured ticks (1 PPS): 25001585013: captured ticks (1 PPS): 25001586014: captured ticks (1 PPS): 25001586015: captured ticks (1 PPS): 25001587016: captured ticks (1 PPS): 25001587017: captured ticks (1 PPS): 25001588018: captured ticks (1 PPS): 25001589019: captured ticks (1 PPS): 25001589020: captured ticks (1 PPS): 25001590021: captured ticks (1 PPS): 25001591022: captured ticks (1 PPS): 25001590023: captured ticks (1 PPS): 25001579024: captured ticks (1 PPS): 25001580025: captured ticks (1 PPS): 25001581026: captured ticks (1 PPS): 25001582027: captured ticks (1 PPS): 25001582028: captured ticks (1 PPS): 25001582029: captured ticks (1 PPS): 25001584030: captured ticks (1 PPS): 25001584031: captured ticks (1 PPS): 25001585average: 25001584.000000 ticksstarting to capture 1 Hz RTC calibration output (target)000: captured ticks (RTC calib.): 24998260001: captured ticks (RTC calib.): 24998259002: captured ticks (RTC calib.): 24998259003: captured ticks (RTC calib.): 24998261004: captured ticks (RTC calib.): 24998262005: captured ticks (RTC calib.): 24998262006: captured ticks (RTC calib.): 24998249007: captured ticks (RTC calib.): 24998251008: captured ticks (RTC calib.): 24998252009: captured ticks (RTC calib.): 24998251010: captured ticks (RTC calib.): 24998253011: captured ticks (RTC calib.): 24998252012: captured ticks (RTC calib.): 24998256013: captured ticks (RTC calib.): 24998255014: captured ticks (RTC calib.): 24998255015: captured ticks (RTC calib.): 24998256016: captured ticks (RTC calib.): 24998257017: captured ticks (RTC calib.): 24998258018: captured ticks (RTC calib.): 24998259019: captured ticks (RTC calib.): 24998259020: captured ticks (RTC calib.): 24998258021: captured ticks (RTC calib.): 24998260022: captured ticks (RTC calib.): 24998260023: captured ticks (RTC calib.): 24998261024: captured ticks (RTC calib.): 24998263025: captured ticks (RTC calib.): 24998263026: captured ticks (RTC calib.): 24998252027: captured ticks (RTC calib.): 24998252028: captured ticks (RTC calib.): 24998256029: captured ticks (RTC calib.): 24998248030: captured ticks (RTC calib.): 24998254031: captured ticks (RTC calib.): 24998254average: 24998256.000000 tickscapture process finishedcorrection factor:24998256.000000 / 25001584.000000 =0.99986690282821655273RTC crystal runs too slow!correction: -133.09716796875000000000 ppmcorrection value (ticks +/- 32 s interval):MINUS 140use 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 processstarting to capture 1 PPS signal (GPS module)000: captured ticks (1 PPS): 25001590001: captured ticks (1 PPS): 25001590002: captured ticks (1 PPS): 25001588003: captured ticks (1 PPS): 25001579004: captured ticks (1 PPS): 25001581005: captured ticks (1 PPS): 25001581006: captured ticks (1 PPS): 25001581007: captured ticks (1 PPS): 25001582008: captured ticks (1 PPS): 25001582009: captured ticks (1 PPS): 25001583010: captured ticks (1 PPS): 25001584011: captured ticks (1 PPS): 25001584012: captured ticks (1 PPS): 25001585013: captured ticks (1 PPS): 25001586014: captured ticks (1 PPS): 25001586015: captured ticks (1 PPS): 25001587016: captured ticks (1 PPS): 25001588017: captured ticks (1 PPS): 25001588018: captured ticks (1 PPS): 25001588019: captured ticks (1 PPS): 25001589020: captured ticks (1 PPS): 25001590021: captured ticks (1 PPS): 25001590022: captured ticks (1 PPS): 25001587023: captured ticks (1 PPS): 25001578024: captured ticks (1 PPS): 25001580025: captured ticks (1 PPS): 25001580026: captured ticks (1 PPS): 25001580027: captured ticks (1 PPS): 25001581028: captured ticks (1 PPS): 25001582029: captured ticks (1 PPS): 25001582030: captured ticks (1 PPS): 25001583031: captured ticks (1 PPS): 25001583average: 25001584.000000 ticksstarting to capture 1 Hz RTC calibration output (target)000: captured ticks (RTC calib.): 25001310001: captured ticks (RTC calib.): 25002073002: captured ticks (RTC calib.): 25001310003: captured ticks (RTC calib.): 25002074004: captured ticks (RTC calib.): 25001311005: captured ticks (RTC calib.): 25001313006: captured ticks (RTC calib.): 25001312007: captured ticks (RTC calib.): 25002076008: captured ticks (RTC calib.): 25001301009: captured ticks (RTC calib.): 25002065010: captured ticks (RTC calib.): 25001302011: captured ticks (RTC calib.): 25002066012: captured ticks (RTC calib.): 25001304013: captured ticks (RTC calib.): 25001304014: captured ticks (RTC calib.): 25001306015: captured ticks (RTC calib.): 25002069016: captured ticks (RTC calib.): 25001306017: captured ticks (RTC calib.): 25002070018: captured ticks (RTC calib.): 25001309019: captured ticks (RTC calib.): 25002071020: captured ticks (RTC calib.): 25001309021: captured ticks (RTC calib.): 25001310022: captured ticks (RTC calib.): 25001310023: captured ticks (RTC calib.): 25002074024: captured ticks (RTC calib.): 25001312025: captured ticks (RTC calib.): 25002075026: captured ticks (RTC calib.): 25001312027: captured ticks (RTC calib.): 25002078028: captured ticks (RTC calib.): 25001303029: captured ticks (RTC calib.): 25001302030: captured ticks (RTC calib.): 25001304031: captured ticks (RTC calib.): 25002065average: 25001594.000000 tickscapture process finishedcorrection factor:25001594.000000 / 25001584.000000 =1.00000035762786865234RTC crystal runs too fast!correction: -0.35762786865234375000 ppmcalibration complete! NO FURTHER CORRECTION REQUIREDall done------------------------------TODO: Update RTC Smooth Calibration parameters on the fly, while the microcontroller is running, with the same technique...
2018-04-15 05:47 PM
,
,
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
2018-04-15 06:12 PM
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... ;pEdit: IIRC there's quite a lot of useful info on this topic in this app note: