An experiment in accurate timekeeping

In late 2022 ZeptoBars shared an approach in the Sensor Watch community to boost that watch's accuracy through fine calibration and dithered error correction in software. This triggered my curiosity: can I reduce the approach to the bare minimum and build an exceptionally accurate clock using only ordinary components? Here is the result: a clock implemented in 8KB of firmware on an ATmega88V with a 60-cent quartz crystal. The clock is ticking and the experiment is in progress! The CR2032 coin cell battery should power it long enough for us to see how many seconds the clock drifts in a year, with room to spare.

The full source code, schematic, PCB and laser cutter design files are available in the Github repository. Some WIP threads from Mastodon are here and here.

User interface

Just like any old quartz clock, RAQC's user interface consists of a simple LCD display and a few buttons. In its default mode, when it's showing the current time, it looks like this:


The clock has a set of screens that you can navigate with short and long presses of the MODE button. The settings screens use the UP and DOWN buttons to change values.

Fine-tuning and calibrating

What makes RAQC different from a conventional digital clock is that you can set the time with sub-second precision without the need for good reflexes. Every time you you calibrate this way, RAQC updates the calculated error of its quartz crystal and becomes more accurate.

Here's how to calibrate the clock:

Precisely adjusting seconds

To fine-tune the time on RAQC, you need an accurate reference clock that shows seconds updating in real time. The clock on your laptop or cell phone is not good for this purpose, and neither is the time displayed by most websites. All of these update their time regularly so they're never off by a lot, but they're unlikely to be very accurate at any one moment.

Reliable sources of time are specialized websites like time.is; devices that take their time from a GPS signal; or radio clocks that show the time from a long-wave signal like DCF77. The most straightforward of these is time.is.

The photo above shows RAQC's Adjust seconds screen. (The photo was taken at the prototype stage, but this works exactly the same in the final build.) "40" on the right is the current seconds value; it keeps ticking in real time. The value to the left of the dot, -4, is the current adjustment. In the background you can see a part of time.is in a browser window, showing the true seconds value of "39". RAQC's time is a bit ahead of the truth, so we want to turn it back a little.

The adjustment value, which you can change using UP and DOWN, is in multiples of 1/32 seconds (31.25 milliseconds). A value of -4 means we're turning back the clock by 125 milliseconds.

Don't worry about the specific numbers you see here. Just keep adjusting up and down until the seconds on your clock and the seconds from time.is are ticking in perfect synchrony. Then press MODE twice to go to the Delta error screen. There, store your adjustment by long-pressing DOWN (the first time you do this) or UP (for every subsequent calibration). When you long-press UP, the Delta error value gets added to the
Current error from the previous screen, making the clock more accurate.

Here's a video of the process:

Circuit design

The point of RAQC is to create a remarkably accurate clock from entirely unremarkable, cheap parts. These are the main building blocks:

Hardware

The clock's design emphasizes the raw electronics: it is a PCB enclosed in a transparent laser-cut case. This is what the PCB looks like on its own:

Interesting details:

Accurate timekeeping with error correction

Quartz clocks like RAQC measure time using a quartz crystal that oscillates at a frequency of 32,768 kHz. Due to small manufacturing differences the frequency of every particular crystal will be slightly off from the nominal value. These tiny differences are measured in ppm (parts per million), which is like a percentage, but in units of one-millionths instead of one-hundredths.

In addition to the static offset of individual crystals, their frequency also varies dynamically with temperature. Crystals are manufactured in a way that their frequency peaks at 25 °C and decreases at both higher and lower temperatures. The diagram below is from the datasheet of the crystal in RAQC:

On a hot summer day, with the temperature at 40 degrees, the crystal will be almost 10ppm slower, which would translate to the clock being over 5 minutes slow per year if not compensated for.

RAQC does two things to enhance accuracy:

  1. It calculates the crystal's static error through a series of fine time adjustments, and subsequently compensates for the known error;
  2. It measures temperature every 10 minutes and applies a correction to compensate for the dynamic error in each 10-minute period, based on the diagram from the crystal's datasheet.

Implementation in the ATmega

The code implementing this is not very complicated. It resides partly in corrector.cpp, and partly in the timer's interrupt service routine ISR(TIMER2_COMPA_vect) in main.cpp. The timer itself is set up in void setupTimer2() in main.cpp.

Low-power techniques

RAQC is special not only because of its accurate timekeeping but also because it does this in an ordinary ATmega at very low power. These are the techniques it uses:

Current draw measurements

The circuit's current draw is very uneven: it draws a steady low current when the ATmega is in power save mode, interspersed with brief bursts once per second when it wakes up. This is impossible to measure precisely with the multimeter that I have access to, so I created the following setup:

With this setup I measured an average current draw of 14.3uA, which includes the ATmega and the LCD display.

The measurement above did not include the time when the DS18B20 is active. Going by its nominal current draw of 1mA for 200msec once every 10 minutes, the DS18B20 adds the equivalent of 0.5uA, yielding a combined total of 14.8uA.

I assume, pessimistically, that a CR2032 coin cell battery has a capacity of 200mAh. At 15uA that yields 13,333 hours of operation, which is slightly more than 1.5 years.

Future experiments

Will RAQC achieve the remarkable level of accuracy it was created for? In this case, literally only time will tell. I'll report back every few months, and also when the first battery has been exhausted.

There are also a few additional enhancements/improvements that I'd like to explore.

Calibrate center temperature. The crystal's 25°C center temperature is unfortunately also just a nominal value, and the manufacturer allows a deviation of several degrees. It is possible to empirically determine the center temperature (and verify the overall temperature curve) through a series of experiments where we run the clock at a specific temperature for some amount of time and measure its error. Lacking an expensive temperature-controlled oven this is feasible only if the temperature-stabilized times are short -- so we can rely on the short-time-stable temperature differentials in a normal household. The tiny errors over a short period like 30 or 60 minutes might be reliably measured using the time signal from a GPS receiver. This would be a complicated but not unfeasible process that I'd like to undertake in a future iteration. Through the exposed pins it is possible to replace the timekeeping firmware with one used for determining the center temperature, and the same pins allow receiving the time signal from a GPS unit.

Crystal aging. The crystal's static error is expected to shift negative as the crystal ages. Most of the change happens in the first year, after which a lower, steady change is expected each year. This effect can also be measured, and compensated for in software, by recording each calibration. I plan to add this functionality in an updated firmware after enough time has passed.

More compact form. The current hardware, even on the PCB, retains aspects of a prototype. The main reason is my reluctance to solder small SMD parts. Should I overcome that barrier, an LCD driver and a next-generation microntroller like SAMD21 might allow a smaller form factor and an even smaller power envelope.