Thanks!! Did you wired the bms via UART port directly to ESP32 board ( TX pin 6 and RX pin 5)? Sorry the original thread mentioned RS485. If it’s RS485… i’m guessing you’ll need the TTL → RS485 board in between?
I’m using a UART RS485 converter
Nope, not with the default esphome RS485 component
@Footz355 @dimksum Can both of you shared your wiring diagram to the 100 balancer I’ve tried setting this up for the past weekend and getting no luck getting any info. For context these are the hardware I’m using along with the 100balance bms port shown previously.
bms - can/485 plug. pin 1 and 2 connect to rs485-uart converter. converter connect to esp (tx-rx, rx-tx)
I have doubts about that.
k i tried that setup and no go…
BMS pin 1 (B - right most pin next to UART plug on BMS) → B on TTL to RS485 Device
BMS pin 2 (A - 2nd right most pin next to UART plug on BMS) → A on TTL to RS485 Device
Then from R0 → ESP GPIO16 (uart 2 rt) and DI → ESP GPIO17 (uart 2 tx)
Also tried
R0 → ESP GPIO17 (uart 2 tx) and DI → ESP GPIO16 (uart 2 rt)
My config
uart:
id: uart_0
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 9600
stop_bits: 1
If you can spot any issues with my setup that’ll be great! thanks for your help. Also if you don’t mine, can you post the model of your ESP32, TTL to RS845 board and etc?
[20:33:03][VV][scheduler:226]: Running interval ‘update’ with interval=5000 last_execution=422417 (now=427418)
[20:33:03][V][modbus_controller:226]: 2 modbus commands already in queue
[20:33:03][VV][modbus_controller:232]: Updating range 0xD457
[20:33:03][V][modbus_controller:195]: Range : D457 Size: 1 (0) skip: 0
[20:33:03][W][modbus_controller:182]: Duplicate modbus command found: type=0x10 address=54359 count=1
[20:33:03][VV][modbus_controller:232]: Updating range 0x30
[20:33:03][V][modbus_controller:195]: Range : 30 Size: 1 (3) skip: 0
[20:33:03][W][modbus_controller:182]: Duplicate modbus command found: type=0x3 address=48 count=1
[20:33:03][VV][api.service:697]: on_ping_request: PingRequest {}
[20:33:04][VV][api.service:043]: send_ping_response: PingResponse {}
[20:33:07][V][modbus_controller:042]: Sending next modbus command to device 129 register 0xD457 count 1
[20:33:07][VV][uart.arduino_esp32:194]: Flushing…
[20:33:07][V][modbus:231]: Modbus write raw: 81.03.00.38.00.0B (6)
[20:33:07][V][modbus_controller:565]: Command sent 0 0xD457 1 send_count: 5
[20:33:07][D][uart_debug:114]: >>> 81:03:00:38:00:0B:9A:00
[20:33:07][D][main:058]: Response data only had 8 bytes!!
[20:33:08][VV][scheduler:226]: Running interval ‘update’ with interval=5000 last_execution=427417 (now=432419)
[20:33:08][V][modbus_controller:226]: 2 modbus commands already in queue
[20:33:08][VV][modbus_controller:232]: Updating range 0xD457
[20:33:08][V][modbus_controller:195]: Range : D457 Size: 1 (0) skip: 0
[20:33:08][W][modbus_controller:182]: Duplicate modbus command found: type=0x10 address=54359 count=1
[20:33:08][VV][modbus_controller:232]: Updating range 0x30
[20:33:08][V][modbus_controller:195]: Range : 30 Size: 1 (3) skip: 0
[20:33:08][W][modbus_controller:182]: Duplicate modbus command found: type=0x3 address=48 count=1
[20:33:12][D][modbus_controller:038]: Modbus command to device=129 register=0xD457 no response received - removed from send queue
[20:33:12][V][modbus_controller:042]: Sending next modbus command to device 129 register 0x30 count 1
[20:33:12][VV][uart.arduino_esp32:194]: Flushing…
[20:33:12][V][modbus:210]: Modbus write: 81.03.00.30.00.01.9B.C5 (8)
[20:33:12][V][modbus_controller:565]: Command sent 3 0x30 1 send_count: 1
[20:33:12][D][uart_debug:114]: >>> 81:03:00:30:00:01:9B:C5
[20:33:12][D][main:058]: Response data only had 8 bytes!!
[20:33:13][VV][scheduler:226]: Running interval ‘update’ with interval=5000 last_execution=432417 (now=437424)
[20:33:13][V][modbus_controller:226]: 1 modbus commands already in queue
[20:33:13][VV][modbus_controller:232]: Updating range 0xD457
[20:33:13][V][modbus_controller:195]: Range : D457 Size: 1 (0) skip: 0
[20:33:13][VV][modbus_controller:232]: Updating range 0x30
[20:33:13][V][modbus_controller:195]: Range : 30 Size: 1 (3) skip: 0
[20:33:13][W][modbus_controller:182]: Duplicate modbus command found: type=0x3 address=48 count=1
Hi What do you mean?
Rs485 converter is not a serial “communicator”, it’s a “translator”, so generally tx is connected to tx pin and rx to rx pin.
Like in yours rx goes to RO pin (receiver out).
In your case you also need to control DE and RE pins.
Add this to Modbus:
flow_control_pin: GPIO4
and make a connection from Gpio4 to both DE and RE.
Also make sure you power your converter at 3.3V, not 5V.
ps. use code tags when posting your code or logs
Ah ok… thanks for the info. I’ll try that… I believe the wiring diagram will be closer to this other post (SRNE integration with HA). I was able to get that one to work last night.
Yep.
Just leave the termination resistor there if you don’t have some evidence that is should be removed.
OH YEA!! it worked… Granted there’s a very limited info that’s being presented…
Do you have more sensors/config you can share?
Just request another range of addresses where you have info that you need.
And then pick them one by one like it was done for these four.
Thanks!
K took a while but figure out the pattern… in case this helps others
uart:
- id: uart_0
tx_pin: 19
rx_pin: 18
baud_rate: 9600
stop_bits: 1
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());
if (bytes.size() == 27) {
ESP_LOGD("main", "MATCHED CELL INFO");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int tv = (bytes[3] << 8) | bytes[4];
id(tbv).publish_state(tv);
int current = ((bytes[5] << 8) | bytes[6]) - 30000;
id(cd).publish_state(current);
int so = (bytes[7] << 8) | bytes[8];
id(soc).publish_state(so);
ESP_LOGD("main", "PLACE HOLDER 0x3B - 0x3D - life, batt qty, batt temp qty");
int maxcv = ((bytes[15] << 8) | bytes[16]);
id(cvmax).publish_state(maxcv);
int maxci = ((bytes[17] << 8) | bytes[18]);
id(cimax).publish_state(maxci);
int mincv = ((bytes[19] << 8) | bytes[20]);
id(cvmin).publish_state(mincv);
int minci = ((bytes[21] << 8) | bytes[22]);
id(cimin).publish_state(minci);
int di = (bytes[23] << 8) | bytes[24];
id(dif).publish_state(di);
}
if (bytes.size() == 13) {
ESP_LOGD("main", "MATCHED MISC INFO");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int brc = (bytes[3] << 8) | bytes[4];
id(battremaincap).publish_state(brc);
int bct = (bytes[5] << 8) | bytes[6];
id(battcycletime).publish_state(bct);
int bs = (bytes[7] << 8) | bytes[8];
id(balancingstate).publish_state(bs);
int bc = (bytes[9] << 8) | bytes[10];
id(balancecurrent).publish_state(bc);
}
if (bytes.size() == 23) {
ESP_LOGD("main", "MATCHED MISC INFO 2");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int cmstat = (bytes[3] << 8) | bytes[4];
id(chargingmosstatus).publish_state(cmstat);
int dmstat = (bytes[5] << 8) | bytes[6];
id(dischargingmosstatus).publish_state(dmstat);
int avgv = (bytes[13] << 8) | bytes[14];
id(cvavg).publish_state(avgv);
int pow = (bytes[15] << 8) | bytes[16];
id(power).publish_state(pow);
int ener = (bytes[17] << 8) | bytes[18];
id(energy).publish_state(ener);
int mt = ((((bytes[19] << 8) | bytes[20]) - 40) * 9/5) + 32;
id(mostemp).publish_state(mt);
}
if (bytes.size() == 61) {
ESP_LOGD("main", "MATCHED CELLS VOLTAGE");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int cv1 = (bytes[3] << 8) | bytes[4];
id(cellv1).publish_state(cv1);
int cv2 = (bytes[5] << 8) | bytes[6];
id(cellv2).publish_state(cv2);
int cv3 = (bytes[7] << 8) | bytes[8];
id(cellv3).publish_state(cv3);
int cv4 = (bytes[9] << 8) | bytes[10];
id(cellv4).publish_state(cv4);
int cv5 = (bytes[11] << 8) | bytes[12];
id(cellv5).publish_state(cv5);
int cv6 = (bytes[13] << 8) | bytes[14];
id(cellv6).publish_state(cv6);
int cv7 = (bytes[15] << 8) | bytes[16];
id(cellv7).publish_state(cv7);
int cv8 = (bytes[17] << 8) | bytes[18];
id(cellv8).publish_state(cv8);
int cv9 = (bytes[19] << 8) | bytes[20];
id(cellv9).publish_state(cv9);
int cv10 = (bytes[21] << 8) | bytes[22];
id(cellv10).publish_state(cv10);
int cv11 = (bytes[23] << 8) | bytes[24];
id(cellv11).publish_state(cv11);
int cv12 = (bytes[25] << 8) | bytes[26];
id(cellv12).publish_state(cv12);
int cv13 = (bytes[27] << 8) | bytes[28];
id(cellv13).publish_state(cv13);
int cv14 = (bytes[29] << 8) | bytes[30];
id(cellv14).publish_state(cv14);
int cv15 = (bytes[31] << 8) | bytes[32];
id(cellv15).publish_state(cv15);
int cv16 = (bytes[33] << 8) | bytes[34];
id(cellv16).publish_state(cv16);
int cv17 = (bytes[35] << 8) | bytes[36];
id(cellv17).publish_state(cv17);
int cv18 = (bytes[37] << 8) | bytes[38];
id(cellv18).publish_state(cv18);
int cv19 = (bytes[39] << 8) | bytes[40];
id(cellv19).publish_state(cv19);
int cv20 = (bytes[41] << 8) | bytes[42];
id(cellv20).publish_state(cv20);
int cv21 = (bytes[43] << 8) | bytes[44];
id(cellv21).publish_state(cv21);
int cv22 = (bytes[45] << 8) | bytes[46];
id(cellv22).publish_state(cv22);
int cv23 = (bytes[47] << 8) | bytes[48];
id(cellv23).publish_state(cv23);
int cv24 = (bytes[49] << 8) | bytes[50];
id(cellv24).publish_state(cv24);
int t1 = ((((bytes[51] << 8) | bytes[52]) - 40) * 9/5) + 32;
id(temp1).publish_state(t1);
int t2 = ((((bytes[53] << 8) | bytes[54]) - 40) * 9/5) + 32;
id(temp2).publish_state(t2);
int t3 = ((((bytes[55] << 8) | bytes[56]) - 40) * 9/5) + 32;
id(temp3).publish_state(t3);
int t4 = ((((bytes[57] << 8) | bytes[58]) - 40) * 9/5) + 32;
id(temp4).publish_state(t4);
}
modbus:
- id: modbus0
uart_id: uart_0
send_wait_time: 1000ms
disable_crc: true
flow_control_pin: 4
# int at = ((((bytes[73] << 8) | bytes[74]) - 40) * 9/5) + 32;
# id(ambienttemp).publish_state(at);
modbus_controller:
- id: bms
address: 0x81
modbus_id: modbus0
command_throttle: 5000ms
update_interval: 2s
setup_priority: -20
sensor:
- platform: template
id: tbv
name: "Voltage" # 0x38 register
filters:
- multiply: 0.1
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cd
name: Current # 0x39 register
filters:
- multiply: 0.1
accuracy_decimals: 1
unit_of_measurement: "A"
state_class: measurement
device_class: current
- platform: template
id: soc
name: SOC # 0x3A register
filters:
- multiply: 0.1
unit_of_measurement: "%"
accuracy_decimals: 0
state_class: measurement
icon: mdi:battery
device_class: battery
- platform: template
id: cvmax
name: "Cell Volt Max" # 0x3E register
filters:
- multiply: 0.001
accuracy_decimals: 3
unit_of_measurement: "V"
icon: mdi:sine-wave
state_class: measurement
device_class: Voltage
- platform: template
id: cimax
name: "Cell Index Max" # 0x3F register
accuracy_decimals: 0
- platform: template
id: cvmin
name: "Cell Volt Min" # 0x40 register
filters:
- multiply: 0.001
accuracy_decimals: 3
unit_of_measurement: "V"
device_class: Voltage
state_class: measurement
icon: mdi:sine-wave
- platform: template
id: cimin
name: "Cell Index Min" # 0x41 register
accuracy_decimals: 0
- platform: template
id: dif
name: "Cell Volt delta" # 0x42 register
filters:
- multiply: 0.001
accuracy_decimals: 3
unit_of_measurement: "V"
device_class: Voltage
state_class: measurement
icon: mdi:sine-wave
- platform: template
id: battremaincap
name: "Battery Remain Capacity" # 0x4B register
#filters:
# - multiply: 0.001
accuracy_decimals: 1
unit_of_measurement: "Ah"
device_class: battery
state_class: measurement
icon: mdi:battery
- platform: template
id: battcycletime
name: "Battery Num Cycles" # 0x4C register
accuracy_decimals: 0
device_class: battery
state_class: measurement
icon: mdi:battery-sync
- platform: template
id: balancingstate
name: "Balancing State [0:off,1:pas,2:act]" # 0x4D register
accuracy_decimals: 0
device_class: battery
icon: mdi:power-plug
- platform: template
id: balancecurrent
name: "Balance Current" # 0x4E register
filters:
- multiply: 0.001
accuracy_decimals: 0
unit_of_measurement: "mA" # guessing
device_class: battery
state_class: measurement
icon: mdi:scale-unbalanced
#0x4F-0x51 equilibrium position
- platform: template
id: chargingmosstatus
name: "Charging Mos Status [0:off|1:on]" # 0x52 register
state_class: measurement
device_class: battery
accuracy_decimals: 0
- platform: template
id: dischargingmosstatus
name: "Discharging Mos Status [0:off|1:on]" # 0x53 register
state_class: measurement
device_class: battery
accuracy_decimals: 0
- platform: template
id: cvavg
name: "Cell Volt Avg" # 0x57 register
filters:
- multiply: 0.001
accuracy_decimals: 3
unit_of_measurement: "V"
icon: mdi:sine-wave
state_class: measurement
device_class: Voltage
- platform: template
id: power
name: "Power" # 0x58 register
# filters:
# - multiply: 0.001
accuracy_decimals: 1
unit_of_measurement: "W"
device_class: battery
state_class: measurement
icon: mdi:flash
- platform: template
id: energy
name: "Energy" # 0x59 register
# filters:
# - multiply: 0.001
accuracy_decimals: 1
unit_of_measurement: "Wh"
device_class: battery
state_class: measurement
icon: mdi:meter-electric
- platform: template
id: mostemp
name: "MOS Temp" # 0x5A register
accuracy_decimals: 1
unit_of_measurement: "f"
device_class: temperature
state_class: measurement
icon: mdi:thermometer
# - platform: template
# id: ambienttemp
# name: "Ambient Temp" # 0x5B register
# # filters:
# # - multiply: 0.001
# accuracy_decimals: 1
# unit_of_measurement: "f"
# # device_class: temperature
# state_class: measurement
# icon: mdi:thermometer
- platform: template
id: temp1
name: "Temperature 1" # 0x30 register
accuracy_decimals: 1
unit_of_measurement: "f"
device_class: temperature
state_class: measurement
icon: mdi:thermometer
- platform: template
id: temp2
name: "Temperature 2" # 0x32 register
accuracy_decimals: 1
unit_of_measurement: "f"
device_class: temperature
state_class: measurement
icon: mdi:thermometer
- platform: template
id: temp3
name: "Temperature 3" # 0x34 register
accuracy_decimals: 1
unit_of_measurement: "f"
device_class: temperature
state_class: measurement
icon: mdi:thermometer
- platform: template
id: temp4
name: "Temperature 4" # 0x36 register
accuracy_decimals: 1
unit_of_measurement: "f"
device_class: temperature
state_class: measurement
icon: mdi:thermometer
- platform: template
id: cellv1
name: "Cell Volt 01" # 0x00 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv2
name: "Cell Volt 02" # 0x02 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv3
name: "Cell Volt 03" # 0x04 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv4
name: "Cell Volt 04" # 0x06 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv5
name: "Cell Volt 05" # 0x08 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv6
name: "Cell Volt 06" # 0x0A register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv7
name: "Cell Volt 07" # 0x0C register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv8
name: "Cell Volt 08" # 0x0E register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv9
name: "Cell Volt 09" # 0x10 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv10
name: "Cell Volt 10" # 0x12 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv11
name: "Cell Volt 11" # 0x14 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv12
name: "Cell Volt 12" # 0x16 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv13
name: "Cell Volt 13" # 0x18 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv14
name: "Cell Volt 14" # 0x1A register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv15
name: "Cell Volt 15" # 0x1C register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv16
name: "Cell Volt 16" # 0x1E register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv17
name: "Cell Volt 17" # 0x20 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv18
name: "Cell Volt 18" # 0x22 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv19
name: "Cell Volt 19" # 0x24 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv20
name: "Cell Volt 20" # 0x26 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv21
name: "Cell Volt 21" # 0x28 register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv22
name: "Cell Volt 22" # 0x2A register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv23
name: "Cell Volt 23" # 0x2C register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
- platform: template
id: cellv24
name: "Cell Volt 24" # 0x2E register
filters:
- multiply: 0.001
accuracy_decimals: 2
unit_of_measurement: "V"
state_class: measurement
icon: mdi:meter-electric
device_class: Voltage
# Get Cell Voltages + temp 0x00 - 0x37 (56 bytes /2 = 28 registers [0x1C]) ) | total bytes = 56 + 5 = 61 Bytes
- platform: modbus_controller
modbus_controller_id: bms
id: custom_cellinfo
custom_command: [0x81, 0x03, 0x00, 0x00, 0x00, 0x1C]
# 0x38 first register to read, 0xB = 11 register count (27 byte response [1Byte = ADDR, 1Byte = CMD, 1Byte = Length, 2Bytes = CRC, reminder = register count x 2]) - ORIG
- platform: modbus_controller
modbus_controller_id: bms
id: custom_cellinfo2
custom_command: [0x81, 0x03, 0x00, 0x38, 0x00, 0x0B]
- platform: modbus_controller
modbus_controller_id: bms
id: custom_otherinfo
custom_command: [0x81, 0x03, 0x00, 0x4B, 0x00, 0x04]
- platform: modbus_controller
modbus_controller_id: bms
id: custom_otherinfo2
custom_command: [0x81, 0x03, 0x00, 0x52, 0x00, 0x09]
Nice job!!
Thanks, great work.
Greetings.
Looks like you cracked it, great.
Do you still require the excel file?? Sorry, I don’t visit here to often.
Here is the complete file:
I have just tested it and it works!! Thank you so much!!
As for temperature in Fahrenheit to switch to Celcius I have to change this formula?:
int t1 = ((((bytes[51] << 8) | bytes[52]) - 40) * 9/5) + 32;
id(temp1).publish_state(t1);
int t2 = ((((bytes[53] << 8) | bytes[54]) - 40) * 9/5) + 32;
id(temp2).publish_state(t2);
int t3 = ((((bytes[55] << 8) | bytes[56]) - 40) * 9/5) + 32;
id(temp3).publish_state(t3);
int t4 = ((((bytes[57] << 8) | bytes[58]) - 40) * 9/5) + 32;
id(temp4).publish_state(t4);
Thanks for figuring this all out. If I just could somehow get you a coffee or something remotely…
Edit:
Did you get the right battery temperatures? I only get -40, the same as you.
Also, do you have your ESP board connected on one RS-485 bus to your inverter and BMS? If so how does your code look like? When I try to integrate both codes for my SMG inverter and BMS I have a bunch of duplicate modbus command notifications in log. When they run from separate boards, they work ok. Managed to merge both SMG II and 100balance configs on one yaml and one ESP32
Greetings again. I came up with a slight inconvenience using the yaml for bms, merged together with yaml for my inverter:
---
substitutions:
name: SMG-II
esphome:
name: smgbalance
friendly_name: SMGBALANCE
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG
api:
encryption:
key: IiJ+FkXDMYddK6U7rzfq/XN81rKFmh3iheaVofbNnZo=
ota:
platform: esphome
password: 8ab32666264fa56690a9eecb30b7e7c7
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.86
gateway: 192.168.1.100
subnet: 255.255.255.0
ap:
ssid: Smgii-62 Fallback Hotspot
password: HMVA5x3DAjDy
captive_portal: null
uart:
- id: uart_0
baud_rate: 9600
tx_pin: GPIO17
rx_pin: GPIO16
stop_bits: 1
parity: NONE
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());
if (bytes.size() == 27) {
ESP_LOGD("main", "MATCHED CELL INFO");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int tv = (bytes[3] << 8) | bytes[4];
id(tbv).publish_state(tv);
int current = ((bytes[5] << 8) | bytes[6]) - 30000;
id(cd).publish_state(current);
int so = (bytes[7] << 8) | bytes[8];
id(soc).publish_state(so);
ESP_LOGD("main", "PLACE HOLDER 0x3B - 0x3D - life, batt qty, batt temp qty");
int maxcv = ((bytes[15] << 8) | bytes[16]);
id(cvmax).publish_state(maxcv);
int maxci = ((bytes[17] << 8) | bytes[18]);
id(cimax).publish_state(maxci);
int mincv = ((bytes[19] << 8) | bytes[20]);
id(cvmin).publish_state(mincv);
int minci = ((bytes[21] << 8) | bytes[22]);
id(cimin).publish_state(minci);
int di = (bytes[23] << 8) | bytes[24];
id(dif).publish_state(di);
}
if (bytes.size() == 13) {
ESP_LOGD("main", "MATCHED MISC INFO");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int brc = (((bytes[3] << 8) | bytes[4]) / 10);
id(battremaincap).publish_state(brc);
int bct = (bytes[5] << 8) | bytes[6];
id(battcycletime).publish_state(bct);
int bs = (bytes[7] << 8) | bytes[8];
id(balancingstate).publish_state(bs);
int bc = (bytes[9] << 8) | bytes[10];
id(balancecurrent).publish_state(bc);
}
if (bytes.size() == 23) {
ESP_LOGD("main", "MATCHED MISC INFO 2");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int cmstat = (bytes[3] << 8) | bytes[4];
id(chargingmosstatus).publish_state(cmstat);
int dmstat = (bytes[5] << 8) | bytes[6];
id(dischargingmosstatus).publish_state(dmstat);
int avgv = (bytes[13] << 8) | bytes[14];
id(cvavg).publish_state(avgv);
int pow = (bytes[15] << 8) | bytes[16];
id(power).publish_state(pow);
int ener = (bytes[17] << 8) | bytes[18];
id(energy).publish_state(ener);
int mt = (((bytes[19] << 8) | bytes[20]) - 40);
id(mostemp).publish_state(mt);
}
if (bytes.size() == 61) {
ESP_LOGD("main", "MATCHED CELLS VOLTAGE");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int cv1 = (bytes[3] << 8) | bytes[4];
id(cellv1).publish_state(cv1);
int cv2 = (bytes[5] << 8) | bytes[6];
id(cellv2).publish_state(cv2);
int cv3 = (bytes[7] << 8) | bytes[8];
id(cellv3).publish_state(cv3);
int cv4 = (bytes[9] << 8) | bytes[10];
id(cellv4).publish_state(cv4);
int cv5 = (bytes[11] << 8) | bytes[12];
id(cellv5).publish_state(cv5);
int cv6 = (bytes[13] << 8) | bytes[14];
id(cellv6).publish_state(cv6);
int cv7 = (bytes[15] << 8) | bytes[16];
id(cellv7).publish_state(cv7);
int cv8 = (bytes[17] << 8) | bytes[18];
id(cellv8).publish_state(cv8);
int cv9 = (bytes[19] << 8) | bytes[20];
id(cellv9).publish_state(cv9);
int cv10 = (bytes[21] << 8) | bytes[22];
id(cellv10).publish_state(cv10);
int cv11 = (bytes[23] << 8) | bytes[24];
id(cellv11).publish_state(cv11);
int cv12 = (bytes[25] << 8) | bytes[26];
id(cellv12).publish_state(cv12);
int cv13 = (bytes[27] << 8) | bytes[28];
id(cellv13).publish_state(cv13);
int cv14 = (bytes[29] << 8) | bytes[30];
id(cellv14).publish_state(cv14);
int cv15 = (bytes[31] << 8) | bytes[32];
id(cellv15).publish_state(cv15);
int cv16 = (bytes[33] << 8) | bytes[34];
id(cellv16).publish_state(cv16);
int cv17 = (bytes[35] << 8) | bytes[36];
id(cellv17).publish_state(cv17);
int cv18 = (bytes[37] << 8) | bytes[38];
id(cellv18).publish_state(cv18);
int cv19 = (bytes[39] << 8) | bytes[40];
id(cellv19).publish_state(cv19);
int cv20 = (bytes[41] << 8) | bytes[42];
id(cellv20).publish_state(cv20);
int cv21 = (bytes[43] << 8) | bytes[44];
id(cellv21).publish_state(cv21);
int cv22 = (bytes[45] << 8) | bytes[46];
id(cellv22).publish_state(cv22);
int cv23 = (bytes[47] << 8) | bytes[48];
id(cellv23).publish_state(cv23);
int cv24 = (bytes[49] << 8) | bytes[50];
id(cellv24).publish_state(cv24);
int t1 = (((bytes[51] << 8) | bytes[52]) - 40);
id(temp1).publish_state(t1);
int t2 = (((bytes[53] << 8) | bytes[54]) - 40);
id(temp2).publish_state(t2);
int t3 = (((bytes[55] << 8) | bytes[56]) - 40);
id(temp3).publish_state(t3);
int t4 = (((bytes[57] << 8) | bytes[58]) - 40);
id(temp4).publish_state(t4);
}
modbus:
- id: modbus0
uart_id: uart_0
send_wait_time: 1000ms
disable_crc: true
#flow_control_pin: 4
# int at = (((bytes[73] << 8) | bytes[74]) - 40);
# id(ambienttemp).publish_state(at);
modbus_controller:
- id: smg0
address: 1
modbus_id: modbus0
command_throttle: 400ms
update_interval: 20s
- id: bms
address: 0x81
modbus_id: modbus0
command_throttle: 5000ms
update_interval: 2s
setup_priority: -20
Rest of the code are sensors.
The issue is it seems with this part:
if (bytes.size() == 13) {
ESP_LOGD("main", "MATCHED MISC INFO");
ESP_LOGD("main", "Response data %d", bytes[0]);
ESP_LOGD("main", "Response data %d", bytes[1]);
int brc = (((bytes[3] << 8) | bytes[4]) / 10);
id(battremaincap).publish_state(brc);
int bct = (bytes[5] << 8) | bytes[6];
id(battcycletime).publish_state(bct);
int bs = (bytes[7] << 8) | bytes[8];
id(balancingstate).publish_state(bs);
int bc = (bytes[9] << 8) | bytes[10];
id(balancecurrent).publish_state(bc);
}
Log output from my ESP is as follows:
[08:40:23][D][uart_debug:114]: <<< 51:03:08:01:98:00:18:00:00:75:30:4A:55
[08:40:23][D][main:051]: Response data only had 13 bytes!!
[08:40:23][D][main:087]: MATCHED MISC INFO
[08:40:23][D][main:088]: Response data 81
[08:40:23][D][main:089]: Response data 3
[08:40:23][D][sensor:094]: 'Battery Remain Capacity': Sending state 40.00000 Ah with 1 decimals of accuracy
[08:40:23][D][sensor:094]: 'Battery Num Cycles': Sending state 24.00000 with 0 decimals of accuracy
[08:40:23][D][sensor:094]: 'Balancing State [0:off,1:pas,2:act]': Sending state 0.00000 with 0 decimals of accuracy
[08:40:23][D][sensor:094]: 'Balance Current': Sending state 30.00000 mA with 0 decimals of accuracy
or on another run I get:
[08:40:27][D][uart_debug:114]: <<< 01:03:08:00:00:00:00:00:01:00:03:84:16
[08:40:27][D][main:051]: Response data only had 13 bytes!!
[08:40:27][D][main:087]: MATCHED MISC INFO
[08:40:27][D][main:088]: Response data 1
[08:40:27][D][main:089]: Response data 3
[08:40:27][D][sensor:094]: 'Battery Remain Capacity': Sending state 0.00000 Ah with 1 decimals of accuracy
[08:40:27][D][sensor:094]: 'Battery Num Cycles': Sending state 0.00000 with 0 decimals of accuracy
[08:40:27][D][sensor:094]: 'Balancing State [0:off,1:pas,2:act]': Sending state 1.00000 with 0 decimals of accuracy
[08:40:27][D][sensor:094]: 'Balance Current': Sending state 0.00300 mA with 0 decimals of accuracy
It seems the uart debug lambda is configured to wait for a particular byte size to get the info I need, but the byte size is present twice in the debug info (don’t know if that is caused by adding my inverter modbus config to bms config), and causes those HA entities to zero out for a minute or so, to show up again for some seconds, and to zero out again.
Question is: Is there a possibility to disregard info from 01:03:08:00:00:00:00:00:01:00:03:84:16, and receive only info from 51:03:08:01:98:00:18:00:00:75:30:4A:55 ?? I guess the condition shouldn’t be byte size oriented, but more address oriented?? Any ide how could I go about it?
It needs to be byte oriented. It was the easiest way to make 4 separate requests and identify the responses.
The easiest way to resolve your problem is to make one of those request (that gives 13 bytes) longer, adding register count by 1, so the response will be 15bytes.
Another option is to verify also the first byte value.