Since nothing beats a test case - I’ve cut back my app to the basic code that sets up and processes the input. This can be run stand-alone, as long as you have a meter to test the WKP/A7 pin, confirming the pull-up is not re-applied after System.sleep() initiated reset:
#include "Particle.h"
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
// Note A7 is also WKP
#define PWRGOOD A7
// Set base timing intervals for various functional actions (mS)
const unsigned short DEBOUNCE_TIMEBASE=20;
typedef struct InputStruct{
bool state;
bool raw;
unsigned short hist;
} InputStruct;
// digital Input variables (set aynchronously by interrupt or via timer event)
// pwrGood - from SMPS module (high impedance open drain if regulated output between 4 and 6V).
volatile InputStruct pwrGood;
Timer inputTimer(DEBOUNCE_TIMEBASE, _inputHandler);
//SerialLogHandler logHandler(LOG_LEVEL_ALL);
SerialLogHandler logHandler(LOG_LEVEL_TRACE);
// consume any typed char
void serialEvent()
{
char c;
while (Serial.available())
c = Serial.read();
switch (c) {
case 'f' :
Log.info("serEvt: Firmware DFU requested");
delay(100);
System.dfu();
break;
case 's' :
Log.info("serEvt: set pinMode requested");
pinMode(PWRGOOD,INPUT_PULLUP);
break;
case 'r' :
Log.info("serEvt: reset requested");
//System.sleep(SLEEP_MODE_DEEP,15);
//System.sleep(SLEEP_MODE_SOFTPOWEROFF,15);
delay(100);
System.reset();
break;
case 'z' :
Log.info("serEvt: sleep mode/reset requested");
//System.sleep(SLEEP_MODE_DEEP,15);
//System.sleep(SLEEP_MODE_SOFTPOWEROFF,15);
delay(100);
System.sleep(SLEEP_MODE_DEEP,10);
break;
}
}
void setup() {
//Configure Sensing
pinMode(PWRGOOD,INPUT); //WKP pin (PGOOD, requires pull-up)
pinMode(PWRGOOD,INPUT_PULLUP); //WKP pin (PGOOD, requires pull-up)
// disabled for now, to reduce variable factors //
// attachInterrupt(PWRGOOD, _pwrInterrupt, CHANGE);
// initialise
pwrGood.raw = (HIGH == digitalRead(PWRGOOD));
inputTimer.start();
Serial.begin();
// seems to need several seconds to set up Serial if you want it to wait for terminal reliably
delay(2000);
while(!Serial.isConnected()) {
delay(500);
}
Log.info("setup(); pwrGood.raw: %d", pwrGood.raw);
}
void loop() {
Log.info("loop(); Pwr Good.raw/.state: %d/%d", pwrGood.raw, pwrGood.state);
delay(2500);
}
// timer handler for physical inputs (Switches, Sensing)
// Called once per INPUT_TIMEBASE interval (mS) to process current values of input globals
// Effectively, used to debounce inputs.
// The variables processed by this handler could change in real-time due to interrupts,
// however, the debounce function won't care - it just tests the raw value once per call.
void inputDebouncer(volatile InputStruct &input)
{
if (input.raw) input.hist++;
else input.hist--;
if (input.hist > 8) input.hist = 8;
if (input.hist < 1) input.hist = 1;
//hysteresis
if (input.state) {
if (3 > input.hist) input.state = false;
} else {
if (6 < input.hist) input.state = true;
}
}
void _inputHandler()
{
// polling power good IO for now, in case interrupt handler issue after sleep()
pwrGood.raw = (HIGH == digitalRead(PWRGOOD));
// debounce inputs
inputDebouncer(pwrGood);
}
// if power regulator running, pwr good input is low
void _pwrInterrupt(){
pwrGood.raw = (HIGH == digitalRead(PWRGOOD));
}
// End
While it’s probably not pertinent, I left in my timer based debounce code, to reflect the actual use case.
Sample output:
Response after post-DFU reset:
0000002054 [app] INFO: setup(); pwrGood.raw: 1
0000002054 [app] INFO: loop(); Pwr Good: 1
0000007057 [app] INFO: loop(); Pwr Good: 1
0000012059 [app] INFO: loop(); Pwr Good: 1
0000013072 [app] INFO: serEvt: sleep mode/reset requested
<-- usb serial disconnect
in new terminal session -->
Response after System.sleep()
0000002054 [app] INFO: setup(); pwrGood.raw: 0
0000002054 [app] INFO: loop(); Pwr Good: 0
0000007057 [app] INFO: loop(); Pwr Good: 0
0000012057 [app] INFO: serEvt: set pinMode requested
0000012059 [app] INFO: loop(); Pwr Good: 0
0000017062 [app] INFO: loop(); Pwr Good: 0
[Edited to include reset() and sleep() test.]
If the System.reset() call is used, the Electron behaves as expected, and re-asserts input pull-up in setup(). Only System.sleep(…) calls seem not to restore the pull-up, and actively prevent the pull-up being subsequently restored by repeated pinMode() requests (‘s’ key action above).