mirror of
https://github.com/meshtastic/firmware.git
synced 2026-11-08 15:24:57 -05:00
fix(power): stop a battery-less board deep-sleeping itself forever (#11821)
* fix(power): stop a battery-less board deep-sleeping itself forever The low-battery counter only reset inside its `hasBattery && !hasUSB` guard, so a board with no battery - whose floating divider drifts in and out of the battery-present window - ratcheted the count up across the gaps until it tripped `sds_secs`, which defaults to a ~24.8-day deep sleep. The button could not rescue it either, because `doDeepSleep()` force-holds `BUTTON_PIN` and a held pad ignores `ext1_wakeup_prepare()`'s re-route to RTC; `rtc_gpio_isolate()`'s pin list has the same effect on boards whose button is GPIO 2 or 34. Separately the cutoff now scales by `NUM_CELLS`, without which no multi-cell pack can ever read low enough to shut down at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(power): satisfy trunk check Apply the `ascii-dash` autoformat that `trunk fmt` wants on the comments this PR's file already carries, and rename the no-battery test so its `test_` prefix plus exactly 35 characters stops matching trufflehog's Lob API-key shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c3df4914b4
commit
8a9e10d120
5 files changed
+197
-21
No files matched your search
+27
-13
@@ -784,7 +784,7 @@ class ADS1115BatteryLevel : public AnalogBatteryLevel
|
||||
sum += _ads.computeVolts(raw);
|
||||
}
|
||||
// Piggyback a toggle-engine watchdog on this same throttle interval.
|
||||
// Only re-arm when VBUS is absent — calling this while attached
|
||||
// Only re-arm when VBUS is absent - calling this while attached
|
||||
// would restart CC toggling and could glitch an active sink attach.
|
||||
if (_aw35615.isReady() && !_aw35615.isVbusPresent()) {
|
||||
_aw35615.rearmToggle();
|
||||
@@ -812,7 +812,7 @@ class ADS1115BatteryLevel : public AnalogBatteryLevel
|
||||
|
||||
bool vbus = _aw35615.isVbusPresent();
|
||||
if (!vbus) {
|
||||
// VBUS just went away (or has been away) — make sure the CC
|
||||
// VBUS just went away (or has been away) - make sure the CC
|
||||
// toggle engine is re-armed so the next attach gets detected.
|
||||
_aw35615.rearmToggle();
|
||||
}
|
||||
@@ -830,7 +830,7 @@ class ADS1115BatteryLevel : public AnalogBatteryLevel
|
||||
if (_aw35615.isReady()) {
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
// Charging == VBUS present AND we're attached as a sink.
|
||||
// (isSinkAttached() is a latched result — safe to trust here since
|
||||
// (isSinkAttached() is a latched result - safe to trust here since
|
||||
// isVbusIn() above keeps re-arming toggle on every detach.)
|
||||
return _aw35615.isVbusPresent() && _aw35615.isSinkAttached();
|
||||
}
|
||||
@@ -1097,6 +1097,20 @@ void Power::shutdown()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Consecutive readings only: a battery-less board's floating divider drifts in and out of the
|
||||
// "battery present" window, and a count that survived the gaps would deep-sleep a USB-powered node.
|
||||
bool updateLowVoltageCounter(uint8_t &counter, bool hasBattery, bool hasUsb, uint16_t battMv, uint16_t cutoffMv)
|
||||
{
|
||||
if (!hasBattery || hasUsb || battMv >= cutoffMv) {
|
||||
counter = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (counter < UINT8_MAX)
|
||||
counter++;
|
||||
return counter > LOW_VOLTAGE_READINGS_BEFORE_SHUTDOWN;
|
||||
}
|
||||
|
||||
/// Reads power status to powerStatus singleton.
|
||||
//
|
||||
// TODO(girts): move this and other axp stuff to power.h/power.cpp.
|
||||
@@ -1229,16 +1243,16 @@ void Power::readPowerStatus()
|
||||
// is 2.0 to 2.5V, current OCV min is set to 3100 that is large enough.
|
||||
//
|
||||
|
||||
if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
|
||||
if (batteryLevel->getBattVoltage() < OCV[NUM_OCV_POINTS - 1]) {
|
||||
low_voltage_counter++;
|
||||
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
|
||||
if (low_voltage_counter > 10) {
|
||||
LOG_INFO("Low voltage detected, trigger deep sleep");
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
}
|
||||
} else {
|
||||
low_voltage_counter = 0;
|
||||
if (batteryLevel) {
|
||||
// getBattVoltage() reports pack voltage; the OCV table is per cell.
|
||||
const bool shutdownNow =
|
||||
updateLowVoltageCounter(low_voltage_counter, powerStatus2.getHasBattery(), powerStatus2.getHasUSB(),
|
||||
batteryLevel->getBattVoltage(), OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
|
||||
if (low_voltage_counter)
|
||||
LOG_DEBUG("Low voltage counter: %d/%d", low_voltage_counter, LOW_VOLTAGE_READINGS_BEFORE_SHUTDOWN);
|
||||
if (shutdownNow) {
|
||||
LOG_INFO("Low voltage detected, trigger deep sleep");
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user