fix(power): support SGM41562 family on T-Impulse Plus (#11298)

* fix(power): support SGM41562 family on T-Impulse Plus

* chore: format SGM41562 code
This commit is contained in:
LILYGO_L
2026-08-03 10:56:45 +00:00
committed by GitHub
parent 5792e8751b
commit ddb7bbf090
2 files changed
+122 -13

No files matched your search

+99 -12
View File
@@ -4,6 +4,8 @@
#include <Arduino.h>
#include "Throttle.h"
SGM41562 *sgm41562 = nullptr;
bool initSGM41562(TwoWire &wire)
@@ -52,34 +54,119 @@ bool SGM41562::begin(TwoWire &wire, uint8_t address)
{
wire_ = &wire;
address_ = address;
chipType_ = ChipType::Unknown;
uint8_t id;
if (!readReg(REG_DEVICE_ID, id)) {
LOG_WARN("SGM41562: I2C read failed at 0x%02X", address_);
return false;
}
if (id != DEVICE_ID_EXPECTED) {
LOG_WARN("SGM41562: unexpected device ID 0x%02X (expected 0x%02X)", id, DEVICE_ID_EXPECTED);
if (!resetRegisters()) {
LOG_WARN("SGM41562: register reset failed");
return false;
}
LOG_INFO("SGM41562: detected at 0x%02X (id 0x%02X)", address_, id);
// Mirror the vendor reference init sequence: PCB OTP off, NTC off,
// watchdog off, charger enabled. These match LilyGo's stock firmware
// for the T-Impulse Plus.
delay(120);
writeReg(REG_SYS_VOLTAGE_REG, 0xB7);
writeReg(REG_MISC_OP_CONTROL, 0x40);
writeReg(REG_CHARGE_TERM_TIMER, 0x1A);
writeReg(REG_POWER_ON_CFG, 0xA4);
chipType_ = detectChipType(id);
if (chipType_ == ChipType::Unknown) {
LOG_WARN("SGM41562: unsupported device ID 0x%02X", id);
return false;
}
if (!applyInitSequence()) {
LOG_WARN("SGM41562: %s initialization failed", chipTypeName(chipType_));
chipType_ = ChipType::Unknown;
return false;
}
LOG_INFO("SGM41562: detected %s at 0x%02X (id 0x%02X)", chipTypeName(chipType_), address_, id);
lastRefreshMs_ = 0;
return refresh();
}
const char *SGM41562::chipTypeName(ChipType type)
{
switch (type) {
case ChipType::SGM41562:
return "SGM41562";
case ChipType::SGM41562A:
return "SGM41562A";
case ChipType::SGM41562B:
return "SGM41562B";
case ChipType::SGM41562S:
return "SGM41562S";
case ChipType::SGM41562SA:
return "SGM41562SA";
case ChipType::Unknown:
default:
return "unknown";
}
}
bool SGM41562::resetRegisters()
{
uint8_t value;
if (!readReg(REG_CHARGE_CURRENT, value))
return false;
if (!writeReg(REG_CHARGE_CURRENT, value | 0x80))
return false;
delay(10);
return true;
}
SGM41562::ChipType SGM41562::detectChipType(uint8_t deviceId)
{
switch (deviceId) {
case DEVICE_ID_SGM41562:
return ChipType::SGM41562;
case DEVICE_ID_SGM41562_A:
return ChipType::SGM41562A;
case DEVICE_ID_SGM41562_S:
return ChipType::SGM41562S;
case DEVICE_ID_SGM41562_B_SA:
return detectIdZeroChipType();
default:
return ChipType::Unknown;
}
}
SGM41562::ChipType SGM41562::detectIdZeroChipType()
{
uint8_t chargeVoltage;
uint8_t systemVoltage;
if (!readReg(REG_CHARGE_VOLTAGE, chargeVoltage) || !readReg(REG_SYS_VOLTAGE_REG, systemVoltage))
return ChipType::Unknown;
if (chargeVoltage == 0xA3 && systemVoltage == 0x37)
return ChipType::SGM41562B;
if (chargeVoltage == 0x8D && systemVoltage == 0x73)
return ChipType::SGM41562SA;
LOG_WARN("SGM41562: unknown ID 0x00 reset values (REG04=0x%02X, REG07=0x%02X)", chargeVoltage, systemVoltage);
return ChipType::Unknown;
}
bool SGM41562::applyInitSequence()
{
if (hasExtendedRegisterMap()) {
return writeReg(REG_SYS_VOLTAGE_REG, 0x73) && writeReg(REG_MISC_OP_CONTROL, 0x40) &&
writeReg(REG_CHARGE_TERM_TIMER, 0x1A) && writeReg(REG_SYSTEM_STATUS, 0x40) &&
writeReg(REG_EXT_INPUT_CURRENT, 0xCA) && writeReg(REG_POWER_ON_CFG, 0xA4);
}
return writeReg(REG_SYS_VOLTAGE_REG, 0xB7) && writeReg(REG_MISC_OP_CONTROL, 0x40) && writeReg(REG_CHARGE_TERM_TIMER, 0x1A) &&
writeReg(REG_SYSTEM_STATUS, 0x40) && writeReg(REG_POWER_ON_CFG, 0xA4);
}
bool SGM41562::hasExtendedRegisterMap() const
{
return chipType_ == ChipType::SGM41562S || chipType_ == ChipType::SGM41562SA;
}
bool SGM41562::refresh()
{
uint32_t now = millis();
if (lastRefreshMs_ != 0 && (now - lastRefreshMs_) < 250)
if (lastRefreshMs_ != 0 && Throttle::isWithinTimespanMs(lastRefreshMs_, 250))
return true; // cached
lastRefreshMs_ = now == 0 ? 1 : now;
+23 -1
View File
@@ -28,6 +28,15 @@
class SGM41562
{
public:
enum class ChipType : uint8_t {
Unknown = 0,
SGM41562,
SGM41562A,
SGM41562B,
SGM41562S,
SGM41562SA,
};
enum class ChargeStatus : uint8_t {
NotCharging = 0b00,
Precharge = 0b01,
@@ -48,6 +57,8 @@ class SGM41562
bool isInputPowerGood() const { return inputPowerGood_; }
bool isThermalRegulation() const { return thermalReg_; }
uint8_t faultMask() const { return faultMask_; }
ChipType chipType() const { return chipType_; }
static const char *chipTypeName(ChipType type);
// Control.
bool setChargeEnable(bool enable);
@@ -62,10 +73,16 @@ class SGM41562
bool inputPowerGood_ = false;
bool thermalReg_ = false;
uint8_t faultMask_ = 0;
ChipType chipType_ = ChipType::Unknown;
bool readReg(uint8_t reg, uint8_t &value);
bool writeReg(uint8_t reg, uint8_t value);
bool updateReg(uint8_t reg, uint8_t mask, uint8_t value);
bool resetRegisters();
ChipType detectChipType(uint8_t deviceId);
ChipType detectIdZeroChipType();
bool applyInitSequence();
bool hasExtendedRegisterMap() const;
// SGM41562 register addresses
static constexpr uint8_t REG_INPUT_SOURCE = 0x00;
@@ -80,6 +97,8 @@ class SGM41562
static constexpr uint8_t REG_FAULT = 0x09;
static constexpr uint8_t REG_I2C_ADDR_MISC = 0x0A;
static constexpr uint8_t REG_DEVICE_ID = 0x0B;
static constexpr uint8_t REG_EXT_INPUT_CURRENT = 0x0C;
static constexpr uint8_t REG_EXT_CURRENT = 0x0D;
// Bit positions in REG_POWER_ON_CFG.
static constexpr uint8_t POWER_ON_CFG_CHG_DISABLE = 0x08; // bit 3: 1 = charging disabled
@@ -91,7 +110,10 @@ class SGM41562
static constexpr uint8_t SYS_STATUS_PG = 0x02; // bit 1: input power good
static constexpr uint8_t SYS_STATUS_THERM_REG = 0x01; // bit 0: thermal regulation
static constexpr uint8_t DEVICE_ID_EXPECTED = 0x04;
static constexpr uint8_t DEVICE_ID_SGM41562_B_SA = 0x00;
static constexpr uint8_t DEVICE_ID_SGM41562_A = 0x02;
static constexpr uint8_t DEVICE_ID_SGM41562 = 0x04;
static constexpr uint8_t DEVICE_ID_SGM41562_S = 0x09;
};
extern SGM41562 *sgm41562;