## Lab: Precision GPS Clock Build a clock using GPS time signals and an LCD display. **Background:** GPS provides atomic-clock accuracy (~10 ns). Adjust for local timezone. **Libraries:** - TinyGPS++ (Mikal Hart): [GitHub](https://github.com/mikalhart/TinyGPSPlus) - LiquidCrystal (UNO R3): Built-in. - Time (Paul Stoffregen): [GitHub](https://github.com/PaulStoffregen/Time) **Required Hardware:** - GY-NEO6MV2 - Lonely Binary UNO R3 - 1602 LCD **Wiring:** | GY-NEO6MV2 | Lonely Binary UNO R3 | |------------|----------------| | VCC | 5V | | GND | GND | | TX | 2 | | RX | 3 | | LCD 1602 | Lonely Binary UNO R3 | |----------|----------------| | VCC | 5V | | GND | GND | | RS | 7 | | EN | 8 | | D4 | 12 | | D5 | 11 | | D6 | 10 | | D7 | 9 | **Code:** ```cpp #include
#include
#include
#include
#include
const int offset = 11; // Local Time Zone (e.g., UTC+11 for Sydney)
const int rs = 7, en = 8, d4 = 12, d5 = 11, d6 = 10, d7 = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int rx = 2, tx = 3, gpsBaud = 9600;
SoftwareSerial ss(rx, tx);
TinyGPSPlus gps;
time_t prevDisplay = 0;
uint32_t lastUpdateMillis = 0;
void showWelcome() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("== GPS CLOCK ==");
lcd.setCursor(0, 1);
lcd.print(" Initializing..");
}
void showLCDClock() {
String strHour = hour() < 10 ? "0" + String(hour()) : String(hour());
String strMinute = minute() < 10 ? "0" + String(minute()) : String(minute());
String strSecond = second() < 10 ? "0" + String(second()) : String(second());
String strMonth = month() < 10 ? "0" + String(month()) : String(month());
String strDay = day() < 10 ? "0" + String(day()) : String(day());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(strHour + ":" + strMinute + ":" + strSecond + " ");
lcd.setCursor(0, 1);
lcd.print(strMonth + "/" + strDay + "/" + year() + " ");
}
void showLastUpdate() {
unsigned long age = millis() - lastUpdateMillis;
lcd.setCursor(0, 1);
lcd.print("LAST UPD: ");
if (age < 1000) {
lcd.print("NOW ");
} else if (age < 60000) {
lcd.print(String(age / 1000) + "S AGO");
} else if (age < 3600000) {
lcd.print(String(age / 60000) + "M AGO");
} else if (age < 86400000) {
lcd.print(String(age / 3600000) + "H AGO");
} else {
lcd.print("TAKE OUTSIDE!");
}
}
void setup() {
lcd.begin(16, 2);
showWelcome();
ss.begin(gpsBaud);
}
void loop() {
while (ss.available() > 0) {
if (gps.encode(ss.read())) {
if (gps.date.isValid() && gps.time.isValid()) {
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(),
gps.date.day(), gps.date.month(), gps.date.year());
adjustTime(offset * SECS_PER_HOUR);
lastUpdateMillis = millis();
}
}
}
if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) {
prevDisplay = now();
showLCDClock();
showLastUpdate();
}
}
}
```
**Code Explanation:**
- `setTime()`/`adjustTime()`: Sets and offsets time using Time library.
- Ternary operators ensure two-digit formatting.
- `millis()` tracks updates; UNO R3 uses it for internal timing (rolls over after ~50 days).
**Results:** LCD shows local time and last GPS update.
**Tips:** For standalone clocks, add RTC (e.g., DS3231) for backup.
**Related Information:** GPS time is leap-second adjusted; compare with NTP for network syncing.
- Choosing a selection results in a full page refresh.