diff --git a/src/Power.cpp b/src/Power.cpp index a7da6f7a9..6ee658f2b 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -692,7 +692,9 @@ bool Power::setup() bool found = false; if (axpChipInit()) { found = true; - } else if (lipoInit()) { + } else if (cw2015Init()) { + found = true; + } else if (max17048Init()) { found = true; } else if (lipoChargerInit()) { found = true; @@ -1321,7 +1323,7 @@ bool Power::axpChipInit() /** * Wrapper class for an I2C MAX17048 Lipo battery sensor. */ -class LipoBatteryLevel : public HasBatteryLevel +class MAX17048BatteryLevel : public HasBatteryLevel { private: MAX17048Singleton *max17048 = nullptr; @@ -1369,18 +1371,18 @@ class LipoBatteryLevel : public HasBatteryLevel virtual bool isCharging() override { return max17048->isBatteryCharging(); } }; -LipoBatteryLevel lipoLevel; +MAX17048BatteryLevel max17048Level; /** * Init the Lipo battery level sensor */ -bool Power::lipoInit() +bool Power::max17048Init() { - bool result = lipoLevel.runOnce(); - LOG_DEBUG("Power::lipoInit lipo sensor is %s", result ? "ready" : "not ready yet"); + bool result = max17048Level.runOnce(); + LOG_DEBUG("Power::max17048Init lipo sensor is %s", result ? "ready" : "not ready yet"); if (!result) return false; - batteryLevel = &lipoLevel; + batteryLevel = &max17048Level; return true; } @@ -1388,7 +1390,88 @@ bool Power::lipoInit() /** * The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel */ -bool Power::lipoInit() +bool Power::max17048Init() +{ + return false; +} +#endif + +#if !MESHTASTIC_EXCLUDE_I2C && HAS_CW2015 + +class CW2015BatteryLevel : public AnalogBatteryLevel +{ + public: + /** + * Battery state of charge, from 0 to 100 or -1 for unknown + */ + virtual int getBatteryPercent() override + { + int data = -1; + Wire.beginTransmission(CW2015_ADDR); + Wire.write(0x04); + if (Wire.endTransmission() == 0) { + if (Wire.requestFrom(CW2015_ADDR, (uint8_t)1)) { + data = Wire.read(); + } + } + return data; + } + + /** + * The raw voltage of the battery in millivolts, or NAN if unknown + */ + virtual uint16_t getBattVoltage() override + { + uint16_t mv = 0; + Wire.beginTransmission(CW2015_ADDR); + Wire.write(0x02); + if (Wire.endTransmission() == 0) { + if (Wire.requestFrom(CW2015_ADDR, (uint8_t)2)) { + mv = Wire.read(); + mv <<= 8; + mv |= Wire.read(); + // Voltage is read in 305uV units, convert to mV + mv = mv * 305 / 1000; + } + } + return mv; + } +}; + +CW2015BatteryLevel cw2015Level; + +/** + * Init the CW2015 battery level sensor + */ +bool Power::cw2015Init() +{ + + Wire.beginTransmission(CW2015_ADDR); + uint8_t getInfo[] = {0x0a, 0x00}; + Wire.write(getInfo, 2); + Wire.endTransmission(); + delay(10); + Wire.beginTransmission(CW2015_ADDR); + Wire.write(0x00); + bool result = false; + if (Wire.endTransmission() == 0) { + if (Wire.requestFrom(CW2015_ADDR, (uint8_t)1)) { + uint8_t data = Wire.read(); + LOG_DEBUG("CW2015 init read data: 0x%x", data); + if (data == 0x73) { + result = true; + batteryLevel = &cw2015Level; + } + } + } + return result; +} + +#else +/** + * The CW2015 battery level sensor is unavailable - default to AnalogBatteryLevel + */ +bool Power::cw2015Init() { return false; } diff --git a/src/configuration.h b/src/configuration.h index 66fa4492d..7b7c603ba 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -233,6 +233,7 @@ along with this program. If not, see . #define NAU7802_ADDR 0x2A #define MAX30102_ADDR 0x57 #define SCD4X_ADDR 0x62 +#define CW2015_ADDR 0x62 #define MLX90614_ADDR_DEF 0x5A #define CGRADSENS_ADDR 0x66 #define LTR390UV_ADDR 0x53 diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index dffcd8fb6..0edd5e7a7 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -88,7 +88,8 @@ class ScanI2C BH1750, DA217, CHSC6X, - CST226SE + CST226SE, + CW2015 } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index c6ef34846..445e9342c 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -541,7 +541,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) break; SCAN_SIMPLE_CASE(BHI260AP_ADDR, BHI260AP, "BHI260AP", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address); + case SCD4X_ADDR: { + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x8), 1); + if (registerValue == 0x18) { + logFoundDevice("CW2015", (uint8_t)addr.address); + type = CW2015; + } else { + logFoundDevice("SCD4X", (uint8_t)addr.address); + type = SCD4X; + } + break; + } SCAN_SIMPLE_CASE(BMM150_ADDR, BMM150, "BMM150", (uint8_t)addr.address); #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); diff --git a/src/power.h b/src/power.h index e4b456d3b..b129e2b74 100644 --- a/src/power.h +++ b/src/power.h @@ -103,8 +103,10 @@ class Power : private concurrency::OSThread bool axpChipInit(); /// Setup a simple ADC input based battery sensor bool analogInit(); - /// Setup a Lipo battery level sensor - bool lipoInit(); + /// Setup cw2015 battery level sensor + bool cw2015Init(); + /// Setup a 17048 battery level sensor + bool max17048Init(); /// Setup a Lipo charger bool lipoChargerInit(); /// Setup a meshSolar battery sensor