From a212bbc28acb10a23928cc06dd9b79919e4da3b0 Mon Sep 17 00:00:00 2001 From: eleksir Date: Sat, 17 Aug 2019 11:50:23 +0300 Subject: [PATCH] Port changes from photoresistor branch * Poll RTC by trigger, set via ISR * Change blink state by trigger, set via ISR * Set time compensation trigger in ISR * Refresh clock by timer * Re-calculate displayed time only ater rtcsync or when time adjusted by buttons * Simplify draw algo --- simpleclock.ino | 177 +++++++++++++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 71 deletions(-) diff --git a/simpleclock.ino b/simpleclock.ino index 88f2837..1107055 100644 --- a/simpleclock.ino +++ b/simpleclock.ino @@ -20,20 +20,25 @@ const long adjust_interval = 200; // delay between consecutive number increments const long bounce_delay = 20; // contact bounce compensation const int hrs_btn = A0; // put hour adjusting button on A0 lane const int min_btn = A1; // put minute adjusting button on A1 lane -bool btn_pushed = false; // is button pushed? -unsigned long currentPushTimer; +volatile bool btn_pushed = false; // is button pushed? unsigned long previousPushTimer = 0; -uint8_t minutes; -uint8_t hours; /* dot blinking stuff */ -unsigned long currentMillis; -unsigned long previousMillis = 0; -const long interval = 500; -bool dot = true; +volatile bool dot = true; /* time inaccuracy compensation flag */ -bool compflag = true; +volatile bool compflag1 = true; +volatile bool compflag2 = false; +const uint8_t timeSkew = 8; // assume that clock runs faster than should +volatile bool timeSkewEven = false; // comp. 1 additional second per 2 days + +/* time vars */ +volatile uint8_t mysecond; +volatile uint8_t myminute; +volatile uint8_t myhour; + +/* rtc sync flag */ +volatile bool rtcsync = true; void setup() { @@ -69,22 +74,84 @@ void setup() // setup control buttons pinMode(hrs_btn, INPUT_PULLUP); pinMode(min_btn, INPUT_PULLUP); + +/* Timer stuff + * timer0 being used in millis() micros() delay() etc, it has 8 bit resolution + * timer2 being used in analogWrite() tone() notone(), it has 8 bit resolution + * timer1 being used in servo lib has 16 bit resolution + * We'll use timer1, since we have no mechanical parts and don't need servo lib + */ + // initialize timer1 + noInterrupts(); // disable all interrupts + TCCR1A = 0; + TCCR1B = 0; + + TCNT1 = 34286; // preload timer 65536-16MHz/256/2Hz + TCCR1B |= (1 << CS12); // 256 prescaler + TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt + interrupts(); // enable all interrupts +} + +ISR(TIMER1_OVF_vect) +{ +/* Feed clock twice per second */ + TCNT1 = 34286; // preload timer + // do not read rtc if time beng adjusted by buttons + (btn_pushed) ? rtcsync : rtcsync = true; + +/* Also switch dot */ + if (dot) + dot = false; + else + dot = true; + +/* time compensation magic */ + if ((myhour == 21) and (myminute == 21) and (mysecond == 21) + and (compflag2)) { + compflag1 = true; + (timeSkewEven) ? timeSkewEven = false : timeSkewEven; + } + + if ((myhour == 21) and (myminute == 21) and (mysecond == 23)) { + compflag1 = false; + compflag2 = true; + } } void loop() { - currentMillis = millis(); - currentPushTimer = currentMillis; - char str[4]; - float d; + unsigned long currentMillis = millis(); - clock.getTime(); +/* + * Let's implement time compenstion for individual rtc module time + * charachteristics. In in my case quartz resonator as inaccurate as + * about +8.5 seconds per 24 hours + */ + if (compflag1 && compflag2) { + if (timeSkewEven) { + clock.fillByHMS(myhour, myminute, (mysecond - timeSkew - 1)); + } else { + clock.fillByHMS(myhour, myminute, (mysecond - timeSkew)); + } + + clock.setTime(); + compflag2 = false; + } + + if (rtcsync) { + clock.getTime(); + mysecond = clock.second; + myminute = clock.minute; + myhour = clock.hour; + updateTimeStr(myhour, myminute); + rtcsync = false; + } // push button magic if ((!btn_pushed) and ((digitalRead(hrs_btn) == LOW) or (digitalRead(min_btn) == LOW))) { - if (currentPushTimer - previousPushTimer >= initial_delay) { - previousPushTimer = currentPushTimer; + if (currentMillis - previousPushTimer >= initial_delay) { + previousPushTimer = currentMillis; btn_pushed = true; } } @@ -92,79 +159,47 @@ void loop() if (btn_pushed and (digitalRead(hrs_btn) != LOW) and (digitalRead(min_btn) != LOW)) { // compensate possible contact bounce with delay - if (currentPushTimer - previousPushTimer >= bounce_delay) { + if (currentMillis - previousPushTimer >= bounce_delay) { btn_pushed = false; } } if (btn_pushed) { - if (currentPushTimer - previousPushTimer >= adjust_interval) { - previousPushTimer = currentPushTimer; + if (currentMillis - previousPushTimer >= adjust_interval) { + previousPushTimer = currentMillis; if (digitalRead(hrs_btn) == LOW) { - hours = clock.hour + 1; - (hours > 23) ? hours = 0 : hours; - clock.fillByHMS(hours, clock.minute, 0); + myhour++; + (myhour > 23) ? myhour = 0 : myhour; + clock.fillByHMS(myhour, myminute, 0); clock.setTime(); } if (digitalRead(min_btn) == LOW) { - minutes = clock.minute + 1; - (minutes > 59) ? minutes = 0 : minutes; - clock.fillByHMS(clock.hour, minutes, 0); + myminute++; + (myminute > 59) ? myminute = 0 : myminute; + clock.fillByHMS(myhour, myminute, 0); clock.setTime(); } } - } - if (currentMillis - previousMillis >= interval) { - previousMillis = currentMillis; - - if (dot) - dot = false; - else - dot = true; - } - - /* - * Let's implement time compenstion for individual rtc module time - * charachteristics. In in my case quartz resonator as inaccurate as - * +/- about 5-8 seconds per 24 hours, maybe its require more EMI - * shielding? - */ - - if ((clock.hour == 21) and (clock.minute == 21) and - (clock.second == 21) and (compflag)) { - clock.fillByHMS(clock.hour, clock.minute, 14); - clock.setTime(); - compflag = false; - } - - if ((clock.hour == 21) and (clock.minute == 21) and - (clock.second == 23) and (!compflag)) { - compflag = true; - } - - // make blinking dot - if (clock.hour > 0) { - if (dot) { - Display.setNumber((clock.hour * 100 + clock.minute), 2); - } else { - Display.setNumber((clock.hour * 100 + clock.minute)); - } - } else { - /* 0 o'clock is an exception, we don't want to see "00.00", we - want see "0.00" or "0 00", so we have to use this "hack" */ - if (dot) { - d = float(clock.minute) / 100; - Display.setNumber(d, 2); - } else { - sprintf(str, "%2d%02d", clock.hour, clock.minute); - Display.setChars(str); - } + updateTimeStr(myhour, myminute); } Display.refreshDisplay(); } +void updateTimeStr(uint8_t h, uint8_t m) +{ + if (dot) { + char str[5]; + sprintf(str, "%2d.%02d", h, m); + Display.setChars(str); + } else { + char str[4]; + sprintf(str, "%2d%02d", h, m); + Display.setChars(str); + } +} + /* vim: set filetype=cpp: */