[DeviceOS 6.1.0] B524 freezes on ULTRA_LOW_POWER wakeup?

We have a device that every 2-ish minutes wakes up, listens for a bluetooth beacon (using the BeaconScanner library) and goes into sleep again using ULP.

However, we see that on wakeup (no function after System.sleep is executed), the device hangs in an idle state until the HW watchdog restarts the device. It can be seen on the power consumption below:


All the small peaks are when the devices wakes up, measures for a couple of seconds and goes to sleep again. However, you can see that the device wakes up, never does anything until the hardware watchdog resets and it starts connecting again (the big power consumption peak)

We are using

SYSTEM_MODE(SEMI_AUTOMATIC);                                             // Semi-automatic mode for controlling connectivity manually
SYSTEM_THREAD(ENABLED);                                                  // Separate System Thread Enabled

The sleep function is as below:

void Class::measurementSleep(int measurementDelay, std::chrono::seconds measurementSleepTime, bool hallEnabled)
{
   Class::instance().setPanicCode(234);
   // Initialize Power Configuration
   SystemSleepConfiguration measurementSleepConfig;
   // Power Configuration using ULTRA_LOW_POWER, HALL_PIN for restart and compensated sleep duration - SystemSleepMode::ULTRA_LOW_POWER
   measurementSleepConfig.mode(SystemSleepMode::ULTRA_LOW_POWER).duration(Class::instance().getCompensatedSleepTime(measurementDelay, measurementSleepTime));

   // Set error code
   Class::instance().setPanicCode(216);
   if (hallEnabled)
   {
      measurementSleepConfig.gpio(IOConstants::HALL_PIN, CHANGE);
   }
   Class::instance().setPanicCode(217);
   // Handle network standby for cellular interface based on constants or time limit
   if (Class::instance().getNetworkStandby()) // (measurementSleepTime.count() * Class::instance().getNumberOfMeasurements()) < CloudConstants::NETWORK_STANDBY_LIMIT)
   {
      classLogger.info("Setting network to standby");
      measurementSleepConfig.network(NETWORK_INTERFACE_CELLULAR, SystemSleepNetworkFlag::INACTIVE_STANDBY);
   }

   // Ensure onboard peripherals are put to sleep before sleeping device
   ClassPower::instance().sleepFuelGauge();
   Class::instance().setPanicCode(218);
   // Do one last system/watchdog checkin
   Class::instance().systemCheckin();

   classLogger.info("Going to sleep...");
   // Execute SystemSleepConfiguration and enter sleep
   Class::instance().setPanicCode(219);
   SystemSleepResult result = System.sleep(measurementSleepConfig);
   Class::instance().setPanicCode(220);
   // If device was woken up due to hall effect being triggered
   if (result.wakeupReason() == SystemSleepWakeupReason::BY_GPIO)
   {
      Class::instance().setPanicCode(268);
      classLogger.info("Device was woken up by hall effect sensor");
      // Hall sensor was triggered during sleep, so let's restart! or should we use resetPending and compile all measurements beforehand?
      System.reset(RESET_APP_ENUM::HALL_MEASUREMENT_SLEEP, RESET_NO_WAIT);
      // set pending, transmit measurements and restart?
   }
  Class::instance().setPanicCode(273);
}

We recieve the panic/error code 219, which means it never gets to after the System.sleep (i.e. error code 220).

Any idea on what goes wrong?

There is a possibility you are running into one of two issues:

How is your sensor configured? Is there an interface with a push-pull driver that outputs high or low logic level? Or do you have an external pull-up or pull-down? What size?

However, I think you may be running into an issue on the nRF52 with CHANGE interrupts in ULP or STOP mode sleep.

If wake on GPIO CHANGE is enabled and the interrupt triggers while you are in the process of going to sleep, the device may never wake. This does not happen in hibernate, or if using rising or falling.

If you need to use a change interrupt for some reason, another thing to test is to using attachInterrupt() to attach a CHANGE interrupt to your wake pin in setup(). The function does not need to do anything, but it needs to be assigned. This has an effect on how the wake interrupt is configured, and may or may not make a difference in behavior in your case.

Thank you for the detailed reply @rickkas7, I'll try to change my interrupt type and test it out.

Our sensor is sending bluetooth beacons, so we are solely utilizing the bluetooth-part of the B524 module - there's no wired interface being utilized in the above scenario.

The weird thing is it seems (like a previous issue I've had) that adding some delay (100ms) before BLE.on and some delay after BLE.off, seem to mitigate the high power consumption issue after the wakeup/watchdog reset sequence, after it froze. However I really do not like the "symptom-like fix" it provides, as I'm still unsure what the underlying issue is. Also, it seems to wake up at the correct time, so I'm unsure why hangs/freezes during wakeup, but it could maybe be some threading/bluetooth? I'm guessing here.

Oh, that's a different situation. The delay, while not ideal, is probably is necessary. Some BLE operations run on a separate thread, so it probably is necessary to provide time for those operations to complete. Ideally there would be a way to wait for those operations to complete, but I don't think there's an API for that.

1 Like

I've tried increasing the delay with 200 ms for turning on and off the BLE, I still get the error from time to time, and I'm having a hard time debugging it without using JTAG+BLE.

Does it make sense to incorporate BLE.end() before shutting it off? and BLE.begin() after turning it on?

Is there a reason you need to turn it off? You should stop scanning if you are doing that, but otherwise it should turn on and off automatically within Device OS.

Same for cellular, except in the case where you want to wake and not reconnect to cellular, in which case you do need to manually disconnect before going to sleep.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.