Support multi-I2C and fix ESP32-S3 USB logging
Add dynamic I2C bus selection for battery gauge to support boards with multiple I2C controllers (e.g., Sticky uses Wire1 to avoid conflicts with GT911 touch). Fix logging on ESP32-S3 USB-Serial-JTAG by using esp_rom_printf instead of Serial, which incorrectly reports disconnected state.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include "Logging.h"
|
||||
|
||||
#include <esp_rom_sys.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#define MAX_ENTRY_LEN 256
|
||||
@@ -59,9 +61,18 @@ void logPrintf(const char* level, const char* origin, const char* format, ...) {
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// ESP32-S3 over USB-Serial-JTAG (HWCDC): Serial's `operator bool` reads false under a
|
||||
// host monitor (and HWCDC.write itself drops when it thinks it's disconnected), so the
|
||||
// `if (logSerial)` path below silently swallows every line. esp_rom_printf writes to the
|
||||
// always-on ROM/IDF console — the same channel that carries the boot banner and ARDUHAL
|
||||
// logs — so output is actually visible. `buf` is already fully formatted; pass via %s.
|
||||
esp_rom_printf("%s", buf);
|
||||
#else
|
||||
if (logSerial) {
|
||||
logSerial.print(buf);
|
||||
}
|
||||
#endif
|
||||
addToLogRingBuffer(buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,27 @@
|
||||
|
||||
HalPowerManager powerManager; // Singleton instance
|
||||
|
||||
namespace {
|
||||
// The fuel gauge's I2C controller (Wire or Wire1) per the active board profile.
|
||||
// On single-bus SoCs (ESP32-C3, SOC_I2C_NUM == 1) Wire1 doesn't exist, so always
|
||||
// use Wire. On Sticky the gauge is on Wire1 so it doesn't fight the GT911 touch,
|
||||
// which owns Wire.
|
||||
TwoWire& gaugeWire() {
|
||||
#if SOC_I2C_NUM > 1
|
||||
if (BoardConfig::ACTIVE.batteryGauge.i2cBus == 1) return Wire1;
|
||||
#endif
|
||||
return Wire;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void HalPowerManager::begin() {
|
||||
const auto& gauge = BoardConfig::ACTIVE.batteryGauge;
|
||||
if (gauge.gaugeAddr != 0) {
|
||||
// Board has an I2C fuel gauge (X3, LilyGo, Sticky, ...). Pins/freq come from
|
||||
// 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);
|
||||
gaugeWire().begin(gauge.i2cSda, gauge.i2cScl, gauge.i2cHz);
|
||||
gaugeWire().setTimeOut(4);
|
||||
_batteryUseI2C = true;
|
||||
} else if (BoardConfig::ACTIVE.batteryAdc >= 0) {
|
||||
// ADC-sensed board (X4: GPIO0, M5Paper: GPIO35). Skip when the profile leaves
|
||||
@@ -116,19 +129,20 @@ uint16_t HalPowerManager::getBatteryPercentage() const {
|
||||
// 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);
|
||||
if (Wire.endTransmission(false) != 0) {
|
||||
TwoWire& w = gaugeWire();
|
||||
w.beginTransmission(gaugeAddr);
|
||||
w.write(BQ27220_SOC_REG);
|
||||
if (w.endTransmission(false) != 0) {
|
||||
_batteryLastPollMs = now;
|
||||
return _batteryCachedPercent;
|
||||
}
|
||||
Wire.requestFrom(gaugeAddr, (uint8_t)2);
|
||||
if (Wire.available() < 2) {
|
||||
w.requestFrom(gaugeAddr, (uint8_t)2);
|
||||
if (w.available() < 2) {
|
||||
_batteryLastPollMs = now;
|
||||
return _batteryCachedPercent;
|
||||
}
|
||||
const uint8_t lo = Wire.read();
|
||||
const uint8_t hi = Wire.read();
|
||||
const uint8_t lo = w.read();
|
||||
const uint8_t hi = w.read();
|
||||
const uint16_t soc = (hi << 8) | lo;
|
||||
_batteryCachedPercent = soc > 100 ? 100 : soc;
|
||||
_batteryLastPollMs = now;
|
||||
|
||||
Reference in New Issue
Block a user