Since I have all the components—a GPS timesource, a voltage controlled OCXO, and a microcontroller with some DACs—I thought I'd try to make a simple GPS Disiplined Oscillator.

By measurement, I found that my particular OCXO's voltage compensation input sits at 2.5V when not driven, has a 30kOhm input impedance, and that hand tuning it with a single-turn pot gave a pretty good 10MHz+-.1Hz at 2.42V.

The Metro M4 Express is based around the SAMD51 family microcontroller and includes two 12-bit voltage-mode DAC outputs on A0 and A1. To expand the precision by around 3 bits, I selected some junk drawer resistors and connected the two DACs as shown. The concept is that during manual setup, the human sets the FINE DAC to half scale and then finds a COARSE DAC setting that gives 10MHz. Then, an algorithm turns the FINE knob continuously to align the OCXO with GPS time.

While serious concerns can be raised about how connecting two DACs like this is unlikely to give good linearity and the like, we really aren't concerned with specific voltages, since the voltage adjust input is going to have significant nonlinearities too.

Next, the algorithm. In a previous entry, I wrote some code to use the built-in frequency counting feature of my ublox GPS receiver. I have tried two main variants: First, to steer the FINE DAC up or down by 1 count every second according to whether the estimated frequency is above or below 10MHz; second, to accumulate the frequency estimate over multiple seconds until the error bars totally excluded 10MHz, and then adjust one step up or down. As a sub-variant, I tried .5x, 1x, and 1.5x of the GPS-estimated error.

In each case I assessed the effect by letting it run for a few hours and using my oscilloscope to check in and see how my two 10MHz signals are running compared to each other. And in each case, I found the result unsatisfactory.

With the method that used 1.5x of the GPS-estimated error, the direction of adjustment was consistent with the error I saw on the scope, but it was simply not able to catch up (e.g., doing adjustments every 30-120s) with the OCXO's inherent drift. With the other methods, the estimates were too noisy to make the supposed "steering" into anything but a random walk when the sign of the error should have been consistent and clear.

One possibility is that the poor performance is actually due to poor reception by this GPS receiver; its antenna is much shorter and possibly lower-quality, so I can't place it with a good view of the sky. As the connector is a tiny laptops-style (U.FL, I think) I can't just swap it for one of my SMA-connector antennas. I should assess this more directly by scoping its frequency output instead of the OCXO's. If that seems to be the problem, I could pick up a U.FL-SMA pigtail and a better antenna.

Another possibility is that there is a bug in my code which calculates frequency from the TIM-TM2 messages. Except for restoring the high bits of the clock counts, there doesn't seem to be anything too subtle there, and I am not seeing frequency estimates so bad they would indicate errors of 65,536 counts per second which would be the result of the most likely bug manifestation.

I might be reading too much into the short term performance of the OCXO compared to the GPS-synthesized 10MHz signal I'm using as a reference.

I might be getting deliberately bad performance from the ublox module since it is not a "6T" (timing variant).

In all, there seem to be a lot of uncertainties and it's not clear from what direction I should attack the problem.