Last active
November 8, 2025 17:50
-
-
Save jstockdale/b84ea838266bfe3279a60e7150566673 to your computer and use it in GitHub Desktop.
Revisions
-
jstockdale revised this gist
Jul 16, 2024 . 1 changed file with 25 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,8 +18,10 @@ */ #define LED_PIN LED_BUILTIN // built in LED solid briefly on wakeup/boot, flashes dim while sensing, flashes bright if it detects t-beam is off or unresponsive #define VOLTAGE_DIVIDER_5V_PIN A1 // we read an analog voltage divider 10k between 5V and A1, 10k between GND and A1 to determine if VBUS has power #define MOSFET_GATE_PIN D2 // should normally be low but we pull high to ground out the solar usb connection to simulate reconnecting #define POWER_PIN D8 // connect floating leg of t-beam power button to D8; used to power on the t-beam normally #define SENSE_PIN A9 // one method we use to determine state is via an analog voltage threshold on GPIO0 #define RESET_PIN D10 // connect RST on t-beam to D10; used to hard boot if the t-beam has power but no uart activity #define UART_RX_PIN D7 // connect TX on t-beam to D7; we read the tx line to see if the t-beam is alive or "stuck" @@ -32,6 +34,7 @@ #define WATCH_LOOPS 150 int sensorValue = 0; // variable to store the analog value from SENSE_PIN int voltageValue = 0; // variable to store the analog value from VOLTAGE_DIVIDER_5V_PIN bool detectBool = false; int detectCount = 0; @@ -84,8 +87,13 @@ void setup() { // we will set them to OUTPUT only when powering or resetting the device pinMode(POWER_PIN, INPUT); pinMode(RESET_PIN, INPUT); // GPIO0 (SENSE_PIN) and VOLTAGE_DIVIDER_5V_PIN sense pins are always INPUT pinMode(SENSE_PIN, INPUT); pinMode(VOLTAGE_DIVIDER_5V_PIN, INPUT); // MOSFET_GATE_PIN is always OUTPUT pinMode(MOSFET_GATE_PIN, OUTPUT); // set MOSFET_GATE_PIN to HIGH to ground out solar panel digitalWrite(MOSFET_GATE_PIN, HIGH); // built-in led is always OUTPUT pinMode(LED_PIN, OUTPUT); @@ -94,7 +102,10 @@ void setup() { // setup UART connected to t-beam Serial1.begin(UART_BAUD, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN); delay(1000); // wait a bit to make sure serial is initialized // Say hello Serial.println("Hello world! Watchdog initialized."); // start listening for t-beam on Serial1 Serial1.onReceive(onReceiveFunction, false); @@ -113,6 +124,9 @@ void setup() { */ esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds"); Serial.println("Reconnecting solar panel; setting MOSFET_GATE_PIN to LOW."); digitalWrite(MOSFET_GATE_PIN, LOW); } // loop until we think we should go to sleep @@ -121,16 +135,21 @@ void loop() { digitalWrite(LED_PIN, LOW); // read GPIO0 / SENSE_PIN sensorValue = analogRead(SENSE_PIN); voltageValue = analogRead(VOLTAGE_DIVIDER_5V_PIN); Serial.println("State: GPIO0 analog " + String(sensorValue) + ", UART RX " + String(uart_received_bytes) + " bytes, 5V divider analog " + String(voltageValue)); digitalWrite(LED_PIN, HIGH); if(sensorValue > 2000 && uart_received_bytes > 0 || voltageValue < 2000) { // if sensorValue is above 2000 when reading the ADC and the UART has received data // we think the t-beam is turned on and most likely functioning properly // turn off the led, count the loop, and zero the detect count // if voltageValue is below 2000 we don't have (enough) power, so ... we can't // do anything until VBUS power comes back on. either from a usb charger or // the solar panel getting sufficient light. digitalWrite(LED_PIN, HIGH); detectCount = 0; ++okCount; } else { // if voltageValue is 2000 or more, we likely have solar or usb power // if sensorValue is 2000 or less, the device is probably off // if sensorvalue is 4095 and uart_received_bytes == 0, the device is probably "stuck" digitalWrite(LED_PIN, LOW); -
jstockdale revised this gist
Jun 25, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -25,7 +25,7 @@ #define UART_RX_PIN D7 // connect TX on t-beam to D7; we read the tx line to see if the t-beam is alive or "stuck" #define UART_TX_PIN D6 // this can be a no connect; not currently used #define UART_BAUD 115200 // Any baudrate from 300 to 115200 #define MIN_LOOPS 150 #define MAX_LOOPS 600 -
jstockdale revised this gist
Jun 24, 2024 . 1 changed file with 6 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,9 +27,9 @@ #define UART_BAUD 38400 // Any baudrate from 300 to 115200 #define MIN_LOOPS 150 #define MAX_LOOPS 600 #define WATCH_LOOPS 150 int sensorValue = 0; // variable to store the analog value from SENSE_PIN @@ -71,11 +71,12 @@ void onReceiveFunction(void) { // This is a callback function that will be activated on UART RX events size_t available = Serial1.available(); uart_received_bytes = uart_received_bytes + available; //Serial.printf("onReceive Callback:: There are %d bytes available: ", available); while (available--) { //Serial.print((char)Serial1.read()); Serial1.read(); } //Serial.println(); } void setup() { -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 10 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -87,12 +87,17 @@ void setup() { pinMode(SENSE_PIN, INPUT); // built-in led is always OUTPUT pinMode(LED_PIN, OUTPUT); // setup main serial for program output Serial.begin(115200); // setup UART connected to t-beam Serial1.begin(UART_BAUD, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN); delay(250); // wait a bit to make sure serial is initialized // start listening for t-beam on Serial1 Serial1.onReceive(onReceiveFunction, false); Serial.println("Listening for t-beam serial tx on: " + UART_RX_PIN); //Increment wake number and print it every wake cycle ++bootCount; @@ -113,18 +118,7 @@ void setup() { void loop() { // turn on the built-in LED digitalWrite(LED_PIN, LOW); // read GPIO0 / SENSE_PIN sensorValue = analogRead(SENSE_PIN); Serial.println("State: " + String(sensorValue) + ", " + String(uart_received_bytes)); digitalWrite(LED_PIN, HIGH); @@ -199,6 +193,7 @@ void loop() { if(okCount > WATCH_LOOPS || (detectBool == false && loopCount > MIN_LOOPS) || loopCount > targetLoops) { Serial.println("Going to sleep now"); Serial.flush(); Serial1.onReceive(NULL); esp_deep_sleep_start(); } -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ Basic deep sleep sketch based on examples provided with xiao-esp32-s3 *** PRE-ALPHA *** 2024-06-23 - version rc-0; updated to use Serial1 Copyright 2024 @jstockdale/Off by One, Inc. -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -145,7 +145,7 @@ void loop() { ++detectCount; detectBool = true; Serial.println(detectCount); // we add one to targetLoops (up to a max of MAX_LOOPS) if the device is off // this behaves well since the UART tx detection isn't perfect but is a weird hack // TODO(jstockdale): fix the way the various loop limits interact if(targetLoops < MAX_LOOPS) { -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,8 +22,8 @@ #define POWER_PIN D8 // connect floating leg of t-beam power button to D8; used to power on the t-beam normally #define RESET_PIN D10 // connect RST on t-beam to D10; used to hard boot if the t-beam has power but no uart activity #define UART_RX_PIN D7 // connect TX on t-beam to D7; we read the tx line to see if the t-beam is alive or "stuck" #define UART_TX_PIN D6 // this can be a no connect; not currently used #define UART_BAUD 38400 // Any baudrate from 300 to 115200 -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -25,7 +25,7 @@ #define UART_TX_PIN D7 // connect TX on t-beam to D7; we read the tx line to see if the t-beam is alive or "stuck" #define UART_RX_PIN D6 // this can be a no connect; not currently used #define UART_BAUD 38400 // Any baudrate from 300 to 115200 #define MIN_LOOPS 100 #define MAX_LOOPS 600 -
jstockdale revised this gist
Jun 23, 2024 . 1 changed file with 96 additions and 68 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,7 @@ Basic deep sleep sketch based on examples provided with xiao-esp32-s3 *** PRE-ALPHA *** version rc-0; updated to use Serial1 UNTESTED Copyright 2024 @jstockdale/Off by One, Inc. @@ -10,30 +11,34 @@ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. by @jstockdale */ #define LED_PIN LED_BUILTIN // built in LED solid briefly on wakeup/boot, flashes dim while sensing, flashes bright if it detects t-beam is off or unresponsive #define SENSE_PIN A9 // one method we use to determine state is via an analog voltage threshold on GPIO0 #define POWER_PIN D8 // connect floating leg of t-beam power button to D8; used to power on the t-beam normally #define RESET_PIN D10 // connect RST on t-beam to D10; used to hard boot if the t-beam has power but no uart activity #define UART_TX_PIN D7 // connect TX on t-beam to D7; we read the tx line to see if the t-beam is alive or "stuck" #define UART_RX_PIN D6 // this can be a no connect; not currently used #define UART_BAUD 38400 // Any baudrate from 300 to 115200 #define MIN_LOOPS 100 #define MAX_LOOPS 600 #define WATCH_LOOPS 100 int sensorValue = 0; // variable to store the analog value from SENSE_PIN bool detectBool = false; int detectCount = 0; int okCount = 0; volatile int loopCount = 0; // used to track our total number of elapsed loops during boot and each wake cycle volatile int targetLoops = MIN_LOOPS; // current target number of loops; we add WATCH_LOOPS to the current loop count each time we reset the device to extend the runtime of the watchdog #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ #define TIME_TO_SLEEP 600 /* Time ESP32 will go to sleep (in seconds) */ @@ -59,18 +64,34 @@ void print_wakeup_reason() { } } // volatile declaration will avoid any compiler optimization when reading variable values volatile size_t uart_received_bytes = 0; void onReceiveFunction(void) { // This is a callback function that will be activated on UART RX events size_t available = Serial1.available(); uart_received_bytes = uart_received_bytes + available; Serial.printf("onReceive Callback:: There are %d bytes available: ", available); while (available--) { Serial.print((char)Serial1.read()); } Serial.println(); } void setup() { // set up POWER_PIN and RESET_PIN as INPUT so that they are high impedence // we will set them to OUTPUT only when powering or resetting the device pinMode(POWER_PIN, INPUT); pinMode(RESET_PIN, INPUT); // GPIO0 (SENSE_PIN) sense pin is always INPUT pinMode(SENSE_PIN, INPUT); // built-in led is always OUTPUT pinMode(LED_PIN, OUTPUT); Serial.begin(115200); // setup serial Serial1.begin(UART_BAUD, SERIAL_8N1, UART_RX_PIN, UART_TX_PIN); delay(250); // wait a bit to let serial startup //Increment wake number and print it every wake cycle @@ -91,89 +112,96 @@ void setup() { // loop until we think we should go to sleep void loop() { // turn on the built-in LED digitalWrite(LED_PIN, LOW); // bitbang read the uartTxPin for uartTxReadCycles to hopefully see a HIGH (1) // for(int i = 0; i < uartTxReadCycles; i++) { // uartTxValue = digitalRead(uartTxPin); // if(uartTxValue == HIGH) { // // we only care that the UART went high while we were looking // // UART is high between transmissions if the device is on and responding // // UART floats around 0V and reads LOW when the t-beam is powered but "stuck" (requires hard boot) // // since we think the device is okay, we won't reset after pressing power // resetAfterPower = false; // break; // } // } sensorValue = analogRead(SENSE_PIN); Serial.println("State: " + String(sensorValue) + ", " + String(uart_received_bytes)); digitalWrite(LED_PIN, HIGH); if(sensorValue > 2000 && uart_received_bytes > 0) { // if GPIO0 is above 2000 when reading the ADC and the UART has received data // we think the t-beam is turned on and most likely functioning properly // turn off the led, count the loop, and zero the detect count digitalWrite(LED_PIN, HIGH); detectCount = 0; ++okCount; } else { // if sensorValue is 2000 or less, the device is probably off // if sensorvalue is 4095 and uart_received_bytes == 0, the device is probably "stuck" digitalWrite(LED_PIN, LOW); delay(5); digitalWrite(LED_PIN, HIGH); okCount = 0; ++detectCount; detectBool = true; Serial.println(detectCount); // we add one to targetLoops (up to a max of maxLoops) if the device is off // this behaves well since the UART tx detection isn't perfect but is a weird hack // TODO(jstockdale): fix the way the various loop limits interact if(targetLoops < MAX_LOOPS) { ++targetLoops; Serial.println("++targetLoops"); } } if(detectCount >= WATCH_LOOPS) { // we have observed the t-beam to be off for WATCH_LOOPS consecutive sense-loops // we will power on the device by pulling the POWER_PIN to ground for 500ms Serial.println("Powering ESP32-S3 ON"); digitalWrite(POWER_PIN, HIGH); pinMode(POWER_PIN, OUTPUT); digitalWrite(POWER_PIN, LOW); digitalWrite(LED_PIN, LOW); delay(500); digitalWrite(POWER_PIN, HIGH); digitalWrite(LED_PIN, HIGH); pinMode(POWER_PIN, INPUT); delay(100); if(uart_received_bytes == 0) { // since we didn't see any serial data tx from the t-beam, we think it is "stuck" // hard boot / reset the device by pulling RESET_PIN to ground for 500ms Serial.println("Resetting ESP32-S3 by pulling RST to GND"); digitalWrite(RESET_PIN, HIGH); pinMode(RESET_PIN, OUTPUT); digitalWrite(RESET_PIN, LOW); delay(500); digitalWrite(RESET_PIN, HIGH); pinMode(RESET_PIN, INPUT); delay(100); } // zero counters okCount = 0; detectCount = 0; // increase targetLoops by WATCH_LOOPS so we can see if we're successful or try until MAX_LOOPS if (targetLoops < MAX_LOOPS) { Serial.println("Current loop count: " + String(loopCount)); Serial.println("Updating target loops from: " + String(targetLoops)); targetLoops = (loopCount + 1 + WATCH_LOOPS > MAX_LOOPS) ? MAX_LOOPS : loopCount + 1 + WATCH_LOOPS; Serial.println("Updated target loops to: " + String(targetLoops)); } } // deep sleep to save power if we've seen WATCH_LOOPS consecutive ok loops // or performed MIN_LOOPS sense-loops where the t-beam is always-on // TODO(jstockdale): improve this logic if(okCount > WATCH_LOOPS || (detectBool == false && loopCount > MIN_LOOPS) || loopCount > targetLoops) { Serial.println("Going to sleep now"); Serial.flush(); esp_deep_sleep_start(); } ++loopCount; delay(100); } -
jstockdale created this gist
Jun 23, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,179 @@ /* Basic deep sleep sketch based on examples provided with xiao-esp32-s3 *** PRE-ALPHA *** Copyright 2024 @jstockdale/Off by One, Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. by @jstockdale */ int sensorPin = A9; // one method we use to determine state is via an analog voltage threshold on GPIO0 int powerPin = D8; // connect floating leg of t-beam power button to D8; used to power on the t-beam normally int resetPin = D10; // connect RST on t-beam to D10; used to hard boot if the t-beam has power but no uart activity int uartTxPin = D7; // connect TX on t-beam to D7; we bitbang read the tx line to see if the t-beam is alive int ledPin = LED_BUILTIN; // built in LED solid briefly on wakeup/boot, flashes dim while sensing, flashes bright if it detects t-beam is off or unresponsive int sensorValue = 0; // variable to store the analog value from sensorPin int uartTxValue = 0; // variable to store the state of the tx uart pin (digital read) int uartTxReadCycles = 10; // how many times should we bitbang read the UART tx pin to decide if the device is on (it's ok if this is very occasionally wrong because of the data on the tx pin) bool resetAfterPower = true; // if we don't see any activity on the UART, after pressing power we will reset/hard boot the device by pulling RST to ground using resetPin bool detectBool = false; int detectCount = 0; int okCount = 0; int loopCount = 0; // used to track our total number of elapsed loops during boot and each wake cycle int minLoops = 100; // minimum number of sense-read loops that will be performed (approx .1s per loop) if device is on int maxLoops = 600; // maximum number of sense-read loops to perform before sleeping (approx .1s per loop; hard limit) int targetLoops = minLoops; // current target number of loops; we add watchLoops to the current loop count each time we reset the device to extend the runtime of the watchdog int watchLoops = 100; // number of sense-read loops to perform before powering or rebooting device #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ #define TIME_TO_SLEEP 600 /* Time ESP32 will go to sleep (in seconds) */ RTC_DATA_ATTR int bootCount = 0; /* Method to print the reason by which ESP32 has been awaken from sleep */ void print_wakeup_reason() { esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); switch (wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0: Serial.println("Wakeup caused by external signal using RTC_IO"); break; case ESP_SLEEP_WAKEUP_EXT1: Serial.println("Wakeup caused by external signal using RTC_CNTL"); break; case ESP_SLEEP_WAKEUP_TIMER: Serial.println("Wakeup caused by timer"); break; case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("Wakeup caused by touchpad"); break; case ESP_SLEEP_WAKEUP_ULP: Serial.println("Wakeup caused by ULP program"); break; default: Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); break; } } void setup() { // set up powerPin and resetPin as INPUT so that they are high impedence // we will set them to OUTPUT only when powering or resetting the device pinMode(powerPin, INPUT); pinMode(resetPin, INPUT); // UART and GPIO0 (sensorPin) sense pin are always INPUT pinMode(uartTxPin, INPUT); pinMode(sensorPin, INPUT); // built-in led is always OUTPUT pinMode(ledPin, OUTPUT); Serial.begin(115200); // setup serial delay(250); // wait a bit to let serial startup //Increment wake number and print it every wake cycle ++bootCount; Serial.println("Sleep cycle count: " + String(bootCount)); //Print the wakeup reason for ESP32 print_wakeup_reason(); /* here we configure the wake up source we set our ESP32 to wake up every TIME_TO_SLEEP seconds */ esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds"); } // loop until we think we should go to sleep void loop() { // turn on the built-in LED digitalWrite(ledPin, LOW); // bitbang read the uartTxPin for uartTxReadCycles to hopefully see a HIGH (1) for(int i = 0; i < uartTxReadCycles; i++) { uartTxValue = digitalRead(uartTxPin); if(uartTxValue == HIGH) { // we only care that the UART went high while we were looking // UART is high between transmissions if the device is on and responding // UART floats around 0V and reads LOW when the t-beam is powered but "stuck" (requires hard boot) // since we think the device is okay, we won't reset after pressing power resetAfterPower = false; break; } } sensorValue = analogRead(sensorPin); Serial.println("State: " + String(sensorValue) + ", " + String(uartTxValue)); digitalWrite(ledPin, HIGH); if(sensorValue > 2000 && uartTxValue == 1) { // if GPIO0 is above 2000 when reading the ADC and the UART recently went HIGH // we think the t-beam is turned on and most likely functioning properly // turn off the led, count the loop, and zero the detect count digitalWrite(ledPin, HIGH); detectCount = 0; ++okCount; } else { // if sensorValue is 2000 or less, the device is probably off // if sensorvalue is 4095 and uartTxValue is 0, the device is probably "stuck" digitalWrite(ledPin, LOW); delay(5); digitalWrite(ledPin, HIGH); okCount = 0; ++detectCount; detectBool = true; Serial.println(detectCount); // we add one to targetLoops (up to a max of maxLoops) if the device is off // this behaves well since the UART tx detection isn't perfect but is a weird hack // TODO(jstockdale): fix the way the various loop limits interact if(targetLoops < maxLoops) { ++targetLoops; Serial.println("++targetLoops"); } } if(detectCount >= watchLoops) { // we have observed the t-beam to be off for watchLoops consecutive sense-loops // we will power on the device by pulling the powerPin to ground for 500ms Serial.println("Powering ESP32-S3 ON"); digitalWrite(powerPin, HIGH); pinMode(powerPin, OUTPUT); digitalWrite(powerPin, LOW); digitalWrite(ledPin, LOW); delay(500); digitalWrite(powerPin, HIGH); digitalWrite(ledPin, HIGH); pinMode(powerPin, INPUT); delay(100); if(resetAfterPower) { // since we didn't see the tx pin go high on the t-beam, we think it is "stuck" // we're also hard booting / resetting the device by pulling resetPin to ground for 500ms Serial.println("Resetting ESP32-S3 by pulling RST to GND"); digitalWrite(resetPin, HIGH); pinMode(resetPin, OUTPUT); digitalWrite(resetPin, LOW); delay(500); digitalWrite(resetPin, HIGH); pinMode(resetPin, INPUT); delay(100); } // zero counters okCount = 0; detectCount = 0; if (targetLoops < maxLoops) { Serial.println("Current loop count: " + String(loopCount)); Serial.println("Updating target loops from: " + String(targetLoops)); targetLoops = (loopCount + 1 + watchLoops > maxLoops) ? maxLoops : loopCount + 1 + watchLoops; Serial.println("Updated target loops to: " + String(targetLoops)); } } // deep sleep to save power if we've seen watchLoops consecutive ok loops // or performed minLoops sense-loops where the t-beam is always-on if(okCount > watchLoops || (detectBool == false && loopCount > minLoops) || loopCount > targetLoops) { Serial.println("Going to sleep now"); Serial.flush(); esp_deep_sleep_start(); } ++loopCount; delay(100); }