# nRF52 Power Management ## Overview The nRF52 Power Management module provides battery protection features to prevent over-discharge, minimise likelihood of brownout and flash corruption conditions existing, and enable safe voltage-based recovery. ## Features ### Boot Voltage Protection - Checks battery voltage immediately after boot and before mesh operations commence - If voltage is below a configurable threshold (e.g., 3300mV), the device configures voltage wake (LPCOMP + VBUS) and enters protective shutdown (SYSTEMOFF) - Prevents boot loops when battery is critically low - Skipped when external power (USB VBUS) is detected ### Voltage Wake (LPCOMP + VBUS) - Configures the nRF52's Low Power Comparator (LPCOMP) before entering SYSTEMOFF - Enables USB VBUS detection so external power can wake the device - Device automatically wakes when battery voltage rises above recovery threshold or when VBUS is detected ### Early Boot Register Capture - Captures RESETREAS (reset reason) and GPREGRET2 (shutdown reason) before SystemInit() clears them - Allows firmware to determine why it booted (cold boot, watchdog, LPCOMP wake, etc.) - Allows firmware to determine why it last shut down (user request, low voltage, boot protection) ### Shutdown Reason Tracking Shutdown reason codes (stored in GPREGRET2): | Code | Name | Description | |------|------|-------------| | 0x00 | NONE | Normal boot / no previous shutdown | | 0x4C | LOW_VOLTAGE | Runtime low voltage threshold reached | | 0x55 | USER | User requested powerOff() | | 0x42 | BOOT_PROTECT | Boot voltage protection triggered | ## Supported Boards | Board | Implemented | LPCOMP wake | VBUS wake | |-------|-------------|-------------|-----------| | Seeed Studio XIAO nRF52840 (`xiao_nrf52`) | Yes | Yes | Yes | | RAK4631 (`rak4631`) | Yes | Yes | Yes | | Heltec T114 (`heltec_t114`) | Yes | Yes | Yes | | GAT562 Mesh Watch13 | Yes | Yes | Yes | | Promicro nRF52840 | No | No | No | | RAK WisMesh Tag | No | No | No | | Heltec Mesh Solar | No | No | No | | LilyGo T-Echo / T-Echo Lite | No | No | No | | SenseCAP Solar | Yes | Yes | Yes | | WIO Tracker L1 / L1 E-Ink | No | No | No | | WIO WM1110 | No | No | No | | Mesh Pocket | No | No | No | | Nano G2 Ultra | No | No | No | | ThinkNode M1/M3/M6 | No | No | No | | T1000-E | No | No | No | | Ikoka Nano/Stick/Handheld (nRF) | No | No | No | | Keepteen LT1 | No | No | No | | Minewsemi ME25LS01 | No | No | No | Notes: - "Implemented" reflects Phase 1 (boot lockout + shutdown reason capture). - User power-off on Heltec T114 does not enable LPCOMP wake. - VBUS detection is used to skip boot lockout on external power, and VBUS wake is configured alongside LPCOMP when supported hardware exposes VBUS to the nRF52. ## Technical Details ### Architecture The power management functionality is integrated into the `NRF52Board` base class in `src/helpers/NRF52Board.cpp`. Board variants provide hardware-specific configuration via a `PowerMgtConfig` struct and override `initiateShutdown(uint8_t reason)` to perform board-specific power-down work and conditionally enable voltage wake (LPCOMP + VBUS). ### Early Boot Capture A static constructor with priority 101 in `NRF52Board.cpp` captures the RESETREAS and GPREGRET2 registers before: - SystemInit() (priority 102) - which clears RESETREAS - Static C++ constructors (default priority 65535) This ensures we capture the true reset reason before any initialisation code runs. ### Board Implementation To enable power management on a board variant: 1. **Enable in platformio.ini**: ```ini -D NRF52_POWER_MANAGEMENT ``` 2. **Define configuration in variant.h**: ```c #define PWRMGT_VOLTAGE_BOOTLOCK 3300 // Won't boot below this voltage (mV) #define PWRMGT_LPCOMP_AIN 7 // AIN channel for voltage sensing #define PWRMGT_LPCOMP_REFSEL 2 // REFSEL (0-6=1/8..7/8, 7=ARef, 8-15=1/16..15/16) ``` 3. **Implement in board .cpp file**: ```cpp #ifdef NRF52_POWER_MANAGEMENT const PowerMgtConfig power_config = { .lpcomp_ain_channel = PWRMGT_LPCOMP_AIN, .lpcomp_refsel = PWRMGT_LPCOMP_REFSEL, .voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK }; void MyBoard::initiateShutdown(uint8_t reason) { // Board-specific shutdown preparation (e.g., disable peripherals) bool enable_lpcomp = (reason == SHUTDOWN_REASON_LOW_VOLTAGE || reason == SHUTDOWN_REASON_BOOT_PROTECT); if (enable_lpcomp) { configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel); } enterSystemOff(reason); } #endif void MyBoard::begin() { NRF52Board::begin(); // or NRF52BoardDCDC::begin() // ... board setup ... #ifdef NRF52_POWER_MANAGEMENT checkBootVoltage(&power_config); #endif } ``` For user-initiated shutdowns, `powerOff()` remains board-specific. Power management only arms LPCOMP for automated shutdown reasons (boot protection/low voltage). 4. **Declare override in board .h file**: ```cpp #ifdef NRF52_POWER_MANAGEMENT void initiateShutdown(uint8_t reason) override; #endif ``` ### Voltage Wake Configuration The LPCOMP (Low Power Comparator) is configured to: - Monitor the specified AIN channel (0-7 corresponding to P0.02-P0.05, P0.28-P0.31) - Compare against VDD fraction reference (REFSEL: 0-6=1/8..7/8, 7=ARef, 8-15=1/16..15/16) - Detect UP events (voltage rising above threshold) - Use 50mV hysteresis for noise immunity - Wake the device from SYSTEMOFF when triggered VBUS wake is enabled via the POWER peripheral USBDETECTED event whenever `configureVoltageWake()` is used. This requires USB VBUS to be routed to the nRF52 (typical on nRF52840 boards with native USB). **LPCOMP Reference Selection (PWRMGT_LPCOMP_REFSEL)**: | REFSEL | Fraction | VBAT @ 1M/1M divider (VDD=3.0-3.3) | VBAT @ 1.5M/1M divider (VDD=3.0-3.3) | |--------|----------|------------------------------------|--------------------------------------| | 0 | 1/8 | 0.75-0.82 V | 0.94-1.03 V | | 1 | 2/8 | 1.50-1.65 V | 1.88-2.06 V | | 2 | 3/8 | 2.25-2.47 V | 2.81-3.09 V | | 3 | 4/8 | 3.00-3.30 V | 3.75-4.12 V | | 4 | 5/8 | 3.75-4.12 V | 4.69-5.16 V | | 5 | 6/8 | 4.50-4.95 V | 5.62-6.19 V | | 6 | 7/8 | 5.25-5.77 V | 6.56-7.22 V | | 7 | ARef | - | - | | 8 | 1/16 | 0.38-0.41 V | 0.47-0.52 V | | 9 | 3/16 | 1.12-1.24 V | 1.41-1.55 V | | 10 | 5/16 | 1.88-2.06 V | 2.34-2.58 V | | 11 | 7/16 | 2.62-2.89 V | 3.28-3.61 V | | 12 | 9/16 | 3.38-3.71 V | 4.22-4.64 V | | 13 | 11/16 | 4.12-4.54 V | 5.16-5.67 V | | 14 | 13/16 | 4.88-5.36 V | 6.09-6.70 V | | 15 | 15/16 | 5.62-6.19 V | 7.03-7.73 V | **Important**: For boards with a voltage divider on the battery sense pin, LPCOMP measures the divided voltage. Use: `VBAT_threshold ≈ (VDD * fraction) * divider_scale`, where `divider_scale = (Rtop + Rbottom) / Rbottom` (e.g., 2.0 for 1M/1M, 2.5 for 1.5M/1M, 3.0 for XIAO). ### SoftDevice Compatibility The power management code checks whether SoftDevice is enabled and uses the appropriate API: - When SD enabled: `sd_power_*` functions - When SD disabled: Direct register access (NRF_POWER->*) This ensures compatibility regardless of BLE stack state. ## CLI Commands Power management status can be queried via the CLI: | Command | Description | |---------|-------------| | `get pwrmgt.support` | Returns "supported" or "unsupported" | | `get pwrmgt.source` | Returns current power source - "battery" or "external" (5V/USB power) | | `get pwrmgt.bootreason` | Returns reset and shutdown reason strings | | `get pwrmgt.bootmv` | Returns boot voltage in millivolts | On boards without power management enabled, all commands except `get pwrmgt.support` return: ``` ERROR: Power management not supported ``` ## Debug Output When `MESH_DEBUG=1` is enabled, the power management module outputs: ``` DEBUG: PWRMGT: Reset = Wake from LPCOMP (0x20000); Shutdown = Low Voltage (0x4C) DEBUG: PWRMGT: Boot voltage = 3450 mV (threshold = 3300 mV) DEBUG: PWRMGT: LPCOMP wake configured (AIN7, ref=3/8 VDD) ``` ## Phase 2 (Planned) - Runtime voltage monitoring - Voltage state machine (Normal -> Warning -> Critical -> Shutdown) - Configurable thresholds - Load shedding callbacks for power reduction - Deep sleep integration - Scheduled wake-up - Extended sleep with periodic monitoring ## References - [nRF52840 Product Specification - POWER](https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html) - [nRF52840 Product Specification - LPCOMP](https://infocenter.nordicsemi.com/topic/ps_nrf52840/lpcomp.html) - [SoftDevice S140 API - Power Management](https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/group__nrf__sdm__api.html)