Issue when USB is disconnected

Appreciate the feedback regarding locked up Boron and related terminology. The lock-up happens by unplugging the USB during the delay. I have a power switch built in so it is easy enough to recycle but that’s not ideal.

I am also happy to share my firmware since so many techniques where adapted from the forum. Note that short of using the Adafruit TPL5111 the code below is demonstrating my lowest in-line sleep power consumption thus far. Suggestions for further improvements related to power reduction (or anything for that matter) are welcome!

#include "Particle.h"
#include <DS18B20.h>
#include <math.h>
#include <DiagnosticsHelperRK.h>

// DS18B20 set up
const int MAXRETRY = 4; // retry limit
DS18B20 ds18b20(D4, true); //Sets Pin D4 for Temp Sensor, D3 Low, D5 High

// LoopDelayDefault constant
const int LOOPDEFAULT = 3540000;  // roughly 1 hour

String  fstr;
String  myID;
String  firmware;
String  vardata;
String  sensordata;
double  celsius;
double  fahrenheit;
int     loopcount;
bool    isChargingEnabled;
int     delaymode;
int     loopdelay;   

// Function prototypes  
// Could be Particle functions
int     chargeStatus(String arg1);
int     powerSource(String arg1);
int     chargEnabled(String arg1);

// Run application on its own thread
SYSTEM_THREAD(ENABLED);
// System setup
SYSTEM_MODE(SEMI_AUTOMATIC);

// Logging
SerialLogHandler logHandler(LOG_LEVEL_ALL);

// Disable battery charging    
PMIC power;

// Battery
FuelGauge fuel;

// Cellular signal;
CellularSignal sig;

// Visual indicator that we are publishing
const int BLUELED = D7; 

/*******************************************************************************
 * Function Name  : setup
 * Description    : None.
 *******************************************************************************/
void setup() {
    
    // Initialize vars
    fstr = "";
    myID = "";
    firmware = "CloudAppV104";
    sensordata = "";
    vardata = "";
    celsius;
    fahrenheit;
    isChargingEnabled = true;
    delaymode = 0;
    loopdelay = LOOPDEFAULT;  
    
    EEPROM.get(10, loopcount);
    if(loopcount == 0xFFFFFFFF) {
        // EEPROM was empty -> initialize value
        loopcount = 0;
    }
   
    // Delay for serial
    Serial.begin();
    delay(5000);
  
    // Set voltage target objective
    power.setChargeVoltage(4208);  // default was 4112
    
    // Set needed pins
    pinMode(BLUELED, OUTPUT);
    pinMode(D3, OUTPUT);
    pinMode(D5, OUTPUT);
    
    // Onboard sensor (not configured as an array or bus)
    digitalWrite(D3, LOW);   // ground
    digitalWrite(D5, HIGH);  // voltage
    
    // Connect to the cloud if not already
    if (!Particle.connected()) {
        Particle.connect(); 
        delay(15000);
    }
    
    // Log Messages
    Log.info("System version: %s", (const char*)System.version());
    Log.info("System deviceID: %s", (const char*)System.deviceID());
    
    // End of setup
    Log.info("Setup end");
}


/*******************************************************************************
 * Function Name  : loop
 * Description    : None.
 *******************************************************************************/
void loop() {
    // Loop start
    Log.info("Loop start");
  
    // Are we connected?
    if (Particle.connected()) {
        Log.info("Already connected to the cloud");
    } else {
        Log.info("Connecting to the cloud");
        Particle.connect();
        delay(15000);
    }
   
    // Cellular signal
    sig = Cellular.RSSI();
    
    // Loopcount
    loopcount++;
    // Signed int - lets not overflow it
    if (loopcount == 2147483647) loopcount = 0;
    EEPROM.put(10, loopcount);
    
    // Get the temperatures
    getTemp();
    
    // Adjust for testing
    fahrenheit = fahrenheit + 0;
    
    // Format the temperature
    fstr = String::format("%04d",int(fahrenheit));
    
    // If USB is connected then there is no point in disabling cellular, just
    // use simple delay mechanism
    if (powerSource("x") < 5) 
    {
        if (delaymode==0) {
            // if we were on delaymode 0 (battery) but are
            // now plugged in, change to 1 (USB).
            delaymode=1;
        }
    }
    // If we are back on battery then flip back 
    // to the most efficient mode.
    else delaymode = 0;
    
    // Allow battery charging?
    if ((celsius < 0) || (powerSource("x") > 4)) {
        power.disableCharging();
        isChargingEnabled=false;
    } else {
        power.enableCharging();
        isChargingEnabled=true;
    }
    
    // START PUBLISHING
    // START PUBLISHING
    digitalWrite(BLUELED, HIGH);
    vardata = String::format("F=%s L=%d D=%d M=%d P=%d E=%d C=%d",(const char*)firmware,loopcount,loopdelay,delaymode,powerSource("x"),isChargingEnabled,chargeStatus("x"));
    sensordata = String::format("V1|%2.2f|%f|V=%f|S=%.02f%%|Q=%.02f%%|%s",celsius,fuel.getSoC(),fuel.getVCell(),sig.getStrength(),sig.getQuality(),(const char*)vardata);
    
    // Trigger the webhook
    if (Particle.connected()) {
        Particle.publish("sensordata", sensordata, PRIVATE, NO_ACK);
        // Write it to the log
        Log.info(sensordata);
    }
    
    delay(5000);
    digitalWrite(BLUELED, LOW);
    // END PUBLISHING
    // END PUBLISHING
    
    // For testing
    // delaymode = 0;
    
    // delaymode 1 is the default when USB
    // is connected.  delaymode 0 when running on battery.
    if (delaymode==1) { 
        // USB
        Log.info("Delay (2 minutes) at %d past the hour", Time.minute());
        delay(115000);
    } else {
        // Battery (delaymode 0)
        // 02mAh with no pulse - BSF WITHOUT TPL5111
        // ~1%/day on 6600mAh Li-ion battery
        // how can we get this down even lower??
        Log.info("Sleep with %d seconds at %d past the hour", (loopdelay/1000), Time.minute());
        Cellular.off();
        delay(5000);
        System.sleep({}, {}, (loopdelay/1000)); 
        Cellular.on();
        Cellular.connect();
        delay(5000);
    }
    
    // Loop end
    Log.info("Loop end");
}


/*******************************************************************************
 * Function Name  : getTemp
 * Description    : None.
 *******************************************************************************/
void getTemp() {
    // Only fire up the probe when needed
    digitalWrite(D5, HIGH);  
    delay(1000);
    float _temp;
    int   i = 0;
    
    do { _temp = ds18b20.getTemperature(); } 
    while (!ds18b20.crcCheck() && MAXRETRY > i++);
    if (i < MAXRETRY) {
        celsius = _temp;
        fahrenheit = ds18b20.convertToFahrenheit(_temp);
    } else {
        celsius = fahrenheit = -99;
    }
    // Turn the probe off
    digitalWrite(D5, LOW);  // voltage
}


/*******************************************************************************
 * Function Name  : chargeStatus
 * Description    : is battery charging
 *******************************************************************************/
int chargeStatus(String arg1) {
    Log.info("Charging status requested: %d", (((power.getSystemStatus() >> 4) & 0x3)==2));
    return (((power.getSystemStatus() >> 4) & 0x3)==2);
}


/*******************************************************************************
 * Function Name  : powerSource
 * Description    : what is our power source?
 *******************************************************************************/
int powerSource(String arg1) {
    // POWER_SOURCE_UNKNOWN = 0
	// POWER_SOURCE_VIN = 1
	// POWER_SOURCE_USB_HOST = 2
	// POWER_SOURCE_USB_ADAPTER = 3
	// POWER_SOURCE_USB_OTG = 4
	// POWER_SOURCE_BATTERY = 5
    int pwr = DiagnosticsHelper::getValue(DIAG_ID_SYSTEM_POWER_SOURCE);
    Log.info("Power source is: %d", pwr);
    return pwr;
}


/*******************************************************************************
 * Function Name  : chargEnabled
 * Description    : Is charger enabled
 *******************************************************************************/
int chargEnabled(String arg1) {
    Log.info("Is charging enabled requested: %d", isChargingEnabled);
    return (int) isChargingEnabled;
}