Application Guidance - Use of Watchdog but Low Power Infinite Sleep?

So I discovered some unexpected yet explainable behavior and looking for some guidance on best way to account for it. It seems the "gotcha" is here:

nRF52 platform (Boron, B-Series SoM, Argon, Tracker SoM): stop() is not available due to hardware limitations. Watchdog.start - Watchdog - Hardware | Reference | Particle

I recently added an infinite Ultra_Low_Power sleep mode any time the battery SoC is less than 5%. This way, the device enters an infinite sleep state until the user applies power. This should be better on the battery and also prevent many "brown outs" and other rare unattended side affects as the battery is fully depleted.

In my case, I'm using the Low_Bat_UC as the interrupt to immediately wake the device up if the user happened to apply power. This is my Low Battery Sleep State:

case st_LowBatterySlp:
      {

       // Turn off the software and hardware watchdog. We might sleep a very long time. 
        ab1805.stopWDT(); 
        Watchdog.stop(); // This actually doesn't do anything on the nRF52 as once started it can't be stopped

        //Configure for sleeping. The only way we can wake back up is from the interrupt that power was applied. 
        SystemSleepConfiguration config;
        config.mode(SystemSleepMode::ULTRA_LOW_POWER)
              .gpio(LOW_BAT_UC, FALLING);
        SystemSleepResult result = System.sleep(config);

        //When we do wake back up finally... start the watchdog and then publish the status - this will also cause us to connect to the cloud. 
        Watchdog.start(); //Start the Watchdog
        ab1805.resumeWDT();
        ab1805.updateWakeReason();

        newState = st_PubStat; // Go connect to the cloud and publish something. 
        
      }
      break;

This is the Watchdog implementation. I choose 250 min as it seemed acceptable in my scenario. Note, I also use an AB1805 external RTC as a hardware watchdog to protect against application code issues. I use the MCU hardware watchdog as more of a cloud side watchdog.

  // Watchdog is always active and only gets pet when the device publishes a successful event. ACK. 
  Watchdog.init(WatchdogConfiguration()
    .capabilities(WatchdogCap::SLEEP_RUNNING)
    .timeout(250min));
  Watchdog.start();

I only pet the watchdog with a successful publish ack using the PublishQueuePosix library callback. This is my "cloud side" watchdog. Basically if the device never gets an acknowledge from a publish event in 250 minutes, something is wrong and should also reset itself.

PublishQueuePosix::instance().withPublishCompleteUserCallback([](bool succeeded, const char *eventName, const char *eventData) {
      if (succeeded){
        Watchdog.refresh();
        // Log.info("Refresh the watchdog... an event was successfully published with ACK: %s", eventName);
      }
      else{
        // Log.error("Publish failed: %s", eventName);
      }
    });

So now the dilemma... if I want to sleep for an infinite period of time due to low battery, but once the watchdog is started, it can't be stopped, what do I do?

Option 1: Don't sleep for an infinite period of time, rather, sleep for say 240 minutes (some duration less than the hardware watchdog. Simply wake up, pet the watchdog manually here as well, check the battery SoC again and if it is still below 5% then just stay in the same state and immediately go back to sleep. This should be minimal impact to battery SoC every 240 minutes.

Option 2: Before sleeping, update the hardware watchdog timeout to the maximum value 131071 sec or ~1.5 days, likely still check.

Option 3: Somehow some way stop the watchdog? Seems strange to not be able to stop it once it's started but that's what the docs say and I believe the docs. :slight_smile:

Other ideas?

You can't stop the watchdog on nRF52. If you System.reset() and don''t start it again, it will be stopped, but it requires a reset.

Option 1 is usually the best idea. As long as you turn off cellular before sleep, it will stay off on wake, and you can go back to sleep on nRF52 in under a second and the MCU only uses less than 10 mA so the power consumption is practically 0.

1 Like

Thanks @rickkas7 I figured that would work well.

I ended up doing this and it now does not get reset by the watchdog and mostly stays sleep, besides the very brief waking up every 240 mins to pet the watchdog. Appreciate the guidance!

    // Sleep without an alarm due to low battery. Only way to wake up out of this state is by power being applied. 
    // This should prevent random issues with brownouts and other issues that might cause the device to hang with low battery. 
    case st_LowBatterySlp:
      {

        // Turn off the hardware watchdog. We might sleep a very long time. 
        ab1805.stopWDT(); 

        //Configure for sleeping. We will sleep for 240 minutes (4 hours). We can only sleep this long as the watchdog will eventually reset the device if we don't wake up after 250 minutes. 
        // We will wake up either for power being applied or due to a 240 minute sleep duration. When we do, let's check why, we power is still not applied, then we go back to sleep. 
        SystemSleepConfiguration config;
        config.mode(SystemSleepMode::ULTRA_LOW_POWER)
              .gpio(LOW_BAT_UC, FALLING)
              .duration(240min);
        SystemSleepResult result = System.sleep(config);

        //When we do wake back up finally... start and pet the watchdogs. 
        Watchdog.refresh(); 
        ab1805.resumeWDT();
        ab1805.updateWakeReason();

        //If we are now powered, then let's go publish status. Otherwise, we stay in this state and go back to sleep for another 240 minutes. 
        if (sns.isPowered("cmd") == 1 or System.batteryCharge() > 5){
          newState = st_PubStat;
        }        
      }
      break;
  }
2 Likes