Crystal Oscillator Accuracy

Posted on
  • Does anyone know anything about the accuracy of crystals? I'm wondering whether 32kHz crystals are actually more accurate than 4Mhz ones... Having looked at Farnell it seems like the majority of them hover around the 20 parts per million range, but that sounds a bit strange to me.

    The reason I'm looking into this is the Pico's timekeeping. At the moment it uses its internal low-speed oscillator for timekeeping, which seems to have a tolerance of around 100,000 parts per million :)

    I'm considering going back to using the original (much more simple) timekeeping that uses the high speed oscillator, and then only using the low-speed oscillator to wake from Deep Sleep. It'd mean that the Pico's timekeeping would be properly accurate as long as it wasn't in Deep Sleep, and it might also mean I could do some calibration too.

  • A build with this in will be available here shortly.

    The timing is way better as would be expected, but I'm totally unconvinced about the timing that's being got from Deep Sleep.

  • I don't have your answer but this ST Application note is deeply linked to crystals on STM32 family and might help you.
    There is also a discussion on mbed which is argueing about a 10% accuracy.
    See the last post it seems to be written in the specifications. I did not found that particular spec on st.com :(
    This reference manual says 'around 32 kHz' which is not a good sign.
    However, the chapters about the RTC seems more optimistic.

    17.2 RTC main features
    The RTC unit main features are the following (see Figure 159: RTC block diagram):
    • Calendar with subseconds, seconds, minutes, hours (12 or 24 format), day (day of
    week), date (day of month), month, and year.
    • Daylight saving compensation programmable by software.
    • Two programmable alarms with interrupt function. The alarms can be triggered by any
    combination of the calendar fields.
    • Automatic wakeup unit generating a periodic flag that triggers an automatic wakeup
    interrupt.
    • Reference clock detection: a more precise second source clock (50 or 60 Hz) can be
    used to enhance the calendar precision.
    • Accurate synchronization with an external clock using the subsecond shift feature.
    • Maskable interrupts/events:
    – Alarm A
    – Alarm B
    – Wakeup interrupt
    – Timestamp
    – Tamper detection
    • Digital calibration circuit (periodic counter correction)
    – 5 ppm accuracy
    0.95 ppm accuracy, obtained in a calibration window of several seconds
    ...

    Frankly I totally lost just from this document.

  • Thanks - it's more a matter of looking at the external crystals themselves though (rather than the chip). I know only too well how rubbish the internal low-speed oscillator on the STM32F4 is :)

    Some chips allow you to calibrate the internal RC oscillators, but it seems the STM32 doesn't. The best I can do is to change the divisor (which is usually 32768), but even that seems hard to do on the fly. I do have a branch with some code in, but I can't get it working reliably.

    If 32kHz crystals aren't actually much more accurate than the 8Mhz ones, then it's not such a big deal switching over to use the 8Mhz crystal on the Pico.

  • They have an application note about calibrating the RTC from an external clock and, or do some smooth adjustments in orders to compensate for temperature changes, which could be used from time to time when the Pico or Standard boards are awaken and thus 'correct' the LSI clock.
    I have been aware of those problem by trying to log the internal temperature sensor on the sdcard during more than a few days.
    While in a box outside by temperatures under 0°C all night and days, I had a shift in the clock which was terribly higher than while the box was on my desk more ar less at 20°C.
    This alone made the data log time and date rather difficult to use in real conditions.

    I also actually missed the capability to create a directory on SDcard. That's mainly to avoid sd wear problem. I turned around this by creating the whole tree structure on a PC before starting the experiment.

  • Coarse calibration: The maximum calibration ranges from -63 ppm to 126 ppm.

    Sadly the RTC is around 100,000 ppm out - so can't be calibrated like that :(

    I guess I could save the prescaler alongside the saved code, and could then load it at boot-time. It wouldn't be dynamic, but I guess it would actually make a really big improvement as I think the drift isn't that high - it's the change in frequency between individual chips that really sucks.

    You could always solder a watch crystal on and it'll magically use that and make really good time :)

    Good point about creating directories. I'll file a bug for it.

  • I have a 1v4 Espruino board and a Kickstarter Pico. So I am not totally sure this would help with temperature. Now it seems that the HSI is more precise than that and could be used to calibrate the RTC or LSI...

  • Timing accuracy is one part of the problem. You shall consider power consumption too. I'm sure using the 32kHz oscillator will by much more efficient than using the 8MHz one in deep sleep mode.

  • Well, the build that'd linked above:

    • Uses the 8Mhz oscillator normally
    • In deep sleep, uses the 32kHz osc (it can't use anything else)

    So you get the best of both worlds. It means it'll be accurate normally, but if you use setDeepSleep it won't be as good. I think it's a reasonable compromise.

  • I dig a bit more and found some examples on github about using lsi to autocalibrate the rtc
    https://github.com/g4lvanix/STM32F4-workarea/tree/master/Project/STM32F4xx_StdPeriph_Examples/RTC/RTC_LSI

  • Is your Espruino 1v4 not keeping good time either? That should have a proper 32kHz crystal on it?

    Thanks! That's basically what I was doing in the branch I have that doesn't work very well, but there are some issues:

    • In his example it's only accurate to 1 part in 128, so he'll never be more accurate than 7800 ppm - it's better, but not great. Pretty sure that could be improved to 1 part in 16384 though.
    • LSI will still drift as the chip gets warm - if you auto-calibrate when the chip starts up it'll almost certainly drift off quickly if you're running full-tilt for any period of time.
    • Every time you set the prescaler, it seems to set the subsecond counter to 0 (as far as I could tell from the datasheet) - so you if you keep doing it all the time to keep track of drift you'll lose accuracy as well!
    • The code I use to maintain sub-32kHz accuracy via the RTC depends heavily on the subsecond counter - I've had trouble getting it working reliably right after the timer period changes.

    So I could actually expose that functionality as a function, E.calibrateRTC() - but I think realistically this is something users would have to call themselves. E.calibrateRTC() could save the new prescaler value into flash though - that could be a good compromise.

    ... or if I'm using the HSE for timekeeping, I could keep track what the LSI speed was all the time - and when I go into Deep Sleep I could adjust the amount of ticks I sleep for with that in mind... So not trying to 'fix' the LSI speed, but actually just being aware of it and working around it.

  • Yes, my Espruino 1v4 did not kept accurately time with interpreter 1v72 in spite of its external 32 khz...
    Now I need to look back at my sources to get it was drifting. Actually, i used egyptian fractions to correct the time.
    A user access to calibrate would be a good idea. Apparently, there is the same example for stm32l1 on another github repository.
    So far 7800 ppm is terribly better than 100 000 ppm, and it should ease a lot of log.
    As far as I understand there are some eeprom available to save calibration results.
    Also the smooth calibration is designed to handle temperature drift, which I guess should become usefull once we get down to autocalibration predicted results.
    The best of all would be to use the 1 hz pulse from a gps which is possible with almost all gps chips. The ublox one's are capable of doing it on their tx pin. However you have to disable all nmea sentences on rus1. At least there also a special pin, but it is not always outputed depending of your gps board manufacturer.

  • Frustrating about the 1v4 - I'll test it when I get back from holiday in a week. Not sure if there's much I can do if the crystal isn't the right frequency, but if it is stable then at least the calibration might work.

    So far 7800 ppm is terribly better than 100 000 ppm, and it should ease a lot of log.

    true :)

    Interesting idea exposing it in such a way that it can be calibrated by an external input. I'll have a think about that.

    As far as I understand there are some eeprom available to save calibration results.

    Sadly no (maybe on the L1?) - but it could go into flash along with the saved code.

  • I thought you said that there was a tiny amount of non-volatile memory outside the normal flash on the STM32 chips? But in different places on different boards?

  • Well, if it is not in some eeprom, maybe could it be just after the bootloader in flash page 0. After all, those calibration parameters are really not so often changed. If i remenber well, flash doesn't need to be erased if you just switch bits from 1 to 0 which allows to write once each byte valued $ff without erasing the whole relevant page. Padding the last bootloader page with $ff bytes could, somehow dangerously, allow to save hardware specific parameters in a safe place with respect to interpreter's versions...

  • I thought you said that there was a tiny amount of non-volatile memory outside the normal flash on the STM32 chips?

    Sadly it's only nonvolatile if there's a battery connected - there's 64-80 bytes that survive a reset, but when power is disconnected it's gone.

    maybe could it be just after the bootloader in flash page 0

    Yes, for writing once that's definitely possible. It then gets dangerous trying to change the value though.

    Nothing stops the value being written alongside the saved code though... I think that would probably still be fine? I could make sure reset() didn't clear the calibration data and then you'd be sorted.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Crystal Oscillator Accuracy

Posted by Avatar for Gordon @Gordon

Actions