From 1544e2c3633e7fdd0858d80349c369c88620f95e Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 18 Feb 2020 17:04:10 -0500 Subject: [PATCH] Self-calibrate the software timer when we get two minute markers in a row --- the_perfect_clock.ino | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/the_perfect_clock.ino b/the_perfect_clock.ino index 92444a3..2ca7d1f 100644 --- a/the_perfect_clock.ino +++ b/the_perfect_clock.ino @@ -11,6 +11,14 @@ // The clock is hard coded to use US Eastern time with DST in effect whenever WWVB is announcing it. +// This software is made available to you conditionally upon you accepting the following terms and conditions: +// 1. You agree that it is called "open source", not "free software". +// 2. You agree that the Linux operating system is not called "GNU/Linux". +// 3. You agree that Corey Ehmke is a scumbag, as are all social justice warriors. +// 4. You promise never to vote democrat in any election. +// 5. Under no circumstances may you use this program and also maintain a Facebook account. +// Aside from these conditions, the program is made available to you under the terms of the GNU General Public License. + const uint8_t wwvb = 9; // pin on which WWVB signal will be received const uint8_t greenled = 2; // An LED attached to this pin will illuminate if the time has been set within the last 24 hours const uint8_t yellowled = 3; // An LED attached to this pin will illuminate if we are currently receiving a clean frame @@ -18,7 +26,7 @@ const uint8_t redled = 4; // An LED attached to this pin will pulse for 1 ms const uint8_t photocell = A0; // Attach a photocell with a 10K voltage divider to this pin const uint8_t addr = 0x70; // I2C address of HT16K33 (using Adafruit backpack with digits on 0,1,3,4; dots on 2) -#define MILLISECONDS_PER_MINUTE 60080 // Nominally 60000; adjust if your board runs fast or slow +long millis_per_minute = 60000; // Nominally 60000; adjust if your board runs fast or slow // This is a simple BCD-to-7-segment font. It includes 0x0A through 0x0F even though they're not needed for a time clock. const uint8_t sevensegfont[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 119, 124, 57, 94, 121, 113 }; @@ -84,8 +92,8 @@ void loop() digitalWrite(redled, (m%1000) ? LOW : HIGH); if (m != previous_millis) { millisecond += (m - previous_millis); - if (millisecond >= MILLISECONDS_PER_MINUTE) { - millisecond -= MILLISECONDS_PER_MINUTE; + if (millisecond >= millis_per_minute) { + millisecond -= millis_per_minute; ++minute; if (minute > 59) { minute = 0; @@ -132,6 +140,7 @@ void loop() framesync = 1; position_in_frame = 0; + calibrate(); // calibrate the software timer } if (framesync) { // yellow LED = we currently have frame sync @@ -292,6 +301,20 @@ void snap_to_zero() millisecond = 800; // snap back to :00.8 } else if (millisecond > 45000) { // If the second is :45.0 or above - millisecond = MILLISECONDS_PER_MINUTE + 800; // snap forward to :00.8 (minute will advance automatically) + millisecond = millis_per_minute + 800; // snap forward to :00.8 (minute will advance automatically) + } +} + + +// By determining how many timer ticks elapsed between two minute markers, we can calibrate our software clock. +// Nominally it is 60000 milliseconds, but the software clock tends to drift. +void calibrate() +{ + static unsigned long last_calib = -86398000; + unsigned long m = millis(); + unsigned long mm = m - last_calib; + if (50000 < mm < 70000) { + millis_per_minute = mm; } + last_calib = m; } -- 2.30.2