mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 17:27:59 +01:00
DALY Modbus BMS: split data request into two requests
This commit is contained in:
parent
206562bebf
commit
2f6d552589
3 changed files with 140 additions and 90 deletions
|
@ -13,6 +13,12 @@ static const char *const TAG = "daly_hkms_bms";
|
||||||
static const uint8_t DALY_MODBUS_REQUEST_ADDRESS_OFFSET = 0x80;
|
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_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;
|
||||||
|
|
||||||
static const uint8_t MODBUS_CMD_READ_HOLDING_REGISTERS = 0x03;
|
static const uint8_t MODBUS_CMD_READ_HOLDING_REGISTERS = 0x03;
|
||||||
|
|
||||||
void DalyHkmsBmsComponent::set_daly_address(uint8_t daly_address) {
|
void DalyHkmsBmsComponent::set_daly_address(uint8_t daly_address) {
|
||||||
|
@ -25,13 +31,10 @@ void DalyHkmsBmsComponent::set_daly_address(uint8_t daly_address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DalyHkmsBmsComponent::loop() {
|
void DalyHkmsBmsComponent::loop() {
|
||||||
// If update() was unable to send we retry until we can send.
|
if (this->read_state_ == ReadState::IDLE) {
|
||||||
if (!this->waiting_to_update_)
|
|
||||||
return;
|
return;
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DalyHkmsBmsComponent::update() {
|
|
||||||
// If our last send has had no reply yet, and it wasn't that long ago, do nothing.
|
// If our last send has had no reply yet, and it wasn't that long ago, do nothing.
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (now - this->last_send_ < this->get_update_interval() / 2) {
|
if (now - this->last_send_ < this->get_update_interval() / 2) {
|
||||||
|
@ -40,25 +43,43 @@ void DalyHkmsBmsComponent::update() {
|
||||||
|
|
||||||
// The bus might be slow, or there might be other devices, or other components might be talking to our device.
|
// The bus might be slow, or there might be other devices, or other components might be talking to our device.
|
||||||
if (this->waiting_for_response()) {
|
if (this->waiting_for_response()) {
|
||||||
this->waiting_to_update_ = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->waiting_to_update_ = false;
|
uint8_t start_address;
|
||||||
|
uint8_t register_count;
|
||||||
|
switch (this->read_state_)
|
||||||
|
{
|
||||||
|
case ReadState::READ_CELL_VOLTAGES:
|
||||||
|
start_address = DALY_MODBUS_READ_CELL_VOLTAGES_ADDR;
|
||||||
|
register_count = DALY_MODBUS_READ_CELL_VOLTAGES_LENGTH;
|
||||||
|
break;
|
||||||
|
case ReadState::READ_DATA:
|
||||||
|
start_address = DALY_MODBUS_READ_DATA_ADDR;
|
||||||
|
register_count = DALY_MODBUS_READ_DATA_LENGTH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Sending modbus read request to %d: start register %d, register count %d",
|
||||||
|
this->daly_address_, start_address, register_count);
|
||||||
|
|
||||||
// send the request using Modbus directly instead of ModbusDevice so we can send the data with the request address
|
// send the request using Modbus directly instead of ModbusDevice so we can send the data with the request address
|
||||||
uint8_t modbus_request_address = this->daly_address_ + DALY_MODBUS_REQUEST_ADDRESS_OFFSET;
|
uint8_t modbus_device_request_address = this->daly_address_ + DALY_MODBUS_REQUEST_ADDRESS_OFFSET;
|
||||||
this->parent_->send(
|
|
||||||
modbus_request_address,
|
this->parent_->send(modbus_device_request_address, MODBUS_CMD_READ_HOLDING_REGISTERS, start_address, register_count,
|
||||||
MODBUS_CMD_READ_HOLDING_REGISTERS,
|
0, nullptr);
|
||||||
0x00,
|
|
||||||
DALY_MODBUS_REGISTER_COUNT,
|
|
||||||
0,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
this->last_send_ = millis();
|
this->last_send_ = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DalyHkmsBmsComponent::update() {
|
||||||
|
if(this->read_state_ == ReadState::IDLE){
|
||||||
|
this->read_state_ = ReadState::READ_CELL_VOLTAGES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
// Other components might be sending commands to our device. But we don't get called with enough
|
// Other components might be sending commands to our device. But we don't get called with enough
|
||||||
// context to know what is what. So if we didn't do a send, we ignore the data.
|
// context to know what is what. So if we didn't do a send, we ignore the data.
|
||||||
|
@ -68,18 +89,37 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
}
|
}
|
||||||
this->last_send_ = 0;
|
this->last_send_ = 0;
|
||||||
|
|
||||||
// Also ignore the data if the message is too short. Otherwise we will publish invalid values.
|
ESP_LOGD(TAG, "Got modbus response: %d bytes", data.size());
|
||||||
if (data.size() < DALY_MODBUS_REGISTER_COUNT * 2) {
|
|
||||||
|
size_t register_count;
|
||||||
|
size_t register_offset;
|
||||||
|
|
||||||
|
switch (this->read_state_)
|
||||||
|
{
|
||||||
|
case ReadState::READ_CELL_VOLTAGES:
|
||||||
|
register_offset = DALY_MODBUS_READ_CELL_VOLTAGES_ADDR;
|
||||||
|
register_count = DALY_MODBUS_READ_CELL_VOLTAGES_LENGTH;
|
||||||
|
break;
|
||||||
|
case ReadState::READ_DATA:
|
||||||
|
register_offset = DALY_MODBUS_READ_DATA_ADDR;
|
||||||
|
register_count = DALY_MODBUS_READ_DATA_LENGTH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid read state");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.size() < register_count * 2) {
|
||||||
ESP_LOGD(TAG, "Not enough data in modbus response");
|
ESP_LOGD(TAG, "Not enough data in modbus response");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto get_register = [&](size_t i) -> uint16_t {
|
auto get_register = [&](size_t i) -> uint16_t {
|
||||||
return encode_uint16(data[i * 2], data[i * 2 + 1]);
|
return encode_uint16(data[(i - register_offset) * 2], data[(i - register_offset) * 2 + 1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto publish_sensor_state = [&](sensor::Sensor *sensor, size_t i, int16_t offset, float factor,
|
auto publish_sensor_state = [&](sensor::Sensor *sensor, size_t i,
|
||||||
int32_t unavailable_value = -1) -> void {
|
int16_t offset, float factor, int32_t unavailable_value = -1) -> void {
|
||||||
if (sensor == nullptr)
|
if (sensor == nullptr)
|
||||||
return;
|
return;
|
||||||
uint16_t register_value = get_register(i);
|
uint16_t register_value = get_register(i);
|
||||||
|
@ -87,6 +127,7 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
sensor->publish_state(value);
|
sensor->publish_state(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this->read_state_ == ReadState::READ_CELL_VOLTAGES) {
|
||||||
#ifdef USE_SENSOR
|
#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_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_2_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 1 , 0, 0.001);
|
||||||
|
@ -104,7 +145,11 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
publish_sensor_state(this->cell_14_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 13, 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_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);
|
publish_sensor_state(this->cell_16_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 15, 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);
|
publish_sensor_state(this->temperature_1_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 , -40, 1, 255);
|
||||||
publish_sensor_state(this->temperature_2_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 1, -40, 1, 255);
|
publish_sensor_state(this->temperature_2_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 1, -40, 1, 255);
|
||||||
publish_sensor_state(this->temperature_3_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 2, -40, 1, 255);
|
publish_sensor_state(this->temperature_3_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 2, -40, 1, 255);
|
||||||
|
@ -172,6 +217,9 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||||
this->precharging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_PRECHG_MOS_ACTIVE) > 0);
|
this->precharging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_PRECHG_MOS_ACTIVE) > 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
this->read_state_ = ReadState::IDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DalyHkmsBmsComponent::dump_config() {
|
void DalyHkmsBmsComponent::dump_config() {
|
||||||
|
|
|
@ -87,6 +87,8 @@ class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevic
|
||||||
uint32_t last_send_;
|
uint32_t last_send_;
|
||||||
uint8_t daly_address_;
|
uint8_t daly_address_;
|
||||||
|
|
||||||
|
enum class ReadState{ READ_CELL_VOLTAGES, READ_DATA, IDLE } read_state_{ReadState::IDLE};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace daly_hkms_bms
|
} // namespace daly_hkms_bms
|
||||||
|
|
|
@ -47,7 +47,7 @@ static const uint16_t DALY_MODBUS_ADDR_MOS_TEMP = 0x5A;
|
||||||
static const uint16_t DALY_MODBUS_ADDR_BOARD_TEMP = 0x5B;
|
static const uint16_t DALY_MODBUS_ADDR_BOARD_TEMP = 0x5B;
|
||||||
static const uint16_t DALY_MODBUS_ADDR_HEATING_TEMP = 0x5C;
|
static const uint16_t DALY_MODBUS_ADDR_HEATING_TEMP = 0x5C;
|
||||||
|
|
||||||
static const uint16_t DALY_MODBUS_REGISTER_COUNT = 0x5D;
|
static const uint16_t DALY_MODBUS_REGISTER_MAX = 0x5C;
|
||||||
|
|
||||||
} // namespace daly_hkms_bms
|
} // namespace daly_hkms_bms
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
Loading…
Reference in a new issue