Reduced hysteresis to 3 samples. Expanded valid pulse width range.
[the_perfect_clock.git] / the_perfect_clock.ino
index f120ad15fe7b3944adec79193e4cb246882ce93d..25294922e37eb4ea9aae6ba721ffdb062b21e995 100644 (file)
@@ -1,6 +1,6 @@
 // "The Perfect Clock" 
 
-// Copyright (C) 2019-2022 by Art Cancro <ajc@citadel.org>
+// Copyright (C) 2019-2023 by Art Cancro <ajc@citadel.org>
 
 // My perfect clock has no buttons and cannot be set manually.  This version uses a WWVB receiver module
 // attached to pin D9 of the Arduino, and sets the clock any time it receives a complete frame.  The clock
 // 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.
 
+// On my clock, there is a green LED on 2, a yellow LED on 3, and a red LED on 4.
+
 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
-const uint8_t redled = 4;      // An LED attached to this pin will pulse for 1 ms every second
-const uint8_t boardled = LED_BUILTIN;
+const uint8_t last24led = 2;   // An LED attached to this pin will illuminate if the time has been set within the last 24 hours
+const uint8_t cleantimecodeled = LED_BUILTIN;  // An LED attached to this pin will illuminate if we are currently receiving a clean frame
+const uint8_t timecodeled = 3;
 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)
 
@@ -54,10 +55,9 @@ int time_is_set = 0;         // nonzero when time has been set at least once
 void setup() {
        int i;
 
-       pinMode(boardled, OUTPUT);      // The built-in LED will display the raw WWVB signal pulses
-       pinMode(greenled, OUTPUT);      // This LED will illuminate if the time has been set within the last 24 hours
-       pinMode(yellowled, OUTPUT);     // This LED will illuminate if we are currently receiving a clean frame
-       pinMode(redled, OUTPUT);        // This LED pulses for 1 ms every second
+       pinMode(timecodeled, OUTPUT);   // The built-in LED will display the raw WWVB signal pulses
+       pinMode(last24led, OUTPUT);     // This LED will illuminate if the time has been set within the last 24 hours
+       pinMode(cleantimecodeled, OUTPUT);      // This LED will illuminate if we are currently receiving a clean frame
        pinMode(wwvb, INPUT);   // Input pin for WWVB receiver signal
        pinMode(photocell, INPUT);      // Input pin for photocell
 
@@ -87,8 +87,12 @@ void setup() {
 // Note: only write to the display when the readout needs to be updated.
 // Speaking I2C on every loop iteration jams the WWVB receiver.
 void loop() {
+
+  // Reading it three times and taking the average gives us some hysteresis
+  int signal = (digitalRead(wwvb) + digitalRead(wwvb) + digitalRead(wwvb)) / 3;
+
+  // has the timer ticked?
        unsigned long m = millis();
-       digitalWrite(redled, (m % 1000) ? LOW : HIGH);
        if (m != previous_millis) {
                millisecond += (m - previous_millis);
                if (millisecond >= millis_per_minute) {
@@ -102,12 +106,17 @@ void loop() {
                                }
                        }
                }
-       }
+  }
        previous_millis = m;
 
        int pulse_length;
-       int signal = digitalRead(wwvb);                         // is the input high or low right now?
-       digitalWrite(boardled, signal);                 // use the onboard LED to show the signal
+
+  if (signal) {
+    analogWrite(timecodeled, 5);       // it's too bright on my board so we dim it; change to digitalWrite() if not needed
+  }
+  else {
+    digitalWrite(timecodeled, LOW);
+  }
 
        if (signal && (!previous_signal)) {                     // leading edge of pulse detected
                start_of_pulse = millis();
@@ -115,13 +124,13 @@ void loop() {
        else if ((!signal) && (previous_signal)) {              // trailing edge of pulse detected
                pulse_length = millis() - start_of_pulse;
 
-               if (pulse_length > 175 && pulse_length < 225) { // "0" bit ~= 200 ms (represented as "0")
+               if (pulse_length > 150 && pulse_length < 250) { // "0" bit ~= 200 ms (represented as "0")
                        this_pulse = 0;
                }
-               else if (pulse_length > 475 && pulse_length < 525) {    // "1" bit ~= 500 ms (represented as "1")
+               else if (pulse_length > 450 && pulse_length < 550) {    // "1" bit ~= 500 ms (represented as "1")
                        this_pulse = 1;
                }
-               else if (pulse_length > 775 && pulse_length < 825) {    // marker bit ~= 800 ms (represented as "2")
+               else if (pulse_length > 750 && pulse_length < 850) {    // marker bit ~= 800 ms (represented as "2")
                        this_pulse = 2;
                }
                else {
@@ -146,10 +155,10 @@ void loop() {
                }
 
                if (framesync) {        // yellow LED = we currently have frame sync
-                       analogWrite(yellowled, 10);     // (we run it at a low intensity)
+                       digitalWrite(cleantimecodeled, HIGH);   // (we run it at a low intensity)
                }
                else {
-                       digitalWrite(yellowled, LOW);
+                       digitalWrite(cleantimecodeled, LOW);
                }
 
                if ((framesync) && (position_in_frame < 60)) {
@@ -179,10 +188,10 @@ void loop() {
        }
 
        if ((m - last_sync) < 86400000) {       // green LED = got a good sync in the last 24 hours
-               digitalWrite(greenled, HIGH);
+               digitalWrite(last24led, HIGH);
        }
        else {
-               digitalWrite(greenled, LOW);
+               digitalWrite(last24led, LOW);
        }
 }