I completed a GPS CLOCK project 24th of August 2020
I used M. Ray Burnette clock plan that was origanally posted on Hackster.io, but since removed.
The GPS module I used was hacked from an EAGLE Fish Elite 502c Marine GPS map plotter.
I modified the sketch for a Arduino Pro-Mini to read the Eagles 4800 baud serial data stream ($GPGGA sentence).
The clock worked flawlessly displaying TIME (hours & minutes), the MONTH and DATE, plus the DAY of the week.
Now, the clock still correctly deplays the Hours and Minutes (AM or PM) plus the Day of the week,
but does NOT display the correct Month and Date. However the DATE does increment each day.
To troubleshoot, I checked the circuit wiring and power, and updated the Adafruit_GPS.h library then reloaded the sketch to Arduino Pro-Mini (GitHub - adafruit/Adafruit_GPS: An interrupt-based GPS Arduino library for no-parsing-required use)
The Problem is still there! Does anyone have suggestions to fix this?
HERE IS THE SKETCH:
// FILENAME: GPS_ATOMIC_CLOCK.ino
// Uploaded to finished clock project 24th of August 2020. Worked Great!
// ##################################################################################
// 21SEPT2022 * Two years after working fine, it stared to display incorrect Month and Date,
// but TIME HOURS & MINTES plus DAY was correct??? I checked the circuit wiring and power but ok,
// I then reloaded the sketch but it did not fix the problem?
// Display Error: THUR SEPT 28 read THUR FEB 13
//
// 21APRIL2023 * The clock display still shows incorrect Month and Date.
// Display Error: FRI APRIL 21 reads FRI SEP 05.
// I updated the Adafruit_GPS.h library and reloaded the code to Arduino Pro-Mini,
// but did not fix the problem!
// ##################################################################################
/*
https://www.hackster.io/rayburne/5-billion-arduino-gps-clock-for-25-496a20
Uses Adafruit_GPS library https://github.com/adafruit/Adafruit-GPS-Library
-by M. Ray Burnette, modified Aug/2020 by F.W.McLennan
This sketch finds GMT time using a GPS module hacked from an
EAGLE Fish Elite 502c, but any gps module should work fine.
Module sends its 4800 baud serial data stream to Arduino UNO
which parces time information and sends it to 16X2 LCD display
An internal jumper changes the time for Daylight Savings Time,
GMT to PDT (Pacific daylight time) and PST (Pacific Standard Time)
The GPS module is hooked up to Arduino pins 9(RX) and 8(TX).
GPS module draws 65mA@3.3v, so needs seperate Power Supply.
*/
#include "Adafruit_GPS.h"
#include "Utilities.h"
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <Streaming.h>
// Connect the GPS TX (transmit) to Arduino Digital pin D9 (RX).
SoftwareSerial mySerial(9, 8) ; // Arduino Rx, Tx
Adafruit_GPS GPS(&mySerial) ;
uint8_t last_seconds ;
uint8_t TimeZoneHour = 8; // Affected as -1 for DST (PDT)
uint8_t LocalHour ;
uint8_t LocalMinute ;
uint8_t LocalSecond ;
uint8_t LocalMonth ;
uint8_t LocalDay ;
uint8_t LocalYear ;
byte nRow; // line count
byte nColumn; // character count
boolean PM ;
boolean DST ; // Daylight Savings Time: Pin A3 DST = LOW, Std time = HIGH
boolean OnOff ; // LED status
boolean FirstTime ; // Before satellite time is available via $GPRMC
boolean GPSDEBUG ; // set by digital pin D11
// ***** CODE ERROR REPAIR *****
// I added const in the follwing line, which fixed a compile error.
char* const PROGMEM BlankLine[] = {" "}; // fifteen spaces
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
//*****************************************************
void setup()
{
lcd.begin(16, 2) ; // standard 1602 parallel, 2 lines by 16 characters
// analogReference(DEFAULT); Default is either 5v or 3.3v depending on cpu used.
FirstTime = true ; // Virgin state of GPS software variables
// -------------------------------------------------------------------
//328 Log Arduino
//Pin Port RefName Signal usage for GPS time-date
//___ ___ _______ _______________________________________________
// 15 PB1 (D 9) GPS serial input @BAUD
// 16 PB2 (D 10) BAUD (hi = 9600 lo = 4800)
// 17 PB3 (D 11) DEBUG (hi = OFF lo = on)
// 18 PB4 (D 12) F/C MODE (hi = F lo = C)
// 19 PB5 (D 13) LED Cycle On-Off at 1 second
// 23 PC0 (A 0) Junction of 10K NTC Thermistor & 10k Resistor
// 26 PC3 (A 3) Digital - Daylight Savings Time (Lo = True)
pinMode( A3, INPUT) ; // DST hi = NO low = YES
digitalWrite( A3, HIGH); // turn on pullup resistor
pinMode( 10, INPUT) ; // BAUD hi = 9600 lo = 4800
digitalWrite( 10, HIGH); // turn on pullup resistor
pinMode( 11, INPUT) ; // GPSDEBUG
digitalWrite( 11, HIGH); // turn on pullup resistor
// pinMode( 12, INPUT) ; // F/C temperature display NOT USED
// digitalWrite( 12, HIGH); // turn on pullup resistor
pinMode( 13, OUTPUT) ; // Standard Arduino LED for status
OnOff = false ;
digitalWrite(13, OnOff) ;
if ( digitalRead(11) ) { // D11 low for GPS Debug mode echo to terminal
GPSDEBUG = false ; // Default
} else {
GPSDEBUG = true ;
Serial.begin(115200) ; // connect at 115200 debug output to console
}
if ( digitalRead(10) ) { // D10 high for 9600 BAUD GPS module
GPS.begin(9600) ; // Default
if (GPSDEBUG) Serial << "9600 BAUD \n \r" ;
} else {
GPS.begin(4800) ;
if (GPSDEBUG) Serial << "4800 BAUD \n \r" ;
}
if ( digitalRead(A3) ) { // A3 low for Daylight Savings Time
DST = false ; // Default
if (GPSDEBUG) Serial << "DST = NO \n \r" ;
} else {
DST = true ;
if (GPSDEBUG) Serial << "DST = YES \n \r" ;
TimeZoneHour = TimeZoneHour - 1 ;
}
if (GPSDEBUG) Serial.println("GPS time-date Debug Display:") ;
lcd.setCursor(0, 0); lcd << BlankLine[0] ; // clear upper row
lcd.setCursor(0, 1); lcd << BlankLine[0] ; // clear lower row
lcd.setCursor(0, 0); // Position 1, Top Line
lcd.print("GPS ATOMIC CLOCK");
lcd.setCursor(0, 1); // Position 0, Bottom Line
lcd.print("by Fred McLennan");
delay(3000) ; // credits
}
//*****************************************************
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
}
PM = false ;
// BIG if() active only once per second after GPS decodes new GPS.seconds
// ... then fall through and update the LCD
if (last_seconds != GPS.seconds) {
FirstTime = false; // GPS signal decoding has come on line since uC reset
OnOff = !OnOff ; // Status LED
digitalWrite(13, OnOff) ; // Blink LED
last_seconds = GPS.seconds ;
LocalHour = GPS.hour ;
LocalMinute = GPS.minute ;
LocalSecond = GPS.seconds ;
LocalMonth = GPS.month ;
LocalDay = GPS.day ;
LocalYear = GPS.year ;
if (LocalHour >= TimeZoneHour) {
LocalHour = LocalHour - TimeZoneHour ;
} else {
// Correct for period when London is a day ahead
LocalHour = (LocalHour + 24) - TimeZoneHour ;
LocalDay = LocalDay - 1 ;
if ( LocalDay == 0)
{
LocalDay = DaysInMonth[ LocalMonth - 1] ; // 0 - 11
LocalMonth = LocalMonth - 1 ; // January in London still December Westward
if ( LocalMonth == 0) // GPS months are 01 through 12
{
LocalMonth = 12 ;
LocalDay = DaysInMonth[ 11 ] ; // lastday of December
}
// Need to deal with LocalMonth = 2 and leapyear
if ( LocalMonth == 2 && (LocalYear % 4) ) LocalDay = LocalDay + 1 ;
}
}
if (LocalHour >= 12)
{
PM = true ;
if (LocalHour > 12) LocalHour = LocalHour - 12 ;
}
//************************************************************
// PRINT TIME TO LCD
lcd.setCursor(0, 0) ;
lcd.print(" ") ; //Clear positions 0 - 2
lcd.setCursor(3, 0) ;
if (LocalHour < 10) lcd.print(" ") ; // position 3
lcd.print(LocalHour) ; // positions 3, 4
lcd.setCursor(5, 0) ;
lcd.print(":") ; // position 5
lcd.setCursor(6, 0) ;
if (LocalMinute < 10) {
lcd.print("0") ; // position 6
lcd.print(LocalMinute) ; // position 7
} else {
lcd.print(LocalMinute) ; // positions 6, 7
}
lcd.setCursor(8, 0) ;
lcd.print(" ") ; //Clear position 8
// STOP PRINTING SECONDS
/*
// cd.setCursor(5, 0) ;
// lcd.print(":") ; // position 5
// lcd.setCursor(6, 0) ;
// if (LocalSecond < 10) {
// lcd.print("0") ; // position 6
//lcd.print(LocalSecond) ; // position 7
} else {
lcd.print(LocalSecond) ; // positions 6, 7
}
*/
// PRINT AM/PM
if (PM) {
if (DST) {
lcd.print("PM *") ; // positions 10 & 11
} else {
lcd.print("PM ") ;
}
} else {
if (DST) {
lcd.print("AM *") ; // positions 8 - 14
} else {
lcd.print("AM ") ;
}
}
//************************************************************
// PRINT DATE TO LCD
// Day-Of-Week, and Month and Date info is shown every 10 seconds
if ((LocalSecond % 10) == 0) {
lcd.setCursor(0, 1) ;
lcd.print(" ") ; // clear positions 0 - 3
lcd.setCursor(3, 1); // LOWER line
lcd.print(DayOfWeek[dow(LocalYear, LocalMonth, LocalDay)]) ; // positions 3 - 5
lcd.print(" "); // postition 6
lcd.setCursor(7, 1) ;
lcd.print(NameOfMonth[LocalMonth - 1]) ; // positions 7 - 9
lcd.setCursor(10, 1) ;
lcd.print(" ") ; // position 10
lcd.setCursor(11, 1) ;
if (LocalDay < 10) {
lcd.print("0") ; // position 11
lcd.print(LocalDay) ;
} else {
lcd.print(LocalDay) ; // positions 11, 12
}
lcd.setCursor(13, 1) ;
lcd.print(" ") ; // position 13 - 15
// DO NOT DISPLAY YEAR
/*
lcd.setCursor(13, 1) ;
lcd.print(LocalYear) ; // positions 13, 14
lcd.print(" ") ; // position 15
*/
}
//************************************************************
if (GPSDEBUG) {
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
}
} else { // GPS must lock on before clock works.
if (FirstTime) {
lcd.setCursor(0, 0); // Position 2, Top Line
lcd.print("Initializing GPS"); //gps coordinates
lcd.setCursor(0, 1); // Position 0, Bottom Line
lcd.print("Wait +/- 15 Min.");
}
}
} // loop end