GPS Clock

A simple desk clock that gets time from GPS

Similar projects worth following
GPS is best known as a ubiquitous, accurate positioning system (obvious from the name), but the way it actually works requires distributing hyper-accurate time information. This makes it possible (and, actually, pretty easy) to make a clock that you never have to set as long as it gets good GPS reception.

Yes, this is way overkill... but GPS is getting so cheap that you might as well.

GPS time information is often precise down to the tens of nano-seconds. But if all you want to do is display time for humans, you probably would be satisfied with 4 orders of magnitude less precision, which is what this design achieves - 200 µs accuracy with 100 ms granularity.

Over the course of the project, the clock has undergone a number of design revisions. The original design paired an ATTiny841 with a MAX6951 display driver. The 6951 connects to up to 8 seven-segment common cathode LED display digits (with decimal). This project is going to use 7 of them (6 large and 1 small for the 10th of a second digit), plus two LEDs for AM and PM, 4 for two colons between the 3 large groups, and a FIX LED from the GPS module. There are also two pushbuttons for parameter setting (timezone, DST config and display brightness).

The GPS module has a bidirectional UART and a PPS output. What complicates things just slightly is that the NMEA timecodes on the serial port describe the current second, meaning they happen just after the PPS signal. The serial codes aren't precise enough to do more than name the current second. Actual timing needs to come from the PPS signal. So the serial data needs to have a second added to it, and the result is stored in a buffer in RAM. The PPS interrupt transfers that buffer to the display chip. For tenths of a second, a timer in the controller is used for interpolation. The correct counting rate is determined by counting how many timer ticks occur between adjacent PPS interrupts and dividing that by 10. The timer runs from the controller's RC oscillator, configured for 8 MHz, with a divide-by-8 prescale - so approximately 1 MHz. The controller has interrupt handlers for timer overflow and input capture (for the PPS). The overflow interrupt increments a high order word, allowing us to keep a 32 bit counter. Even at a 1 MHz counting rate, it takes more than an hour to overflow a 32 bit counter, and that gives us microsecond measurement granularity. The RC oscillator's short term stability should be good enough for the purpose, and its stability beyond 2 seconds is mooted by the way it's being used.

The 6951 chip communicates with SPI. It requires a chip select line to be driven low and then 16 bits of data is clocked in. The write format is 8 bits of address and 8 bits of data. The chip has a bunch of registers inside that allow the display to be fully configured and even dimmed. The chip has a resistor that's used to configure the chip for constant-current for each LED segment to insure correct brightness. The chip's maximum SPI clock speed is over 20 MHz, and the highest SPI rate we can use with an 8 MHz ATTiny is 4 MHz, so we can run it flat out without worry. Our accuracy claim (~200 µs) stems from the fact that a full display update over SPI takes approximately 70 µs start to finish, and that happens in the PPS capture interrupt handler once a second that takes around 100 µs before the display updates commence (we do go to the trouble of updating the least significant digits first so that hopefully most of the time the only actual changes take place much faster). The accuracy of the tenth updates is likely much better, but keep in mind that their timing is estimated via interpolation, so that's based on the stability of the 8 MHz RC oscillator in the controller over τ 2s.

The brains of the clock is an ATTiny841, simply because I have a bunch of them and they have a UART (actually, two). It runs from the internal 8 MHz oscillator. The entire circuit runs from a 3.3 volt supply, so 12 MHz is the maximum frequency that could be used, but that would require adding an external crystal for no other reason (and rearranging the pins to allow the crystal to be connected).

The GPS module is the Skytraq Venus838LPx-T timing module. The board has an edge-mount SMA connector for an external antenna, and passes 5v (or 3.3v selectable with a solder jumper) active antenna power with an AP2331...

Read more »


Schematic of v5.1

Adobe Portable Document Format - 84.80 kB - 08/08/2017 at 06:43



EAGLE schematic of v5.1

sch - 429.85 kB - 08/08/2017 at 06:43



EAGLE board file of v5.1

brd - 185.49 kB - 08/08/2017 at 06:43



Schematic of v5.0.2

Adobe Portable Document Format - 83.63 kB - 07/24/2017 at 15:55



EAGLE schematic of v5.0.2

sch - 424.62 kB - 07/24/2017 at 15:55


View all 9 files

  • 1 × ATXmega32E5 Microprocessors, Microcontrollers, DSPs / ARM, RISC-Based Microcontrollers
  • 1 × SkyTraq Venus838LPx-T
  • 1 × PAM2305AABADJ Power Management ICs / Switching Regulators and Controllers
  • 1 × TBD62783AFNG
  • 1 × TBD62083AFNG

View all 40 components

  • Backup power options

    Nick Sayer09/23/2017 at 03:59 0 comments

    There are four ways you can configure the GPS chip:

    • Without any backup power at all
    • With a super-cap
    • With a primary cell
    • With a secondary cell

    Turns out that the schematic for a secondary cell and a supercap are the same. For the secondary cell, the series resistor limits the charge current to just a trickle to avoid hitting it too hard.

    Of course, the tradeoff between a supercap and secondary cell is that the supercap doesn't hold the power very long, while the secondary cell won't have a terribly long lifetime.

    The primary cell probably is the most effective system. A CR-1220 cell will provide backup power for more or less the same period of time as its shelf life. The circuit is rather different for a primary cell. You use a pair of Schottky diodes with a common cathode connection (A BAT54C is ideal for this). The cathode goes to the VBack pin on the GPS module (with a 1 µF bypass cap). One anode goes to Vcc, the other to the positive side of the primary cell. As long as the battery voltage is lower than Vcc (the nominal voltage of a CR1220 is only 3 volts, not 3.3), this arrangement will prevent back-feeding power into the cell, and prevent the cell from powering anything except the VBack pin when the power is off.

    The primary cell also offers the most flexibility. Adding the battery bail to the board isn't very expensive, and the GPS module will operate just fine with no battery installed. The voltage drop across the schottky diode isn't problematic - VBack is allowed to be slightly lower than Vcc.

  • Crystal vs RC osc

    Nick Sayer08/08/2017 at 06:37 0 comments

    I got a board made of rev 5.1 - the same as the 5.0.2 board but with the footprints added for a 3.2x2.5mm 4-pad crystal and two loading caps on the R port pins. I built that board this evening with a 16 MHz crystal in place, and added support in the code to use the external crystal oscillator and PLL (configured to double) to make a 32 MHz clock. My motivation for doing so was to compare the stability of an undisciplined crystal against the FLL disciplined 32 MHz XMega RC oscillator.

    To measure it, I modified the code to display (instead of the time) the delta of the number of ticks in the capture ISR and the expected value (32 million).

    As I kind of knew from experience, with the FLL corrected RC oscillator, it bounced around fairly wildly several thousand ticks in each direction. The crystal oscillator, by contrast, stayed fairly consistent. In this particular example, it was about 1080 counts slow - about 33 parts per million. If I put my thumb on the crystal, I could get it to diverge a handful of counts or so over the course of a few seconds. That too is kind of to be expected - crystals are sensitive to temperature. But still, the crystal is by far more stable than the RC oscillator. Again, not an unexpected result.

    I'm still undecided whether it's worth adding the part. Unlike the case with the ATTiny841, there's no speed advantage to adding it - the chip still runs at its maximum 32 MHz speed. But if the system clock were that stable, we could switch the firmware over to using a free-running, disciplined clock model as opposed to the absolute interrupt-driven reactive model the clock uses today. In other words, we could just have the capture ISR record the timestamp of the PPS rising edge and let the clock tune itself. Doing so would allow us to reclaim most of the 70 µs capture ISR latency, though we still would likely be stuck with the 100 µs worst-case display update latency. So we'd potentially be able to cut the accuracy spec in half (in fact, if we ran the clock 50 µs ahead of actual time, we could instead wind up with a ±50 µs spec instead of a 0-100 µs slow spec). We could even potentially dare to allow the clock to free-run if GPS drops out from time to time (though that raises the specter of having to quantify how long free-running is acceptable, or how to indicate it and so on).

    That is, however, a mighty big firmware change for a very, very marginal gain for a clock that only has 100 ms granularity.

    Still, since the clock works, I'll commit the code changes to the GitHub repo and upload the latest schematic and board files. You have the choice of populating the crystal footprints with a 16 MHz crystal or not populating them. There is an XTAL macro in the code that determines whether or not the firmware will attempt to use it.

  • A different errata

    Nick Sayer08/06/2017 at 04:25 0 comments

    the latest code for the clock will check the GPS-UTC offset (that is, the leap second count) once an hour at the bottom of the hour. If the default value is wrong, it will set the default to the current value.

    One side effect of this command, it turns out, is that the GPS receiver throws away the fix and survey and starts over. This means that the clock will show "no GPS" until a fix is reestablished.

    This isn't a huge deal - this will only ever happen once the very first time the clock is powered up past the half hour and once for every leap second after that.

    I've sent in an inquiry to SkyTraq to make sure this is an intentional behavior. I'll edit this log when I hear back from them.


    I heard back from SkyTraq. The reboot in response to that command is by design.

  • Errata

    Nick Sayer07/22/2017 at 14:17 0 comments

    The v5 prototypes have shown some reduced sensitivity on the antenna input. The symptom has been S/N numbers in the GPGSA sentences about 10 dB lower than other units show.

    Turns out that the problem is caused by a lack of bypassing on the AP2331. I'm going to add footprints for bypass caps on all future boards, but it appears that just tacking an 0805 or 0603 0.1 µF ceramic cap across the output of the 2331 is a sufficient workaround. Another option is to add an external bias-T if your antenna needs power and open the voltage selection jumper or remove the 0.033 µH bias inductor.

    You can test your own clock by taping the GPS receiver serial output. Use a jumper wire to temporarily tie !RESET to ground on the programming header and watch the S/N numbers compared to the numbers while the controller is running. If there's no difference, then you don't have the symptoms. 

    So far, only the versions with the XMega have shown any issues, and those aren't going to ship before the current inventory is exhausted. 

  • Version 5.0.1

    Nick Sayer07/21/2017 at 16:55 0 comments

    Version 5.0.1 has been built. It replaces the PAM2305 + LDO with a MP2149GJ dual buck regulator. One half of it makes the 3.3 volts for the controller and GPS, the other half makes ~2.3v for the display.

    I'm a bit torn, though. The MP2149GJ is a little pricey in comparison to the older design. I could fairly easily use either a pair of PAM2305 adjustable units or a single adjustable and a single 3.3v fixed (or an LDO - like for v5.0) for less money in terms of the BOM price. But the MP2149GJ reduces the BOM quite a bit - one chip, one inductor twice, one ceramic cap three times, three feedback resistors (one common value between the two sides) instead of (for v5.0) two chips, an inductor, two different pairs of ceramic caps, a third ceramic cap as part of the feedback network and two resistor values.

    I'd still rather have some sort of constant current supply for the LED segments. If I did that, I could feed the TBD62783 from either 3.3v or 5v (depending on the LED Vf), and introduce a current regulator on each of the anode lines. Classically, this would be in the form of a JFET and resistor. But having to do that 8 times with discrete components would be pretty silly.

    There are LED driver chips intended to do the job, but most of them are low-side drain switches, which means that they'd be designed for common anode displays, and most of them use serial input of one form or another instead of parallel. Serial input is nice for saving pins, but I don't really need to save pins - the XMega_E5 has plenty for what we want to do.

  • More on leap second preservation

    Nick Sayer07/17/2017 at 14:33 0 comments

    I exchanged some mail with SkyTraq. While I was coding my leap second default update code, I happened to notice that the newer clocks didn't show the leap second error even when powered up without my new code. It turns out that if you preserve VBatt at all then the module will checkpoint the current GPS-UTC offset in flash when Vcc drops. From what I can tell, it's not stored in the same place, since the GPS offset command doesn't return the current value as the "default," but the supercap is preventing the 2 second delta at every power-up after the very first one.

    I asked them how long VBatt must be maintained in order to have this save take place, as the clock doesn't really benefit a lot from preserving the almanac and current time for 45 minutes (with good reception it boots up in 10 seconds instead of 30), but this leap second offset save really is a good thing. If the same effect could be done with a few dozen ms worth of VBatt, then a 1000µF polymer cap instead of a 0.1F supercap would be just as good at 1/3 the price. I haven't gotten an answer from them about this, but will update this log when I do. The good news is that a suitable polymer cap would fit in the same footprint as the supercap, so future designs can pick either option.


    SkyTraq got back to me with an answer. It turns out that the flash update happens on powerup, if the RAM contents have been preserved by VBatt. So a tantalum or electrolytic cap wouldn't be helpful unless the power came back really quickly. The code to reset the default when it's wrong periodically is the way to go, and with it the value of the supercap has dropped quite a bit, it turns out.  

  • The Leap Second Fix

    Nick Sayer07/15/2017 at 16:51 0 comments

    One issue with the clock is that when it cold boots the built in count of the current number of leap second can be wrong until GPS updates the receiver, which happens about every 12 minutes.

    It would be ideal if the receiver would update this value whenever it determines that it's wrong. It would only ever do so once the first time the clock starts and once every leap second. But it doesn't currently.

    The fantastic news is that this is an operation that we can manually perform with the SkyTraq binary protocol! I found an application note on the Internet, and have used it to add this functionality to the clock. The clock will ask whether the current leap second delta from GPS is valid or not and whether it differs from the default or not. If it is valid and different, an update command is sent to update the default. This action is performed every hour on the half hour.

    In addition, at startup the date code of the GPS module firmware is now displayed briefly after the display self-test.

    These changes are currently being tested in the v5 clock code, but will be back-ported to all versions of the code.

    This obviates the need for the super capacitor on the board, now that I've just had a run of boards manufactured with it installed.

    In looking over the binary protocol, it appears that there may be another good idea now that we can speak the binary protocol. GPS works on a 1024 week cycle, which is just short of 20 years. If you don't do anything, then when that 20 week cycle elapses, the date will wrap around to the beginning. This is the GPS version of the Y2K bug. SkyTraq worked around this by declaring a "UTC reference date" and commands to set and retrieve it. The idea is that the 1024 week window is forced to include the reference date near the beginning. If you update the reference date, the 1024 week window will slide forward along with time. It's probably a good idea to set this value once a year. The alternative is to connect a PC up to the serial pins while holding the !RESET line of the controller low and execute the reference date setting command yourself (SkyTraq has a Windows program to do this for you).

  • How worthy is the clock?

    Nick Sayer07/10/2017 at 16:08 0 comments

      The Hackaday Prize rules ask for answers to a few specific questions:

      1. What are the challenges the project addresses?
      2. How does the instant project address those challenges?
      3. How does solving those challenges change the world?

      The Global Positioning System was fundamentally designed to solve the problem of navigation - knowing where you were in space (relative to the Earth). But solving that problem fundamentally required distributing hyper-accurate time. And providing accurate timekeeping is a secondary goal of GPS. GPS has been widely used in industry and science as a source of accurate time (and from it accurate frequency references, etc).

      For consumers, so-called "Atomic" clocks are available at premium prices in relatively pedestrian retail stores. Such clocks are actually radio clocks (as are GPS clocks), but their source is the WWVB 60 kHz time signal broadcast from Ft. Collins, CO. This signal is only really available in North America, its availability varies widely, and the accuracy of such clocks depends on that level of availability. The attraction of those clocks largely is that they set themselves and automatically corect for Daylight Savings Time. They typically run on batteries which usually need to be replaced at least annually.

      GPS reception is much more available not only around the world, but in North America it relies merely on line of sight reception from the GPS satellites, which are in orbits that move around. Because of that, continuous GPS coverage is easier to obtain than WWVB (where continuous availability is limited to only a few states surrounding Colorado). Because of this a GPS clock doesn't have to maintain its own accurate timekeeping - it can count on continuous service from the GPS system to tell it the current time.

      WWVB's timecode includes DST status, but only for the US (which is sensible given the fact that its coverage area is limited). GPS does not, but GPS includes the date, which is sufficient for a clock to compute DST on its own. In fact, the GPS clock includes rulesets for the EU, Australia and New Zealand in addition to the US (and you can also turn DST off). Adding additional DST rulesets would simply require adding them to the firmware (the same goes for ruleset changes).

      The idea of a clock that sets itself and displays accurate time without any need for maintenance has been made possible by GPS, but that same facility has not been made available routinely to consumers other than via radio clocks limited to use within a particular region. Every modern smart phone or Internet connected computer can obtain accurate time over the Internet, but using something like that as a simple standalone clock would be swatting a fly with a sledgehammer.

      Everything about the design of this project has been about balancing accuracy against cost. No other product of which I am aware offers a display granularity of 100 ms, an accuracy of under 200 µs, and a price tag under US$150.

  • Draft business plan

    Nick Sayer07/10/2017 at 15:39 0 comments

    This is the draft business plan required for Best Product entries in the Hackaday Prize Best Product category.

    The clock is currently in the Tindie store, and selling for prices that are appropriate for the costs of sourcing the components in the current sales quantities.

    To make the GPS clock a better product, the sales volume needs to go up. With sufficient demand, the assemblies can be sourced in quantities that will drive the prices lower. In particular, with sufficient volume, transitioning from the current laser-cut wood and acrylic case to an injection molded plastic case would dramatically reduce the cost of the enclosure (given enough volume to amortize the tooling costs).

    As a product, the clock has some challenges facing it. The clock requires an external antenna. This is because in general people don't want their clocks to sit where GPS reception is best. An external antenna makes placement of the clock itself less troublesome. But not everyone is going to have (or find) a spot sufficiently good for reception.

    Additionally, the clock is just a clock. It has no functionality other than displaying the current time to within 200 µs. This is a deliberate choice - adding more features to the clock makes the user interface more complicated than it otherwise needs to be (and it's already fairly complicated for a consumer product) and further increases the cost.

    Increasing the sales volume would require increased marketing for the clock, but hopefully in the longer term would be offset by reducing manufacturing costs as the volume went up. The same reductions in cost would allow the price to be reduced.

    But even at its current price, the clock is still offers the highest accuracy:price ratio available anywhere. The clock maintains that accuracy with no maintenance of any kind - it even automatically handles daylight savings time changes. Even without the accuracy, a plug-in clock that set itself and automatically tracked DST would already be worth most of the current price.

  • v5.0 build report

    Nick Sayer07/06/2017 at 23:49 0 comments

    The v5.0 variant boards arrived today and I built one with blue LEDs. The bad news is that blue 7 segment LEDs are hopelessly dim. Even blasting them with on the order of 4.3 volts doesn't make them any brighter (it just makes them a little warmer). To make matters worse, I discovered to my horror that the display module for the 10th-of-a-second digit is wrong, and that nobody makes a blue one that size with the correct pinout. So it's back to red. I'll build one of those (or rip the displays out of this one and replace them) later.

    That said, the multiplexing system works beautifully. The one firmware tweak I needed to make was a short delay (a short _NOP() busy-loop) between turning off the anodes (this would really only happen at maximum brightness - at reduced brightness they would have been off already) and shifting to the next cathode and then presenting the new anode values. This is because the high-side buffer chip has a turn-off spec of 2 µs. Before this there was some ghosting in the display at maximum brightness. Other than that (and the fact that blue LEDs suck), the firmware testing I did in advance paid off handsomely and the clock is indistinguishable from the previous versions.

    The next variant is already designed, but ordering it had to wait for this validation. The big change in that one is to replace the LDO and buck converter with a single dual-buck chip - the MP2149GJ. I'm kinda torn about that, though. It costs more than the combination of PAM2305 and LDO, but it's a net BOM reduction (and it's only one active part instead of two).

    For the purposes of the Hackaday Prize, the BOM listed is the v5.0 design. If the clock makes it to the next round of the Best Product category, the v5.0 design will be the one of which 3 copies will be submitted as prototypes.

View all 40 project logs

  • 1
    Installing the through-hole parts (LEDs)

    When you get the board, all of the surface mount components will have been installed and programmed.

    First, install the two .56" 7-segment LED modules for the seconds and tens-of-seconds digits. Make sure the modules sit flat against the board. For each module, solder a single lead and double-check that the module is oriented correctly (decimal point on the bottom) and sits flat against the board. Solder the rest of the pins.

  • 2
    Step 2

    Install the small .3" 7-segment LED module in the tenth-of-a-second spot on the right side of the board. For best results, mount the module so that the top edge lines up with the top edge of the larger modules. The easiest way to do this is to insert the module into the holes and then lay the board face down so that both the .56" modules and the .3" module are resting flat on the surface. Done correctly the 10th-of-a-second digit will be up about 1/8" from the surface of the PCB. Solder just one pin on each corner and verify that the module is straight, oriented correctly (again, decimal point at the bottom), and the top lines up with the top of the second digit before soldering the rest of the pins.

  • 3
    Step 3

    Install two 3mm LEDs for the colon between the minutes and seconds. The short lead of each (the cathode) should be towards the top. Install the two LEDs so that they're about 1/8" up from the board - that is, so that their tops are at or just below the top face of the adjacent 7 segment display. To do this, you can use the same trick as for the 10th-of-a-second digit - insert the leads and flip the board over and allow the LEDs to rest against the work surface along with the 7 segment modules. Solder one lead of each and carefully verify that each LED is the same height up from the board and is plumb in both directions (from the top and side). Once both LEDs are positioned correctly, solder the remaining leads and trim the excess lead lengths.

View all 14 instructions

Enjoy this project?



Dmitry Grinberg wrote 11/28/2016 at 23:38 point

FYI,  Page 18 of MAX6951 datasheet ( mentions that is has a character rom so this would count against you much like the rules said hd44870 LCDs' would. Judging by their diagram it is 8 bit address an d8 bit data for a 256 byte total.

  Are you sure? yes | no

Nick Sayer wrote 11/30/2016 at 22:51 point

I will disagree with the assertion that character generation tables in accessory chips should count (be they for 7seg or dot matrix), but in this case, there are 16 symbols made from 7 bits of data - that's only 16 bytes, which still fits. If you're counting the charlieplexing matrix built into the chip... well, I don't know what to say to that except that any accessory chip like this could be implemented either as an array of static gates or as an embedded microcontroller running code in ROM. It's unclear how you'd go about interpreting that under the rules one way or the other. See also:

On a more fundamental level, the GPS receiver module has firmware that can be upgraded too. If that counts, then the whole project is sunk (at least, as an entry in the 1K contest).

In the end, it will be a matter for the judges.

Regardless, I still intend to build it. The feature set I want to have is already larger than 1K anyway. :)

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates