Design & Build a GPS locked Frequency Standard – Part 4

In this 4th part of this project we upgrade the software to give satellite data and frequency lock display. Plus the current frequency on the display is improved to give reading in MHz, KHz or Hz.

The new software version can be downloaded from the link below:
Below is a link to download a user guide on this project which includes circuit detail, PCB detailed layouts, schematics and software details. The file is a zip file which contains a PDF document:

Reading the GPS module data to extract the number of Satellites detected

When the GPS module starts receiving satellite data it provides a constant stream of data sentences which are know as NMEA sentences. Within this data stream the most important NMEA sentences include the GGA which provides the current Fix data, the RMC which provides the minimum GPS sentences information, and the GSA which provides the Satellite status data. In our project we will use the GGA data stream to extract the number of satellites detected and locked on to.

Below is an example of a typical GGA data sentence:



  • GGA                      Global Positioning System Fix Data
  • 123519.00            Fix taken at 12:35:19 UTC (current time)
  • 4807.03830,N    Latitude 48 deg 07.038′ N
  • 01131.00000,E   Longitude 11 deg 31.000′ E
  • 1 Fix quality:  0 = invalid, 1 = GPS fix (SPS), 2 = DGPS fix, 3 = PPS fix, 4 = Real Time Kinematic,
    5 = Float RTK, 6 = estimated (dead reckoning) (2.3 feature), 7 = Manual input mode,
    8 = Simulation mode
  • 08                    Number of satellites being tracked
  • 0.9                   Horizontal dilution of position
  • 545.4,M         Altitude, Meters, above mean sea level
  • 46.9,M           Height of geoid (mean sea level) above WGS84 ellipsoid
  • (empty field) time in seconds since last DGPS update
  • (empty field) DGPS station ID number
  • *47                   the checksum data, always begins with *

We will be using the data highlighted above to show the number of satellite on our LCD. In order to extract this information we will set up a second Software Serial port.

First we need to identify the NMEA data we need to capture and we do this with the flowing code:

char gpsin[8] = “$GPGGA,”;             //define a character string “$GPGGA,”
if (GPSreceiver.find(gpsin)) {           //if serial data starts with the characters “$GPGGA,”
GPGGAdata = GPSreceiver.readStringUntil(‘\n’);  //read data until carriage return

When the characters “$GPGGA,” are detected it starts reading the remainder of the string data in to the buffer. So the captured data starts from the first digit of the ‘time’ data (and not from the $ character). The captured data then looks as follows:


With in the main loop we will use the substring command to extract the number of satellites from the GGA data sentence. This is a simply and easy way of extracting the data you wish to use. The substring command is defined as follows:
substring(index, to) – this returns a string with the characters starting from index and ending at the character location before the to
So to extract the number of satellites (highlighted in read) from the GGA data sentence below



We use the following code:

sats = GPGGAdata.substring(39,41);

The string “sats” now is equal to “08”
If you wanted to extract other data you simply need to change the “index, to” numbers in the substring. For example to extract the current time to a string labeled time then you would use:

time = GPGGAdata.substring(7,13); //the string “time” now is equal to “123519”

Details of Code used in program loop to extract number of satellites and display on LCD

//new variables added at start of program
String sats; //number of satellites detected
String GPGGAdata;           //satellite data string from GPS module
String FreqStatus;          //used to print Frequency locked if applicable
int satNum;                 //number of satellites detected as an integer
//set up a Software Serial port called GPSreceiver
SoftwareSerial GPSreceiver (14,255); //14(A0) is RX on Arduino connected to GPS TX pin.
//255 a nonexistent pin number used to free up a pin
//in void setup() include serial monitor command and set to 57600 baud.
Serial.begin(57600);                 //this is simply used for testing
//The # key used to tell the unit to display the number of satellites on LCD.
// below is the software code used in the main loop to show number of satellites when //“#” key pressed:
case '#'://# pressed Show number of satellites detected and frequency status
lcd.clear(); //clear LCD
lcd.print("Satellites =");        //print the word 'Satellites =' on the top line of LCD
do {                             //now loop
GPSreceiver.flush();   //clear any data which may be in the Serial Buffer
if (GPSreceiver.available())          //if any GPS data is available
{;         //read GPS serial data streams if available
char gpsin[8] = "$GPGGA,";       //define a character string “$GPGGA,”
if (GPSreceiver.find(gpsin)) {     //if serial data starts with the characters “$GPGGA,”
GPGGAdata = GPSreceiver.readStringUntil('\n'); //read data until a carriage return
sats = GPGGAdata.substring(39,41); //extract number of satellites from data string
satNum = sats.toInt(); //convert sats string to an integer so as to remove leading zero
if (satNum >0){
FreqStatus = "Frequency Locked";  //if satellites detected the status string
//= “Frequency Locked”
FreqStatus = " ";                 //16 spaces to clear line if no lock
Serial.print(GPGGAdata);   //These serial print lines are for testing using
//Serial Monitor
Serial.println(); //full GPGGA data sentence printed and then carriage return
Serial.print("Satellite = ");
lcd.setCursor(13,0); //set cursor position to column 13 of row 0 (first line on LCD)
lcd.print(" ");  //clears number if no satellites detected (3 spaces used)
lcd.setCursor(13,0); //set cursor position to column 13 of row 0 (first line on LCD)
lcd.print(satNum);         //print number of satellites to LCD
lcd.setCursor(0,1); //set cursor position to column 0 of row 1 (second line on LCD)
lcd.print(FreqStatus);     //print Frequency Locked status
while (customKeypad.getKey()!= '#'); //if # key pressed again break out of loop
displayCurrentFrequency();   //and display current frequency subroutine
break;                       //break and return to main program loop

The software for this project is made up of three parts all of which are include in a download zip file.


Once the file is unzipped you will have a folder as above. In this folder you will find the following files shown below:


Please ensure that you are running the latest version of the Arduino IDE which is “Arduino 1.6.7” (older versions may not work). Run the “GPS_Ref_Version6” file and you should find the software opens up in the Arduino IDE as shown below:


Now compile and upload the software to the Arduino nano on the main PCB.

GPS Locked Frequency Standard Project

This project will use a small GPS module which has the u-blox Neo-7 GPS receiver. These modules are readily available on sites like eBay for around £12, they tend to be advertised for use with flight controllers on model aircraft.
The u-blox receiver is normally fitted in the centre of a small PCB. Additional components on the PCB include a 3.3 volt Low Drop Voltage Regulator, timepulse and power on LED’s and EEPROM. There is also some short term back-up supply for the DRAM of the Neo-7 receiver by use of a 0.08F super capacitor (Seiko XH414HG). These capacitors normally only provide power off back-up for around a day or so if you are lucky.
These GPS modules are usually configured by default to provide a 1Hz timing pulse output which is normally used to flash a green LED to indicate when the unit has a fix on satellites and the local oscillator is locked to the GPS signal. By default this timing pulse provides a 100mSec pulse every 1000mSec, as shown below.


This timing pulse can be configured to provide different frequencies and different duty cycle and we will be using this option in this project to change the frequency and fix the duty cycle to 50%.
GPS satellites are primarily used as a navigation system; this global positioning system can also used to disseminate precise time, time intervals, and frequency. The GPS carrier signals originate from an on-board atomic clock (oscillator) which is also monitored and controlled by ground stations in the United States to ensure it agrees with the Coordinated Universal Time (UTC). UTC is the primary time standard by which the world regulates clocks and time.
Atomic clocks are based on the natural atomic oscillations of gases in resonant cavities. When isolated from magnetic fields, rubidium and cesium gases will resonate at specific frequencies under controlled conditions. These frequencies are so accurate that since 1967 the length of the second has been defined as the frequency of a specific resonant mode of the cesium atom, producing 9,192,631,770 oscillations in one second.

The u-blox receiver uses a built-in 48MHz oscillator.

There are various versions of the u-blox receiver available, some of which can be configured to provide a frequency pulse output in the range 0.25Hz to 10MHz. Those which are suitable for this project are listed in the table below:

u-blox Receiver Type Type of Memory fitted Type of Oscillator used
Neo-7M ROM Crystal
Neo-7P FLASH Crystal
Neo-M8M ROM Crystal
Neo-M8Q ROM Crystal

In this project we will use the Neo-7M. As this uses a ROM, the option to use a 3 volt backup battery on the PCB will help to speed up satellite lock after switch-on (this is optional). If the back-up battery is not used it may take a few minutes before the unit locks on to satellites. If the Neo-7N version is used then as it uses a FLASH memory there is no need for a back-up supply.

11 thoughts to “Design & Build a GPS locked Frequency Standard – Part 4”

  1. Read my comments on youtube. The conclusion is that the mcu won’t output a clean clock without a PLL. It can only output a signal synchronized with the 48 MHz clock and will add extra cycles from time to time to generate the right number of cycles ON AVERAGE but not on a single period. With frequencies that are low enough the problem is reduced (because changing the half period by +- 1/48000000 s is negligeable if the half cycle is 1/48000s) but will never disappear.

    1. I have found if you select any random frequency up to about 2 MHz the output always gives a nice clean square wave with no phase jitter. The output waveform of any frequency between 3 MHz to 4 MHz also stays fairly clean. Once you go higher than these frequencies the square wave has some phase noise but the frequency is still accurate when monitored on a frequency counter or spectrum analyser. Choosing frequencies which have a factor of 48 MHz like 4, 6, 8 or 12 MHz does show some slight improvement but the phase jitter on the waveform is still there. To remove this phase jitter altogether a Phase Locked Loop circuit could be used, but I will leave this for future project as it involves a second PCB with a Voltage Controlled Oscillator and a Programmable Frequency Divider in the feedback loop. The project as it stands at the moment does give out an accurate frequency reference signal so is still quite useful for the hobbyist and a good source of reference to check the accuracy of frequency counter.

      1. Thanks for all your helpful work on this project.
        Do you think you could give some advice on how to do the PLL circuit you suggested? It has been nearly a year and a half, and the PLL circuit is for me the most useful part of the project.

  2. I believe the issues you are seeing with “phase distortion” are rather due to the pulse dropping method that ublox uses for synthesis of frequencies that are not integer multiples of the 48 MHz crystal frequency. This means that 12,8,6,4,2,1 MHz etc. will be clean but 10 MHz etc. will not.

    Over an averaging period such as that used by a frequency counter the frequency will look spot on, but as you’ve demonstrated a spectrum analyzer and oscilloscope will notice the difference.

  3. Louis,
    What is the accuracy of the GPS reference ?
    Thank you for your videos and your excellent teaching skills !!

  4. Hi Louis,

    Where did you get your NEO module from ?
    Would you trust Ali-very-fast for those modules at very very low price ?
    Thanks for your projects and videos.

  5. Hi Louis,

    Such a reference std has been on my to-do list for a couple of years. I happened upon your excellent video presentations and am encouraged to do something about it!

    Is it possible to send me a 1:1 image of the final PCB? Ideally a reversed image would be excellent since I routinely use the ‘iron-on’ method for producing my PCBs.


  6. Hello Louis,
    I got it working, and I am very impressed. My previous reference was a 100KHz signal derived from Droitwich. It is interesting to compare the two (with your design producing 100KHz of course). There appear locked of course, but after several hours there was a relative phase shift of about a quarter of a cycle. Probably of no practical consequence but mildly interesting.
    If I might be cheeky enough to suggest two software changes:
    It would be useful if the numeric keys were ignored until the “A” key is pushed. I have a habit of pushing a numeric button, and then remembering that I should have done an A first! Then, when the brain rights itself, using the A does not clear the junk already entered. So a nonsense frequency has to be sent before the process can be done properly.
    Secondly, and related to that, a possible use for the * key would be to erase anything previously entered, to fix a misstype!
    Nice project Louis. Thank you for it.

Leave a Reply

Your email address will not be published. Required fields are marked *