GPS Diciplined Oscillator on the cheap


When using RF test equipment, narrowband radios or other frequency sensitive equipment a reference frequency signal is often used to make all involved systems agree frequency wise. Equipment will typically have a  10MHz reference frequency input that all internal frequencies are synchronized to.

In the recent past it was popular to use cheap surplus Rubidium frequency standards but lately the source of these has more or less dried up. To make a more sustainable way of generating a standard frequency people started using the One Pulse Per Second (1PPS ) output from GPS receivers to synchronize a local oscillator. Many of the designs floating around the internet is striving to achieve the perfect lock using ever more elaborate filters, temperature control and expensive oscillators.

I just wanted something that was one or two orders of magnitude better than a free running crystal oscillator that was simple and cheap.

Less is more

I came up with the following circuit:

The circuit is in part inspired by Lars GPSDO originally presented on EEVblog

I decided to completely get rid of the expensive VCXO used in most designs by using the built in oscillator in a small microcontroller. By varying the capacitance applied to the crystal the frequency can be pulled a tiny amount. To control this capacitance I used a simple 1N4007 rectifier diode as it exhibits a suitable variable capacitance (15-30pF) at the voltage range between 0 and 5V. This variation results in a frequency deviation of around +- 200Hz  of the 20MHz signal or +-10 ppm. A variable capacitor (C7) is used to put the frequency right at 20MHz when the voltage is at half the supply voltage (2.5V). This ensures that the circuit can speed up- and slow down the oscillator an equal amount if needed. C7 is also used to adapt to different models of crystals.

(Note: I did experiment with letting the firmware aid in the adjustment of this capacitor. Using the 1pps signal the firmware can evaluate if the capacitor is tuned right.)

The particular microcontroller I used (ATTINY84) can have its internal clock routed to a physical pin (by fuses set while programming). This serves as the main 10MHz reference output from the system. I used a 20MHz crystal  since the internal clock can be the crystal frequency divided by 2. This has the effect of lowering the frequency sensitivity of the crystal and insuring a proper 50% duty cycle of the output.

To control the voltage over the diode I used a internal PWM generator followed by two low pass filters as a pseudo D/A converter. The PWM signal is generated by a 16 bit timer running at the 10MHz clock frequency giving a PWM frequency of around 152Hz but with a resolution of 16 bit. Since the diode voltage need to change really slowly, in the order of tens of minutes, this 152Hz frequency can be almost completely removed by a slow filter (R14,C11,R13,C8).

Another timer inside the microcontroller is used to generate a 1MHz signal.  The rising edge of the 1PPS signal from the GPS is compared to to the rising edge of one of the 1MHz oscillations by a 4046 phase comparator IC. This generates a pulse between 0 and 1µS that is effectively a measure for the  phase and thereby frequency difference of the 1Hz GPS signal and the 10MHz reference output. The aim of the circuit it to keep the length of this pulse at exactly 0.5µs by slowly varying the voltage across the 1N4007 diode.

The length of the pulse is measured by the microcontroller by passing it through a circuit (R5,D4,C6,R15) that converts the 0-1µS pulse to a 0-1V voltage that can be red by the microcontrollers A/D converter.

The firmware inside the microcontroller starts by reading exactly how many counts of the 10MHz signal is elapsed between two consecutive GPS pulses. this gives a ballpark estimate of how well the oscillator tracks the incoming pulses. A algorithm uses successive approximation to  vary the diode voltage such that 10000000 counts per second is consistently counted:

This graph shows the “DAC” value on the Y axis during successive attempts to count to exactly 10 million per second. With C7 optimally adjusted the DAC value should be around 32000.

This insures that the pulses generated by the 4046 chip is almost at 0.5 µs and the signal edges compared is not some amount of counts off (false lock). By this time the frequency of the output will already be within a fraction of a ppm from the correct 10MHz.

To insure continuous lock and to compensate for the natural tiny jitter of the 1pps signal the firmware continues to compare the phase information from the A/D converter and applies tiny changes to the 152Hz PWM output to keep everything locked.

On Y-axis: 0 represent -900 deg. phase error and 1023 represent +900 deg. Phase noise about 18deg..

A couple of LEDs is signaling the status of the system. By the time frequency is established by simple counting the first LED is lit. Whenever the phase error over time has fallen under a certain range over time the second LED turns on.


The firmware (provided here for completeness) does have a few more things going on in terms of housekeeping and monitoring but the overall function is as described. The code is developed in Atmel Studio but could be converted to Arduino. I used Atmel studio so I had easy access to the programming fuses needed to route the clock signal a external pin.

In the code a state machine handles different stages of signal lock and filtering of the error signals. Lock is maintained with a PID loop driven by the phase error and outputting to a PWM signal that in turn drives the oscillator frequency.


I started out prototyping some of the functionality using a regular Arduino UNO, which have almost the same internal peripherals, then moved on to ATTINY84 for a more compact design:

The Arduino UNO based prototype used an external VCXO. Later I moved to the internal oscillator  of a ATTINY84. Otherwise the circuit is pretty much the same.

Once everything seemed to work I made a CNC routed circuit board. The circuit is so simple that I could keep all the signal traces on one layer and have one full copper layer for grounding. The oscillator is sensible to outside influence so this ground layer helps keep everything more stable. It is possible to solder the crystal housing to the ground layer for even better stability:

The GPS receiver is mounted outside to provide optimal coverage. The more satellites that are in view the less jitter on the 1pps reference signal:


I do have several Rubidium frequency standards. These have an initial frequency accuracy of around 1/10e11 which I in the context of this design just assume to be absolutely correct. I used one of these standards to test how well the circuit was performing.

I plugged the 10MHz output from the Rubidium standard into one channel of an oscilloscope and the output from the circuit into another channel.

By looking at how the two waveforms shifted in time with respect to each other you could visually evaluate the phase of the two oscillators. The program in the microcontroller initially made sure that the frequency of it’s oscillator was within one Hz which is one wave of the 10MHz signal. Thus If the two signals on the oscilloscope stayed within one wave of each other the accuracy would at least be 0.1 ppm. This is already much more accurate than you are able to achieve with even a good crystal oscillator.

A few minutes after the circuit was turned on and it had done the initial search described above, the two waveforms on the oscilloscope seemed to stay within a few waveforms of each other. After another couple of minutes this gradually decreased to fractions of a waveform indicating that a significantly better accuracy than the 0.1ppm was achieved.


I did not aim for perfection with this circuit. Just being able to tune a radio or set a spectrum analyzer within a few tenths of a Hertz was fine for me.  Seeing that you can achieve quite a bit better performance with this simple and very inexpensive circuit is quite surprising.

I personally think having a lightweight fast locking frequency standard is quite nice. I’m not looking to achieve record accuracy I’m fine with a couple of orders of magnitude better than your standard un-locked crystal oscillator.

Leave a Reply