Seeeduino Xiao RTC time drift

Hi everyone!

Using the on-chip RTC of the Seeeduino Xiao I’m experiencing about 16 s/day drift. I’ve tried both using “Seeed Arduino RTC” lib (RTC_SAMD21.h…) and also “RTCZero” at my first tries, with the same results.

Checking the XTAL datasheet, the 20ppm accuracy should lead to less than 2s per day drifting.

I read somewhere it had to do with the PLL programming of the SAMD21 internal clock system by the libraries (or maybe the compiler implementation…).

Any clue on how to get the Seeeduino working with a “fair” accuracy for basic timestamping of less than a minute drift per month, or any workaround?

I started a test on a SAMD21 XIAO device myself. It’s running now 4 hours and is 2 seconds off. So I expect a difference of ~12 seconds/day. And I’m pretty sure that RTC is driven by the crystal. There is a FREQCORR register, which allows to calibrate the RTC. The range is about +/- 128ppm. I’ll try that and report.

Thank you so much robert-hh ! It sounds good.

I’ll have a look to that register too, but I’m not sure about how program register from the C code. I’ll wait for your report.

It’s now 6 hours after I changed the calibration and the clock is still on spot. With the previous setting, it would be already 3 seconds off. I’m not sure how to do that in the Arduino environment. But it seems as if the import the Atmel header files, and then it’s simply:

int8_t value;
RTC->MODE2.FREQCORR.reg = value;

With value being a number between -128 and +127. Positive values make the clock slower, negative ones faster, and the value is about the ppm change to expect. 16 s/day is something like 180ppm off. So you cannot compensate that completely.

After 17 hours I have 2 seconds drift → 3 seconds/day. That what could be expected. Still, the crystal of the board seems not to be great. At the moment in my set-up the input clock to RTC is 1024 Hz. I could check if the range is increased if I set the clock to 512 Hz.

No, changing the RTC input clock frequency does not affect the compensation range.

Hi robert-hh,
I am trying to adjust the delay/advance by writing the code below, but the effect does not show up when I write the maximum/minimum value. It seems that I am able to write to the register.
Where did you write the code, in setup() or in the RTC_SAMD library?

    Serial.println(RTC->MODE2.FREQCORR.reg, HEX);      
    RTC->MODE2.FREQCORR.reg = 0xFF; // -127ppm -11"/day
    //RTC->MODE2.FREQCORR.reg = 0x7F; // +127ppm +11"/day
    Serial.println(RTC->MODE2.FREQCORR.reg, HEX); 

I do not use the Arduino environment. I have it directely coded in the RTC module of MicroPython. It may be that the Arduino Lib resets that register. It may as well be, that Arduino does not use the RTC at all. I would have to check.

I looked through the Arduino source tree for the XIAO Seeeduino (v1.8.3). There is not reference to the RTC hardware. So I assume the clock is emulated in software using e.g. the systick timer. They use however the Crystal as clock source for the system clock. So it is crystal based, but the correction cannot be applied.

Thanks for all this research Robert!

Having the RTC software implemented in the RTC_SAMD21 lib doesn’t sound very nice… specially when we having a specific hardware device for it in the microcontroller. And it even seems to be less useful or reasonable when we have a special library made for SAMD21’s RTC.

I’ll try to go in detail through al these tests and do some checking and let you now if I can add something to this.

The sketch used includes the file “RTC_SAMD21.h”. The clock source for XIAO_SAMD21 is a 32768 Hz crystal oscillator. I’m wondering if I can compensate the RTC module by setting some registers properly. Based on a tip from robert-hh, I will investigate the datasheet and code in a bit more detail.

By reading “RTC_SAMD21.cpp” and the datasheet “19. RTC-Real-Time Counter” ,“19.8.19 Frequency Counter”, I was able to compensate for the RTC.

The RTC error was +14sec/day (+162ppm) without correction. I was able to correct it to +3sec/day (+35ppm) by setting the FREQCORR=0x7F to the maximum possible value of -11sec/day (-127ppm).
It is important to note that the “SIGN” in the datasheet, which indicates the direction of the correction, seems to be incorrect.

#include "RTC_SAMD21.h"
#include "DateTime.h"

RTC_SAMD21 rtc;

void setup()
    DateTime now = DateTime(F(__DATE__), F(__TIME__));
    RTC->MODE2.FREQCORR.reg = 0x7F; // -127ppm -11"/day

No, your code matches the data sheet. Positive value cause the clock to run slower.

“19.8.19 Frequency Correction” explains that frequency increases when SIGN is 0.
Does the increase in frequency mean that the clock slows down?

Bit 7 – SIGN: Correction Sign
Value Description
0 The correction value is positive, i.e., frequency will be increased.
1 The correction value is negative, i.e., frequency will be decreased.

The Sign bit in the Frequency Correction register (FREQCORR.SIGN) determines the direction of the correction. A
positive value will add counts and increase the period (reducing the frequency), and a negative value will reduce
counts per period (speeding up the frequency).


Bit 7 – SIGN Correction Sign
Value Description
0 The correction value is positive, i.e., frequency will be decreased.
1 The correction value is negative, i.e., frequency will be increased.

Document version: DS40001882H
I didn’t see anything in Chapter 48/Change History that talked about RTC correction explicity

The datasheet I am referring to is
“Rev: Atmel-42181J-SAM D21_Datasheet_Complete-07/2016”.
You are right, the SIGN description is reversed.

Hi everyone! I’ve tried msfujino solution programming MODE2.FREQCORR register and it worked OK. From a 15 s/day drift it lowers to an acceptable for my project now, 3 s/day.

Thank you very much to you all who helped!!