my rs485 boardPlease test this YAML.
Which RS485 board are you using ?
If enabled, any changes you make into one of your JK-PB bms will be replicated to all bms of the same model.What settings does this control?:
yambms Broadcasting JK-PB settings to all BMS
# Updated : 2025.04.01
# Version : 1.5.5
# GitHub : https://github.com/Sleeper85/esphome-yambms
# YamBMS ( Yet another multi-BMS Merging Solution )
# This YAML is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
######################## YamBMS Remote Packages Version ########################
# You can compile this YAML directly without the `packages` folder.
# The packages will be automatically downloaded from GitHub.
# Don't forget to configure your WiFi credentials in the secrets.yaml
################################################################################
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
logger:
level: DEBUG # VERBOSE / DEBUG / INFO / WARN
ota:
platform: esphome
# Please use the native `api` component instead of the `mqtt` section.
# If you use Home Assistant, the native API is more lightweight.
# If there is no HA server connected to this API, the ESP32 reboots every 15 minutes to try to resolve the problem.
# The "reboot_timeout: 0s" option will keep your ESP32 up and running even if you lose connection to your HA server.
api:
reboot_timeout: 0s
# If you don't want to use ESPHome's native API you can use MQTT instead.
# In this case don't forget to remove the 'api:' section.
# mqtt:
# broker: !secret mqtt_host
# username: !secret mqtt_username
# password: !secret mqtt_password
# id: mqtt_client
# Please note that enabling this component will take up a lot of memory and may decrease
# stability and be the cause of reboot depending on the capabilities of the board used.
# web_server:
# port: 80
# log: false
# ota: false
# +--------------------------------------+
# | Global Settings |
# +--------------------------------------+
substitutions:
# ESP32 name / hostname
name: yambms
# +--------------------------------------+
# | YamBMS Settings |
# +--------------------------------------+
# Please read the cut-off charging logic README to understand how the YamBMS works
yambms_id: 'Dacha'
yambms_name: 'YamBMS'
yambms_update_interval: '1s'
# Input numbers can be displayed as a slider or an input box, options are 'slider' or 'box'.
yambms_input_number_mode: 'box'
# Please check and fill in the options below correctly according to your battery chemistry and number of cells in series.
# These parameters are important and used for charging logic.
# Battery Chemistry
yambms_battery_chemistry: '1' # 1-LFP | 2-Li-ion | 3-LTO
# Number of cells in series
yambms_cell_count: '8'
# Bulk / Absorption Voltage : corresponds to the Bulk voltage that will be used to charge the battery. (LFP : 27.6V = 3.45V/Cell for 8S battery)
yambms_bulk_v: '27.6'
# Float Voltage : corresponds to the voltage at which the battery would be maintained at the end of charge. (LFP : 26.8V = 3.35V/Cell for 8S battery)
yambms_float_v: '26.8'
# Rebulk voltage, voltage from which a new Bulk charge can start. (LFP : 26.4V = 3.3V/Cell for 8S battery)
yambms_rebulk_v: '26.4'
# Maximum time in minutes that the cut-off step can last before charging is complete
# If your cells are properly balanced this step ends at the fastest after the `cut-off timer`
# This timer can be deactivated with a switch
yambms_eoc_timer: '30'
# Time in seconds during which the end of charge conditions must be respected (cut-off + cells not equalizing)
yambms_cutoff_timer: '60'
# +--------------------------------------+
# | Shunt Settings |
# +--------------------------------------+
shunt_update_interval: '3s' # frequency at which Shunt data is refreshed
shunt_combine_interval: '1s' # frequency at which Shunt data is combined in YamBMS
# +--------------------------------------+
# | BMS Settings |
# +--------------------------------------+
bms_update_interval: '3s' # frequency at which BMS data is refreshed, going below '3s' can cause problems
bms_combine_interval: '1s' # frequency at which BMS data is combined in YamBMS
bms_cutoff_timer: '50s' # time during which the end of charge conditions must be respected (cut-off + cells not equalizing)
# +--------------------------------------+
# | Packages |
# +--------------------------------------+
packages:
############### >>> UNCOMMENT YOUR BOARD <<< ###############
############### >>> ONLY ONE BOARD ! <<< ###############
board:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
- path: 'packages/board/board_ESP32_DevKit-V1.yaml'
########### >>> UNCOMMENT YOUR BOARD OPTIONS <<< ###########
board_options:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
# UART
- path: 'packages/board/board_options_itf_uart_esp_1.yaml'
# ESP32_CAN (SN65HVD230 unit)
- path: 'packages/board/board_options_itf_canbus_esp32_can.yaml'
vars:
canbus_node_id: 'canbus_inverter_1'
############################################################
# shunt:
# url: https://github.com/Sleeper85/esphome-yambms
# ref: main
# refresh: 0s
# files:
# # Shunt 1
# - path: 'packages/shunt/shunt_combine_Victron_SmartShunt_UART.yaml' # shunt_combine_Junctek_KHF_UART.yaml
# vars:
# shunt_id: '1' # must be a number
# shunt_name: 'Shunt 1'
# shunt_uart_id: 'uart_esp_3'
bms:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
# BMS 1
- path: 'packages/bms/bms_combine_JK_UART_4G-GPS_full.yaml'
vars:
bms_id: '1' # must be a number
bms_name: 'JK-b2a8s20p'
bms_uart_id: 'uart_esp_1'
bms_address: '0x01'
# Maximum cell charging cycles is used to calculate the battey SoH.
# MB31=8000.0, LF280K v3=8000.0, LF280K v2=6000.0, LF280=3000.0 (decimal is required)
bms_cell_max_cycles: '6000.0'
# auto charge off triggers for individual BMS
bms_options:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
# BMS 1
- path: 'packages/bms/bms_options_charging_logic.yaml'
vars:
bms_id: '1' # must be a number
yambms:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
- path: 'packages/yambms/yambms.yaml'
canbus:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
- path: 'packages/yambms/yambms_canbus.yaml'
vars:
canbus_id: 'canbus1'
canbus_name: 'CANBUS'
canbus_node_id: 'canbus_inverter_1'
canbus_light_id: 'esp_light'
# The CANBUS link will be considered down if no response from the inverter (0x305 frame) for 5s
# The Deye inverter sends the ACK 0x305 only when it receives the 0x356 frame.
canbus_link_timer: '5s'
# +--------------------------------------+
# | DEBUG ( logger level must be DEBUG ) |
# +--------------------------------------+
debug:
url: https://github.com/Sleeper85/esphome-yambms
ref: main
refresh: 0s
files:
- path: packages/base/device_debug_ESP32.yaml
vars:
debug_name: 'Debug'
debug_update_interval: '5s'
# +--------------------------------------+
# | Custom config |
# +--------------------------------------+
switch:
- platform: template
name: "${name} ${yambms_name} Force Float"
id: ${yambms_id}_switch_force_float
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
entity_category: config
interval:
# Force Float
- interval: ${yambms_update_interval}
then:
- lambda: |-
// Force Float => Float
if (id(${yambms_id}_switch_force_float).state) id(${yambms_id}_charge_status) = "Float";
# Setup min/max value
- interval: 24h # 60s
then:
- lambda: |-
// Float V.
id(${yambms_id}_float_voltage).traits.set_min_value(${yambms_cell_count} * 3.125);
id(${yambms_id}_float_voltage).traits.set_max_value(${yambms_cell_count} * 3.375);
Hi. Can`t get it to work. JK-b2a8s20p. No data from UART port (at the same time, the esphome-jk-bms@syssi project works fine). Maybe I missed something in the config?
- Thx in advanceCode:# Updated : 2025.04.01 # Version : 1.5.5 # GitHub : https://github.com/Sleeper85/esphome-yambms # YamBMS ( Yet another multi-BMS Merging Solution ) # This YAML is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation, either version 3 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>. ######################## YamBMS Remote Packages Version ######################## # You can compile this YAML directly without the `packages` folder. # The packages will be automatically downloaded from GitHub. # Don't forget to configure your WiFi credentials in the secrets.yaml ################################################################################ wifi: ssid: !secret wifi_ssid password: !secret wifi_password logger: level: DEBUG # VERBOSE / DEBUG / INFO / WARN ota: platform: esphome # Please use the native `api` component instead of the `mqtt` section. # If you use Home Assistant, the native API is more lightweight. # If there is no HA server connected to this API, the ESP32 reboots every 15 minutes to try to resolve the problem. # The "reboot_timeout: 0s" option will keep your ESP32 up and running even if you lose connection to your HA server. api: reboot_timeout: 0s # If you don't want to use ESPHome's native API you can use MQTT instead. # In this case don't forget to remove the 'api:' section. # mqtt: # broker: !secret mqtt_host # username: !secret mqtt_username # password: !secret mqtt_password # id: mqtt_client # Please note that enabling this component will take up a lot of memory and may decrease # stability and be the cause of reboot depending on the capabilities of the board used. # web_server: # port: 80 # log: false # ota: false # +--------------------------------------+ # | Global Settings | # +--------------------------------------+ substitutions: # ESP32 name / hostname name: yambms # +--------------------------------------+ # | YamBMS Settings | # +--------------------------------------+ # Please read the cut-off charging logic README to understand how the YamBMS works yambms_id: 'Dacha' yambms_name: 'YamBMS' yambms_update_interval: '1s' # Input numbers can be displayed as a slider or an input box, options are 'slider' or 'box'. yambms_input_number_mode: 'box' # Please check and fill in the options below correctly according to your battery chemistry and number of cells in series. # These parameters are important and used for charging logic. # Battery Chemistry yambms_battery_chemistry: '1' # 1-LFP | 2-Li-ion | 3-LTO # Number of cells in series yambms_cell_count: '8' # Bulk / Absorption Voltage : corresponds to the Bulk voltage that will be used to charge the battery. (LFP : 27.6V = 3.45V/Cell for 8S battery) yambms_bulk_v: '27.6' # Float Voltage : corresponds to the voltage at which the battery would be maintained at the end of charge. (LFP : 26.8V = 3.35V/Cell for 8S battery) yambms_float_v: '26.8' # Rebulk voltage, voltage from which a new Bulk charge can start. (LFP : 26.4V = 3.3V/Cell for 8S battery) yambms_rebulk_v: '26.4' # Maximum time in minutes that the cut-off step can last before charging is complete # If your cells are properly balanced this step ends at the fastest after the `cut-off timer` # This timer can be deactivated with a switch yambms_eoc_timer: '30' # Time in seconds during which the end of charge conditions must be respected (cut-off + cells not equalizing) yambms_cutoff_timer: '60' # +--------------------------------------+ # | Shunt Settings | # +--------------------------------------+ shunt_update_interval: '3s' # frequency at which Shunt data is refreshed shunt_combine_interval: '1s' # frequency at which Shunt data is combined in YamBMS # +--------------------------------------+ # | BMS Settings | # +--------------------------------------+ bms_update_interval: '3s' # frequency at which BMS data is refreshed, going below '3s' can cause problems bms_combine_interval: '1s' # frequency at which BMS data is combined in YamBMS bms_cutoff_timer: '50s' # time during which the end of charge conditions must be respected (cut-off + cells not equalizing) # +--------------------------------------+ # | Packages | # +--------------------------------------+ packages: ############### >>> UNCOMMENT YOUR BOARD <<< ############### ############### >>> ONLY ONE BOARD ! <<< ############### board: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: - path: 'packages/board/board_ESP32_DevKit-V1.yaml' ########### >>> UNCOMMENT YOUR BOARD OPTIONS <<< ########### board_options: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: # UART - path: 'packages/board/board_options_itf_uart_esp_1.yaml' # ESP32_CAN (SN65HVD230 unit) - path: 'packages/board/board_options_itf_canbus_esp32_can.yaml' vars: canbus_node_id: 'canbus_inverter_1' ############################################################ # shunt: # url: https://github.com/Sleeper85/esphome-yambms # ref: main # refresh: 0s # files: # # Shunt 1 # - path: 'packages/shunt/shunt_combine_Victron_SmartShunt_UART.yaml' # shunt_combine_Junctek_KHF_UART.yaml # vars: # shunt_id: '1' # must be a number # shunt_name: 'Shunt 1' # shunt_uart_id: 'uart_esp_3' bms: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: # BMS 1 - path: 'packages/bms/bms_combine_JK_UART_4G-GPS_full.yaml' vars: bms_id: '1' # must be a number bms_name: 'JK-b2a8s20p' bms_uart_id: 'uart_esp_1' bms_address: '0x01' # Maximum cell charging cycles is used to calculate the battey SoH. # MB31=8000.0, LF280K v3=8000.0, LF280K v2=6000.0, LF280=3000.0 (decimal is required) bms_cell_max_cycles: '6000.0' # auto charge off triggers for individual BMS bms_options: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: # BMS 1 - path: 'packages/bms/bms_options_charging_logic.yaml' vars: bms_id: '1' # must be a number yambms: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: - path: 'packages/yambms/yambms.yaml' canbus: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: - path: 'packages/yambms/yambms_canbus.yaml' vars: canbus_id: 'canbus1' canbus_name: 'CANBUS' canbus_node_id: 'canbus_inverter_1' canbus_light_id: 'esp_light' # The CANBUS link will be considered down if no response from the inverter (0x305 frame) for 5s # The Deye inverter sends the ACK 0x305 only when it receives the 0x356 frame. canbus_link_timer: '5s' # +--------------------------------------+ # | DEBUG ( logger level must be DEBUG ) | # +--------------------------------------+ debug: url: https://github.com/Sleeper85/esphome-yambms ref: main refresh: 0s files: - path: packages/base/device_debug_ESP32.yaml vars: debug_name: 'Debug' debug_update_interval: '5s' # +--------------------------------------+ # | Custom config | # +--------------------------------------+ switch: - platform: template name: "${name} ${yambms_name} Force Float" id: ${yambms_id}_switch_force_float restore_mode: RESTORE_DEFAULT_OFF optimistic: true entity_category: config interval: # Force Float - interval: ${yambms_update_interval} then: - lambda: |- // Force Float => Float if (id(${yambms_id}_switch_force_float).state) id(${yambms_id}_charge_status) = "Float"; # Setup min/max value - interval: 24h # 60s then: - lambda: |- // Float V. id(${yambms_id}_float_voltage).traits.set_min_value(${yambms_cell_count} * 3.125); id(${yambms_id}_float_voltage).traits.set_max_value(${yambms_cell_count} * 3.375);
bms1: !include
file: packages/bms/bms_combine_JK_UART_4G-GPS_full.yaml
vars:
bms_id: '1' # must be a number
bms_name: 'JK-BMS 1'
bms_uart_id: 'uart_esp_1'
# Maximum cell charging cycles is used to calculate the battey SoH.
# MB31=8000.0, LF280K v3=8000.0, LF280K v2=6000.0, LF280=3000.0 (decimal is required)
bms_cell_max_cycles: '6000.0'
substitutions:
board_chip: "ESP32"
board_name: "DevKit V1"
# Interfaces GPIOs
# uart_esp_1
tx_pin_1: '17'
rx_pin_1: '16'
# uart_esp_2
tx_pin_2: '19'
rx_pin_2: '18'
# uart_esp_3
tx_pin_3: '26'
rx_pin_3: '25'
# canbus_esp32_can
tx_pin_4: '23'
rx_pin_4: '22'
# canbus_mcp2515
spi_mosi_pin: '13'
spi_miso_pin: '12'
spi_clk_pin: '14'
mcp2515_cs_pin: '15'
Yes, that's right.It looks like you copied @Dmode YAML.
Yes, TX 17 and RX 16 (including swapping). No data.This YAML connects a JK-B BMS to the uart_esp_1 port (TX 17 and RX 16) to JK GPS port.
I don't know yet ))Do you need this additional custom code?
[09:50:20][C][uart.idf:159]: UART Bus 0:
[09:50:20][C][uart.idf:160]: TX Pin: GPIO17
[09:50:20][C][uart.idf:161]: RX Pin: GPIO16
[09:50:20][C][uart.idf:163]: RX Buffer Size: 512
[09:50:20][C][uart.idf:165]: Baud Rate: 115200 baud
[09:50:20][C][uart.idf:166]: Data Bits: 8
[09:50:20][C][uart.idf:167]: Parity: NONE
[09:50:20][C][uart.idf:168]: Stop bits: 1
substitutions:
name: jk-b2a8s20p
device_description: "Monitor a JK-BMS using the GPS port (UART-TTL)"
external_components_source: github://syssi/esphome-jk-bms@main
tx_pin: GPIO17
rx_pin: GPIO16
uart:
- id: uart_0
baud_rate: 115200
rx_buffer_size: 384
tx_pin: ${tx_pin}
rx_pin: ${rx_pin}
jk_modbus:
- id: modbus0
uart_id: uart_0
rx_timeout: 50ms
jk_bms:
- id: bms0
jk_modbus_id: modbus0
update_interval: 5s
Yes, that's right.
Yes, TX 17 and RX 16 (including swapping). No data.
I don't know yet ))
Small part of log:
Code:[09:50:20][C][uart.idf:159]: UART Bus 0: [09:50:20][C][uart.idf:160]: TX Pin: GPIO17 [09:50:20][C][uart.idf:161]: RX Pin: GPIO16 [09:50:20][C][uart.idf:163]: RX Buffer Size: 512 [09:50:20][C][uart.idf:165]: Baud Rate: 115200 baud [09:50:20][C][uart.idf:166]: Data Bits: 8 [09:50:20][C][uart.idf:167]: Parity: NONE [09:50:20][C][uart.idf:168]: Stop bits: 1
This is a part of esphome-jk-bms@syssi config file:
Code:substitutions: name: jk-b2a8s20p device_description: "Monitor a JK-BMS using the GPS port (UART-TTL)" external_components_source: github://syssi/esphome-jk-bms@main tx_pin: GPIO17 rx_pin: GPIO16 uart: - id: uart_0 baud_rate: 115200 rx_buffer_size: 384 tx_pin: ${tx_pin} rx_pin: ${rx_pin} jk_modbus: - id: modbus0 uart_id: uart_0 rx_timeout: 50ms jk_bms: - id: bms0 jk_modbus_id: modbus0 update_interval: 5s
JK-B2A8S20P, hw 11.XA, sw 11.48, using UART-TTL (reported by @BytEvil) (from syssi github page)What BMS firmware and hardware version ?
Yes, I flashed it for testing and then want to use permanently.@syssi code work on the same board with the same GPIOs ?
This is great, but it doesn't work for me yet, but I would like it toThis works for me with the same board as you and a JK-B2A20S20P.
JK-B2A8S20P, hw 11.XA, sw 11.48, using UART-TTL (reported by @BytEvil) (from syssi github page)
Yes, I flashed it for testing and then want to use permanently.
This is great, but it doesn't work for me yet, but I would like it to![]()
I use the same protocol as in the syssi project.With your BMS, do you have the choice of protocol used with the UART1 port?
I use the same protocol as in the syssi project.
tx_pin: GPIO16
rx_pin: GPIO17
Is it possible to connect 2 x JK-PB-RS485 + Shunt BLE to one ESP32_LilyGo-T-CAN485. Or do I have to split it into 2 x ESP32
substitutions:
board_chip: "ESP32"
board_name: "LilyGo T-CAN485"
# Interfaces GPIOs
# uart_esp_1 (RS485 port)
tx_pin_1: '22'
rx_pin_1: '21'
# uart_esp_2
tx_pin_2: '33'
rx_pin_2: '32'
# uart_esp_3
tx_pin_3: '35'
rx_pin_3: '34'
# canbus_esp32_can (CAN port)
tx_pin_4: '27'
rx_pin_4: '26'
# canbus_mcp2515
spi_mosi_pin: '12'
spi_miso_pin: '5'
spi_clk_pin: '18'
mcp2515_cs_pin: '25'
Hi @Sleeper85, sorry for taking some time to reply on this, I recently became father and the little one decided to come a bit early..I understand that communication between the BMU and your two battery packs takes place over an RS485 bus with an unknown BYD protocol.
We could remove the BMU and connect everything to YamBMS (if the BYD RS485 protocol document is easily found).
YamBMS is, in a way, a BMU.
Keep the BMU and connect it to YamBMS via a CAN bus input.
In this case, I assume you have a choice of CAN protocol for the BMU output ?
In both cases, this requires custom development.
What is the protocol configured in your Cerbo GX settings ?yes the BMU sends it's data over CAN to the Cerbo GX.. So what would the procedure be to grab this data on YAMBMS and also the data for 2x JK-B BMS (through bluetooth will be fine) and then send this through CAN output with Victron protocol?
Just integrated my T-Connect S3 board into my Sunsynk's for the first time, so still getting used to it. But I'm finding that with Auto CCL/DCL switched on the battery doesn't discharge. When I turn OFF Auto CCL/DCL it works ok as expected. In the previous version of @Sleeper85 code pre-YAM (JK Bms - CAN) I found the CCL/DCL worked fine and I never had to change anything. This is a more complex system, but am I missing a setting or something?
Slight update: I'm referring to the main dashboard on the control tab. if I turn off the main on/off for auto, but on the two sub buttons, keeping auto charge current on, but turning off auto discharge current works ok.Interesting, if discharge isn't happening then that sounds like autoDCL isn't working for you.
Can you enable both, then send details of your min and max cell voltages, plus the requested charge and discharge current?
After that, do you continue to see the issue when only autoDCL is disabled?
I'd be quite surprised if autoCCL is causing the issue, but we shall see!
When I switch DCL back on, yes I get zero requested discharge current... But I have an idea now - the ONLY ble I can get to work is JK minimal, all the others crash the T-connect board after around 60s (I tried turning off the web server, but it made no difference). Here's the thing - the minimal ble doesn't report any cell voltages in the BMS section, so I reckon there's a fair chance that the auto DCL see's this as an error and shuts down discharge, according to your logic above, even though there's no problem with any cells.When autoDCL is enabled, is the requested discharge current zero?
The logic for autoDCL uses three inputs:
If either of the latter two are unusual values then you can get unexpected values for requested discharge current.
- Max discharge current
- Current minimum cell voltage
- Under voltage cell protection value + 0.2V
I have a Sunsynk (pretty much a Deye), I find Pylon 1.2 or 2 works fineI have a question for you @Sleeper85 I see you have a DEYE, what protocol can you use for your DEYE and your batteries?