GPS Clock

In my basement shop area I have a digital clock and, in the same project box, I have a receiver for Accurite weather sensors.  The weather sensor part is based on an earlier project that I modified to receive and alternately display temperature and humidity from both an indoor and an outdoor sensor.  The clock was based on an earlier project where I used a 4.194304-MHz crystal to get a nice even 2-Hz interrupt from Timer1.  The problem with the clock was that a power glitch meant that I had to reset the time.  I suppose I could have added a battery backup but that was too boring of a solution so I decided to run it on GPS time instead.


GPS Units


I have several GPS units (without displays) that output the standard NMEA sentences.  In a previous project I mentioned a couple of these and showed how to display a bunch of GPS information on a 4-line LCD display.  The smallest and cheapest of the units I have is the NEO-6M so that’s what I built into my clock.

It’s easy to connect the Ublox NEO-6M module to the PIC because it uses a TTL-level serial port and outputs standard NMEA-0183 sentences.  The only real difference is that the NMEA standard specifies a serial baud rate of 4800 but the Ublox unit defaults to 9600 baud.  You can run the free “u-center” program to change the baud rate but I just left it as factory default.  As I mentioned in the previous GPS project there is also a utility program called GPSInfo (put out by Globalsat) that is very handy for viewing GPS information.  You can hook up the GPS unit to a standard USB to TTL cable for checking it out or for setting it up using a PC.  Keep in mind that the GPS chip on the module actually runs at 3.3 volts (via an on-board voltage regulator) so if you want to connect to its RX port you should level shift down from 5 volts.  The TX port can connect directly to the PIC or the PC.

Time Zones

Displaying GPS time is an easy thing to do as long as you just want to display UTC (Universal Time Coordinated).  The NMEA sentences are composed of ASCII characters which can be directly output to the LCD.  The time portion is in the format of HHMMSS.FF (hours, minutes, seconds, and fractional seconds).  For our clock the fractional part is not useful so all we need to deal with is six characters.  The problem is that you then need to convert to your local time and to a 12-hour AM/PM format if you want that.  But sometimes problems are what make life interesting so that’s what the software is really all about.

As for time zones, you might think that there would simply be 24 of them with 12 of them east of the UTC location (+ zones) and 12 of them west of the UTC location (- zones).  In fact, there are a few oddball ones that are fractional hours and a couple that exceed the 12 hour “limit”.  If you happen to live in one of these areas I apologize because my software only accounts for the 24 whole hour zones.  There are also some of us who use Daylight Savings Time part of the year but that is not accounted for in the software.  I may make a later update to the software to handle it but it would require an “opt-out” capability as well as the storage in EEROM of future dates for the transition.  The software would need to be updated if those dates change at some point.  The hardware provides a switch for easy setting of the time zone so I settled for that at the moment.


GPS Connection

The hardware connections are shown in the diagram above.  The connection to the GPS is simply from the GPS transmit output to the PIC serial port receive input.  As mentioned earlier, the switch on PIC pin 4 is for setting the time zone.  The LCD connection is the standard 4-bit setup that has been used in a number of previous projects but the LCD itself is different.  Usually I have used the standard 1602 LCD (16 characters by 2 lines) but I chose to use a surplus 1601 display that has large characters so my old eyes can read it more easily.   The 1601 operates the same as the 1602 except it doesn’t have the second line.  In fact, my test board uses a 1602 and didn’t require any software changes.



The GPS outputs standard NMEA-0183 sentences which are ASCII strings that contain a variety of information.  For this application I chose the GGA sentence simply because that is what I used in my previous GPS project.  Fields of information in NMEA sentences are separated by commas so after the GGA sentence header is detected the software would normally count commas and call the appropriate routine for each desired field of information.  Only the time information is needed here and that is in the first field so no comma counting is needed.

The six time digits are buffered and then processed after all of them are received.  The GPS may output some incomplete messages early on so the buffering routine verifies that each character is an ASCII numerical value.  If a bad character is received, the message is discarded.  This may also happen on rare occasions during normal operation, particularly if the serial port communication drops a bit.  I’ve only seen this once and all that happened is that the time paused for a second and then jumped two seconds instead of one.

In order to convert the UTC to local time, the UTC offset (time zone) must be applied.  Because the UTC time from the GPS is in ASCII format, the software converts the ASCII characters to decimal, adds the tens of hours to the units, and then adds the UTC offset.  The UTC offset is stored as a positive BCD value with a sign bit so it is first converted to an integer value and a two’s complement is done if the sign bit is set.  Once the local time hour value is calculated a lookup table is used to convert it to BCD and then a routine converts the BCD to ASCII for display.  The lookup table needs to handle the 24 hour UTC format as well as +/- 12 time zones.  In order to do this, the UTC times from 0000 to 2300 occupy the middle 24 entries in the table with 12 entries before and 12 entries after to account for the time zones.  I chose to use a 12-hour format so I also added a lookup table for the AM/PM part of the display.

The time zone is retrieved from EEROM during initialization and briefly displayed.  If it has not been set at least once then the setting routines are called.  The setting routines can also be called at any time by pressing the switch.  The setting routines will initialize the display to “UTC OFFSET +77”.  If a negative time zone is required, a short press of the switch will change the value to “-00”.  If a positive time zone is required, then press and hold the switch until the value changes to “+00”.  Once the value is at zero, each short press will increment it up to a maximum of 12.  After reaching the desired time zone, press and hold the switch until the display reads “OFFSET SAVED”.  The software uses a 100ms timeout for switch debounce and counts 10 timeouts (1 second) as the command to transition to the next setting step or to exit.  If you make a mistake during entry, just exit and then press the switch again to reset it.

The NEO-6M doesn’t require a good position fix in order to output the correct time so it should output messages as soon as it gets one satellite.  Until then the display will read “NO DATA”.  That’s it for this post.  Check out my other electronics projects at: