This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Power Cycling Safeguard

Details:

nRF52832

SDK 14.1 with matching SD

Compiling with GCC

I am trying to solve the following problem:

My device is powered by a coin cell (Manganese dioxide). When these cells reach their capacity their internal resistance increases. 

If my device attempts a Bluetooth communication this may cause the battery voltage to dip below the brownout voltage - triggering a system reset.

It is then possible that during startup the device draws too much current and dies again, thereby creating a loop of power cycling which will continue to drain the battery until dead, but also potentially corrupt flash memory in the process.

My current methodology is to somehow keep a count of the number of resets that gets set to zero after startup, if the device resets 5 times without finishing the startup process, kill the startup and go into system off mode.

Unfortunately, no registers are retained on a brownout reset, so I cannot use them to store information on the reset.

I could use flash, but there is a risk of corrupting all of the flash data in the startup sequence as the power could die during initialisation or mid-write.

The solution that seems to be the most elegant is to simply store a variable in RAM, and create a "noinit" section as described here: noinit example

This seems to work for watchdog resets and software resets, but doesn't seem to work for pin resets or brownout resets. On a pin reset (easier to do), the values on reset are pretty consistent, which leads me to believe that some other part of the program that I'm not aware of it writing to that memory?

Are there any other methodologies I could try here? What is the Nordic best practice around this?

  • Wow, I bow to your wisdom. Setting nrf_power_dcdcen knocked about half of the power consumption for the BT radio TX. I had assumed the soft devices used the power driver, and would initialise it with DCDCEN set. 

    I'm just about to test residual battery voltage, do you have a recommended way of implementing it, or any example code that I could work from?

    You are correct, we don't have any external power regulator.

  • Ooh, recognition - thanks! Ratiometric measurements are best, but I would need to see a schematic privately to advise on best course. Your requirement is really to know if the transmission is likely to trigger a brown-out, so one option is to simply turn on something for a fixed short period and measure voltage drop before and at the end, then transmit advertising packet which can include voltage diff or otherwise sent out over unarticulated. Repeat until battery exhausted. Last value received shows worst case level at which transmission will fail at current battery temperature; now you know when to stop .. characterizing at a range of battery temperatures allows use of a look-up table for interpolation, unless you know for example that the device is clamped at body temperature.

    Simply advertising can be handled as above; if your device is also connecting then more measurements will be required but the trick is to avoid absolute measured values and instead use ratiometric values so individual device calibration is not required.

  • For anyone who comes across the same issue I ended up implementing both of these solutions which have been tested on a few partially depleted batteries:

    1. If startup voltage is too low, halt startup.

    2. Monitor the internal resistance of the board by measuring the voltage before and after turning the LED's on.

    Also, the capacitor mentioned makes a big difference (testing a board with a capacitor vs. one with no capacitor the board with the PSU capacitor performed a lot better)

Related