I put together a GPS clock using an Arduino Pro-Mini, AI-Thinker GP-02-Kit GPS module and LCD display. I display the Time in hours/minutes/seconds AM/PM, plus the Date in day/month/date. The problem is the Day and Date display changes to the next day at 5pm, not at midnight. The sketch is attached.
// *CONSTANTS & DECLARATIONS*
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
// *TIMEZONE SWITCH*
const int timeZoneSwitchPin = A3; // Analog pin A3 for PST-DST switch
bool isPST = false; // Flag to track whether in PST or PDT time zone
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // LCD connections
const int lcdColumns = 16;
const int lcdRows = 2;
static const int RXPin = 9, TXPin = 8;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps; // The TinyGPSPlus object
SoftwareSerial ss(RXPin, TXPin); // Serial Connection to GPS module
// UTCTime is the first term in $GNZDA (1)
// *TinyGPSCustom customField(gps, "Nmea Sentence", 1);*
TinyGPSCustom customUTCTime(gps, "GNZDA", 1);
const char* daysOfWeek[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
const char* months[] = {"", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
// *FUNCTION*
void print12HourFormat(int hour, int minute, int second) {
char amPm[] = "AM ";
if (hour >= 12) {
amPm[0] = 'P';
if (hour > 12) {
hour -= 12;
}
}
if (hour == 0) {
hour = 12;
}
// *PRINT TIME TO SERIAL PRINTER*
Serial.print("Pacific Daylight Time: ");
Serial.print(hour);
Serial.print(":");
if (minute < 10) {
Serial.print("0");
}
Serial.print(minute);
Serial.print(":");
if (second < 10) {
Serial.print("0");
}
Serial.print(second);
Serial.print(" ");
Serial.println(amPm); // New line
// *PRINT TIME TO LCD*
lcd.setCursor(3, 0);
lcd.print(hour);
lcd.print(":");
if (minute < 10) {
lcd.print("0");
}
lcd.print(minute);
lcd.print(":");
if (second < 10) {
lcd.print("0");
}
lcd.print(second);
lcd.print(" "); // Print AM/PM right beside seconds-SEE LINE 42
lcd.print(amPm);
}
//Zeller's Congruence algorithm - calculates the day of the week for any canlendar date.
int calculateDayOfWeek(int year, int month, int day) {
if (month < 3) {
month += 12;
year -= 1;
}
int k = year % 100;
int j = year / 100;
// Adjust for leap year - Turn on later...
/*if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
day -= 2;
}
*/
int dayOfWeek = (day + 13 * (month + 1) / 5 + k + k / 4 + j / 4 + 5 * j) % 7;
return (dayOfWeek + 6) % 7;
// Adjust for the weekday array indexing
}
void printDate(int year, int month, int day, int timeZoneOffset) {
int calculatedDayOfWeek = calculateDayOfWeek(year, month, day);
lcd.setCursor(3, 1);
lcd.print(daysOfWeek[calculatedDayOfWeek]);
lcd.print(" ");
lcd.print(months[month]);
lcd.print(" ");
lcd.print(day);
}
void setup() {
Serial.begin(115200);
ss.begin(GPSBaud);
// *TIMEZONE SWITCH*
pinMode(timeZoneSwitchPin, INPUT_PULLUP); // For PST to DST switch on A3
// *PRINT INTRO TO LCD*
lcd.begin(lcdColumns, lcdRows);
lcd.setCursor(0, 0); // Position 1, Top Line
lcd.print("<< GPS CLOCK >> ");
lcd.setCursor(0, 1); // Position 0, Bottom Line
lcd.print("by: Arduino Fan");
delay(4000);
lcd.clear();
Serial.println("#####################################################");
Serial.println(F(" Sketch: GPS_NEW_ATOMIC_CLOCK_19AUG2023_LCD_DATE.ino"));
Serial.println(F(" Compiled by expermenter 20 AUGUST 2023"));
Serial.print(F(" Using TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
Serial.println("#####################################################");
delay(2000);
}
void loop() {
while (ss.available() > 0) {
gps.encode(ss.read());
}
// Print everyting every time anything is updated.
if (gps.altitude.isUpdated() || customUTCTime.isUpdated() || gps.date.isUpdated() || gps.satellites.isUpdated()) {
// ##### *TIMEZONE SWITCH* ##### Read the state of the time zone switch
bool switchState = digitalRead(timeZoneSwitchPin);
// Check if the switch state has changed
if (switchState != isPST) {
isPST = switchState;
Serial.print("Time zone switched to: ");
Serial.println(isPST ? "PST" : "PDT");
}
// Determine time zone offset based on the switch state
int timeZoneOffset = isPST ? 8 : 7;
// ##### *TIMEZONE SWITCH END* #####
// ##### Call the 12-hour time print function with PST offset #####
if (customUTCTime.isUpdated()) {
int hour, minute, second;
if (sscanf(customUTCTime.value(), "%2d%2d%2d", &hour, &minute, &second) == 3) {
// Convert to Pacific Standard Time (PST) from UTC time (UTC - 8 hours)
hour = (hour - timeZoneOffset + 24) % 24; //Change 7-8 for standard time (PST)
// ##################### PRINT TIME TO LCD #############################
print12HourFormat(hour, minute, second);
}
int year = gps.date.year();
int month = gps.date.month();
int day = gps.date.day();
//printDate(year, month, day);
printDate(year, month, day, timeZoneOffset);
}
}
} /* END OF LOOP */