matt448 / gps_rtc_clock Goto Github PK
View Code? Open in Web Editor NEWArduino based nightstand clock that uses GPS and an RTC for timekeeping.
Arduino based nightstand clock that uses GPS and an RTC for timekeeping.
Hi. I've tried to build a clock based on your code; to get a better grasp of it I left only a "skeleton". Surprisingly, my RTC gets correctly set, but then the clock starts to run late - every second it gets behind the actual time. Here is the log with timestamps enabled:
02:03:07.024 -> ---RTC TIME---
02:03:07.024 -> UTC: 2019/6/23 23:3:6
02:03:07.024 -> RTC has set the system time
02:03:07.024 -> 2:03:06
02:03:07.278 -> GPS not ready yet. Waiting for fix. Sat count: 0
02:03:07.646 -> GPS not ready yet. Waiting for fix. Sat count: 10
02:03:07.856 -> New boot. Need to update RTC with GPS time. Sat count: 10
02:03:07.856 -> Setting RTC from GPS
02:03:07.856 ->
02:03:07.856 -> RTC set from GPS
02:03:08.227 -> 2:03:07
02:03:09.461 -> 2:03:08
02:03:10.982 -> 2:03:09
02:03:12.174 -> 2:03:10
02:03:13.341 -> 2:03:11
02:03:14.646 -> 2:03:12
02:03:16.096 -> 2:03:13
02:03:17.274 -> 2:03:14
02:03:18.541 -> 2:03:15
Notice that it was off by a second in the first line, but in 10 seconds it was behind by 3 seconds.
Here is my "skeleton" code:
#include "RTClib.h" //https://github.com/adafruit/RTClib
#include <DS1307RTC.h> //https://github.com/PaulStoffregen/DS1307RTC
#include <Time.h> //https://github.com/PaulStoffregen/Time
#include <Timezone.h> //https://github.com/JChristensen/Timezone
#include <TinyGPS++.h> //https://github.com/mikalhart/TinyGPSPlus
#include <SoftwareSerial.h>
#include <Wire.h>
// Serial config for the GPS module
static const int RXPin = 3, TXPin = 13;
static const uint32_t GPSBaud = 4800;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial GPS_Serial(RXPin, TXPin);
RTC_DS1307 rtc;
bool rtcSet = false;
//Timezone stuff
TimeChangeRule msk = {"MSK", Last, Sun, Mar, 1, 180}; // 3 * 60 = 180 minutes between UTC and Moscow
Timezone tzMSK(msk);
TimeChangeRule *tcr; //pointer to the time change rule, use to get TZ abbrev
time_t utc, local;
//variables for time counting
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long syncTimer = 0;
unsigned long scheduledTimer = 0;
bool newboot = true;
int prevSecond = 0; // for debugging
////////////////////////////////////
// SETUP
////////////////////////////////////
void setup() {
Serial.begin(115200);
GPS_Serial.begin(GPSBaud);
if (! rtc.begin()) {
Serial.println(F("Couldn't find RTC"));
while (1);
}
if (! rtc.isrunning()) {
Serial.println(F("RTC is NOT running!"));
// following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
checkRTCset();
Serial.println();
Serial.println("---RTC TIME---");
DateTime now = rtc.now();
Serial.print("UTC: ");
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus()!= timeSet) {
Serial.println(F("Unable to sync with the RTC"));
} else {
Serial.println(F("RTC has set the system time"));
}
}
////////////////////////////////////
// MAIN LOOP
////////////////////////////////////
void loop() {
currentMillis = millis();
if(!rtcSet){
Serial.println(F("RTC not set"));
setRTCfromGPS();
checkRTCset();
}
// Read GPS data from serial connection until no more data is available
while (GPS_Serial.available() > 0) {
gps.encode(GPS_Serial.read());
}
if (currentMillis > 5000 && gps.charsProcessed() < 10) {
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
utc = now(); // Grab the current time
//printTime(utc, "UTC");
local = tzMSK.toLocal(utc, &tcr);
//printTime(local, tcr -> abbrev);
syncOnBoot();
// Show clock
DisplayTime();
//Syncs GPS time to the RTC regularly.
scheduledSync();
}
////////////////////////////////////
// FUNCTIONS
////////////////////////////////////
void DisplayTime() {
if(!rtcSet) {
Serial.println(F("Waiting for GPS Fix"));
}else{
if (second(local) != prevSecond){
Serial.print(hour(local));
padZero(minute(local));
padZero(second(local));
Serial.println();
}
prevSecond = second(local);
}
}
void checkRTCset() {
DateTime now = rtc.now();
if(now.hour() == 0 && now.minute() == 0 && now.second() == 0 && now.year() < 2010)
{
Serial.println(F("*** RTC TIME NOT SET. ***"));
Serial.println();
}else{
rtcSet = true;
Serial.println(F("RTC TIME SET."));
Serial.println();
}
}
void syncOnBoot() {
if(newboot) {
int satcount = gps.satellites.value();
if (gps.date.isValid() && gps.time.isValid() && satcount > 4) {
Serial.print(F("New boot. Need to update RTC with GPS time. Sat count: "));
Serial.println(satcount);
setRTCfromGPS();
newboot = false;
syncTimer = 0;
} else {
if(currentMillis > (syncTimer + 250)) {
Serial.print(F("GPS not ready yet. Waiting for fix. Sat count: "));
Serial.println(satcount);
syncTimer = currentMillis;
}
}
}
}
void setRTCfromGPS() {
/* This line sets the RTC with an explicit date & time:
rtc.adjust(DateTime(2000, 12, 31, 12, 59, 59));
*/
Serial.println("Setting RTC from GPS");
Serial.println();
if (gps.date.isValid() && gps.time.isValid()) {
rtc.adjust(DateTime(gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second()));
Serial.println(F("RTC set from GPS"));
} else {
Serial.println(F("No GPS fix yet. Can't set RTC yet."));
}
}
void scheduledSync() {
/*
* Re-syncs the RTC with the time stamp from the GPS data regularly.
*/
if(
(currentMillis > (scheduledTimer + 10000)) &&
newboot == false
){ // Only allow RTC sync to happen once every 10 sec
Serial.println(F("Regular scheduled sync about to proceed..."));
if(minute(local) == 50) {
Serial.println(F("Scheduled RTC sync from GPS Time."));
setRTCfromGPS();
}
//Serial.println(F("Adjusted Arduino time from RTC."));
//DateTime now = rtc.now();
scheduledTimer = currentMillis;
}
}
void padZero(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10) {
Serial.print('0');
}
Serial.print(digits);
}
I am really out of ideas. I will greatly appreciate your advice on what might be wrong with my code. Thanks in advance!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.