diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index c705521ad..af65446b4 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -45,6 +45,7 @@ #endif uint16_t getVDDVoltage(); +void cpuDeepSleep(uint32_t msecToWake); // Weak empty variant shutdown prep function. // May be redefined by variant files. @@ -75,7 +76,7 @@ bool powerHAL_isVBUSConnected() bool powerHAL_isPowerLevelSafe() { - static bool powerLevelSafe = true; + static bool powerLevelSafe = true; uint16_t threshold = SAFE_VDD_VOLTAGE_THRESHOLD * 1000; // convert V to mV uint16_t hysteresis = SAFE_VDD_VOLTAGE_THRESHOLD_HYST * 1000; @@ -326,6 +327,24 @@ void nrf52Loop() checkSDEvents(); reportLittleFSCorruptionOnce(); + +#ifdef LOW_VDD_SYSTEMOFF_DELAY_MS // rak_wismeshtag does not have a USB VBUS connected + // If VDD stays unsafe for a while (typically during brownout), + // force System OFF to avoid flash writes / SoftDevice instability loops. + // Skip when VBUS is present to allow recovery while USB-powered. + if (!powerHAL_isVBUSConnected()) { + static uint32_t low_vdd_since_ms = 0; + if (!powerHAL_isPowerLevelSafe()) { + if (low_vdd_since_ms == 0) + low_vdd_since_ms = millis(); + if ((uint32_t)(millis() - low_vdd_since_ms) >= (uint32_t)LOW_VDD_SYSTEMOFF_DELAY_MS) { + cpuDeepSleep(portMAX_DELAY); + } + } else { + low_vdd_since_ms = 0; + } + } +#endif } #ifdef USE_SEMIHOSTING diff --git a/variants/nrf52840/rak_wismeshtag/variant.h b/variants/nrf52840/rak_wismeshtag/variant.h index 5b20e4d93..6014af871 100644 --- a/variants/nrf52840/rak_wismeshtag/variant.h +++ b/variants/nrf52840/rak_wismeshtag/variant.h @@ -225,7 +225,29 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG #define AREF_VOLTAGE 3.0 #define VBAT_AR_INTERNAL AR_INTERNAL_3_0 #define ADC_MULTIPLIER 1.73 -#define OCV_ARRAY 4240, 4112, 4029, 3970, 3906, 3846, 3824, 3802, 3776, 3650, 3072 +#define OCV_ARRAY 4160, 4020, 3940, 3870, 3810, 3760, 3740, 3720, 3680, 3620, 2990 // updated OCV array for rak_wismeshtag + +// Wake from System OFF when battery rises again (LPCOMP). +// BAT_ADC divider: R22=1M (top), R24=1.5M (bottom) => V_BAT_ADC = VBAT * (1.5 / (1.0 + 1.5)) = 0.6 * VBAT +// RAK4630 module: AIN0 = nrf52840 AIN3 = Pin 5 (A0/BATTERY_PIN) +#define BATTERY_LPCOMP_INPUT NRF_LPCOMP_INPUT_3 +// If VDD is regulated ~3.3V, this wakes around VBAT ~3.09V (good for brownout recovery). +#define BATTERY_LPCOMP_THRESHOLD NRF_LPCOMP_REF_SUPPLY_9_16 //3.09V NRF_LPCOMP_REF_SUPPLY_9_16 = 3.09V + +// Low voltage protection: +// If VDD is below SAFE_VDD_VOLTAGE_THRESHOLD for longer than this delay (and no USB VBUS), +// the device will enter System OFF to avoid brownout loops and flash corruption. +#ifndef LOW_VDD_SYSTEMOFF_DELAY_MS +#define LOW_VDD_SYSTEMOFF_DELAY_MS 5000 +#endif + +#ifndef SAFE_VDD_VOLTAGE_THRESHOLD +#define SAFE_VDD_VOLTAGE_THRESHOLD 2.9 +#endif + +#ifndef SAFE_VDD_VOLTAGE_THRESHOLD_HYST +#define SAFE_VDD_VOLTAGE_THRESHOLD_HYST 0.1 +#endif #define RAK_4631 1