Last active
July 8, 2023 13:54
-
-
Save tablatronix/efa5d525d704e4b8b9ece31af0c99fdf to your computer and use it in GitHub Desktop.
example to use eeprom to store reset states to trigger an action on purposeful resets
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 characters
/** | |
* detect mutiple resets in order to trigger events using resets or power cycles alone | |
* reset board within resettimeout(5000ms) after boot and do so resetcnt(4) times | |
* has led indicator of reset window and serial output for better clarity | |
* | |
* This is blocking using a delay for timeout, can easily be changed to use a timer | |
* This is not wear leveled, but you could replace with spiffs(slower), or use a ring counter to level it | |
* You could also add a smaller window for reset by adding a pre-delay, to prevent reduce flash writes during glitchy or fast power cycles | |
* either way USE WITH CAUTION as you are writing twice every time your reset or repower the board, soft resets and wdt should not trigger this however. | |
* | |
* @author tablatronix | |
**/ | |
#include <EEPROM.h> | |
#ifdef ESP8266 | |
extern "C" { | |
#include "user_interface.h" | |
} | |
#endif | |
int addr = 0; // eeprom address to store reset cnt | |
int resetcnt = 4; // how many resets to trigger | |
int resettimeout = 5000; // ms to timeout | |
#define RESET_LED LED_BUILTIN | |
const char * const RST_REASONS[] = | |
{ | |
"REASON_DEFAULT_RST", | |
"REASON_WDT_RST", | |
"REASON_EXCEPTION_RST", | |
"REASON_SOFT_WDT_RST", | |
"REASON_SOFT_RESTART", | |
"REASON_DEEP_SLEEP_AWAKE", | |
"REASON_EXT_SYS_RST" | |
}; | |
void blinkled(int pin, int blinks){ | |
for(int i=0;i<blinks-1;i++){ | |
digitalWrite(RESET_LED, LOW); | |
delay(100); | |
digitalWrite(RESET_LED, HIGH); // leave led on | |
delay(100); | |
} | |
} | |
int getResetReason(){ | |
const rst_info * resetInfo = system_get_rst_info(); | |
Serial.print(F("system_get_rst_info() reset reason: ")); | |
Serial.println(RST_REASONS[resetInfo->reason]); | |
return resetInfo->reason; | |
} | |
void setResetCounter(int cnt){ | |
Serial.println("RESET write: " + (String)cnt); | |
EEPROM.write(addr,cnt); | |
EEPROM.commit(); | |
} | |
void handleReset(){ | |
// these are not the resets we are looking for | |
if(getResetReason() != REASON_EXT_SYS_RST) return; | |
pinMode(RESET_LED, OUTPUT); | |
digitalWrite(RESET_LED, HIGH); // turn led off | |
EEPROM.begin(512); | |
// get resets cnt | |
int resets = EEPROM.read(addr); | |
Serial.println("RESET Count: " + (String)resets); | |
// are we there yet? | |
if(resets == resetcnt-1){ | |
setResetCounter(0); | |
blinkled(RESET_LED,8); | |
handleResetCallback(); | |
return; | |
} | |
blinkled(RESET_LED,2); | |
digitalWrite(RESET_LED, LOW); // turn led off | |
// bump resets | |
resets++; | |
setResetCounter(resets); | |
// timeout | |
delay(resettimeout); | |
Serial.println("RESET timeout"); | |
setResetCounter(0); | |
digitalWrite(RESET_LED, HIGH); // turn led off | |
} | |
void handleResetCallback(){ | |
Serial.println("RESET CALLBACK"); | |
// do stuff | |
} | |
// minimal function example | |
bool ifResetAction(){ | |
int numresets = 4; | |
int resettimeout = 5000; | |
int addr = 0; | |
bool resetstate = false; | |
const rst_info * resetInfo = system_get_rst_info(); | |
if(resetInfo->reason == 6){ | |
EEPROM.begin(512); | |
int resetcnt = EEPROM.read(addr); | |
Serial.println("RESET: reset count = "+(String)(resetcnt+1)); | |
resetstate = (resetcnt == numresets-1); | |
resetcnt = (resetcnt+1) % (numresets); | |
EEPROM.write(addr,resetcnt); | |
EEPROM.commit(); | |
if(resetstate) return true; | |
Serial.printf("RESET: blocking for %d ms\n",resettimeout); | |
delay(resettimeout); | |
Serial.println("RESET: timeout reached"); | |
EEPROM.write(addr,0); | |
EEPROM.commit(); | |
} | |
return false; | |
} | |
void setup(){ | |
Serial.begin(115200); | |
delay(500); | |
Serial.println("\nSetup"); | |
handleReset(); | |
// if(ifResetAction()) Serial.println("RESET: TRIGGERED"); // minimal example function | |
} | |
void loop(){ | |
Serial.println(millis()); | |
delay(1000); | |
} |
added single function minimal example
Tested on adafruit huzzah and official (amica) nodemcu 1.0
I have never see a reset method other than REASON_EXT_SYS_RST
I suppose I should add REASON_DEFAULT_RST
support in case it is ever encountered, but I would like to know how it works first. Maybe power up and pull enable after ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sorry for all the updates, I accidentally had my ST gist plugin set to auto upload.
added led blinking status
This is a proof of concept, it could be reduced to a few lines of inline code and stuck in another sketch to add functionality, maybe I will add a tiny implementation example.