Is the Teensy 4.1 RTC crystal temperature compensated?

munch

Member
Hi all!


Just got a T4.1, to replace my Mega 2560, for a datalogging project.

I want to timestamp every measurement (at say 50Hz) with real-time millisecond accuracy, and thought I could try the on-board RTC.

I wanted to know whether the Teensy 4.1 RTC crystal is temperature compensated? Or in such a case, would I be better off using my DS3231?


Thanks in advance!
 
To my knowledge the the RTC crystal is not temperature compensated.
Here some test code (T4.x) which prints the drift of the RTC crystal and the drift of FCPU relative to a GPS pps signal (1Hz). The pps signal is connected to pin 11 and triggers a pin interrupt. The corresponding ISR reads out the RTC counter (see: https://github.com/TeensyUser/doc/wiki/The-real-time-clock#reading-out-the-rtc) and the cycle counter (see https://github.com/TeensyUser/doc/wiki/Using-the-cycle-counter), transforms both to seconds and prints out the difference to the 'real' time (GPS time).

Code:
#include "Arduino.h"

// read out the RTC counter
uint64_t get_RTC_periods()
{
    uint32_t hi1 = SNVS_HPRTCMR, lo1 = SNVS_HPRTCLR;
    while (true)
    {
        uint32_t hi2 = SNVS_HPRTCMR, lo2 = SNVS_HPRTCLR;
        if (lo1 == lo2 && hi1 == hi2)
        {
            return (uint64_t)hi2 << 32 | lo2;
        }
        hi1 = hi2;
        lo1 = lo2;
    }
}

// readout the cycle counter
uint64_t cycles64()
{
    static uint32_t oldCycles = ARM_DWT_CYCCNT;
    static uint32_t highDWORD = 0;

    uint32_t newCycles = ARM_DWT_CYCCNT;
    if (newCycles < oldCycles)
    {
        ++highDWORD;
    }
    oldCycles = newCycles;
    return (((uint64_t)highDWORD << 32) | newCycles);
}

void ISR()
{
    static int n            = 0;
    static uint64_t rtc_0   = get_RTC_periods();
    static uint64_t cyCnt_0 = cycles64();

    double t_rtc = (double)(get_RTC_periods() - rtc_0) / 32768.0;
    double t_cyc = (double)(cycles64() - cyCnt_0) / F_CPU_ACTUAL;

    Serial.printf("%d %.6e %.6e\n", n, t_rtc - n, t_cyc - n);
    n++;
}

void setup()
{
    attachInterrupt(11, ISR, RISING);
}

void loop()
{
}

Here the resulting data printed against time:
Screenshot 2022-01-30 115937.png

-> My RTC crystal drifts with about 10ppm, the main clock with about 8.4ppm relative to the GPS signal.

You can use the code above (either RTC or cycle counter) to generate your time stamp if the accuracy is good enough for your application.
 
How accurate do you want it to be?
"One millisecond" is a very imprecise specification. If you take that as a benchmark, the Teensy crystal is definitely sufficient.

Maybe you should take the normal approach.
Write and test the program. Only if it is too inaccurate, start with optimizations.
 
If you want a highly accurate RTC, I suggest you look at the RV3028, see here and here.
The manufacturer quotes an accuracy of +/- 1ppm at 25degC. If you "speak to them nicely" they will send you free samples and a development board.
I have been using one quite successfully on Teensy.
 
Ah amazing, thanks for all the advice, and the code!!
Since I have a DS3231, I might as well use that, but will certainly consider the other options in case the situation demands them.
 
-> My RTC crystal drifts with about 10ppm, the main clock with about 8.4ppm relative to the GPS signal.

This got me thinking: how accurate is the millis() / elapsedMillis() function in ppm? Is it similar to the main clock's accuracy?
 
This got me thinking: how accurate is the millis() / elapsedMillis() function in ppm? Is it similar to the main clock's accuracy?

Millis and Micros, etc - all run from another 'normal' quality typical crystal. And updated by a millisecond tick interrupt that can lose ticks if interrupts are disabled too long by running code.
 
Back
Top