GPSDO YT, Disciplined Oscillator 10Mhz Reference Frequency. Low Cost. Accurate.





Introduction: GPSDO YT, Disciplined Oscillator 10Mhz Reference Frequency. Low Cost. Accurate.


Instead check the new 2x16 lcd display version available here:

I left the old version here for documentation.


Hi guys,

What is a GPSDO ? GPSDO means: GPS disciplined oscillator. GPS for global positioning system. All GPS satellites are equipped with synchronized atomic clock. GPS module receives these signals from several satellites. And by triangulation, he knows his location. But here, what interests us is the pulse per second that is found on the module. With this precise pulse (from atomic clock), we can do a very very accurate oscillator. What for ? For reference, for calibration of frequency counter or just for fun to have one in his lab.

They are many schematic on the internet. I have tried some. Some are good, one with a tiny2313 was 5 hertz too slow. But mine is the most simple, useful and convenient. And i'm giving you the .hex code. They are no VCO and no divider. Circuit with VCO are doing well. But, it must have a pulse signal of 10khz or more continuously. If antenna goes too weak, missing pulse or no pulse at all, the Oscillator (ocxo) is running by itself and the VFC (Voltage Frequency Control) isn't accurate anymore. The VCO feedback needs reference frequency to stick on. If not, It varies from a 1 to 2 Hertz! Also, the cheaper gps module doesn't work in this configuration. We must have at least 10khz to make a VCO. I tried with 1000 hertz. The gap was too large.The frequency varied. So with a ublox neo-6m you can't do a great vco gpsdo because maximum output frequency is 1000Hz. You must buy a neo-7m or upper.

This is how my GPSDO YT works. The controller found the good adjustment for any OCXO with vfc 0 to 5v. If we loose GPs signal, the frequency doesn't move at all. When the signal reappears, the controller takes his last known good value and continue as before. On scope, with a reference oscillator. We can't tell when the signal is lost or when it came back. The signal is the same.

After calibration, you can use the gpsdo without antenna if you want. A few mounts later you will have a very little drift. But.... how much larger ? It's time for some explanation.

Here is some Math... Easy math, follow me with this it's easy. So far the algorithm has 6 phases. Each phase takes a sample of 1 to 1000 seconds, found the good pwm adjustment and go to most longer samples for more accuracy.

Accuracy = (((Number of second x 10E6) + 1)/number of second) - 10E6

Phase 1, 1 second sample for 10,000,000 counts for +- 1 Hz accuracy

phase 2, 10 seconds sample for 100,000,000 counts for +-0.1Hz accuracy

Phase 3, 60 seconds sample for 600,000,000 counts for +-0.01666 Hz accuracy

Phase 4, 200 seconds Sample for 2,000,000,000 counts for +-0.005 Hz accuracy

Phase 5, 900 seconds sample for 9,000,000,000 counts for +-0.001111 Hz accuracy

Phase 6, 1000 seconds sample for 10 billions counts for +-0.001 Hz accuracy

Worst case . When we get phase 6. This number can change a bit each 1000 seconds or not. some time it will be 10,000,000,001 or 9,999,999,999 So, +or - 0,000,000.001 variation for 1000s. Now we must know the value for 1 second.

10Mhz = 1 second

For 1 second = 10,000,000,001 count/1000s = 10,000,000.001 Hz (worst case for 1 second)

10,000,000.001 - 10,000,000 = 0.001 Hz/s faster or slower

0.001Hz X 60 X 60 X24 X365 = 31536 Hz/years

So remember, 10Mhz is 1 second, 31536Hz X 1 / 10E6 = 0,0031536 second/ year

Another faster method for calculation. one miss fo 10E9Mhz is 1/10E9= 1E-10

1E-10 x 60x60x24x365 = 0,0031536 second/year.

Is that accurate enough for you?

however, you must have a good OXCO. I prefer Double Oven 12v Sinus output. More stable, quiet and accurate. But i have same result with simple 5V. For exemple, a stp 2187 have a stability short time (allan deviation) of 2x10-12 = 0.000,000,000,02 Hz of stability. In the same time, when gps pulse is available, Avr will always correct pwm (frequency). The uC is always counting... always. This mean that on display you will not see date and time. When uC is sampling 900s, this one is busy for 900 seconds. It must count all clock. Problem is uC is running at 10Mhz. Each clock must be count. It is counting itself. If only one clock is missing the sample will not be good and pwm adjustement will not be right. I can't refresh display each second.

When the sampling is started. Uc start to count timer0. Each 256 clock generates an interruption. X register is incremented. when it's full Y register is incremented and X reseted to 0 and so on. At the end, at he last one gps pulse, the count is stopped. And now and only now i can update display and do some math for pwm calculation.

knowing that, i have only 25,6 us (256 clock before interrupt) to read and display time or other. It's impossible. One interrution can be buffed, not 2. I could refresh the time after 1000s... but it will be not pratical to see time with 15, 16 minutes interval. I have a watch, a clock, a cell phone to know time :) I'm doing a 10Mhz reference. Not a clock.

Another problem i had, some avr instruction have 2 cycles. Including the rjmp instruction. This means if the first or last gps pulse came up at the same time of a 2 cycles instruction, the uC will miss a clock. Because uC will finish the instruction before begin the interrupt. So the counter will start or stop one cycle later. So i can't do a time wait loop... But in fact, i have no other choice. I needed to loop somewhere!! I So i'm using rjmp and nop (this do nothing) instruction. Nop is an one cycle instruction. I have put 400 nop instruction for one rjmp on atmega48. 2000 on atmega88 and atmega328p version. So the chances are less to first or last pulse come at rjmp instruction. But yes it's possible and if this happen, this error will be corrected at the next sampling.

The display is optional. You can do circuit with, uC, OCXO and low-pass filter (resistor capacitor) only, turn on and wait. After 1 hour you will have an acceptable frequency. But to reach phase 6. It takes a couple of hours.

Pwm is 16 bits. 65535 step. 5v/65535 = 76,295 uV

OCXO variation is 2Hz by 1V. 1v/76,295uV = 13107 step for 2 hz. 2/13107 = 152.59uHz by step of pwm

The phase 5, is changing pwm by 3, phase 6 is 2. step... Why 3 ? because 3 is changing frequency by 0.000,000,000,4 at 15 minutes scale. and 4 is my magic number in my algorithm. For exemple, if in phase one, first frequency found is 10.000,003Mhz. I lower down by 0,000,000.4 step.

Too large step can pass from 10.000003 to 10.000001 and after 9,999998Hz. I'm missing the target.

With 0,0000004. It's quicker than 0,1 and i'm more sure of not bypass a number. And so on. I'm doing the same with 10 seconds, 60 seconds and 200s phase and 900s. 1000s is running mode and use a pwm step of 2

Please note that phase 5 is more longer to achieve. The gap between 4 and 5 is larger. But it help to pass from 5 to 6 quicker.

When phase 6 has counted exactly 10 billions, the pwm values is saved in eeprom. Now, it's time for the running mode. This one count 1000 seconds sample but with 2 step pwm only. At running mode, the real frequency is displayed and updated at 1000 seconds interval. If signal is lost in running mode it pass in self running. No change of pwm in this mode. When signal come back, it return to phase 5 to resynchronization.

If circuit is unplug after eeprom is saved. This one will begin at phase 5 at power on with eeprom pwm value.

For erasing eeprom value, just press the button at at start-up. Pwm 50% will be load and calibration will start from phase 1.

I pass many hours to try different thing, configuration of the circuit. I did many tests, with OP amp, buffer and other chip. And at the end... the best result i got doesn't need it. Just a good stable power supply and some filtering capacitor. So I keep this simple.

Step 1: Buy Parts

The first thing to do is buy the parts. Because often shipping is very very long.

Gps module: I'm using a ublox neo-6m. I bought this one on ebay. Do a search, it's cost about 7 to 10 us dollars.

By default, this receiver have the 1 pulse by second enabled. We don't need to do anything.

You can use any gps module with a 1 Hertz pulse output. You have one. Use that!

OCXO: I tried 2 oscillators. A double oven stp2187 12v sine wave output. And a ISOTEMP 131-100 5V, square wave output. Both come from radioparts16 on ebay. I had a very good service from them and the price was cheaper.

AVR: Code fit on a little atmega48. But i suggest to buy an atmega88 or atmega328p. It's almost the same price. Buy this on digikey or ebay. I'm using the dip version. You can buy surface mount version, but pay attention, pins aren't the same to the schematic.

Lcd display: Any 4x20 HD44780 compatible display will work. Guess where i bought mine :) Yes on ebay a couple years ago. Now it's more expensive than before. But available under $20 US.

Maybe in the near future, i'll do a code for a 2x16 display. Those displays are only 4$. And between you and me, a 2 lines display would be sufficient.

You must have an AVR ISP Programmer. Programming an AVR isn't like an Arduino. Arduino has already be programmed to communicate on serial port. A brand new avr must be programmed with ISP or Parallel High Voltage Programmer. We are using isp here.

A 74hc04 or 74ac0, volt regulator 7812 and 7805, resistors, capacitor.... digikey, ebay

Step 2: Here Is Schematic and Gpsdo_YT_v1_0.hex

I think that the schematic is all you need to realise this project. You can use a copper clad board with etching method or just perforated board if you like.

You can use any box you want, but i suggest a metal box. Or just on a breadboard for fun like mine :)

I'm waiting for antenna extension and bnc connector to put my project in a box.

You must choose the right fuse bit. Be sure that external oscillator is selected. If you have trouble with External Oscillator, try External Crystal. And the low.ckdiv8 clock is unchecked. See picture. Pay attention, when the external clock fuses bit, you must provide an external clock to program or run the code. In other words, connect the Oscillator in xtal1 pin.

By the way... you can use the same code to do a frequency counter with 1 second gate. Just enter clock to be measured in xtal1 pin and you will have a +-1 Hz frequency counter.

I will be updating the project as soon as i have new stuff.

In the meantime, if the project interests you, you have enough material to start and even finish it before me

I uploaded 2 videos, you can see phase one and the last one.

I'm available for any questions or comments. Thank you.

February 26 2017.... Version 1.1 available.

-atmega48 isn't supported anymore. Not enough space.

-Added number of satellite locked.

-Support 2x16 lcd. If you have a 4x20, will be working too. But 2 last line will display nothing.

Step 3: Logs in Eeprom

Here is the dump of eeprom after a couple hours uf running time. I'll explain how to read this. Again, it's easy :)

At address 00,01 is stored pwm value. As soon phase 5 count 9 billion, pwm value is updated every time the counter reaches exactly 10 billion.

As soon we are at phase 5. All counts are stored in eeprom after pwm value. Start at address 02, after 03 and so on.

This exemple came from my 5 volts ocxo. We can read pwm value of 0x9A73 = 39539 decimal on 65536. = 60,33% or 3.0165 Volt.

So address 00:01 is 0x9A73

Next, you can read 03. For 9,000,000,003 Pwm is lowered by 3 because we are yet in phase 5

00 for 10,000,000.000 pwm stay is untouch and we pass to running mode (phase 6)

02 for 10,000,000.002 In that case, pwm value is lowered from 2

01 for 10,000,000.001 pwm value is lowered from 2

01 for 10,000,000.001 pwm value is lowered from 2 again

00 for 10,000,000.000 pwm stay is untouch

00 for 10,000,000.000 pwm stay is untouch

00 for 10,000,000.000 pwm stay is untouch

Now you know how to read the eeprom. Each 1000 seconds new value is written in eeprom. When eeprom is full, it restarts from address 2.

FF value mean 9,999,999.999

You can with this dump track the accuracy, without any LCD display.

You can dump the eeprom file with an isp programmer.

I hope that i gave you enough information. If not, let me know. Advice, error, anything.


5 People Made This Project!


  • Epilog Challenge 9

    Epilog Challenge 9
  • First Time Author Contest 2018

    First Time Author Contest 2018
  • Paper Contest 2018

    Paper Contest 2018

We have a be nice policy.
Please be positive and constructive.




Hello Yannik,

I have problem. After starting, GPSDO enters first phase for a sec and shows on display 'no signal detected'. I've checked with oscilloscope that IC's gets PPS signal. What can be problem?

Best regards Patrick

Very strange problem, this message appears when the watchdog timeout. The pps pulse reset the watchdog. which version of are you using ? Have you tried the 1.4 (atmega328 only) ? See my other gpsdo.

Also, is your fuse bits are set correctly ? Be sure to uncheck CKDIV8. If not you will run 8 times slower and the watchdog will probably timeout.

Thank you very much for respond.

I'm using version 1.0 with ATmega328. I'm pretty sure that I've unchecked CKDIV8 but I'll try to reprogram it again.

Hi Yannik,

Where can I download the squematics with a better resolution?

Kind regards

Here on instructable, just click 2 or 3 times on the schematic. You will able to download the (1657x1282) 26 KB size. Let me know if you have any problem. By the way, this one is obsolete. You can use my other instructable here

Hi, Yannick, would it be possible for you to release the code for the program? I'd like to alter it to work on a 2x16 LCD Display.

Done and tested... Hex is now available. Try it and please, tell me what you think :)

I almost finish. I did it. And i added number of locked satellite. Just add a wire between Tx from gps reciever and RX pin2 of atmega. .Hex soon

Hi Cuita, instead i'll do that for you. In a meantime i'll maybe add number of locked satellites. It's working with neo 6m but not with neo 8m... i must found why!! Probably 2x16 and 2x20 will be compatible. But code for 4x20 isn't the same memory adresses.

After you could try the code and tell me what you thing about that. Change to make etc..,