RTC to milliseconds

Hi CE makers & forum,

I’m trying to find a real time clock that is accurate to milliseconds. Are there any precision modules that could do this?

It’s for a film project which requires synchronisation to frames per second - typically 24 or 25. I would have to convert any milliseconds units to fit into this time format.

So I could get a frame accurate result to:
Hours, minutes, seconds, frames

I was looking at the piicodev module and also the adafruit precision rtc modules.

The accuracy is important but it wouldn’t have to be frame accurate for extended periods of time. These units are usually re-calibrated each day.

Do you think it can be done or am I seeking precision that is tough to obtain?




Hi Leo
Does the “Real Time” accuracy have to be milliseconds or are you referring to “Timing”. The two would be quite different.

These days it is not difficult to measure time duration down to microseconds but that is not “Real Time”

25 frames is easy as it is a direct division with a whole number result. 24 is a bit trickier. 24 was (is???) the rate for cinema but 25 (30 for USA) for TV. This has to do with power supply frequency the reasons I will not go into here. I think that for 35mm film scanned for TV at 25 FPS the difference was small enough to ignore. I am not absolutely certain but I think this was the case.

The TV time is referred to a Rubidium standard but I am not sure what resolution is available to the average user. The same with SatNav. The time is available in Hr, Min, Sec but I am not sure if a smaller resolution is provided.

Another quick question. If you want “Real Time” what are you going to set it against ???
Cheers Bob


Hi Bob,

Thanks for your reply.

To give some further context, I work in Visual effects in film, and this question about sub-second accuracy is for another project where I need to accurately synchronise captured data to what is being filmed.
On a film production, the timecode is set by the sound department, where they ‘jam’ the camera or other devices with the “real time” that their sound recording devices are set to. Synchronising the RTC to this presents another challenge, but the first challenge is if i can obtain the accuracy.

The idea of having the sync “to the frame” is to marry the sound and picture, however I want to try and use this (for another project) where I record the rotations and positions of the camera using sensors. However this pursuit is largely pointless if i can’t register / match the data I’m capturing to a relevant timecode. It would be near impossible to match the data afterwards.

This film timecode format is:


The last part FF being frames per second is a division that can alternate between 24, 25 and 30 FPS (frames per second) - as you mentioned. So depending on the project, this last parameter is set and becomes a division of 24, 35, or 30ths of a second.

What I am seeking to do really needs to be frame accurate. Slippage of a frame or so is correctable, but I am after that kind of accuracy.

I suppose I could try and divide up the milliseconds using math into 24/25/30 parts per second, but I was just wondering if any of the RTCs have accessible millisecond parameters.

Obscure enough? :slight_smile:




Hi Leo
I get most of it. You want “elapsed” time more so than the actual “time of day”

I have a couple of PC video editors that use the same format so understand where this is coming from.

During my teenage years I did a bit of projectionist work at a country cinema. If for some reason I got a film slippage or the film was incorrectly threaded between the gate and sound detection system an error of up to a bit over 1 frame could pass but anything over that got a bit embarrassing when lip synch got a bit out.

Doing it that way will finish up with fractions of a msec except for 25 which would be an error that could compound over time. I haven’t given this much thought but off the top of my head I can’t see any way out except maybe putting up with the small error and re-synchronising every second or even 5sec to remove the compounding of the error.

Sorry I can’t help here as I am not familiar with the inner workings of the RTCs around so can’t help you there.

Just had another thought. What if you got an accurate 1 second “tick” ( from RTC, GPS etc) then using a Phase Locked Loop (PLL) multiplied this by 24, 25, 30. That may give you a synchronising "tick) every frame which might just suit your purpose. This technique is used at higher frequencies using mostly a 1MHz reference for accurate local oscillator generation in radio receivers, I have not seen it at frequencies this low but the principles are there.

I am interested to see how you progress with this.
Cheers Bob


I started looking around at accurate and in stock TCXO oscillators (temperature compensated) and the best I could find at reasonable price was 0.28ppm. Still, that’s up to 0.000028% drift (0.1008 seconds per hour).

If that works for you, then perhaps first build a basic proof of concept using an Arduino and make use of the millis() function for timing. If happy with the proof of concept, use the Arduino application circuit and swap the oscillator.

Failing that, it seems that time sync is the way to go. I am curious what protocol the other gear uses, is it LTC or something else?


@Leo97682 Some of these codebases might be useful to you ( I haven’t looked into any of them though ).
I was involved with timecode as used in show control systems, specifically the Linear TimeCode (LTC) audio stuff, where we were generating and distributing LTC to various remote show control systems to solve some sync issues between audio/video playback and a motion base


Any current MCU module could be set up to be configurable as a RTC with a resolution of 24, 25 or 30 fps (or better) and accuracy within the current frame for the length of time of a typical movie. I don’t know how it would do for 24 hours, but it would be interesting to test.

So the question comes down to this ‘calibration’ process, as you mention. If that process can be done conveniently within the time required for the MCU to maintain the required accuracy then rolling your own RTC from a simple MCU such as an Arduino would be the way to go. That option has the benefit of allowing you to build whatever custom procedure is required to enable the clock device to be ‘jammed’ from the sound recording devices at the same time as the camera is - which would address the other issue that you mention.


Duh - brain fade - here is the link to the set of different timecode software ideas - was on the way out the door to another project meeting - just click on the "Build software … " and you will get to the list of topics


Happens to the best of us Murray :wink:

Thanks for those code snippets, they seem super helpful, and might just conquer half of this pursuit!

1 Like

Thanks Bob,

You’re exactly right with the film slippage you talk of. As my project is not to sync sound and visuals, some slippage is acceptable because I can adjust later, but if i can obtain accuracy it saves me the work.

Your idea about the sync ‘tick’ is a good one! But I do not understand what a Phase Lock Loop is.

Good ideas all round here, thanks all.


Hi Leo

A bit hard to explain quickly but…It is a system where you can produce a wanted frequency with the accuracy and stability of a reference signal.
The reference is commonly 1 MHz but it does not have to be.
This is input to a comparator which can be Phase, Frequency or both.
There would be a VCO (voltage controlled oscillator) which will provide the required output signal.
Say for instance an output signal of 100MHz is required.
The output signal (produced by the VCO) would be divided by 100 to compare with the reference 1MHz.
The comparator would generate an error voltage which is applied to the VCO in such a sense the output signal is pulled so as to provide a divided signal of 1MHz to match the reference. That is the required 100MHz.

That is as simple as I can explain the operation and if you draw yourself a little block diagram it might make more sense.

This technique is used in frequency synthesis for receiver local oscillators so if you see a radio receiver marketed as a “PLL” receiver this is what is implied.
This is used in the radio frequency area well up into the hundreds of MHz and I don’t know how one would implement it at the very low frequencies you need like 1Hz reference and 24, 25 and 30 Hz. There may be a way of doing something similar digitally but I have not given it much thought. Mainly because I have never had a use for such a system. I will think about it.
Cheers Bob

1 Like

Hi Leo,

Forgive my separation from the film industry, but from some quick reading, my understanding is that timecode is an audio-like signal that conveys the current time as a stream of binary decimal numbers.

My way of going about this would be to feed this data into your microcontroller (maybe some creative use of the UART peripheral?) and attach your sensor values when you’re data logging.

Ideally, you’d stick a timecode output into an oscilloscope, and work out what format/voltage it uses. Do you have access to one?

Do you have wireless timecode sync devices in your setup?

This is a really cool project!


Me being a C programmer - I think that this is one of the better libraries for generating / decoding Linear Time Code … GitHub - x42/libltc: Linear/Logitudinal Time Code (LTC) Library

If you are recording the timecode as an audio track (a common use) then the audio levels can be critical. Otherwise as long as the signal generated has a clean wave form, and any distribution amps dont overdrive or otherwise distort the signal, then you should be ok.

From a Timecode system I have used in a previous lifetime
input levels through a balanced 600 ohm transformer -absolute minimum input level with no noise :
120mV p-p, 60mV peak, 42mV RMS, -25dB

You should make sure that a SMPTE Longitudinal TimeCode stripe is recorded and played back at suitable levels. It is definitely not the case that higher levels are better. SMPTE timecode is a pulse or rectangular wave signal, where signal levels do matter. The most common error is recording at too high a level which causes waveform distortions leading to errors. Recording at too high a level will also exacerbate audio crosstalk, breakthrough of the sync tone onto audio signals. Recording at too low a level may make the stripe replay susceptible to crosstalk, leading to corruption of the signal seen by the timecode reader. Excessive volume in the stripe replay path may swamp the input circuits of a timecode reader, impairing its ability to interpret the sync signal.

A SMPTE Longitudinal TimeCode stripe is best recorded at just a few dB above the minimum level which allows correct reading. The best way to arrive at appropriate working level settings is usually trial-and-error. Most audio tracks work well with the stripe recorded as low as 10 dB below reference level. Audio tracks with noise reduction may work better with stripes recorded as high as just 3 dB below reference level.


I am having trouble visualising this problem. Duration is between two events. What are the events? I understand they are frames, but your average microprocessor doesn’t have an eye that looks at frames as they whizz by so I am assuming some sort of electrical pulse from somewhere? and the equipment needs to do pulse in->elapsed time out? how is the elapsed time out captured? I envisage a simple system that is reset, the first pulse it gets it sets its internal timer to zero and outputs (via a serial port at 9600 baud?) a time stamp at zero. At every subsequent pulse it outputs the duration since zero in a suitable format. Or is it the other way around? The device gets a reset then outputs pulses at precisely timed intervals (and the relevant code via the serial port?). And does this equipment need to be portable, or can it be set up where a GPS receiver acts as the time source?

I have been fiddling with GPS units and microprocessors for a while, I think I could create a device that would give the arrival time of pulses to within a few microseconds of the actual time. And not have any long term drift (the GPS gives accurate time). The time between pulses could be resolved to less than a microsecond. But because I don’t understand the problem in mechanistic terms, I may be on the wrong track.

1 Like

Typical timecode distribution / isolation amplifiers

1 Like

I still don’t see where this is going. As far as I can work out, there is no need for accurate timing. There is a sequence of video frames and they are numbered with nominal time. For instance the 100,000th frame would be labeled 0:33:20:00 if recorded at a nominal 50 frames a second; 1:06:40:00 if recorded at 25 frames a second; 1:09:26:15 if recorded at 24 frames a second. If there is other equipment running at the same time as the video, it would “time” stamp with the linear timecode as each frame is taken.

For some applications (e.g. television) it would be possible to ensure the frame rate is exact to the microsecond. This is desirable. But it seems to me that is not a necessary requirement. As long as the frame numbers are synchronized on the various bits of gear, they could all run 0.1% fast or 0.1% slow resulting in a run time that was a few seconds an hour out.

Please enlighten me. I am finding this quite interesting.

1 Like

In a past life, we needed to get a high accuracy repeating signal over an hour period. In our application, we needed to generate a pulse between a specified value of 90 to 130 Hz with high accuracy, which is in the same ballpark as what you are attempting.

We ended up using a microcontroller board with a TCXO 32.768kHz watch crystal, something like this one. It ended up being better than trying to use more expensive TCVCXO crystals. The reason was that the accuracy of the crystals at high precision is not only dependent on the voltage and temperature, but also dependent on the capacitance of the lines between the microcontroller and the crystal, which can vary with each microcontroller and the way it is soldered to the board.

Accuracy is also dependent on the supply voltage. We had the best success with 470 uF electrolytic capacitors on each VCC pin of the microcontroller to GND in parallel with a 4.7µF tantalum to smooth out the voltage spikes as much as possible.

Trying to get 100% repeatability with each board was an impossible nightmare as each crystal is slightly different. So we took the fully contructed microcontroller board and programmed it with a program to calibrate the crystal against an NTP time source on a PC. The calibration values were then stored on the microcontroller flash/eeprom (later and earlier storage mechanisms), along with the temperature profile for that crystal batch.

Even though these were temperature compensated devices, they were still not accurate enough for our application. These values were painstakingly derived from hours of work with an oven to develop a temperature compensation profile. Fortunately, it turned out the temperature profile was almost universally accurate for all of the individual crystals in a batch, so we didn’t need to do this with each board, but rather with a board from each batch of crystals we used. We did not stick to the ppm paradigm in the datasheets and our calibration values were calculated on the number of ticks (positive or negative) per 512 seconds exactly, the reason for which will become clear below.

The next headache was getting an exact frequency emitted. For our 32.768 kHz crystals, we ended up interrupting on each timer tick by making the clock pin act as an external interrupt pin as well as a 16-bit timer source pin. We were running the microcontroller at 8MHz, and it wasn’t doing anything else, so executing an ISR 32k per second wasn’t an issue as we had 244 CPU cycles per interrupt to play with and could do most of our processing in the main loop and not in the ISR itself anyway.

We set up a combined 24-bit register that incremented each tick and triggered adjustments to the timer counter register when those registers matched our calculated adjustments we needed to make. A full 24-bit count was exactly 512 seconds, which represented nearly 16.8 million ticks of the oscillator. Our RAM was constrained, so we ended up taking the most significant byte (MSB) of the 24-bit register and looking up a tick adjustment from a 256-byte signed character RAM array. The lookup was only triggered if the MSB value changed to avoid duplications. The timer counter was increased or decreased by the signed byte value in the array.

We only wanted a pulse output, so we set an ISR on timer match and set a pin high. The tick ISR set the pin low, so the pin stayed high for 30.5µs.

If we needed to add compensations into the array, we spread them over the full array to minimise big compensatory corrections. So, for a -4 tick adjustment, 1 was subtracted from the values in the array at locations 0, 64, 128 and 192. For a +6 tick adjustment, we added 1 into locations 0,42,85,128 and 170 and 213. We also checked that the timer counter would not go beyond its set top value or underflow due to an adjustment. If it would be problematic, the adjustment was saved and attempted again the next tick until it was successful.

An array lookup also triggered an ADC reading of the temperature too (every 2 seconds). If a temperature compensation was required, the old temperature profile was subtracted from the array and the new compensation was added into the array by spreading the adjustment(s) over the full array (as above).

I won’t bore you with the tortuous way we calculated compensation adjustments to the timer match values as you are in the fortunate situation of having pre-selected specific timings, something we did not. Here are the tables for the values you will need for 24, 25 and 30 fps:

cumulative ticks for 24fps mod timer match mod carry timer top
1365.333 1365.333 1365 0
2730.667 2730.667 2731 0
4096 4096 4096 0
5461.333 5461.333 5461 0
6826.667 6826.667 6827 0
8192 8192 8192 0
9557.333 9557.333 9557 0
10922.67 10922.67 10923 0
12288 12288 12288 0
13653.33 13653.33 13653 0
15018.67 15018.67 15019 0
16384 16384 16384 0
17749.33 17749.33 17749 0
19114.67 19114.67 19115 0
20480 20480 20480 0
21845.33 21845.33 21845 0
23210.67 23210.67 23211 0
24576 24576 24576 0
25941.33 25941.33 25941 0
27306.67 27306.67 27307 0
28672 28672 28672 0
30037.33 30037.33 30037 0
31402.67 31402.67 31403 0
32768 32768 32768 0
34133.33 34133.33 34133 0
35498.67 35498.67 35499 0
36864 36864 36864 0
38229.33 38229.33 38229 0
39594.67 39594.67 39595 0
40960 40960 40960 0
42325.33 42325.33 42325 0
43690.67 43690.67 43691 0
45056 45056 45056 0
46421.33 46421.33 46421 0
47786.67 47786.67 47787 0
49152 49152 49152 0
50517.33 50517.33 50517 0
51882.67 51882.67 51883 0
53248 53248 53248 0
54613.33 54613.33 54613 0
55978.67 55978.67 55979 0
57344 57344 57344 0
58709.33 58709.33 58709 0
60074.67 60074.67 60075 0
61440 61440 61440 0
62805.33 62805.33 62805 0
64170.67 64170.67 64171 0
65536 0 0 0
cumulative ticks for 25fps mod timer match mod carry timer top
1310.72 1310.72 1311 0
2676.053 2676.053 2676 0
4041.387 4041.387 4041 0
5406.72 5406.72 5407 0
6772.053 6772.053 6772 0
8137.387 8137.387 8137 0
9502.72 9502.72 9503 0
10868.05 10868.05 10868 0
12233.39 12233.39 12233 0
13598.72 13598.72 13599 0
14964.05 14964.05 14964 0
16329.39 16329.39 16329 0
17694.72 17694.72 17695 0
19060.05 19060.05 19060 0
20425.39 20425.39 20425 0
21790.72 21790.72 21791 0
23156.05 23156.05 23156 0
24521.39 24521.39 24521 0
25886.72 25886.72 25887 0
27252.05 27252.05 27252 0
28617.39 28617.39 28617 0
29982.72 29982.72 29983 0
31348.05 31348.05 31348 0
32713.39 32713.39 32713 0
34078.72 34078.72 34079 0
35444.05 35444.05 35444 0
36809.39 36809.39 36809 0
38174.72 38174.72 38175 0
39540.05 39540.05 39540 0
40905.39 40905.39 40905 0
42270.72 42270.72 42271 0
43636.05 43636.05 43636 0
45001.39 45001.39 45001 0
46366.72 46366.72 46367 0
47732.05 47732.05 47732 0
49097.39 49097.39 49097 0
50462.72 50462.72 50463 0
51828.05 51828.05 51828 0
53193.39 53193.39 53193 0
54558.72 54558.72 54559 0
55924.05 55924.05 55924 0
57289.39 57289.39 57289 0
58654.72 58654.72 58655 0
60020.05 60020.05 60020 0
61385.39 61385.39 61385 0
62750.72 62750.72 62751 0
64116.05 64116.05 64116 0
65481.39 65481.39 65481 0 65481
66846.72 1311.107 1311 0.386667
68212.05 2676.44 2676 0.386667
69577.39 4041.773 4042 0.386667
70942.72 5407.107 5407 0.386667
72308.05 6772.44 6772 0.386667
73673.39 8137.773 8138 0.386667
75038.72 9503.107 9503 0.386667
76404.05 10868.44 10868 0.386667
77769.39 12233.77 12234 0.386667
79134.72 13599.11 13599 0.386667
80500.05 14964.44 14964 0.386667
81865.39 16329.77 16330 0.386667
83230.72 17695.11 17695 0.386667
84596.05 19060.44 19060 0.386667
85961.39 20425.77 20426 0.386667
87326.72 21791.11 21791 0.386667
88692.05 23156.44 23156 0.386667
90057.39 24521.77 24522 0.386667
91422.72 25887.11 25887 0.386667
92788.05 27252.44 27252 0.386667
94153.39 28617.77 28618 0.386667
95518.72 29983.11 29983 0.386667
96884.05 31348.44 31348 0.386667
98249.39 32713.77 32714 0.386667
99614.72 34079.11 34079 0.386667
100980.1 35444.44 35444 0.386667
102345.4 36809.77 36810 0.386667
103710.7 38175.11 38175 0.386667
105076.1 39540.44 39540 0.386667
106441.4 40905.77 40906 0.386667
107806.7 42271.11 42271 0.386667
109172.1 43636.44 43636 0.386667
110537.4 45001.77 45002 0.386667
111902.7 46367.11 46367 0.386667
113268.1 47732.44 47732 0.386667
114633.4 49097.77 49098 0.386667
115998.7 50463.11 50463 0.386667
117364.1 51828.44 51828 0.386667
118729.4 53193.77 53194 0.386667
120094.7 54559.11 54559 0.386667
121460.1 55924.44 55924 0.386667
122825.4 57289.77 57290 0.386667
124190.7 58655.11 58655 0.386667
125556.1 60020.44 60020 0.386667
126921.4 61385.77 61386 0.386667
128286.7 62751.11 62751 0.386667
129652.1 64116.44 64116 0.386667
131017.4 65481.77 65482 0.386667 65482
cumulative ticks for 30fps mod timer match mod carry timer top
1092.267 1092.267 1092 0
2457.6 2457.6 2458 0
3822.933 3822.933 3823 0
5188.267 5188.267 5188 0
6553.6 6553.6 6554 0
7918.933 7918.933 7919 0
9284.267 9284.267 9284 0
10649.6 10649.6 10650 0
12014.93 12014.93 12015 0
13380.27 13380.27 13380 0
14745.6 14745.6 14746 0
16110.93 16110.93 16111 0
17476.27 17476.27 17476 0
18841.6 18841.6 18842 0
20206.93 20206.93 20207 0
21572.27 21572.27 21572 0
22937.6 22937.6 22938 0
24302.93 24302.93 24303 0
25668.27 25668.27 25668 0
27033.6 27033.6 27034 0
28398.93 28398.93 28399 0
29764.27 29764.27 29764 0
31129.6 31129.6 31130 0
32494.93 32494.93 32495 0
33860.27 33860.27 33860 0
35225.6 35225.6 35226 0
36590.93 36590.93 36591 0
37956.27 37956.27 37956 0
39321.6 39321.6 39322 0
40686.93 40686.93 40687 0
42052.27 42052.27 42052 0
43417.6 43417.6 43418 0
44782.93 44782.93 44783 0
46148.27 46148.27 46148 0
47513.6 47513.6 47514 0
48878.93 48878.93 48879 0
50244.27 50244.27 50244 0
51609.6 51609.6 51610 0
52974.93 52974.93 52975 0
54340.27 54340.27 54340 0
55705.6 55705.6 55706 0
57070.93 57070.93 57071 0
58436.27 58436.27 58436 0
59801.6 59801.6 59802 0
61166.93 61166.93 61167 0
62532.27 62532.27 62532 0
63897.6 63897.6 63898 0
65262.93 65262.93 65263 0 65263

Then we need to add in an adjustment for rounding errors. 32768 divides by 24 exactly, so that’s not a problem. For 25 and 30, there will be 0.04033 missing and 0.03347 ticks excess per second, respectively. To compensate for this, we need to spread 20 ticks and -17 ticks per 512 seconds into the tick adjustment array. So for 25 fps, we add 1 to each value at indexes: 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240. For the 30 fps, we subtract 1 from each value at indexes: 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255. This will leave 0.497 and -0.138 ticks unadjusted per each 512 seconds.

In theory, this gives an error rate of +0.002 and -0.00089 frames per hour, respectively. These are ideal results and, depending on your device, your mileage may vary! We ultimately achieved results between 30 and 150 RTC ticks between each of our devices for the frequency we were aiming to achieve over an hour window, so it wasn’t as good as ideal, but it was sufficiently close to get away with.

Unfortunately, I don’t have the actual code we used and I’ve recreated the algorithm from memory. Good luck!


You may get some more suggestions here: RTC with milliseconds - Page 1

1 Like

Getting high accuracy in standalone is difficult, which is why I like GPS disciplined oscillators. I have built some with a basic deviation from correct frequency of ±2 or 3 parts per billion and if used as a timer less than a microsecond for as long as you like (because the oscillator is locked long term to the GPS, which is locked to NIST, which is about as accurate as it gets).

Your method seems very indirect. I would start with binary 32,768 in 2 bytes followed by 4 zero bytes.
Each time the ADC is read, add or subtract a temperature compensation to that. Then divide the desired frequency into the 6 byte number, the top two bytes say how many 32768 whole interrupts are required, the remaining 4 bytes are a residual.

In the oscillator IRC, subtract 1 from a copy of the whole interrupt count until it hits zero. At that point, load a timer to initiate the output pulse, add the residual to a 4 byte accumulator, when the accumulator has a carry out then add 1 to the whole interrupt count to make the copy for the next count down. There is a conversion required to convert residual to a timer value that equates to the clock frequency of the processor. This is done each output pulse so a maximum of 130 times a second, plenty of spare cycles to do it.

I don’t know what processor you used, it may have a convenient feature like the PIC16F628A where Timer 1 can trigger an output pulse without software intervention. This ensures a pulse jitter less than a microsecond.

Using a 32 bit residual will give far more accuracy than needed, the limitation will be the 32768Hz oscillator.

1 Like

I couldn’t agree more about using GPS as an exact timing source and I have done so in other projects. However, for applications buried, for example, in the bowels of a machine bay, engine room or sound booth there aren’t any realistic options for getting a GPS signal.

We could have used an ethernet-based device to get an NTP system running, but that wasn’t really necessary or practical in our application as to run any cables would have required extra work, site permissions, as well as qualified cable-laying technicians.

Our system was diagnostic and ran for only up to 1 hour. It was better to sync the devices at the start using a common triggering pulse and then move them under their independent battery power into various positions on the gear for the testing. We did the most sensitive tests first, such as calculating phase angles and zero crossing detections and then moved onto tripping timing, etc.

The “very indirect” method we used was primarily to avoid making adjustments in a cluster as this would negatively impact on our results. Making sparing changes over a wide range worked out the best. If clustering of compensation adjustments isn’t an issue, your approach would be simpler, I agree.

Agreed, most microcontrollers can trigger an output pin when a timer match or top event occurs. However, in our case, the ATMEGA16L microcontroller we used had a 16-bit timer and we were using its output compare match pins to drive an LED display. That is why we manually triggered an alternate pin using the ISR. In any case, one tick of a 32,768kHz clock gives 244 CPU clock cycles at 8MHz, so it would be triggered repeatably (on all boards) within 10 CPU cycles (~1µs) of the timer event, which is a much smaller time-frame than the drift error of even 1 RTC clock, which would occur within a few minutes of running our setup anyway. Our 1s pulse was also often used after the more time-critical tests had already been conducted by secondary systems that counted and operated spring-contacts or drove a solenoid at a specified time, so those events were a lot slower and somewhat less time-critical anyway.