16static constexpr uint8_t REG_VERSION = 0x00;
17static constexpr uint8_t REG_VCELL = 0x02;
18static constexpr uint8_t REG_SOC = 0x04;
19static constexpr uint8_t REG_MODE = 0x08;
20static constexpr uint8_t REG_SOC_ALERT = 0x0B;
21static constexpr uint8_t REG_BATINFO = 0x10;
23static constexpr uint8_t MODE_NORMAL = 0x00;
24static constexpr uint8_t MODE_SLEEP = 0x30;
25static constexpr uint8_t UPDATE_FLAG = 0x80;
26static constexpr uint8_t RESTART_MODES[] PROGMEM = {0xF0, MODE_SLEEP, MODE_NORMAL};
27static constexpr uint8_t RESTART_STEPS =
sizeof(RESTART_MODES);
29static constexpr uint16_t VCELL_MASK = 0x3FFF;
30static constexpr float VCELL_VOLTS_PER_LSB = 312.5e-6f;
32static constexpr uint32_t STEP_DELAY_MS = 20;
33static constexpr uint32_t READY_POLL_MS = 100;
34static constexpr uint8_t READY_ATTEMPTS = 40;
35static constexpr uint32_t INIT_RETRY_MS = 1000;
36static constexpr uint8_t INIT_ATTEMPTS = 3;
38static bool version_is_running(uint8_t version) {
return (version & 0xFD) == 0x0D; }
41static bool woke_from_deep_sleep() {
50 uint8_t stored[PROFILE_SIZE];
51 uint8_t expected[PROFILE_SIZE];
52 if (!this->
read_bytes(REG_BATINFO, stored, PROFILE_SIZE))
55 matches = std::memcmp(stored, expected, PROFILE_SIZE) == 0;
61 uint8_t
buffer[1 + PROFILE_SIZE] = {REG_BATINFO};
88 !this->
read_byte(REG_SOC_ALERT, &config)) {
92 const bool has_profile = (config & UPDATE_FLAG) != 0;
93 bool matches = has_profile && woke_from_deep_sleep();
100 ESP_LOGI(TAG,
"Uploading battery profile");
102 this->
init_failed_(LOG_STR(
"Battery profile upload failed"));
109 if (mode == MODE_SLEEP) {
111 if (!this->
write_byte(REG_MODE, MODE_NORMAL)) {
119 if (mode != MODE_NORMAL || !version_is_running(version)) {
137 if (step + 1 < RESTART_STEPS) {
148 if (this->
read_byte(REG_VERSION, &version) && version_is_running(version) && this->
read_byte(REG_SOC, &soc) &&
150 ESP_LOGD(TAG,
"Gauge ready %u ms after boot", (
unsigned)
millis());
155 if (attempt + 1 >= READY_ATTEMPTS) {
156 this->
init_failed_(LOG_STR(
"Gauge did not become ready"));
168 if (this->
read_byte(REG_SOC, &soc) && soc <= 100) {
189 ESP_LOGCONFIG(TAG,
"CW2017:");
190 LOG_I2C_DEVICE(
this);
191 LOG_UPDATE_INTERVAL(
this);
BedjetMode mode
BedJet operating mode.
void mark_failed()
Mark this component as failed.
void status_set_warning()
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
void status_clear_warning()
void init_failed_(const LogString *reason)
sensor::Sensor * battery_level_sensor_
void restart_step_(uint8_t step)
sensor::Sensor * battery_voltage_sensor_
void wait_ready_(uint8_t attempt)
void dump_config() override
bool read_profile_matches_(bool &matches)
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
bool write_byte(uint8_t a_register, uint8_t data) const
bool read_byte(uint8_t a_register, uint8_t *data)
bool read_byte_16(uint8_t a_register, uint16_t *data)
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
void publish_state(float state)
Publish a new state to the front-end.
ESPHOME_LOG_TAG(TAG, "cw2017")
bool woke_from_deep_sleep()
Return true when this boot is a wake from deep sleep.
@ ERROR_OK
No error found during execution of method.
void progmem_memcpy(void *dst, const void *src, size_t len)
uint32_t IRAM_ATTR HOT millis()
uint8_t progmem_read_byte(const uint8_t *addr)