Issue integrating 100balance BMS with ESPHome via RS-485

The problem is that on rs485 I get different response lengths. but through the UART connection I began to receive consistently the same length of response

Yesterday you had good solid debug logs…

You said yesterday that this is a bad protocol for rs485 and nothing will work

Modbus library doesn’t have output for response from unknown address. Dead end.
So the idea is to use that only for request and grab the data from uart_debug.
When you get it working, the code above should only print the byte count, 8 and 7 to confirm that you have those bytes “on your hands”.

[18:27:43][C][modbus_controller:345]: ModbusController:
[18:27:43][C][modbus_controller:346]:   Address: 0x81
[18:27:44][D][uart_debug:114]: >>> 81:03:00:30:00:01:9B:C5
[18:27:44][D][main:047]: Response data only had 8 bytes!!
[18:27:44][W][modbus:144]: Got Modbus frame from unknown address 0x51! 
[18:27:45][D][uart_debug:114]: <<< 51:03:02:00:41:B8:78
[18:27:45][D][main:047]: Response data only had 7 bytes!!
[18:27:48][W][modbus_controller:182]: Duplicate modbus command found: type=0x3 address=48 count=1
[18:27:49][D][uart_debug:114]: >>> 81:03:00:30:00:01:9B:C5
[18:27:50][D][main:047]: Response data only had 8 bytes!!
[18:27:50][W][modbus:144]: Got Modbus frame from unknown address 0x51! 
[18:27:50][D][uart_debug:114]: <<< 51:03:02:00:41:B8:78
[18:27:50][D][main:047]: Response data only had 7 bytes!!
[18:27:55][D][uart_debug:114]: >>> 81:03:00:30:00:01:9B:C5
[18:27:55][D][main:047]: Response data only had 8 bytes!!
[18:27:55][W][modbus:144]: Got Modbus frame from unknown address 0x51! 
[18:27:55][D][uart_debug:114]: <<< 51:03:02:00:41:B8:78
[18:27:55][D][main:047]: Response data only had 7 bytes!!
uart:
  - id: uart_0
    baud_rate: 9600
    tx_pin: D2
    rx_pin: D3
    
    debug:
      direction: BOTH
      dummy_receiver: true
      after:
         delimiter: "\n"
      sequence:
          - lambda: |-
              UARTDebug::log_hex(direction, bytes, ':');
              ESP_LOGD("main", "Response data only had %d bytes!!", bytes.size() );
              std::string str(bytes.begin(), bytes.end());
              int temperature = bytes[4]-40;
              id(temp).publish_state(temperature);
modbus:
  - id: modbus0
    uart_id: uart_0
    send_wait_time: 1000ms
    disable_crc: true

modbus_controller:
  - id: bms
    address: 0x81
    modbus_id: modbus0
    command_throttle: 5000ms
    update_interval: 10s
    setup_priority: -20

sensor:
  - platform: template
    id: temp

  - platform: modbus_controller
    modbus_controller_id: bms
    name: Temperature 1
    address: 0x30
    register_type: holding

and i have correct temperature :upside_down_face: )

Good’
Try to add this:

if (bytes.size() == 7) {
ESP_LOGD("main", "Response data &d", bytes[4]);
}

Edit: I didn’t see your replay

Thus, to obtain data from one sensor, you need to make 2 sensors. But what to do to get and parse the remaining parameters (voltage, SOC…)?

How many, and what kind of values they are?

about 10-15 parameters

You request them all at once and parse correct bytes to correct sensor

I don’t understand how

tell me the first and the last register address


0x00…0x64
Can you give an example for two registers?

Quite long, I don’t know the max you can do, but for 2 it would be:
custom_command: [ 0x81, 0x03, 0x00, 0x00,0x00, 0x02]

for 100
custom_command: [ 0x81, 0x03, 0x00, 0x00,0x00, 0x64]

anyway add this to exclude your request (tx)
if (bytes.size() != 8) {
Edit: not valid for request of 2 registers, but for any other number yes.

I understand this, but how can I then understand that lambda received data from the parameter I need?

first (0x00) is bytes[4]
second (0x01) is bytes[5]
and so on

Actually you could also do it in several requests and use number of registers as a identifier.
For example you request 8 addresses
custom_command: [ 0x81, 0x03, 0x00, 0x52,0x00, 0x08]

it gives you response of 14 bytes

if (bytes.size() == 14) {
int chargingMosStatus = bytes[4];
id(cms).publish_state(chargingMosStatus);
int dischargeMosStatus = bytes[5];
id(dms).publish_state(dischargeMosStatus);

and so on

if request/response sizes are different from each other you can identify them and remap them to right sensors.

thank’s, but why this code don’t work
total battery voltage. address 0x38

sensor:
  - platform: modbus_controller
    modbus_controller_id: bms
    name: "Total voltage"
    custom_command: [0x81, 0x03, 0x00, 0x38, 0x00, 0x01]
    value_type: U_DWORD
    lambda: |-
      ESP_LOGV("Modbus Sensor TV","Got new data" );
      float vv = (data[3]+data[4])* 0.1;
      return vv;

and i see

[20:32:01][C][modbus_controller:346]:   Address: 0x81
[20:32:03][D][uart_debug:114]: >>> 81:03:00:38:00:01:1A:07
[20:32:03][D][main:047]: Response data only had 8 bytes!!
[20:32:03][D][uart_debug:114]: <<< 51:03:02:01:0A
[20:32:03][D][main:047]: Response data only had 5 bytes!!
[20:32:03][W][modbus:144]: Got Modbus frame from unknown address 0x51! 
[20:32:03][D][uart_debug:114]: <<< F9:DF
[20:32:03][D][main:047]: Response data only had 2 bytes!!
[20:32:03][W][modbus_controller:182]: Duplicate modbus command found: type=0x30 address=46809 count=2
[20:32:08][D][uart_debug:114]: >>> 81:03:00:38:00:01:1A:07

my battery voltage is 26.6
266 = 01:0A i see this in answer, but sensor is empty

For multiple reasons.
You already tried to grab the data in modbus_controller and it doesn’t have any output for non corresponding slave address. So that data doesn’t return anything.
Also, you have 5 bytes response, so there is something else wrong as well.

Why you have to try randomly things if you already have working setup?