Thursday, May 8, 2014

A sub-second accurate GPS clock

I was able to finish a project from some time ago. I wanted to have a sub-second accurate GPS clock. The idea is that you could stick this clock in the background of something you're filming and get reasonably good and accurate timestamps. Of course, since it's using an LCD display, it's not going to be tremendously good, but for the price, I don't think anyone can complain.

To make it work, you connect up a GPS module of your choice to the RX and TX lines (experiments with SoftwareSerial on other lines were a failure) and the PPS pin to digital pin 2. You'll also need to connect up an AdaFruit RGB LCD shield, or replace LiquidTWI2 with LiquidCrystal and wire the display parallel-style.

This sketch is time-zone and DST aware, so you may need to edit the "summer" and "winter" timezone rule declarations. Depending on your GPS module, you may also need to change the GPS_BAUD or change the interrupt from RISING to FALLING.

#include <Wire.h>

#include <LiquidTWI2.h>

//#include <SoftwareSerial.h>

#include <TinyGPS.h>

#include <Time.h>

#include <Timezone.h>

#define PPS_PIN 2

#define PPS_INT 0

#define RX_PIN 4

#define TX_PIN 3

#define GPS_BAUD 4800

#define LCD_I2C_ADDR 0x20 // for adafruit shield or backpack

LiquidTWI2 display(LCD_I2C_ADDR, 0, 0);

//SoftwareSerial gps_port(RX_PIN, TX_PIN);

#define gps_port Serial

TinyGPS gps;

time_t prevTime = 0; // when the digital clock was displayed

unsigned int prevTenths = 99; // not 0-9

boolean complained = false;

unsigned long last_pps_millis;

/*

For this to work, an extension must be made to the Arduino Time library. This

method's intent is to designate the precise start of a second. It does this by

replacing the prevMillis value saved in the library with the current value of

millis(), but preserving any "owed" updates.

void syncSecond() {

unsigned long now_millis = millis();

while (((int)(now_millis - prevMillis)) > 500) { // 500 so we sync to the *nearest* second