diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 876dc9c3..1c8042ee 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -110,6 +110,10 @@ void setup() { board.begin(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.begin(); +#endif + #ifdef DISPLAY_CLASS DisplayDriver* disp = NULL; if (display.begin()) { @@ -229,4 +233,7 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.loop(); +#endif } diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index e37078ce..f636c32a 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -34,6 +34,10 @@ void setup() { board.begin(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.begin(); +#endif + #if defined(MESH_DEBUG) && defined(NRF52_PLATFORM) // give some extra time for serial to settle so // boot debug messages can be seen on terminal @@ -154,17 +158,31 @@ void loop() { #endif rtc_clock.tick(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.loop(); +#endif if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) { - #if defined(NRF52_PLATFORM) +#if defined(NRF52_PLATFORM) +#ifdef HAS_EXTERNAL_WATCHDOG + uint32_t sleep_interval = external_watchdog.getIntervalMs()/1000; + board.sleep((sleep_interval > 1800) ? 1800 : sleep_interval); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet +#else + board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet +#endif board.sleep(1800); // nrf ignores seconds param, sleeps whenever possible - #else +#else if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep +#ifdef HAS_EXTERNAL_WATCHDOG + uint32_t sleep_interval = external_watchdog.getIntervalMs()/1000; + board.sleep((sleep_interval > 1800) ? 1800 : sleep_interval); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet +#else board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet +#endif lastActive = millis(); nextSleepinSecs = 5; // Default: To work for 5s and sleep again } else { nextSleepinSecs += 5; // When there is pending work, to work another 5s } - #endif +#endif } } diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 825fb007..d20ebc6d 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -24,6 +24,10 @@ void setup() { board.begin(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.begin(); +#endif + #ifdef DISPLAY_CLASS if (display.begin()) { display.startFrame(); @@ -113,4 +117,7 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.loop(); +#endif } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index ab14d393..43cf5cc0 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -560,6 +560,10 @@ void setup() { board.begin(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.begin(); +#endif + if (!radio_init()) { halt(); } fast_rng.begin(radio_get_rng_seed()); @@ -591,4 +595,7 @@ void setup() { void loop() { the_mesh.loop(); rtc_clock.tick(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.loop(); +#endif } diff --git a/examples/simple_sensor/main.cpp b/examples/simple_sensor/main.cpp index 330adcc2..346f4dfc 100644 --- a/examples/simple_sensor/main.cpp +++ b/examples/simple_sensor/main.cpp @@ -58,6 +58,10 @@ void setup() { board.begin(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.begin(); +#endif + #ifdef DISPLAY_CLASS if (display.begin()) { display.startFrame(); @@ -147,4 +151,7 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); +#ifdef HAS_EXTERNAL_WATCHDOG + external_watchdog.loop(); +#endif } diff --git a/src/helpers/ExternalWatchdogManager.h b/src/helpers/ExternalWatchdogManager.h new file mode 100644 index 00000000..9ef8abaa --- /dev/null +++ b/src/helpers/ExternalWatchdogManager.h @@ -0,0 +1,12 @@ +#pragma once + +class ExternalWatchdogManager { +protected: + unsigned long next_feed_watchdog; +public: + ExternalWatchdogManager() { next_feed_watchdog = 0; } + virtual bool begin() { return false; } + virtual void loop() { } + virtual unsigned long getIntervalMs() const { return 0; } + virtual void feed() { } +}; diff --git a/variants/heltec_mesh_solar/platformio.ini b/variants/heltec_mesh_solar/platformio.ini index 7bfbac85..1bc7e7fa 100644 --- a/variants/heltec_mesh_solar/platformio.ini +++ b/variants/heltec_mesh_solar/platformio.ini @@ -14,6 +14,11 @@ build_flags = ${nrf52_base.build_flags} -D LORA_TX_POWER=22 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + -D HAS_EXTERNAL_WATCHDOG + -D EXTERNAL_WATCHDOG_DONE_PIN=9 + -D EXTERNAL_WATCHDOG_WAKE_PIN=10 + -D EXTERNAL_WATCHDOG_TIMEOUT_MS=480000 ;(6*60*1000) ; 6 minute watchdog + build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/heltec_mesh_solar> diff --git a/variants/heltec_mesh_solar/target.cpp b/variants/heltec_mesh_solar/target.cpp index 1ea33e1f..a40b8ce9 100644 --- a/variants/heltec_mesh_solar/target.cpp +++ b/variants/heltec_mesh_solar/target.cpp @@ -13,6 +13,7 @@ VolatileRTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); SolarSensorManager sensors = SolarSensorManager(nmea); +SolarExternalWatchdog external_watchdog; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; @@ -121,3 +122,35 @@ bool SolarSensorManager::setSettingValue(const char* name, const char* value) { } return false; // not supported } + +bool SolarExternalWatchdog::begin() { + next_feed_watchdog = 0; + pinMode(EXTERNAL_WATCHDOG_WAKE_PIN, INPUT); + pinMode(EXTERNAL_WATCHDOG_DONE_PIN, OUTPUT); + delay(1); + digitalWrite(EXTERNAL_WATCHDOG_DONE_PIN, LOW); + delay(1); + feed(); + return true; +} +void SolarExternalWatchdog::loop() { + if (millis() > next_feed_watchdog) { + feed(); + next_feed_watchdog = millis() + EXTERNAL_WATCHDOG_TIMEOUT_MS; + } +} + +unsigned long SolarExternalWatchdog::getIntervalMs() const { + unsigned long interval_ms = 0; + interval_ms = next_feed_watchdog - millis(); + if(interval_ms > EXTERNAL_WATCHDOG_TIMEOUT_MS) { + interval_ms = EXTERNAL_WATCHDOG_TIMEOUT_MS; + } + return interval_ms; +} + +void SolarExternalWatchdog::feed() { + digitalWrite(EXTERNAL_WATCHDOG_DONE_PIN, HIGH); + delay(1); + digitalWrite(EXTERNAL_WATCHDOG_DONE_PIN, LOW); +} diff --git a/variants/heltec_mesh_solar/target.h b/variants/heltec_mesh_solar/target.h index f1921abf..124e3afb 100644 --- a/variants/heltec_mesh_solar/target.h +++ b/variants/heltec_mesh_solar/target.h @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef DISPLAY_CLASS #include #endif @@ -30,10 +31,20 @@ public: bool setSettingValue(const char* name, const char* value) override; }; +class SolarExternalWatchdog : public ExternalWatchdogManager { +public: + SolarExternalWatchdog() {} + bool begin() override; + void loop() override; + unsigned long getIntervalMs() const override; + void feed() override; +}; + extern MeshSolarBoard board; extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SolarSensorManager sensors; +extern SolarExternalWatchdog external_watchdog; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; diff --git a/variants/heltec_mesh_solar/variant.h b/variants/heltec_mesh_solar/variant.h index 14956619..3c1b378d 100644 --- a/variants/heltec_mesh_solar/variant.h +++ b/variants/heltec_mesh_solar/variant.h @@ -34,8 +34,8 @@ #define PIN_SERIAL1_RX (37) #define PIN_SERIAL1_TX (39) -#define PIN_SERIAL2_RX (9) -#define PIN_SERIAL2_TX (10) +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) //////////////////////////////////////////////////////////////////////////////// // I2C pin definition