Use board config for battery monitoring setup

Replace hardcoded X3-specific I2C pins and frequencies with values from the active board profile. Add support for boards with I2C fuel gauges (X3, LilyGo, Sticky) and ADC-based battery sensing (X4, M5Paper). Skip ADC setup when batteryAdc is unassigned to prevent GPIO mux faults.
This commit is contained in:
Justin Mitchell
2026-06-15 12:29:24 -04:00
parent 9b7b9e9094
commit 6acecd8ea6
+16 -11
View File
@@ -11,15 +11,17 @@
HalPowerManager powerManager; // Singleton instance HalPowerManager powerManager; // Singleton instance
void HalPowerManager::begin() { void HalPowerManager::begin() {
if (gpio.deviceIsX3()) { const auto& gauge = BoardConfig::ACTIVE.batteryGauge;
// X3 uses an I2C fuel gauge for battery monitoring. if (gauge.gaugeAddr != 0) {
// I2C init must come AFTER gpio.begin() so early hardware detection/probes are finished. // Board has an I2C fuel gauge (X3, LilyGo, Sticky, ...). Pins/freq come from
Wire.begin(X3_I2C_SDA, X3_I2C_SCL, X3_I2C_FREQ); // the active board profile, not hardcoded X3 values. I2C init must come AFTER
// gpio.begin() so early hardware detection/probes are finished.
Wire.begin(gauge.i2cSda, gauge.i2cScl, gauge.i2cHz);
Wire.setTimeOut(4); Wire.setTimeOut(4);
_batteryUseI2C = true; _batteryUseI2C = true;
} else { } else if (BoardConfig::ACTIVE.batteryAdc >= 0) {
// Battery ADC pin from the active board profile (X4: GPIO0, M5Paper: GPIO35), // ADC-sensed board (X4: GPIO0, M5Paper: GPIO35). Skip when the profile leaves
// not a hardcoded X4 pin. // batteryAdc unassigned (PIN_UNASSIGNED) — pinMode(255) faults the GPIO mux.
pinMode(BoardConfig::ACTIVE.batteryAdc, INPUT); pinMode(BoardConfig::ACTIVE.batteryAdc, INPUT);
} }
normalFreq = getCpuFrequencyMhz(); normalFreq = getCpuFrequencyMhz();
@@ -109,15 +111,18 @@ uint16_t HalPowerManager::getBatteryPercentage() const {
return _batteryCachedPercent; return _batteryCachedPercent;
} }
// Read SOC directly from I2C fuel gauge (16-bit LE register). // Read SOC directly from the I2C fuel gauge (16-bit LE register). Gauge
// On I2C error, keep last known value to avoid UI jitter/slowdowns. // address comes from the active board profile (all current gauges are
Wire.beginTransmission(I2C_ADDR_BQ27220); // BQ27220-class, SOC at 0x2C). On I2C error, keep last known value to avoid
// UI jitter/slowdowns.
const uint8_t gaugeAddr = BoardConfig::ACTIVE.batteryGauge.gaugeAddr;
Wire.beginTransmission(gaugeAddr);
Wire.write(BQ27220_SOC_REG); Wire.write(BQ27220_SOC_REG);
if (Wire.endTransmission(false) != 0) { if (Wire.endTransmission(false) != 0) {
_batteryLastPollMs = now; _batteryLastPollMs = now;
return _batteryCachedPercent; return _batteryCachedPercent;
} }
Wire.requestFrom(I2C_ADDR_BQ27220, (uint8_t)2); Wire.requestFrom(gaugeAddr, (uint8_t)2);
if (Wire.available() < 2) { if (Wire.available() < 2) {
_batteryLastPollMs = now; _batteryLastPollMs = now;
return _batteryCachedPercent; return _batteryCachedPercent;