GPS clock not syncing after reset

I am working on a GPS clock with TimeZone and DST off set using World Clock sketches. I have found that if I reset the Arduino or power it off for any period of time, the displayed time does not match the GPS time. It acts as if the sketch is reading a default time from memory.

Here is the sketch file: I know it's not clean, it's still a work in process.

#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_GPS.h>
#include <Adafruit_GFX.h>
#include <SoftwareSerial.h>
#include <idDHT11.h>  // Tempature & Humidity Sensor
#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <Timezone.h>    //https://github.com/JChristensen/Timezone

int light;
int gpsTime;
int cgpsTime;
int idDHT11pin = 2; //Digital pin for comunications
int idDHT11intNumber = 0; //interrupt number (must be the one that use the previus defined pin (see table above)

//declaration
void dht11_wrapper(); // must be declared before the lib initialization

// Lib instantiate
idDHT11 DHT11(idDHT11pin,idDHT11intNumber,dht11_wrapper);
#define LIGHTPIN 0
Adafruit_7segment matrix1 = Adafruit_7segment();  // Main display
Adafruit_7segment matrix2 = Adafruit_7segment();  // Speed display
Adafruit_7segment matrix3 = Adafruit_7segment();  // Tempature display
Adafruit_7segment matrix4 = Adafruit_7segment();  // Humidity display
SoftwareSerial mySerial(6, 7);

Adafruit_GPS GPS(&mySerial);
#define GPSECHO  false

boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

//  World Clock Settings
//US Eastern Time Zone (New York, Detroit)
TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -240};  //Eastern Daylight Time = UTC - 4 hours
TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, -300};   //Eastern Standard Time = UTC - 5 hours
Timezone usET(usEDT, usEST);

TimeChangeRule *tcr;        //pointer to the time change rule, use to get the TZ abbrev
time_t utc;

// These constants are for the LED Dim Function and won't change:
const int sensorPin = A0;    // pin that the sensor is attached to

// variables:
int sensorValue = 0;         // the sensor value
int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
unsigned long previousMillis = 0;    //This stores the last time DimDisplay was updated
const long interval = 30000;     // interval at which DimDisplay will be updated
const unsigned long TaskAtime  = 500UL;   //Runs TaskA every 500 milli seconds
const unsigned long TaskBtime  = 15000UL; //Runs TaskB every 60 seconds
const unsigned long TaskCtime  = 30000UL; //Runa TaskC every 60 seconds

unsigned long TimeA;                      //Times up, Task A time
unsigned long TimeB;                      //Times up, Task B time
unsigned long TimeC;                      //Times up, Task C time

void setup()  
{
  matrix1.begin(0x70);  // Clock Display
  matrix2.begin(0x72);  // Speed Display
  matrix3.begin(0x71);  // Tempature Display
  matrix4.begin(0x74);  // Humidity Display
 
  Serial.begin(115200);
  Serial.println("Steve's UTC GPS Seven Segment Clock with AutoDim, Speed, Tempature & Humidity");
    setTime(usET.toUTC(compileTime()));  // World Clock Setting

   GPS.begin(9600);
  
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
   GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
   useInterrupt(true);

  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}


// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  if (GPSECHO)
    if (c) UDR0 = c;  
 }

void useInterrupt(boolean v) {
  if (v) {
     OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
{     //This is for the LED Dim Function
  TimeA = millis();                      //Initailize  
  TimeB = TimeA;                         //Initialize
  TimeC = TimeA;                        // Initialize
} 
}

void dht11_wrapper() {
  DHT11.isrCallback();
}

uint32_t timer = millis();


void loop()                     // run over and over again
{
  unsigned long millisNow = millis();

  //==================
  if (millisNow - TimeA >= TaskAtime) //Is it time to run Task A?
  {
    TimeA = millis();                 //Re-initialize
    TaskA();
  } 

  //==================
  if (millisNow - TimeB >= TaskBtime) //Is it time to run Task B?
  {
    TimeB = millis();                 //Re-initialize
    TaskB();
  }  

//==================
  if (millisNow - TimeC >= TaskCtime) //Is it time to run Task B?
  {
    TimeC = millis();                 //Re-initialize
    TaskC();
  }  
 // calibrate during the first five seconds 
       while (millis() < 5000) 
         sensorValue = analogRead(sensorPin);

    // record the maximum sensor value
    if (sensorValue > sensorMax) 
      sensorMax = sensorValue;
    

    // record the minimum sensor value
    if (sensorValue < sensorMin) 
      sensorMin = sensorValue;
    


} 


// FUNCTIONS

void TaskA()
{
  // in case you are not using the interrupt above, you'll
  // need to 'hand query' the GPS, not suggested :(
  if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) UDR0 = c;
      // writing direct to UDR0 is much much faster than Serial.print 
      // but only one character can be written at a time. 
  }
  

  if (GPS.newNMEAreceived()) {

  
    GPS.parse(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
    if (GPS.hour) 
 
   {   
   gpsTime = (((GPS.hour) *100)+ GPS.minute);
     if (gpsTime < 10, '0'); 

 }
}

    Serial.println();
    utc = now();
printTime(usET.toLocal(utc, &tcr), tcr -> abbrev, " New York");
}

//Function to return the compile date and time as a time_t value
time_t compileTime(void)
{
#define FUDGE 25        //fudge factor to allow for compile time (seconds, YMMV)

    char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
    char chMon[3], *m;
    int d, y;
    tmElements_t tm;
    time_t t;

    strncpy(chMon, compDate, 3);
    chMon[3] = '\0';
    m = strstr(months, chMon);
    tm.Month = ((m - months) / 3 + 1);

    tm.Day = atoi(compDate + 4);
    tm.Year = atoi(compDate + 7) - 1970;
    tm.Hour = atoi(compTime);
    tm.Minute = atoi(compTime + 3);
    tm.Second = atoi(compTime + 6);
    t = makeTime(tm);
    return t + FUDGE;        //add fudge factor to allow for compile time
}

//Function to print time with time zone
void printTime(time_t t, char *tz, char *loc)
{
    Serial.print(" GPS Time: "); 
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println();
    matrix1.print((hour(t) *100)+ minute(t));
      if(hour(t) *100 < 10)
     matrix1.writeDigitNum(0, 0);
      if(hour(t) *100 < 1)
      matrix1.writeDigitNum(1, 0);
       if(minute(t) < 10)
      matrix1.writeDigitNum(3, 0);
      matrix1.writeDigitNum(0x02, true);
    matrix1.writeDisplay();
    matrix2.print((GPS.speed),1);
    sPrintI00(hour(t));
    sPrintDigits(minute(t));
    sPrintDigits(second(t));
    Serial.print(' ');
    Serial.print(weekday(t));
    Serial.print(' ');
    sPrintI00(day(t));
    Serial.print(' ');
    Serial.print(month(t));
    Serial.print(' ');
    Serial.print(year(t));
    Serial.print(' ');
    Serial.print(tz);
    Serial.print(' ');
    Serial.print(loc);
    Serial.println();
}

void sPrintI00(int val)
{
    if (val < 10) Serial.print('0');
    Serial.print(val, DEC);
    return;
}

void sPrintDigits(int val)
{
    Serial.print(':');
    if(val < 10) Serial.print('0');
    Serial.print(val, DEC);
}

//==================
void TaskB()
{
unsigned long currentMillis = millis();
  // read the sensor: 
     sensorValue = analogRead(sensorPin);
  // apply the calibration to the sensor reading
     sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);
  // in case the sensor value is outside the range seen during calibration
     sensorValue = constrain(sensorValue, 0, 255);
  
  if(currentMillis >= interval); 
    // save the last time you udated LED setBgightness command
    previousMillis = currentMillis; 
    
    if (previousMillis > interval)
        previousMillis = 0;
        matrix1.setBrightness((sensorValue) / 16);
        matrix2.setBrightness((sensorValue) / 16);
        matrix3.setBrightness((sensorValue) / 16);
        matrix4.setBrightness((sensorValue) / 16);
}

//==================
void TaskC()
{
 light = analogRead(LIGHTPIN);
 
  matrix3.print(DHT11.getFahrenheit(), 1);
  matrix3.writeDisplay();
  matrix4.print(DHT11.getHumidity(), 1);
  matrix4.writeDisplay();
  delay(500);
}

What do you think this line in setup() does:

setTime(usET.toUTC(compileTime()));  // World Clock Setting

Lots of GPS clocks use poor GPS modules or some only turn on the GPS periodically to set a crystal RTC. Many GPS libraries force a 3D lat/Lon lock before passing the time/date. But time/caste dies not require GPS position lock!

I modified the Adafruit GPS lib to only provide time/date info. It does this very quickly... By not requiring a lock, I easily get GPS signal in my basement during the worst storms!

http://forum.arduino.cc/index.php?topic=199216.0
Or
http://www.hackster.io/rayburne/5-billion-arduino-gps-clock-for-25

Should the setTime() command be in the void loop and not in the void setup?

What I am getting, when I originally load the Sketch, all is working fine. If I remove power from the Arduino, then the time is off by how ever long the Arduino is off. This leads me to believe, on rebooting, the setTime command is being read and applied before any of the GPS reads are excited in the void loop.

Great idea to skip the requirement for a GPS lock Ray!

setTime(usET.toUTC(compileTime()));

To me, this looks like the default time is set (once, at startup) to the time when the code was most recently compiled.

I believe that the World Clock Sketch that I have been using to base the TimeZone and EDT setting was written to use an RTC. Here I am using a GPS, so I think that I will need to change some commands to pull the time from the GPS….

I guess you could say, I'm SLOWLY learning….

Thanks for the input guy's…..

I looked a bit further in the code you posted, and it contains this function to produce the "compile time" from the current time and date in the PC running the Arduino IDE, which is then used to set the clock at startup. You can safely eliminate all this code, and in setup() initialize the clock display some arbitrary time, perhaps all zeros.

//Function to return the compile date and time as a time_t value
time_t compileTime(void)
{
#define FUDGE 25        //fudge factor to allow for compile time (seconds, YMMV)

    char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
    char chMon[3], *m;
    int d, y;
    tmElements_t tm;
    time_t t;

    strncpy(chMon, compDate, 3);
    chMon[3] = '\0';
    m = strstr(months, chMon);
    tm.Month = ((m - months) / 3 + 1);

    tm.Day = atoi(compDate + 4);
    tm.Year = atoi(compDate + 7) - 1970;
    tm.Hour = atoi(compTime);
    tm.Minute = atoi(compTime + 3);
    tm.Second = atoi(compTime + 6);
    t = makeTime(tm);
    return t + FUDGE;        //add fudge factor to allow for compile time
}

jimallen60:
I believe that the World Clock Sketch that I have been using to base the TimeZone and EDT setting was written to use an RTC. Here I am using a GPS, so I think that I will need to change some commands to pull the time from the GPS….
I guess you could say, I'm SLOWLY learning….
Thanks for the input guy's…..

Yes.
But "commands" as you say are actually functions in a library or your code. The Adafruit GPS library provides functions for you to use directly!
Ladyada already did the work for you:

ode:
/*
Originally based on Adafruit example sketch: "parsing"
Utilizes the Adafruit_GPS library https://github.com/adafruit/Adafruit-GPS-Library
20131115: GPS_Parsing_Test
  Heavily mucked by M. Ray Burnette to simply use (most) any dumb serial TTL GPS for time-date
  Tested with ancient #28146 Parallax module
  Arduino 1.0.5:

  Program:    9090 bytes
  (.text + .data + .bootloader)

  Data:        754 bytes
  (.data + .bss + .noinit)
*/

#include "Adafruit_GPS.h"
#include <SoftwareSerial.h>
#include <Streaming.h>

//   Connect the GPS TX (transmit) pin to Digital 3
SoftwareSerial mySerial(3, 2);

Adafruit_GPS GPS(&mySerial);

// Set GPSDEBUG to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
// Could be as simple as checking a digital pin to-Gnd state
#define GPSDEBUG  false  // should be a check of a digital pin to Gnd

uint8_t last_seconds ;
uint8_t TimeZoneHour = -5 ;  // needs to be a pin-to-ground adjustment for DST
uint8_t LocalHour ;

void setup()  
{
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  Serial.begin(115200);
  Serial.println("GPS time-date:");
  // Some GPS are 4800 and some are 9600 or faster
  GPS.begin(4800);
  delay(1000);
  // Add a DST check of a digital pin for DayLightSavingTime or
  // Use multiple digital pins to set any TimeZone
}


void loop()
{
    // read data from the GPS
    char c = GPS.read();
    if (GPSDEBUG)  // Raw character echo to monitor
      if (c) Serial.print(c);

  // if a sentence is received, check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // return to top of loop() if sentence does not verify correctly or completely
  }

  // BIG if() active only once per second since this sketch is time-date focused
  if (last_seconds != GPS.seconds) {    last_seconds = GPS.seconds;
    LocalHour = GPS.hour + TimeZoneHour;
    Serial.print("\nTime: ") ;
    Serial << ((LocalHour<10)?"0":"") ; 
    Serial.print(LocalHour, DEC); 
    Serial << (':') ;
    Serial << ((GPS.minute<10)?"0":"") ;
    Serial.print (GPS.minute, DEC); 
    Serial << (':') ;
    Serial << ((GPS.seconds<10)?"0":"") ;
    Serial.print(GPS.seconds, DEC) ;

    Serial.print("\nDate: ");
    Serial << ((GPS.day<10)?"0":"") ;
    Serial.print(GPS.day, DEC) ;              //DD
    Serial << "/" << ((GPS.month<10)?"0":"") ;
    Serial.print(GPS.month, DEC) ;            //MM
    Serial << "/20" ;
    Serial.println(GPS.year, DEC) ;           //YYYY