diff --git a/.gitignore b/.gitignore index addf833..d6ae83e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .clang_complete .gcc-flags.json firmware.bin +/data/* diff --git a/platformio.ini b/platformio.ini index efbba14..65afd88 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,6 +19,8 @@ lib_deps = MD_MAX72XX IOTAppStory-ESP NTPClient + ESPAsyncTCP + ESP Async WebServer upload_port = /dev/cu.wchusbserial1420 upload_speed = 921600 diff --git a/src/MD_RobotEyes_Data.h b/src/MD_RobotEyes_Data.h index 2fbc6c2..b738bdb 100644 --- a/src/MD_RobotEyes_Data.h +++ b/src/MD_RobotEyes_Data.h @@ -23,21 +23,21 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqWink[] /*PROGMEM*/ = { { 2, 0 }, FRAME_TIME/2 }, { { 3, 0 }, FRAME_TIME/2 }, { { 4, 0 }, FRAME_TIME/2 }, - { { 5, 0 }, FRAME_TIME * 2 }, + { { 5, 0 }, FRAME_TIME }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqRight[] /*PROGMEM*/ = { { { 0, 0 }, FRAME_TIME }, { { 6, 6 }, FRAME_TIME }, - { { 7, 7 }, FRAME_TIME * 5 }, + { { 7, 7 }, FRAME_TIME * 3 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqLeft[] /*PROGMEM*/ = { { { 0, 0 }, FRAME_TIME }, { { 8, 8 }, FRAME_TIME }, - { { 9, 9 }, FRAME_TIME * 5 }, + { { 9, 9 }, FRAME_TIME * 3 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqUp[] /*PROGMEM*/ = @@ -53,7 +53,7 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqDown[] /*PROGMEM*/ = { { 00, 00 }, FRAME_TIME }, { { 14, 14 }, FRAME_TIME }, { { 15, 15 }, FRAME_TIME }, - { { 16, 16 }, FRAME_TIME * 5 }, + { { 16, 16 }, FRAME_TIME * 3 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqAngry[] /*PROGMEM*/ = @@ -62,7 +62,7 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqAngry[] /*PROGMEM*/ = { { 22, 17 }, FRAME_TIME }, { { 23, 18 }, FRAME_TIME }, { { 24, 19 }, FRAME_TIME }, - { { 25, 20 }, 2000 }, + { { 25, 20 }, 1000 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqSad[] /*PROGMEM*/ = @@ -70,14 +70,14 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqSad[] /*PROGMEM*/ = { { 00, 00 }, FRAME_TIME }, { { 32, 27 }, FRAME_TIME }, { { 33, 28 }, FRAME_TIME }, - { { 34, 29 }, 2000 }, + { { 34, 29 }, 1000 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqEvil[] /*PROGMEM*/ = { { { 00, 00 }, FRAME_TIME }, { { 39, 37 }, FRAME_TIME }, - { { 40, 38 }, 2000 }, + { { 40, 38 }, 1000 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqEvil2[] /*PROGMEM*/ = @@ -86,7 +86,7 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqEvil2[] /*PROGMEM*/ = { { 54, 17 }, FRAME_TIME }, { { 55, 18 }, FRAME_TIME }, { { 56, 19 }, FRAME_TIME }, - { { 57, 20 }, 2000 }, + { { 57, 20 }, 1000 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqSquint[] /*PROGMEM*/ = @@ -95,7 +95,7 @@ const MD_RobotEyes::animFrame_t MD_RobotEyes::seqSquint[] /*PROGMEM*/ = { { 54, 54 }, FRAME_TIME }, { { 55, 55 }, FRAME_TIME }, { { 56, 56 }, FRAME_TIME }, - { { 57, 57 }, 2000 }, + { { 57, 57 }, 1000 }, }; const MD_RobotEyes::animFrame_t MD_RobotEyes::seqDead[] /*PROGMEM*/ = diff --git a/src/Relays.cpp b/src/Relays.cpp new file mode 100644 index 0000000..190725a --- /dev/null +++ b/src/Relays.cpp @@ -0,0 +1,85 @@ +#include "Relays.h" + +static unsigned long last_relay_off_ts=0, last_relay_hold_ts=0; +enum RelayState { RELAY_STATE_OFF=0, RELAY_STATE_ON_EVEN_MINUTE, RELAY_STATE_ON_ODD_MINUTE }; +static RelayState relaysState = RELAY_STATE_OFF; +static RelayState lastRelayOnState = RELAY_STATE_ON_EVEN_MINUTE; +static bool relayCanSwitch=true; + +void Relays::begin(int _relay1Pin, int _relay2Pin) { + relay1Pin = _relay1Pin; + relay2Pin = _relay2Pin; + pinMode(relay1Pin, OUTPUT); + pinMode(relay2Pin, OUTPUT); + digitalWrite(relay1Pin, LOW); + digitalWrite(relay2Pin, LOW); +} + +void Relays::toggle() { + if (relayCanSwitch) { + if (lastRelayOnState == RELAY_STATE_ON_EVEN_MINUTE) { + digitalWrite(relay1Pin, HIGH); + digitalWrite(relay2Pin, LOW); + relaysState = RELAY_STATE_ON_ODD_MINUTE; + // P.print("R-OEv"); + } else { + digitalWrite(relay1Pin, LOW); + digitalWrite(relay2Pin, HIGH); + relaysState = RELAY_STATE_ON_EVEN_MINUTE; + // P.print("R-OOd"); + } + lastRelayOnState = relaysState; + } // else P.print("R-OErr"); + relayCanSwitch = false; + last_relay_hold_ts = millis(); + // increment displayed time + displayedTime_minutes++; + if (displayedTime_minutes >= 60) { + displayedTime_hours++; + displayedTime_minutes -= 60; + if (displayedTime_hours >= 24) { + displayedTime_hours = 0; + } + } + if (fastforwardMode) { + if (displayedTime_hours == targetHours && displayedTime_minutes == targetMinutes) { + // wanted time reached! + fastforwardMode = false; + } + } + Serial.println(F("Toggle Relays")); +} + +void Relays::off(void) { + digitalWrite(relay1Pin, LOW); + digitalWrite(relay2Pin, LOW); + last_relay_off_ts = millis(); + relaysState = RELAY_STATE_OFF; + // P.print("R-Off"); +} + +void Relays::loop(void) { + if (relaysState == RELAY_STATE_OFF) { + if (millis() - last_relay_off_ts > minOffTime_ms) { + relayCanSwitch = true; + if (fastforwardMode) toggle(); + } + } else { + if (millis() - last_relay_hold_ts > holdTime_ms) { + off(); + } + } +} + +void Relays::fwdToTime(unsigned int hours, unsigned int minutes) { + // @TODO + // as we have a 12h clock, we adjust displayedTime to be before the wanted time + if (hours < displayedTime_hours || + (hours == displayedTime_hours && minutes < displayedTime_minutes)) { + displayedTime_hours -= 12; + if (displayedTime_hours < 0) displayedTime_hours += 24; + } + targetHours = hours; + targetMinutes = minutes; + fastforwardMode = true; +} diff --git a/src/Relays.h b/src/Relays.h new file mode 100644 index 0000000..280ae5b --- /dev/null +++ b/src/Relays.h @@ -0,0 +1,40 @@ +// +// FILE: Relays.h +// VERSION: 1.0 +// PURPOSE: Handle two relays used to toggle voltage polarity to control a clock +// +// + +#ifndef _relaysLoaded +#define _relaysLoaded true + +#include + +class Relays { +public: + Relays():holdTime_ms(200), minOffTime_ms(100), fastforwardMode(false) {}; + void begin(int _relay1Pin, int _relay2Pin); + void toggle(); + void off(); + void loop(); + void setHoldTime_ms(unsigned int newValue) { holdTime_ms = newValue; } + void setMinOffTime_ms(unsigned int newValue) { minOffTime_ms = newValue; } + unsigned int getHoldTime_ms() { return holdTime_ms; } + unsigned int getMinOffTime_ms() { return minOffTime_ms; } + void setDisplayedTime(unsigned int h, unsigned int m) { displayedTime_hours = h; displayedTime_minutes = m; } + unsigned int getDisplayedTime_hours() { return displayedTime_hours; } + unsigned int getDisplayedTime_minutes() { return displayedTime_minutes; } + void fwdToTime(unsigned int hours, unsigned int minutes); +protected: + int relay1Pin, relay2Pin; + unsigned int holdTime_ms; + unsigned int minOffTime_ms; + unsigned int displayedTime_hours; + unsigned int displayedTime_minutes; + unsigned int targetHours; + unsigned int targetMinutes; + boolean fastforwardMode; + +}; + +#endif diff --git a/src/data/btn-do.png b/src/data/btn-do.png new file mode 100644 index 0000000..ec3d62d Binary files /dev/null and b/src/data/btn-do.png differ diff --git a/src/data/btn.png b/src/data/btn.png new file mode 100644 index 0000000..6aaca3b Binary files /dev/null and b/src/data/btn.png differ diff --git a/src/data/favicon.ico b/src/data/favicon.ico new file mode 100755 index 0000000..1e72158 Binary files /dev/null and b/src/data/favicon.ico differ diff --git a/src/data/fremoei.gif b/src/data/fremoei.gif new file mode 100755 index 0000000..8bac39b Binary files /dev/null and b/src/data/fremoei.gif differ diff --git a/src/data/icon-0-75x.png b/src/data/icon-0-75x.png new file mode 100644 index 0000000..7e4889b Binary files /dev/null and b/src/data/icon-0-75x.png differ diff --git a/src/data/icon-1-5x.png b/src/data/icon-1-5x.png new file mode 100644 index 0000000..c117af1 Binary files /dev/null and b/src/data/icon-1-5x.png differ diff --git a/src/data/icon-1x.png b/src/data/icon-1x.png new file mode 100644 index 0000000..a63fcd5 Binary files /dev/null and b/src/data/icon-1x.png differ diff --git a/src/data/icon-2x.png b/src/data/icon-2x.png new file mode 100644 index 0000000..28e0d87 Binary files /dev/null and b/src/data/icon-2x.png differ diff --git a/src/data/icon-3x.png b/src/data/icon-3x.png new file mode 100644 index 0000000..d620cfc Binary files /dev/null and b/src/data/icon-3x.png differ diff --git a/src/data/icon-4x.png b/src/data/icon-4x.png new file mode 100644 index 0000000..cfb0e62 Binary files /dev/null and b/src/data/icon-4x.png differ diff --git a/src/data/img_fremo_sw.gif b/src/data/img_fremo_sw.gif new file mode 100644 index 0000000..88a2c25 Binary files /dev/null and b/src/data/img_fremo_sw.gif differ diff --git a/src/data/img_sh0.gif b/src/data/img_sh0.gif new file mode 100644 index 0000000..3b4fec4 Binary files /dev/null and b/src/data/img_sh0.gif differ diff --git a/src/data/index.htm b/src/data/index.htm new file mode 100644 index 0000000..b0b56fc --- /dev/null +++ b/src/data/index.htm @@ -0,0 +1,94 @@ + + + + + + + Fastclock + + + + + + +
+
+
+
+ + + +
+
+ + + diff --git a/src/data/led-off.png b/src/data/led-off.png new file mode 100644 index 0000000..89f78cb Binary files /dev/null and b/src/data/led-off.png differ diff --git a/src/data/led-on.png b/src/data/led-on.png new file mode 100644 index 0000000..d2d8c71 Binary files /dev/null and b/src/data/led-on.png differ diff --git a/src/data/main.css b/src/data/main.css new file mode 100644 index 0000000..4f53364 --- /dev/null +++ b/src/data/main.css @@ -0,0 +1,47 @@ +html { + width: 100%; + height: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +*, *:before, *:after { + -webkit-box-sizing: inherit; + -moz-box-sizing: inherit; + box-sizing: inherit; +} + +:focus { + outline: none; + outline-style: none; + box-shadow: none; + border-color: transparent; +} + +body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background: #EEE; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + text-align: center; + color: #555; +} + +.hdr { + width: 100%; + padding: 15px 0 15px 0; +} + +.btn_cnt { + width: 111px; + margin: 0 auto 0 auto; + padding-top: 5%; +} + +.btn_cnt a { + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); +} diff --git a/src/data/manifest.json b/src/data/manifest.json new file mode 100644 index 0000000..55687e4 --- /dev/null +++ b/src/data/manifest.json @@ -0,0 +1,39 @@ +{ + "name": "Fastclock Client", + "icons": [{ + "src": "icon-0-75x.png", + "sizes": "36x36", + "type": "image/png", + "density": 0.75 + }, { + "src": "icon-1x.png", + "sizes": "48x48", + "type": "image/png", + "density": 1.0 + }, { + "src": "icon-1-5x.png", + "sizes": "72x72", + "type": "image/png", + "density": 1.5 + }, { + "src": "icon-2x.png", + "sizes": "96x96", + "type": "image/png", + "density": 2.0 + }, { + "src": "icon-3x.png", + "sizes": "144x144", + "type": "image/png", + "density": 3.0 + }, { + "src": "icon-4x.png", + "sizes": "192x192", + "type": "image/png", + "density": 4.0 + }], + "start_url": "index.htm", + "display": "standalone", + "orientation": "portrait", + "theme_color": "dimgray", + "background_color": "black" +} diff --git a/src/main.cpp b/src/main.cpp index 8d1bccc..ecc35df 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,8 @@ */ #define COMPDATE __DATE__ __TIME__ +#define APP_VERSION "0.2.18" + // Button pin on the esp for selecting modes. 0 for Generic devices! #define MODEBUTTON D3 #define RELAY1_PIN D1 @@ -12,8 +14,8 @@ #define VERTICAL_BAR_STARTS_TOP false #define DEBUG_RELAYS false #define DEBUG_DISPLAY false -#define STARTUP1_ANIMATION_DURATION_ms 15000 -#define STARTUP2_ANIMATION_DURATION_ms 45000 +#define STARTUP1_ANIMATION_DURATION_ms 2000 +#define STARTUP2_ANIMATION_DURATION_ms 33000 #include #include @@ -24,6 +26,10 @@ #include #include #include "MD_RobotEyes.h" +#include +#include // https://github.com/me-no-dev/AsyncTCP +#include +#include "Relays.h" IOTAppStory IAS(COMPDATE, MODEBUTTON); String deviceName = "wemosMatrixDisplay"; @@ -52,9 +58,11 @@ Your hardware matches the setting for FC-16 modules. Please set FC16_HW. // Arbitrary output pins MD_Parola P = MD_Parola(HARDWARE_TYPE, DISPLAY_DATA_PIN, DISPLAY_CLK_PIN, DISPLAY_CS_PIN, MAX_DEVICES); MD_RobotEyes E; +Relays R; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); +AsyncWebServer server(80); // Field default values char *clockName = "FREMO"; @@ -64,9 +72,7 @@ char *relay1Pin_String = "D1"; char *relay2Pin_String = "D2"; int relay1Pin = D1, relay2Pin = D2; char *relayHoldTime_ms_String = "200"; -unsigned int relayHoldTime_ms = 200; char *relayMinOffTime_ms_String = "100"; -unsigned int relayMinOffTime_ms = 100; unsigned int displayRefresh_ms = 200; // Clock Display Config Parameter @@ -74,7 +80,12 @@ static char * displayClockNameEvery_ms_String = "16000"; static char * displayClockNameDuration_ms_String = "1200"; static uint32_t displayClockNameEvery_ms = 16000; static uint32_t displayClockNameDuration_ms = 1200; -static uint32_t doNotShowClockNameBeforeAndAfterMinuteChange_s = 2; +static uint16_t doNotShowClockNameBeforeAndAfterMinuteChange_s = 2; + +static uint16_t hours, minutes, seconds; +static char minuteProgressIndicator; +static char timeBuffer[10]; + void setupIAS(void) { #if defined ESP8266 @@ -87,7 +98,7 @@ void setupIAS(void) { // preset deviceName this is also your MDNS responder: http://deviceName.local IAS.preSetDeviceName(deviceName); IAS.preSetAppName(F("Wemos2RelaysMatrixDisplays")); - IAS.preSetAppVersion(F("0.2.1")); + IAS.preSetAppVersion(F(APP_VERSION)); IAS.preSetAutoUpdate(true); // define fields @@ -154,8 +165,8 @@ void setupIAS(void) { clockSpeed_modelMsPerRealSec = atoi(clockSpeed_modelMsPerRealSec_String); relay1Pin = IAS.dPinConv(relay1Pin_String); relay2Pin = IAS.dPinConv(relay2Pin_String); - relayHoldTime_ms = atoi(relayHoldTime_ms_String); - relayMinOffTime_ms = atoi(relayMinOffTime_ms_String); + R.setHoldTime_ms(atoi(relayHoldTime_ms_String)); + R.setMinOffTime_ms(atoi(relayMinOffTime_ms_String)); displayClockNameEvery_ms = atoi(displayClockNameEvery_ms_String); displayClockNameDuration_ms = atoi(displayClockNameDuration_ms_String); @@ -163,20 +174,13 @@ void setupIAS(void) { Serial.print(F("Relay1 Pin: ")); Serial.println(relay1Pin); Serial.print(F("Relay2 Pin: ")); Serial.println(relay2Pin); Serial.print(F("Clock speed: ")); Serial.print(clockSpeed_modelMsPerRealSec); Serial.println(F(" model ms per real sec")); - Serial.print(F("Relay hold time (ms): ")); Serial.println(relayHoldTime_ms); - Serial.print(F("Relay min off time (ms): ")); Serial.println(relayMinOffTime_ms); + Serial.print(F("Relay hold time (ms): ")); Serial.println(relayHoldTime_ms_String); + Serial.print(F("Relay min off time (ms): ")); Serial.println(relayMinOffTime_ms_String); Serial.print(F("Clock speed (model ms per real time s): ")); Serial.println(clockSpeed_modelMsPerRealSec); Serial.print(F("Show clock name every (ms): ")); Serial.println(displayClockNameEvery_ms); Serial.print(F("Show clock name for (ms): ")); Serial.println(displayClockNameDuration_ms); } -void setupRelays(int relay1Pin, int relay2Pin) { - pinMode(relay1Pin, OUTPUT); - pinMode(relay2Pin, OUTPUT); - digitalWrite(relay1Pin, LOW); - digitalWrite(relay2Pin, LOW); -} - static MD_MAX72XX *graphicDisplay = NULL; void setupDisplay() { @@ -224,15 +228,118 @@ void setupDisplay() { P.print(intro); } +//called when the url is not defined here return 404 +void onRequest(AsyncWebServerRequest *request){ + //Handle Unknown Request + request->send(404); +} + +void setupFS() { + if(!SPIFFS.begin()){ + Serial.println(F(" SPIFFS Mount Failed")); + return; + } +} + +void setupWebServer() { + server.on("/fwd", HTTP_GET, [](AsyncWebServerRequest *request){ + Serial.println(F("\n WebApp button pressed -- move clock forward")); + + R.toggle(); + + // create json return + String json = "{"; + json += "\"result\":\"OK\","; + json += "\"clockName\":\"" + String(clockName) + "\","; + json += "\"hours\":\"" + String(hours) + "\","; + json += "\"minutes\":\"" + String(minutes) + "\","; + json += "\"seconds\":\"" + String(seconds) + "\""; + json += "}"; + + // return json to WebApp + request->send(200, F("text/json"), json); + json = String(); + }); + + server.on("/clock", HTTP_GET, [](AsyncWebServerRequest *request){ + // create json return + String json = "{"; + json += "\"clockName\":\""+String(clockName)+"\","; + json += "\"clockSpeed\":\""+String(clockSpeed_modelMsPerRealSec)+"\","; + json += "\"relayHoldTime_ms\":\""+String(R.getHoldTime_ms())+"\","; + json += "\"relayMinOffTime_ms\":\""+String(R.getMinOffTime_ms())+"\","; + json += "\"displayRefresh_ms\":\""+String(displayRefresh_ms)+"\","; + json += "\"displayClockNameEvery_ms\":\""+String(displayClockNameEvery_ms)+"\","; + json += "\"displayClockNameDuration_ms\":\""+String(displayClockNameDuration_ms)+"\","; + json += "\"doNotShowClockNameBeforeAndAfterMinuteChange_s\":\""+String(doNotShowClockNameBeforeAndAfterMinuteChange_s)+"\","; + json += "\"real_hours\":\""+String(hours)+"\","; + json += "\"real_minutes\":\""+String(minutes)+"\","; + json += "\"real_seconds\":\""+String(seconds)+"\","; + json += "\"model_hours\":\""+String(hours)+"\","; + json += "\"model_minutes\":\""+String(minutes)+"\","; + json += "\"model_seconds\":\""+String(seconds)+"\""; + json += "}"; + + // return json to WebApp + request->send(200, F("text/json"), json); + json = String(); + }); + + server.on("/setDT", HTTP_GET, [](AsyncWebServerRequest *request){ + String h, m, message; + Serial.println(F("\n Setting displayed time of clock")); + + message = ""; + if (request->hasParam("h")) { + h = request->getParam("h")->value(); + } else { + message += "Parameter h for hours missing. "; + } + if (request->hasParam("m")) { + m = request->getParam("m")->value(); + } else { + message += "Parameter m for minutes missing. "; + } + + R.setDisplayedTime(h.toInt(), m.toInt()); + h = String(); + m = String(); + + // create json return + String json = "{"; + if (message.length() > 0) { + json += "\"result\":\"Error\","; + json += "\"message\": \"" + message + "\""; + } else { + json += "\"result\":\"OK\""; + } + json += "}"; + + // return json to WebApp + request->send(200, F("text/json"), json); + json = String(); + }); + + server.serveStatic("/", SPIFFS, "/"); + server.onNotFound(onRequest); + + // start the HTTP server + server.begin(); + Serial.print(F("HTTP server started at: ")); + Serial.println(WiFi.localIP()); + Serial.println(""); +} + void setup(void) { Serial.println(F("setup():")); setupDisplay(); setupIAS(); + setupFS(); + setupWebServer(); delay(200); - setupRelays(relay1Pin, relay2Pin); - + R.begin(relay1Pin, relay2Pin); timeClient.begin(); Serial.println(F("setup() finished")); } @@ -242,51 +349,6 @@ static bool timeClientInitialized = false; static unsigned long lastTimeOutput_ms = 0; #define TIME_BETWEEN_REALTIME_UPDATE_ms 60000 -static unsigned long last_relay_off_ts=0, last_relay_hold_ts=0; -enum RelayState { RELAY_STATE_OFF=0, RELAY_STATE_ON_EVEN_MINUTE, RELAY_STATE_ON_ODD_MINUTE }; -static RelayState relaysState = RELAY_STATE_OFF; -static RelayState lastRelayOnState = RELAY_STATE_ON_EVEN_MINUTE; -static bool relayCanSwitch=true; - -void toggleRelays() { - if (relayCanSwitch) { - if (lastRelayOnState == RELAY_STATE_ON_EVEN_MINUTE) { - digitalWrite(relay1Pin, HIGH); - digitalWrite(relay2Pin, LOW); - relaysState = RELAY_STATE_ON_ODD_MINUTE; - // P.print("R-OEv"); - } else { - digitalWrite(relay1Pin, LOW); - digitalWrite(relay2Pin, HIGH); - relaysState = RELAY_STATE_ON_EVEN_MINUTE; - // P.print("R-OOd"); - } - lastRelayOnState = relaysState; - } // else P.print("R-OErr"); - relayCanSwitch = false; - last_relay_hold_ts = millis(); - Serial.println(F("Toggle Relays")); -} - -void relaysOff(void) { - digitalWrite(relay1Pin, LOW); - digitalWrite(relay2Pin, LOW); - last_relay_off_ts = millis(); - relaysState = RELAY_STATE_OFF; - // P.print("R-Off"); -} - -void loopRelays(void) { - if (relaysState == RELAY_STATE_OFF) { - if (millis() - last_relay_off_ts > relayMinOffTime_ms) { - relayCanSwitch = true; - } - } else { - if (millis() - last_relay_hold_ts > relayHoldTime_ms) { - relaysOff(); - } - } -} typedef struct { @@ -330,6 +392,7 @@ void loopStartupAnimation() { index++; if (index >= ARRAY_SIZE(eSeq)) index = 0; + P.displayClear(); #if DISPLAY_ANIM_NAME E.setText(eSeq[index].name); #endif @@ -363,14 +426,26 @@ void loopStartupAnimation() { } } +void reInitializeDisplay() { + static unsigned long last_reinit_ts = 0; + #define REINIT_AFTER_ms 5000 + #define AVOID_REINIT_BEFORE_AND_AFTER_FULLMINUTE_FOR_s 3 + + if (last_reinit_ts == 0) last_reinit_ts = millis(); + + if (millis() - last_reinit_ts > REINIT_AFTER_ms + && seconds < 60 - AVOID_REINIT_BEFORE_AND_AFTER_FULLMINUTE_FOR_s + && seconds > AVOID_REINIT_BEFORE_AND_AFTER_FULLMINUTE_FOR_s) { + P.begin(); + last_reinit_ts = millis(); + } +} + void loop(void) { int currentDisplayState; - int hours, minutes, seconds; - char minuteProgressIndicator; static int lastMinutes = 0; static int lastSeconds = 0; - static char timeBuffer[10]; #define MsgSize 10 static char debugMsg[MsgSize+1]; static int recentDisplayState = -1; @@ -415,32 +490,6 @@ void loop(void) if (minuteProgressIndicator > 9) minuteProgressIndicator = 9; snprintf(timeBuffer, 10, "%c %2d:%02d", minuteProgressIndicator, hours, minutes); - //P.displayAnimate(); - //P.displayClear(); - /* DEBUG */ - #if DEBUG_RELAYS - if (seconds != lastSeconds) { - switch (seconds % 4) { - case 0: - digitalWrite(relay1Pin, HIGH); - break; - case 1: - digitalWrite(relay1Pin, LOW); - break; - case 2: - digitalWrite(relay2Pin, HIGH); - break; - case 3: - digitalWrite(relay2Pin, LOW); - break; - } - Serial.print("Rel dbg: "); Serial.println(seconds, HEX); - delay(5); - } - #endif - /* END DEBUG */ - - // standard procedure to display static uint32_t last_clock_refresh = 0; static uint32_t lastTimeClockNameShown = 0; @@ -455,7 +504,8 @@ void loop(void) if ((millis() - lastTimeClockNameShown > displayClockNameEvery_ms) && (seconds < 60-doNotShowClockNameBeforeAndAfterMinuteChange_s) && (seconds > doNotShowClockNameBeforeAndAfterMinuteChange_s)) { - P.begin(); // re-initialize, that fixes display problems due to electrical relais feedbacks + //P.begin(); // re-initialize, that fixes display problems due to electrical relais feedbacks + reInitializeDisplay(); P.setIntensity(2); P.print(clockName); lastTimeClockNameShown = millis(); @@ -463,7 +513,8 @@ void loop(void) } else { // showing clock if (millis() - last_clock_refresh > displayRefresh_ms) { - //P.displayClear(); + // P.begin(); // re-initialize, that fixes display problems due to electrical relais feedbacks + reInitializeDisplay(); P.setIntensity(1); P.print(timeBuffer); last_clock_refresh = millis(); @@ -473,10 +524,10 @@ void loop(void) // toggle relays if (lastMinutes != minutes) { - toggleRelays(); + R.toggle(); lastMinutes = minutes; } lastSeconds = seconds; - loopRelays(); + R.loop(); }