From b024e7968765c2ed3bb9c2eba63325098d77546b Mon Sep 17 00:00:00 2001 From: patagona Date: Mon, 30 Sep 2024 17:39:55 +0200 Subject: [PATCH] DALY Modbus BMS: use loops for cell voltage configs --- .../daly_hkms_bms/daly_hkms_bms.cpp | 49 +++++++------ .../components/daly_hkms_bms/daly_hkms_bms.h | 30 ++++---- esphome/components/daly_hkms_bms/sensor.py | 72 ++++++------------- 3 files changed, 62 insertions(+), 89 deletions(-) diff --git a/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp b/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp index d32d1e5d74..b825d36372 100644 --- a/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp +++ b/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp @@ -14,7 +14,6 @@ static const uint8_t DALY_MODBUS_REQUEST_ADDRESS_OFFSET = 0x80; static const uint8_t DALY_MODBUS_RESPONSE_ADDRESS_OFFSET = 0x50; static const uint8_t DALY_MODBUS_READ_CELL_VOLTAGES_ADDR = DALY_MODBUS_ADDR_CELL_VOLT_1; -static const uint8_t DALY_MODBUS_READ_CELL_VOLTAGES_LENGTH = 16; // 16 cell voltages static const uint8_t DALY_MODBUS_READ_DATA_ADDR = DALY_MODBUS_ADDR_CELL_TEMP_1; static const uint8_t DALY_MODBUS_READ_DATA_LENGTH = DALY_MODBUS_REGISTER_MAX - DALY_MODBUS_ADDR_CELL_TEMP_1 + 1; @@ -52,7 +51,8 @@ void DalyHkmsBmsComponent::loop() { { case ReadState::READ_CELL_VOLTAGES: start_address = DALY_MODBUS_READ_CELL_VOLTAGES_ADDR; - register_count = DALY_MODBUS_READ_CELL_VOLTAGES_LENGTH; + // avoid reading all 48 cell voltages if we only want 16 or so + register_count = this->cell_voltage_sensors_max_; break; case ReadState::READ_DATA: start_address = DALY_MODBUS_READ_DATA_ADDR; @@ -76,7 +76,7 @@ void DalyHkmsBmsComponent::loop() { void DalyHkmsBmsComponent::update() { if(this->read_state_ == ReadState::IDLE){ - this->read_state_ = ReadState::READ_CELL_VOLTAGES; + this->advance_read_state(); } } @@ -98,7 +98,7 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector &data) { { case ReadState::READ_CELL_VOLTAGES: register_offset = DALY_MODBUS_READ_CELL_VOLTAGES_ADDR; - register_count = DALY_MODBUS_READ_CELL_VOLTAGES_LENGTH; + register_count = this->cell_voltage_sensors_max_; break; case ReadState::READ_DATA: register_offset = DALY_MODBUS_READ_DATA_ADDR; @@ -129,25 +129,11 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector &data) { if (this->read_state_ == ReadState::READ_CELL_VOLTAGES) { #ifdef USE_SENSOR - publish_sensor_state(this->cell_1_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 , 0, 0.001); - publish_sensor_state(this->cell_2_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 1 , 0, 0.001); - publish_sensor_state(this->cell_3_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 2 , 0, 0.001); - publish_sensor_state(this->cell_4_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 3 , 0, 0.001); - publish_sensor_state(this->cell_5_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 4 , 0, 0.001); - publish_sensor_state(this->cell_6_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 5 , 0, 0.001); - publish_sensor_state(this->cell_7_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 6 , 0, 0.001); - publish_sensor_state(this->cell_8_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 7 , 0, 0.001); - publish_sensor_state(this->cell_9_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 8 , 0, 0.001); - publish_sensor_state(this->cell_10_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 9 , 0, 0.001); - publish_sensor_state(this->cell_11_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 10, 0, 0.001); - publish_sensor_state(this->cell_12_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 11, 0, 0.001); - publish_sensor_state(this->cell_13_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 12, 0, 0.001); - publish_sensor_state(this->cell_14_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 13, 0, 0.001); - publish_sensor_state(this->cell_15_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 14, 0, 0.001); - publish_sensor_state(this->cell_16_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 15, 0, 0.001); + for (size_t i = 0; i < this->cell_voltage_sensors_max_; i++) + { + publish_sensor_state(this->cell_voltage_sensors_[i], register_offset, DALY_MODBUS_ADDR_CELL_VOLT_1 + i, 0, 0.001); + } #endif - - this->read_state_ = ReadState::READ_DATA; } else if (this->read_state_ == ReadState::READ_DATA) { #ifdef USE_SENSOR publish_sensor_state(this->temperature_1_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 , -40, 1, 255); @@ -217,8 +203,27 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector &data) { this->precharging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_PRECHG_MOS_ACTIVE) > 0); } #endif + } + this->advance_read_state(); +} +void DalyHkmsBmsComponent::advance_read_state() { + switch (this->read_state_) + { + case ReadState::IDLE: + // skip reading cell voltages if there are no cell voltage sensors + if (this->cell_voltage_sensors_max_ == 0) { + this->read_state_ = ReadState::READ_DATA; + } else { + this->read_state_ = ReadState::READ_CELL_VOLTAGES; + } + break; + case ReadState::READ_CELL_VOLTAGES: + this->read_state_ = ReadState::READ_DATA; + break; + case ReadState::READ_DATA: this->read_state_ = ReadState::IDLE; + break; } } diff --git a/esphome/components/daly_hkms_bms/daly_hkms_bms.h b/esphome/components/daly_hkms_bms/daly_hkms_bms.h index 1cb68580dd..7e0abde99e 100644 --- a/esphome/components/daly_hkms_bms/daly_hkms_bms.h +++ b/esphome/components/daly_hkms_bms/daly_hkms_bms.h @@ -18,6 +18,8 @@ namespace esphome { namespace daly_hkms_bms { +static const uint8_t DALY_MODBUS_MAX_CELL_COUNT = 48; + class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevice { public: void loop() override; @@ -28,6 +30,12 @@ class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevic void set_daly_address(uint8_t address); #ifdef USE_SENSOR + void set_cell_voltage_sensor(size_t cell, sensor::Sensor *sensor) { + if(cell > this->cell_voltage_sensors_max_) + this->cell_voltage_sensors_max_ = cell; + this->cell_voltage_sensors_[cell-1] = sensor; + }; + SUB_SENSOR(voltage) SUB_SENSOR(current) SUB_SENSOR(battery_level) @@ -53,22 +61,6 @@ class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevic SUB_SENSOR(temperature_8) SUB_SENSOR(temperature_mos) SUB_SENSOR(temperature_board) - SUB_SENSOR(cell_1_voltage) - SUB_SENSOR(cell_2_voltage) - SUB_SENSOR(cell_3_voltage) - SUB_SENSOR(cell_4_voltage) - SUB_SENSOR(cell_5_voltage) - SUB_SENSOR(cell_6_voltage) - SUB_SENSOR(cell_7_voltage) - SUB_SENSOR(cell_8_voltage) - SUB_SENSOR(cell_9_voltage) - SUB_SENSOR(cell_10_voltage) - SUB_SENSOR(cell_11_voltage) - SUB_SENSOR(cell_12_voltage) - SUB_SENSOR(cell_13_voltage) - SUB_SENSOR(cell_14_voltage) - SUB_SENSOR(cell_15_voltage) - SUB_SENSOR(cell_16_voltage) #endif #ifdef USE_TEXT_SENSOR @@ -87,8 +79,12 @@ class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevic uint32_t last_send_; uint8_t daly_address_; - enum class ReadState{ READ_CELL_VOLTAGES, READ_DATA, IDLE } read_state_{ReadState::IDLE}; + sensor::Sensor *cell_voltage_sensors_[DALY_MODBUS_MAX_CELL_COUNT]{}; + size_t cell_voltage_sensors_max_{0}; + void advance_read_state(); + + enum class ReadState{ READ_CELL_VOLTAGES, READ_DATA, IDLE } read_state_{ReadState::IDLE}; }; } // namespace daly_hkms_bms diff --git a/esphome/components/daly_hkms_bms/sensor.py b/esphome/components/daly_hkms_bms/sensor.py index a2259a371f..cf24a8be8b 100644 --- a/esphome/components/daly_hkms_bms/sensor.py +++ b/esphome/components/daly_hkms_bms/sensor.py @@ -48,23 +48,6 @@ CONF_TEMPERATURE_8 = "temperature_8" CONF_TEMPERATURE_MOS = "temperature_mos" CONF_TEMPERATURE_BOARD = "temperature_board" -CONF_CELL_1_VOLTAGE = "cell_1_voltage" -CONF_CELL_2_VOLTAGE = "cell_2_voltage" -CONF_CELL_3_VOLTAGE = "cell_3_voltage" -CONF_CELL_4_VOLTAGE = "cell_4_voltage" -CONF_CELL_5_VOLTAGE = "cell_5_voltage" -CONF_CELL_6_VOLTAGE = "cell_6_voltage" -CONF_CELL_7_VOLTAGE = "cell_7_voltage" -CONF_CELL_8_VOLTAGE = "cell_8_voltage" -CONF_CELL_9_VOLTAGE = "cell_9_voltage" -CONF_CELL_10_VOLTAGE = "cell_10_voltage" -CONF_CELL_11_VOLTAGE = "cell_11_voltage" -CONF_CELL_12_VOLTAGE = "cell_12_voltage" -CONF_CELL_13_VOLTAGE = "cell_13_voltage" -CONF_CELL_14_VOLTAGE = "cell_14_voltage" -CONF_CELL_15_VOLTAGE = "cell_15_voltage" -CONF_CELL_16_VOLTAGE = "cell_16_voltage" - ICON_CURRENT_DC = "mdi:current-dc" ICON_BATTERY_OUTLINE = "mdi:battery-outline" ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up" @@ -73,6 +56,8 @@ ICON_CAR_BATTERY = "mdi:car-battery" UNIT_AMPERE_HOUR = "Ah" +MAX_CELL_NUMBER = 48 + TYPES = [ CONF_VOLTAGE, CONF_CURRENT, @@ -99,22 +84,7 @@ TYPES = [ CONF_TEMPERATURE_8, CONF_TEMPERATURE_MOS, CONF_TEMPERATURE_BOARD, - CONF_CELL_1_VOLTAGE, - CONF_CELL_2_VOLTAGE, - CONF_CELL_3_VOLTAGE, - CONF_CELL_4_VOLTAGE, - CONF_CELL_5_VOLTAGE, - CONF_CELL_6_VOLTAGE, - CONF_CELL_7_VOLTAGE, - CONF_CELL_8_VOLTAGE, - CONF_CELL_9_VOLTAGE, - CONF_CELL_10_VOLTAGE, - CONF_CELL_11_VOLTAGE, - CONF_CELL_12_VOLTAGE, - CONF_CELL_13_VOLTAGE, - CONF_CELL_14_VOLTAGE, - CONF_CELL_15_VOLTAGE, - CONF_CELL_16_VOLTAGE, + # Cell voltages are handled by loops below ] TEMPERATURE_SENSOR_SCHEMA = sensor.sensor_schema( @@ -133,6 +103,15 @@ CELL_VOLTAGE_SCHEMA = sensor.sensor_schema( accuracy_decimals=3, ) +def get_cell_voltage_key(cell): + return f"cell_{cell}_voltage" + +def get_cell_voltages_schema(): + schema_obj = {} + for i in range(1, MAX_CELL_NUMBER+1): + schema_obj[cv.Optional(get_cell_voltage_key(i))] = CELL_VOLTAGE_SCHEMA + return cv.Schema(schema_obj) + CONFIG_SCHEMA = ( cv.Schema( { @@ -241,24 +220,9 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_TEMPERATURE_8): TEMPERATURE_SENSOR_SCHEMA, cv.Optional(CONF_TEMPERATURE_MOS): TEMPERATURE_SENSOR_SCHEMA, cv.Optional(CONF_TEMPERATURE_BOARD): TEMPERATURE_SENSOR_SCHEMA, - cv.Optional(CONF_CELL_1_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_2_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_3_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_4_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_5_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_6_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_7_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_8_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_9_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_10_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_11_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_12_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_13_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_14_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_15_VOLTAGE): CELL_VOLTAGE_SCHEMA, - cv.Optional(CONF_CELL_16_VOLTAGE): CELL_VOLTAGE_SCHEMA } ) + .extend(get_cell_voltages_schema()) .extend(cv.COMPONENT_SCHEMA) ) @@ -267,7 +231,15 @@ async def setup_conf(config, key, hub): sens = await sensor.new_sensor(sensor_config) cg.add(getattr(hub, f"set_{key}_sensor")(sens)) +async def setup_cell_voltage_conf(config, cell, hub): + key = get_cell_voltage_key(cell) + if sensor_config := config.get(key): + sens = await sensor.new_sensor(sensor_config) + cg.add(hub.set_cell_voltage_sensor(cell, sens)) + async def to_code(config): hub = await cg.get_variable(config[CONF_DALY_HKMS_BMS_ID]) for key in TYPES: - await setup_conf(config, key, hub) \ No newline at end of file + await setup_conf(config, key, hub) + for i in range(1, MAX_CELL_NUMBER+1): + await setup_cell_voltage_conf(config, i, hub)