Hi all,
I am building a GPS synchronized clock and am confused by the behavior of the program. I'm looking for some help. The GPS sentence is used to update/sync a DS3234 RTC clock chip, update a MAX7219 driven 7 segment LED display, and write to an LCD.
I have written three libraries and modified (slightly) the Time.h library. Here's what they do:
The GPS lib is written for a USGlobalSat EM318-02. This is very similar to the 406, but uses an external antenna. I think the commands are the same, and obviously the sentences are to NMEA standard. The initialization call suppresses all sentences except $GPRMC, assures that it is transmitted every second, and resets the communication speed to 9600 baud. When a get time request is sent to the GPS, a TimeElements struct is passed by reference (it is a global variable in the sketch), the GPS sentence is parsed, and the TimeElements struct is updated only if the sentence is valid. I've written a bunch of overhead code to re-initialize variables at each call to make sure that I'm not dealing with old data-- probably more than I need to. I am confident, after innumerable Serial.println() calls, that the data is valid and the TimeElements struct is being filled in correctly.
The DS3234 RTC chip is a very sophisticated device that communicates by SPI with the arduino. My lib is based loosely on the Sparkfun demo sketch. A get time or set time call passes the global TimeElements struct by reference and either uses the struct to set the DS3234 time or get the DS3234 time. No bells and whistles used or accessed. The initialization routine sets the chip to output a 1 Hz square wave, which I use as the heartbeat; it communicates by an interrupt. Again, lots of Serial.println() calls, and I think the right info is being passed to/from the chip.
The MAX7219 lib is a simple library that accepts a TimeElements struct and updates the display on 8 7 segment LED displays. It also permits control over brightness. A silly but useful frill on the clock is a PIR motion detector with very focused directionality (put the detector in a toilet paper tube while prototyping!). As a bedside clock, just wave your hand over the clock and the display brightens!
The Time.h lib is modified only insofar as the the TimeElements struct has int, rather than byte members. This reduces a lot of typecasting in other libs, and the RAM in the Mega is so plentiful a few extra bytes doesn't matter. The only routines I use are makeTime and breakTime, and that is used to set the local time from the UTC time provided by the GPS sentence.
So, what's the quesion?
The sketch initiates fine, gets a GPS time, pops it into the DS3234. Every square wave rising edge I query the DS3234, get the time, and update the displays. For testing purposes, I have set up my update routine to query the GPS every minute and reset the DS3234. I am very confused by the results. The update clearly happens in less than a second, probably more along the line of ~350 ms (writing to an LCD is SLOWWW.). The update routine looks for when Time.Second == 0 and Time.Minute ==0, as output by the DS3234. I then query the GPS, and the GPS time is often several seconds off. Sometimes it's a few seconds ahead, sometimes it's 20 seconds behind. I have been round and round on this. I can understand that the times might not sync by a second or two, but it is beyond me why it varies so greatly and so randomly. Does anyone have any ideas?
BTW, I would be happy to post the code for the GPS library, DS3234 library, and MAX7219 library. Hopefully they would be of use to someone. All the MAXIM RTC chips have a similar basic time register structure, so modification of the library would be relatively simple (swap I2C calls for SPI calls, change a couple of specific registers, etc.) to adapt for other DS series devices.
Thanks.
Ed