implemented SY6970 lipo charger

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Manuel
2026-05-17 22:21:34 +02:00
parent f6f5bfab80
commit f1be5c4ff3
6 changed files with 131 additions and 22 deletions

View File

@@ -176,6 +176,12 @@ XPowersPPM *PPM = NULL;
#include "bq27220.h"
#endif
#ifdef HAS_SY6970
#include "hardware/Arduino_HWIIC.h"
#include "power_chip/Arduino_SY6970.h"
Arduino_SY6970 *SY6970 = NULL;
#endif
#ifdef HAS_PMU
XPowersLibInterface *PMU = NULL;
#else
@@ -1582,7 +1588,7 @@ bool Power::cw2015Init()
}
#endif
#if defined(HAS_PPM) && HAS_PPM
#ifdef HAS_PPM
/**
* Adapter class for BQ25896/BQ27220 Lipo battery charger.
@@ -1699,6 +1705,96 @@ class LipoCharger : public HasBatteryLevel
}
};
#elif defined(HAS_SY6970)
/**
* Adapter class for SY6970 battery charger.
*/
class LipoCharger : public HasBatteryLevel
{
public:
/**
* Init the I2C SY6970 Lipo battery charger
*/
bool runOnce()
{
if (SY6970 == nullptr) {
SY6970 = new Arduino_SY6970(std::make_shared<Arduino_HWIIC>(Arduino_HWIIC(SDA, SCL, &Wire)), SY6970_DEVICE_ADDRESS);
bool result = SY6970->begin();
if (result) {
// some boards can boot with HIZ set, which suppresses normal input/battery behavior
result |=
SY6970->IIC_Write_Device_State(Arduino_IIC_Power::POWER_DEVICE_HIZ_MODE, Arduino_IIC_Power::POWER_DEVICE_OFF);
result |= SY6970->IIC_Write_Device_State(Arduino_IIC_Power::POWER_DEVICE_CHARGING_MODE,
Arduino_IIC_Power::POWER_DEVICE_ON);
result |= SY6970->IIC_Write_Device_State(Arduino_IIC_Power::POWER_DEVICE_ADC_MEASURE,
Arduino_IIC_Power::POWER_DEVICE_ON);
// clear watchdog timer once, then keep watchdog disabled
result |= SY6970->IIC_Write_Device_State(Arduino_IIC_Power::POWER_DEVICE_WATCHDOG_TIMER_RESET,
Arduino_IIC_Power::POWER_DEVICE_ON);
if (result) {
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_WATCHDOG_TIMER, 0);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_CHARGING_TARGET_VOLTAGE_LIMIT, 4284);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_MINIMUM_SYSTEM_VOLTAGE_LIMIT, 3300);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_INPUT_CURRENT_LIMIT, 500);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_FAST_CHARGING_CURRENT_LIMIT, 2112);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_PRECHARGE_CHARGING_CURRENT_LIMIT, 192);
SY6970->IIC_Write_Device_Value(Arduino_IIC_Power::POWER_DEVICE_TERMINATION_CHARGING_CURRENT_LIMIT, 320);
LOG_INFO("SY6970 init succeeded");
return true;
}
}
LOG_WARN("SY6970 init failed");
delete SY6970;
SY6970 = nullptr;
return false;
}
return true;
}
/**
* Battery state of charge, from 0 to 100 or -1 for unknown
*/
virtual int getBatteryPercent() override { return -1; }
/**
* The raw voltage of the battery in millivolts, or NAN if unknown
*/
virtual uint16_t getBattVoltage() override
{
double battVoltage = SY6970->IIC_Read_Device_Value(Arduino_IIC_Power::POWER_BATTERY_VOLTAGE);
return (battVoltage > 0.0) ? static_cast<uint16_t>(battVoltage) : 0;
}
/**
* return true if there is a battery installed in this unit
*/
virtual bool isBatteryConnect() override { return true; }
/**
* return true if there is an external power source detected
*/
virtual bool isVbusIn() override { return SY6970->IIC_Read_Device_Value(Arduino_IIC_Power::POWER_SYSTEM_VOLTAGE) > 4200.0; }
/**
* return true if the battery is currently charging
*/
virtual bool isCharging() override { return SY6970->IIC_Read_Device_Value(Arduino_IIC_Power::POWER_CHARGING_CURRENT) > 1.0; }
};
#else
/**
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::lipoChargerInit()
{
return false;
}
#endif
#if defined(HAS_PPM) || defined(HAS_SY6970)
LipoCharger lipoCharger;
/**
@@ -1707,21 +1803,12 @@ LipoCharger lipoCharger;
bool Power::lipoChargerInit()
{
bool result = lipoCharger.runOnce();
LOG_DEBUG("Power::lipoChargerInit lipo sensor is %s", result ? "ready" : "not ready yet");
LOG_DEBUG("Power::lipoChargerInit lipo charger is %s", result ? "ready" : "not ready yet");
if (!result)
return false;
batteryLevel = &lipoCharger;
return true;
}
#else
/**
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::lipoChargerInit()
{
return false;
}
#endif
#ifdef HELTEC_MESH_SOLAR

View File

@@ -274,6 +274,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define LTR553ALS_ADDR 0x23
#define SEN5X_ADDR 0x69
#define SCD30_ADDR 0x61
#define SY6970_ADDR 0x6A // same address as LSM6DS3
// -----------------------------------------------------------------------------
// ACCELEROMETER

View File

@@ -97,6 +97,7 @@ class ScanI2C
CW2015,
SCD30,
ADS1115,
SY6970
} DeviceType;
// typedef uint8_t DeviceAddress;

View File

@@ -607,7 +607,23 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
case LSM6DS3_ADDR: {
// 1) Try SY6970 signature first: REG14[5:3] == 0b001
uint8_t registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x14), 1);
if (((registerValue >> 3) & 0x07) == 0x01) {
type = SY6970;
logFoundDevice("SY6970", (uint8_t)addr.address);
break;
}
// 2) Fallback to LSM6DS3 signature: WHO_AM_I == 0x6A
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1);
if (registerValue == 0x6A) {
type = LSM6DS3;
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
}
break;
}
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
case TCA9555_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 1);

View File

@@ -28,14 +28,16 @@ build_flags = ${esp32s3_base.build_flags}
-D HAS_SDCARD
lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@1.2.19
# renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio
earlephilhower/ESP8266Audio@1.9.9
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
earlephilhower/ESP8266SAM@1.1.0
# renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.4
# renovate: datasource=github-tags depName=LovyanGFX packageName=https://github.com/lovyan03/LovyanGFX
https://github.com/lovyan03/LovyanGFX/archive/refs/tags/1.2.21.zip
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
https://github.com/meshtastic/ESP8266Audio/archive/343024632ee78d6216907b2353fc943a62422d80.zip
# renovate: datasource=github-tags depName=ESP8266SAM packageName=https://github.com/earlephilhower/ESP8266SAM
https://github.com/earlephilhower/ESP8266SAM/archive/refs/tags/1.1.0.zip
# renovate: datasource=github-tags depName=SensorLib packageName=https://github.com/lewisxhe/SensorLib
https://github.com/lewisxhe/SensorLib/archive/refs/tags/v0.4.1.zip
# renovate: datasource=github-tags depName=Arduino_DriveBus packageName=https://github.com/yuttapichai/Arduino_DriveBus
https://github.com/yuttapichai/Arduino_DriveBus/archive/refs/tags/1.1.5.zip
[env:tdisplay-s3-pro-tft]
board_level = extra
@@ -47,6 +49,7 @@ build_flags =
-D INPUTDRIVER_ENCODER_LEFT=12
-D INPUTDRIVER_ENCODER_RIGHT=16
-D INPUTDRIVER_ENCODER_BTN=0
-D INDEV_EVENT_TRIGGER=LV_EVENT_CLICKED
-D HAS_SCREEN=1
-D HAS_TFT=1
-D USE_I2S_BUZZER
@@ -68,7 +71,7 @@ build_flags =
-D DISPLAY_SIZE=480x222 ; landscape mode
-D DISPLAY_SET_RESOLUTION
-D LGFX_DRIVER=LGFX_TDISPLAY_S3PRO
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_TDISPLAY_S3PRO.h\"
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_T_DISPLAY_S3_PRO.h\"
; -D LVGL_DRIVER=LVGL_TDISPLAY_S3PRO
; -D LV_USE_ST7796=1
-D VIEW_480x222

View File

@@ -31,6 +31,7 @@
#define USE_POWERSAVE
#define SLEEP_TIME 120
#define LED_POWER 38 // green
#define PIN_POWER_EN 42
// GNSS
@@ -40,7 +41,7 @@
#define PCF85063_RTC 0x51
// SY6970 battery charger
#define SY6970_ADDR 0x6A
#define HAS_SY6970
#define SY6970_INT 21
// MAX98357A PCM amplifier