Close
0%
0%

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.

A lot of folks on the Internet have made GPS clocks by simply parsing the NMEA data from the receiver. But getting the full accuracy GPS can provide requires also making use of the PPS signal from the receiver. And if you're going to bother with GPS, why not shoot for maximal accuracy?

This clock achieves an accuracy of no worse than 200 µs away from GPS time.

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 - 125 µs accuracy (with v5 hardware) 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)...

Read more »

gps_clock_5_2.pdf

Schematic of v5.2

Adobe Portable Document Format - 84.77 kB - 04/12/2018 at 05:28

Preview
Download

gps_clock_5_2.sch

EAGLE schematic of v5.2

sch - 424.52 kB - 04/12/2018 at 05:28

See BOM
Download

gps_clock_5_2.brd

EAGLE board file of v5.2

brd - 181.12 kB - 04/12/2018 at 05:28

Download

gps_clock_3_1.pdf

Schematic of v3.1

Adobe Portable Document Format - 77.68 kB - 06/24/2017 at 19:19

Preview
Download

gps_clock_3_1.sch

EAGLE schematic of v3.1

sch - 391.44 kB - 06/24/2017 at 19:18

See BOM
Download

View all 6 files

  • 2 × 5MM TH LED
  • 4 × 3MM TH LED
  • 1 × 0805 SMD LED
  • 1 × 150Ω 0805 resistor
  • 1 × 330Ω 0805 resistor

View all 40 components

  • Improved brightness again

    Nick Sayer11/20/2017 at 07:31 0 comments

    I figured out a way to preserve the 2 µs turn-off delay and still have a brighter display (comparable to what was there before).

    The display raster timer will now alternate between two counts - a short value for the turn-off delay time, and a longer value for the actual display.

    With this configuration, we can go back to a 10 kHz raster rate, but with a 75% duty cycle (actually, 75% of 12.5% since the display lights one digit at a time). This doesn't sound like much, but it's actually dramatic from what you can see.

    The bad news is that the accuracy spec (as you'll recall, it's the PPS ISR latency plus the worst-case display refresh) now becomes 125 µs. But again - that's a worst case value. Since a display update resets the raster, we display the least significant digits immediately, so their latency will be much closer to 25 µs. It's only the hour digit an AM/PM indicators that wind up taking the worst-case time, and they don't change nearly as often.

  • A quick idea to improve accuracy

    Nick Sayer11/05/2017 at 17:45 0 comments

    Right now the spec for the clock is 200 µs.

    I think I can turn the spec for the v5 hardware down to 100 µs.

    Recall that the accuracy spec consists of two parts: the ISR latency for the PPS signal, and the display raster update time. You have to account for both, because at the end of the PPS ISR, you've updated the "registers" that display the time, but you have to potentially wait for an entire raster cycle to occur before the display actually changes.

    Right now, the raster cycle displays all 8 digits, and there are four brightness periods for each digit, meaning a full raster cycle takes 32 interrupts, and they happen at 320 kHz.

    If you flip that around, so that the brightness cycles happen outside and the digit rasters happen inside, then the display raster frequency jumps from 10 kHz to 40 kHz, which means a full raster cycle takes not 100 µs, but 25.

    Now, there's a problem: this only works at full brightness. If you dim the display, then there will be somewhere between 25 µs and 75 µs periods of time when the display is not visible. The workaround for that is to give the code outside of the raster ISR the ability to override the raster cycling and have it start from zero right away. In principle, this should only happen once every 10th of a second (or once a second if tenths are not displayed), so the glitch in display brightness should not wind up being visible.

    I'm going to test this idea and see what the impact is.

    EDIT:

    Turns out today is an excellent day to test changes, seeing as how it's DST transition day. For the purpose of most of the code, the fact that it's the transition month probably is what matters the most.

    The issue with this new display mechanism is that the high side switch has a turn-off specification of 2 µs. Well, with the interrupt timer for display rastering hitting every 100 counts, that means those interrupts are 3.125 µs apart. If you try and put a delay in, then essentially the main loop never gets a chance to run at all.

    The workaround is to, unfortunately, cut the raster rate in half and stick an empty slot between each lit-up slot. This also winds up reducing the brightness a bit, but frankly the maximum brightness was pretty bright, and the loss isn't too noticeable. The four brightness levels are still meaningful.

    With this change, the latency of the PPS ISR is now 26 µs. With the worst-case display update time of 50 µs, that means that the accuracy now is 76 µs, better than twice as good as it was. But more to the point, because the digit raster order goes from least-significant to most, the only really high latency digits are the least important ones. In general, you can count on the 100 ms and 1 second digit to be updated within 12.5 µs of the end of the ISR, or 38.5 µs after PPS.

    Unfortunately, these changes require the v5 display rastering system, so the improvements can't be ported back to the MAX6951 hardware.

  • Whither Holdover

    Nick Sayer11/05/2017 at 17:34 0 comments

    A few people have asked about holdover as a feature. Holdover is the ability of a radio clock (and the GPS clock is a radio clock, of course) to free-run when reception fails.

    It's not been a priority because with proper antenna placement GPS should always be available, and holding over should not be necessary. This assumption has been a driving force in keeping the hardware and firmware simple. When there's no GPS lock, you just display "no GPS" and wait.

    The problem with holdover is that the statement of how accurate the clock is gets a lot more complex. Right now, I can say that the clock is "within 200 µs." In actual fact, the clock is somewhere between 70 and 170 µs slow because it takes 70 µs for it to process the PPS pulse to completion and the display raster cycle is 100 µs long.

    But holdover introduces the possibility of longer term drift as long as reception remains unavailable. The magnitude of any potential drift will be proportional to how long ago the last sync occurred. You can "tune" the crystal oscillator while reception is available - that is, determine the exact number of clock cycles between PPS interrupts - but you need to quantify the magnitude of any potential changes in that offset.

    You can limit the scope of the problem by limiting how long you're willing to hold over before giving up. But even then, if your crystal has a 10 ppm stability, that's still 36 ms in an hour.

    You can throw money at the problem. A TCXO can provide a frequency stability of 50 ppb. That would give you a maximum drift in an hour of 180 µs. But a DOT050V adds $30 to the BOM cost (so $60 to the retail price).

    In any event, you'd definitely want to give some feedback of how long you've been holding over. You could just do this with a single LED - on constantly for GPS being available, and mostly off with a blink code indicating how long holdover has been in effect (n blinks in a row mean n time periods of holdover, and after 5 time periods the clock should give up).

    But again, all of this is just an effort to mitigate poor antenna placement. I'm just not really convinced it's worth the effort.

  • Antenna connection options

    Nick Sayer11/04/2017 at 23:35 0 comments

    So far, the clock has used a drop-in edge-mount SMA connector. Having built and sold a bunch of these, it is a tiny bit awkward that the power and antenna connections are on the side. The back would be better.

    In addition, I've found an amplified patch antenna with a u.fl connector that would be a... not terrible choice for a built-in antenna, if one was going to be forced to use one (it works if you have it sitting in or near a window, for example, but not terribly well in the middle of a room).

    Both of these are reasonably good arguments for trying a board with a u.FL jack mounted on the board instead of the SMA jack. You could bury the patch antenna inside the case somewhere if you wanted to go that way, or you could use an SMA pigtail and mount it anywhere on the back panel. If the antenna was internal, then the hole for the back panel could be a knock-out so that it wouldn't have to be used in that case.

    As for the power jack, replacing the right-angle power jack with a vertical one is potentially an option. The jack is just a little more than a half an inch tall, which means that a square cut-out in the back panel the same size would likely be the best option for exposing it.

  • 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.

    EDIT: I've built a board with the battery backup configuration, and it works just fine.

  • 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.

    Edit:

    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.

    Update:

    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.  

View all 44 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?

Share

Discussions

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

FYI,  Page 18 of MAX6951 datasheet (http://datasheets.maximintegrated.com/en/ds/MAX6950-MAX6951.pdf) 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: http://hackaday.com/2014/12/25/student-trolls-anti-arduino-prof-with-parasite-mcu/

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