syssi / esphome-jk-bms

ESPHome component to monitor and control a Jikong Battery Management System (JK-BMS) via UART-TTL or BLE
Apache License 2.0
488 stars 165 forks source link

Stability - ESP frequently restarts several times a day #622

Open peff74 opened 3 weeks ago

peff74 commented 3 weeks ago

When expanding my system, I noticed that the ESP restarts quite frequently. As I don't have any experience with ESP home devices... I can't judge whether this is normal. image The last reboots are mine, I wanted to get some logs.

[16:22:07][D][Avg Temp:432]: Sensor 2: 17.200001
[16:22:07][D][Avg Temp:442]: Sensor 3 ist ungültig
[16:22:07][D][Avg Temp:450]: Sensor 4 ist ungültig
[16:22:07][D][Avg Temp:458]: Durchschnittstemperatur: 17.049999
[16:22:07][D][sensor:094]: 'Avg BMS Temp': Sending state 17.05000  with 1 decimals of accuracy
[16:22:07][D][climate:396]: 'heat_mat' - Sending state:
[16:22:07][D][climate:399]:   Mode: HEAT
[16:22:07][D][climate:401]:   Action: IDLE
[16:22:07][D][climate:419]:   Current Temperature: 17.05°C
[16:22:07][D][climate:425]:   Target Temperature: 16.00°C
[16:22:07][W][component:237]: Component template.sensor took a long time for an operation (52 ms).
[16:22:07][W][component:238]: Components should block for at most 30 ms.
[16:22:10][W][jk_bms_ble:240]: [20:22:08:25:26:8B] Not connected
[16:22:15][W][jk_bms_ble:240]: [20:22:08:25:26:8B] Not connected
[16:22:17][D][Avg Temp:424]: Sensor 1: 16.900000
[16:22:17][D][Avg Temp:432]: Sensor 2: 17.200001
[16:22:17][D][Avg Temp:442]: Sensor 3 ist ungültig
[16:22:17][D][Avg Temp:450]: Sensor 4 ist ungültig
[16:22:17][D][Avg Temp:458]: Durchschnittstemperatur: 17.049999
[16:22:17][D][sensor:094]: 'Avg BMS Temp': Sending state 17.05000  with 1 decimals of accuracy
[16:22:17][D][climate:396]: 'heat_mat' - Sending state:
[16:22:17][D][climate:399]:   Mode: HEAT
-----------------------------REBOOT--------------------------------
[16:22:28][W][component:170]: Component mqtt cleared Warning flag
[16:22:28][I][mqtt:286]: MQTT Connected!
[16:22:29][I][app:062]: setup() finished successfully!
[16:22:29][I][app:100]: ESPHome version 2024.10.2 compiled on Oct 28 2024, 21:54:25
[16:22:29][I][app:102]: Project syssi.esphome-jk-bms version 2.1.0
[16:22:29][C][logger:185]: Logger:
[16:22:29][C][logger:186]:   Level: DEBUG
[16:22:29][C][logger:188]:   Log Baud Rate: 115200
[16:22:29][C][logger:189]:   Hardware UART: UART0
[16:22:29][C][template.sensor:022]: Template Sensor 'Avg BMS Temp'
[16:22:29][C][template.sensor:022]:   State Class: ''
[16:22:29][C][template.sensor:022]:   Unit of Measurement: ''
[16:22:29][C][template.sensor:022]:   Accuracy Decimals: 1
[16:22:29][C][template.sensor:023]:   Update Interval: 10.0s
[16:22:29][C][uptime.sensor:033]: Uptime Sensor 'Uptime'
[16:22:29][C][uptime.sensor:033]:   Device Class: 'duration'
[16:22:29][C][uptime.sensor:033]:   State Class: 'total_increasing'
[16:22:29][C][uptime.sensor:033]:   Unit of Measurement: 's'
[16:22:29][C][uptime.sensor:033]:   Accuracy Decimals: 0
[16:22:29][C][uptime.sensor:033]:   Icon: 'mdi:timer-outline'
[16:22:29][C][uptime.sensor:034]:   Type: Seconds
[16:22:29][C][switch.gpio:068]: GPIO Switch 'heat_mat'
[16:22:29][C][switch.gpio:091]:   Restore Mode: always OFF

But I can't really see anything in the logs, the device just restarts. I had already replaced the hardware on suspicion, a WT32-ETH01

here my YAML:

substitutions:
  name: jk-bms
  bms0: "${name}"
  bms1: "${name}1"
  device_description: "Monitor and control a JK-BMS via bluetooth"
  external_components_source: github://syssi/esphome-jk-bms@main
  # Akku gross
  bms0_mac_address: 20:22:09:27:7c:44
  # Akku klein
  # mac_address: 20:22:08:25:0f:a9
  # Akku gross_2
  bms1_mac_address: 20:22:08:25:26:8b
  # Please use "JK02_24S" if you own a old JK-BMS < hardware version 11.0 (hardware version >= 6.0 and < 11.0)
  # Please use "JK02_32S" if you own a new JK-BMS >= hardware version 11.0 (f.e. JK-B2A8S20P hw 11.XW, sw 11.26)
  # Please use "JK04" if you have some old JK-BMS <= hardware version 3.0 (f.e. JK-B2A16S hw 3.0, sw. 3.3.0)
  bms0_protocol_version: JK02_32S
  bms1_protocol_version: JK02_32S

esphome:
  name: ${name}
  comment: ${device_description}
  min_version: 2024.6.0
  project:
    name: "syssi.esphome-jk-bms"
    version: 2.1.0
  on_boot:
    priority: 600  
    then:
      - climate.control:
          id: climate_heat_mat
          mode: HEAT  

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

external_components:
  - source: ${external_components_source}
    refresh: 0s

web_server:
  local: false

#wifi:
#  ssid: !secret wifi_ssid
#  password: !secret wifi_password

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

ota:
  - platform: esphome
    password: ""
    on_begin:
      then:
        - switch.turn_off: ble_client_switch0
        - switch.turn_off: ble_client_switch1
        - logger.log: "BLE connection suspended for OTA update"

logger:
  level: DEBUG

# If you don't use Home Assistant please remove this `api` section and uncomment the `mqtt` component!
# api:

mqtt:
   broker: !secret mqtt_host
   username: !secret mqtt_username
   password: !secret mqtt_password
   id: mqtt_client
   discovery: false

esp32_ble_tracker:
  scan_parameters:
   active: false
  on_ble_advertise:
    then:
      - lambda: |-
          if (x.get_name().rfind("JK-", 0) == 0 || x.get_name().rfind("JK_", 0) == 0) {
            ESP_LOGI("ble_adv", "New JK-BMS found");
            ESP_LOGI("ble_adv", "  Name: %s", x.get_name().c_str());
            ESP_LOGI("ble_adv", "  MAC address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
              ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
          }

ble_client:
  - mac_address: ${bms0_mac_address}
    id: client0
  - mac_address: ${bms1_mac_address}
    id: client1

jk_bms_ble:
  - ble_client_id: client0
    protocol_version: ${bms0_protocol_version}
    throttle: 5s
    id: bms0
  - ble_client_id: client1
    protocol_version: ${bms1_protocol_version}
    throttle: 5s
    id: bms1

binary_sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    balancing:
      name: "${bms0} balancing"
    charging:
      name: "${bms0} charging"
    discharging:
      name: "${bms0} discharging"
    online_status:
      name: "${bms0} online status"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    balancing:
      name: "${bms1} balancing"
    charging:
      name: "${bms1} charging"
    discharging:
      name: "${bms1} discharging"
    online_status:
      name: "${bms1} online status"

button:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    retrieve_settings:
      name: "${bms0} retrieve settings"
    retrieve_device_info:
      name: "${bms0} retrieve device info"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    retrieve_settings:
      name: "${bms1} retrieve settings"
    retrieve_device_info:
      name: "${bms1} retrieve device info"

number:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    balance_trigger_voltage:
      name: "${bms0} balance trigger voltage"
    cell_count:
      name: "${bms0} cell count"
    total_battery_capacity:
      name: "${bms0} total battery capacity"
    cell_voltage_overvoltage_protection:
      name: "${bms0} cell voltage overvoltage protection"
    cell_voltage_overvoltage_recovery:
      name: "${bms0} cell voltage overvoltage recovery"
    cell_voltage_undervoltage_protection:
      name: "${bms0} cell voltage undervoltage protection"
    cell_voltage_undervoltage_recovery:
      name: "${bms0} cell voltage undervoltage recovery"
    balance_starting_voltage:
      name: "${bms0} balance starting voltage"
    voltage_calibration:
      name: "${bms0} voltage calibration"
    current_calibration:
      name: "${bms0} current calibration"
    power_off_voltage:
      name: "${bms0} power off voltage"
    max_balance_current:
      name: "${bms0} max balance current"
    max_charge_current:
      name: "${bms0} max charge current"
    max_discharge_current:
      name: "${bms0} max discharge current"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    balance_trigger_voltage:
      name: "${bms1} balance trigger voltage"
    cell_count:
      name: "${bms1} cell count"
    total_battery_capacity:
      name: "${bms1} total battery capacity"
    cell_voltage_overvoltage_protection:
      name: "${bms1} cell voltage overvoltage protection"
    cell_voltage_overvoltage_recovery:
      name: "${bms1} cell voltage overvoltage recovery"
    cell_voltage_undervoltage_protection:
      name: "${bms1} cell voltage undervoltage protection"
    cell_voltage_undervoltage_recovery:
      name: "${bms1} cell voltage undervoltage recovery"
    balance_starting_voltage:
      name: "${bms1} balance starting voltage"
    voltage_calibration:
      name: "${bms1} voltage calibration"
    current_calibration:
      name: "${bms1} current calibration"
    power_off_voltage:
      name: "${bms1} power off voltage"
    max_balance_current:
      name: "${bms1} max balance current"
    max_charge_current:
      name: "${bms1} max charge current"
    max_discharge_current:
      name: "${bms1} max discharge current"   

sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    min_cell_voltage:
      name: "${bms0} min cell voltage"
    max_cell_voltage:
      name: "${bms0} max cell voltage"
    min_voltage_cell:
      name: "${bms0} min voltage cell"
    max_voltage_cell:
      name: "${bms0} max voltage cell"
    delta_cell_voltage:
      name: "${bms0} delta cell voltage"
    average_cell_voltage:
      name: "${bms0} average cell voltage"
    cell_voltage_1:
      name: "${bms0} cell voltage 01"
    cell_voltage_2:
      name: "${bms0} cell voltage 02"
    cell_voltage_3:
      name: "${bms0} cell voltage 03"
    cell_voltage_4:
      name: "${bms0} cell voltage 04"
    cell_voltage_5:
      name: "${bms0} cell voltage 05"
    cell_voltage_6:
      name: "${bms0} cell voltage 06"
    cell_voltage_7:
      name: "${bms0} cell voltage 07"
    cell_voltage_8:
      name: "${bms0} cell voltage 08"
    cell_voltage_9:
      name: "${bms0} cell voltage 09"
    cell_voltage_10:
      name: "${bms0} cell voltage 10"
    cell_voltage_11:
      name: "${bms0} cell voltage 11"
    cell_voltage_12:
      name: "${bms0} cell voltage 12"
    cell_resistance_1:
      name: "${bms0} cell resistance 01"
    cell_resistance_2:
      name: "${bms0} cell resistance 02"
    cell_resistance_3:
      name: "${bms0} cell resistance 03"
    cell_resistance_4:
      name: "${bms0} cell resistance 04"
    cell_resistance_5:
      name: "${bms0} cell resistance 05"
    cell_resistance_6:
      name: "${bms0} cell resistance 06"
    cell_resistance_7:
      name: "${bms0} cell resistance 07"
    cell_resistance_8:
      name: "${bms0} cell resistance 08"
    cell_resistance_9:
      name: "${bms0} cell resistance 09"
    cell_resistance_10:
      name: "${bms0} cell resistance 10"
    cell_resistance_11:
      name: "${bms0} cell resistance 11"
    cell_resistance_12:
      name: "${bms0} cell resistance 12"
    total_voltage:
      name: "${bms0} total voltage"
    current:
      name: "${bms0} current"
    power:
      name: "${bms0} power"
    charging_power:
      name: "${bms0} charging power"
    discharging_power:
      name: "${bms0} discharging power"
    temperature_sensor_1:
      name: "${bms0} temperature sensor 1"
      id: temp_sensor_1
    temperature_sensor_2:
      name: "${bms0} temperature sensor 2"
      id: temp_sensor_2
    power_tube_temperature:
      name: "${bms0} power tube temperature"
    state_of_charge:
      name: "${bms0} state of charge"
    capacity_remaining:
      name: "${bms0} capacity remaining"
    total_battery_capacity_setting:
      name: "${bms0} total battery capacity setting"
    charging_cycles:
      name: "${bms0} charging cycles"
    total_charging_cycle_capacity:
      name: "${bms0} total charging cycle capacity"
    total_runtime:
      name: "${bms0} total runtime"
    balancing_current:
      name: "${bms0} balancing current"
    errors_bitmask:
      name: "${bms0} errors bitmask"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    min_cell_voltage:
      name: "${bms1} min cell voltage"
    max_cell_voltage:
      name: "${bms1} max cell voltage"
    min_voltage_cell:
      name: "${bms1} min voltage cell"
    max_voltage_cell:
      name: "${bms1} max voltage cell"
    delta_cell_voltage:
      name: "${bms1} delta cell voltage"
    average_cell_voltage:
      name: "${bms1} average cell voltage"
    cell_voltage_1:
      name: "${bms1} cell voltage 01"
    cell_voltage_2:
      name: "${bms1} cell voltage 02"
    cell_voltage_3:
      name: "${bms1} cell voltage 03"
    cell_voltage_4:
      name: "${bms1} cell voltage 04"
    cell_voltage_5:
      name: "${bms1} cell voltage 05"
    cell_voltage_6:
      name: "${bms1} cell voltage 06"
    cell_voltage_7:
      name: "${bms1} cell voltage 07"
    cell_voltage_8:
      name: "${bms1} cell voltage 08"
    cell_voltage_9:
      name: "${bms1} cell voltage 09"
    cell_voltage_10:
      name: "${bms1} cell voltage 10"
    cell_voltage_11:
      name: "${bms1} cell voltage 11"
    cell_voltage_12:
      name: "${bms1} cell voltage 12"
    cell_resistance_1:
      name: "${bms1} cell resistance 01"
    cell_resistance_2:
      name: "${bms1} cell resistance 02"
    cell_resistance_3:
      name: "${bms1} cell resistance 03"
    cell_resistance_4:
      name: "${bms1} cell resistance 04"
    cell_resistance_5:
      name: "${bms1} cell resistance 05"
    cell_resistance_6:
      name: "${bms1} cell resistance 06"
    cell_resistance_7:
      name: "${bms1} cell resistance 07"
    cell_resistance_8:
      name: "${bms1} cell resistance 08"
    cell_resistance_9:
      name: "${bms1} cell resistance 09"
    cell_resistance_10:
      name: "${bms1} cell resistance 10"
    cell_resistance_11:
      name: "${bms1} cell resistance 11"
    cell_resistance_12:
      name: "${bms1} cell resistance 12"
    total_voltage:
      name: "${bms1} total voltage"
    current:
      name: "${bms1} current"
    power:
      name: "${bms1} power"
    charging_power:
      name: "${bms1} charging power"
    discharging_power:
      name: "${bms1} discharging power"
    temperature_sensor_1:
      name: "${bms1} temperature sensor 1"
      id: temp_sensor_3
    temperature_sensor_2:
      name: "${bms1} temperature sensor 2"
      id: temp_sensor_4
    power_tube_temperature:
      name: "${bms1} power tube temperature"
    state_of_charge:
      name: "${bms1} state of charge"
    capacity_remaining:
      name: "${bms1} capacity remaining"
    total_battery_capacity_setting:
      name: "${bms1} total battery capacity setting"
    charging_cycles:
      name: "${bms1} charging cycles"
    total_charging_cycle_capacity:
      name: "${bms1} total charging cycle capacity"
    total_runtime:
      name: "${bms1} total runtime"
    balancing_current:
      name: "${bms1} balancing current"
    errors_bitmask:
      name: "${bms1} errors bitmask"

  - platform: uptime
    type: seconds
    name: Uptime

  - platform: template
    name: "Avg BMS Temp"
    id: avg_bms_temp
    update_interval: 10s
    lambda: |-
     float sum = 0.0;
     int count = 0;

     if (!isnan(id(temp_sensor_1).state)) {
       sum += id(temp_sensor_1).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 1: %f", id(temp_sensor_1).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 1 ist ungültig");
     }

     if (!isnan(id(temp_sensor_2).state)) {
       sum += id(temp_sensor_2).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 2: %f", id(temp_sensor_2).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 2 ist ungültig");
     }

     if (!isnan(id(temp_sensor_3).state)) {
       sum += id(temp_sensor_3).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 3: %f", id(temp_sensor_3).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 3 ist ungültig");
     }

     if (!isnan(id(temp_sensor_4).state)) {
       sum += id(temp_sensor_4).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 4: %f", id(temp_sensor_4).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 4 ist ungültig");
     }

     if (count == 0) {
       ESP_LOGD("Avg Temp", "Keine gültigen Temperatursensoren gefunden");
       return NAN;
     } else {
       float avg = sum / count;
       ESP_LOGD("Avg Temp", "Durchschnittstemperatur: %f", avg);
       return avg;
     }

climate:
  - platform: thermostat
    name: "heat_mat"
    sensor: avg_bms_temp
    heat_overrun: 1 °C
    min_idle_time: 60s
    min_heating_off_time: 1s
    min_heating_run_time: 60s
    heat_action:
      - switch.turn_on: heat_mat
    idle_action:
      - switch.turn_off: heat_mat
    visual:
      min_temperature: 0 °C
      max_temperature: 15 °C
      temperature_step: 0.5 °C  
    default_preset: Lower bound
    id: climate_heat_mat
    preset:
      - name: Lower bound
        default_target_temperature_low: 10 °C

switch:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    charging:
      name: "${bms0} charging"
    discharging:
      name: "${bms0} discharging"
    balancer:
      name: "${bms0} balancer"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    charging:
      name: "${bms1} charging"
    discharging:
      name: "${bms1} discharging"
    balancer:
      name: "${bms1} balancer"

  - platform: ble_client
    ble_client_id: client0
    id: ble_client_switch0
    name: "${bms0} enable bluetooth connection"
  - platform: ble_client
    ble_client_id: client1
    id: ble_client_switch1
    name: "${bms1} enable bluetooth connection"

  - platform: gpio
    name: "heat_mat"
    pin: GPIO14
    id: heat_mat

text_sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    errors:
      name: "${bms0} errors"
    total_runtime_formatted:
      name: "${bms0} total runtime formatted"
  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
    errors:
      name: "${bms1} errors"
    total_runtime_formatted:
      name: "${bms1} total runtime formatted"      

or do I have too many sensors or other errors?

syssi commented 3 weeks ago

Could you reduce your YAML configuration step by step just for testing. You are using a lot of heavy components (web_server, mqtt, two instances of the jk_bms_ble component etc.). Does the situation improve if you free some resources? Is you custom code stable / free of memory leaks in general?

peff74 commented 3 weeks ago

I will follow up on your suggestion. Firstly, I have now removed all my components and then deactivated the web server. I now only have a debug component in there to check the heap

image

My code used very little heap, the web used much more, now we are at 100KB free heap. Let's see how it goes image

syssi commented 3 weeks ago

You could free a lot of resources by changing the log level to INFO too.

peff74 commented 3 weeks ago

image something eats the heap and sometimes it comes to a bang...

So it's not in my code or the web server. I have now set the loglevel to Info. Let's wait and see how it reacts.

syssi commented 3 weeks ago

Good job!

peff74 commented 3 weeks ago

image

unfortunately there were more new starts despite loglevel INFO :-( Where else could I start to find out what is causing the problem?

which is clear, it starts with a significant heap loss

syssi commented 3 weeks ago

Please remove one of the BLE client connections as next step.

peff74 commented 3 weeks ago

done image

Now we got 114kb free heap. And the largest free block size has increased quite a bit to 64kb. Far right in the picture at 6:30 pm

peff74 commented 3 weeks ago

image the view this morning. A reboot around 10pm since then it has been running continuously image Here is a zoom into the crash at 10pm. Something seems to be stuck, once he makes it, then the second time it's over

syssi commented 3 weeks ago

Could you post your current YAML configuration? I would like to get an idea which components are still used.

syssi commented 3 weeks ago

Some next steps:

  1. Remove all jk_bms_ble entities from the YAML but don't remove the ble_client connection. We want still be able to connect to the BMS but we want to skip the data decoding.
  2. Remove the mqtt component and add the api or web_server component to check the uptime from time to time.
  3. Remove the complete BLE communication but add a number of template sensors which publish some random states periodically to generate some work/noise.

The idea is to identify the BLE stack or the network communication as root cause.

peff74 commented 3 weeks ago

this is then the YAML if I understand Step1 correctly?

substitutions:
  name: jk-bms
  bms0: "${name}"
#  bms1: "${name}1"
  device_description: "Monitor and control a JK-BMS via bluetooth"
  external_components_source: github://syssi/esphome-jk-bms@main
# Akku gross
  bms0_mac_address: 20:22:09:27:7c:44
# Akku klein
# mac_address: 20:22:08:25:0f:a9
# Akku gross_2
# bms1_mac_address: 20:22:08:25:26:8b
# Please use "JK02_24S" if you own a old JK-BMS < hardware version 11.0 (hardware version >= 6.0 and < 11.0)
# Please use "JK02_32S" if you own a new JK-BMS >= hardware version 11.0 (f.e. JK-B2A8S20P hw 11.XW, sw 11.26)
# Please use "JK04" if you have some old JK-BMS <= hardware version 3.0 (f.e. JK-B2A16S hw 3.0, sw. 3.3.0)
  bms0_protocol_version: JK02_32S
#bms1_protocol_version: JK02_32S

esphome:
  name: ${name}
  comment: ${device_description}
  min_version: 2024.6.0
  project:
    name: "syssi.esphome-jk-bms"
    version: 2.1.0
#  on_boot:
#    priority: 600
#    then:
#      - climate.control:
#          id: climate_heat_mat
#          mode: HEAT

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

external_components:
  - source: ${external_components_source}
    refresh: 0s

#web_server:
#  local: false

#wifi:
#  ssid: !secret wifi_ssid
#  password: !secret wifi_password

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

ota:
  - platform: esphome
    password: ""
    on_begin:
      then:
        - switch.turn_off: ble_client_switch0
#        - switch.turn_off: ble_client_switch1
        - logger.log: "BLE connection suspended for OTA update"

logger:
#  level: DEBUG
  level: INFO

debug:
  update_interval: 5s

# If you don't use Home Assistant please remove this `api` section and uncomment the `mqtt` component!
# api:

mqtt:
   broker: !secret mqtt_host
   username: !secret mqtt_username
   password: !secret mqtt_password
   id: mqtt_client
   discovery: false

esp32_ble_tracker:
  scan_parameters:
   active: false
  on_ble_advertise:
    then:
      - lambda: |-
          if (x.get_name().rfind("JK-", 0) == 0 || x.get_name().rfind("JK_", 0) == 0) {
            ESP_LOGI("ble_adv", "New JK-BMS found");
            ESP_LOGI("ble_adv", "  Name: %s", x.get_name().c_str());
            ESP_LOGI("ble_adv", "  MAC address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
              ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
          }

ble_client:
  - mac_address: ${bms0_mac_address}
    id: client0
#  - mac_address: ${bms1_mac_address}
#    id: client1

# jk_bms_ble:
#  - ble_client_id: client0
#    protocol_version: ${bms0_protocol_version}
#    throttle: 5s
#    id: bms0
#  - ble_client_id: client1
#    protocol_version: ${bms1_protocol_version}
#    throttle: 5s
#    id: bms1

binary_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balancing:
#      name: "${bms0} balancing"
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    online_status:
#      name: "${bms0} online status"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balancing:
#      name: "${bms1} balancing"
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    online_status:
#      name: "${bms1} online status"

button:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    retrieve_settings:
#      name: "${bms0} retrieve settings"
#    retrieve_device_info:
#      name: "${bms0} retrieve device info"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    retrieve_settings:
#      name: "${bms1} retrieve settings"
#    retrieve_device_info:
#      name: "${bms1} retrieve device info"

number:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balance_trigger_voltage:
#      name: "${bms0} balance trigger voltage"
#    cell_count:
#      name: "${bms0} cell count"
#    total_battery_capacity:
#      name: "${bms0} total battery capacity"
#   cell_voltage_overvoltage_protection:
#      name: "${bms0} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms0} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms0} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms0} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms0} balance starting voltage"
#    voltage_calibration:
#      name: "${bms0} voltage calibration"
#    current_calibration:
#      name: "${bms0} current calibration"
#    power_off_voltage:
#      name: "${bms0} power off voltage"
#    max_balance_current:
#      name: "${bms0} max balance current"
#    max_charge_current:
#      name: "${bms0} max charge current"
#    max_discharge_current:
#      name: "${bms0} max discharge current"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balance_trigger_voltage:
#      name: "${bms1} balance trigger voltage"
#    cell_count:
#      name: "${bms1} cell count"
#    total_battery_capacity:
#      name: "${bms1} total battery capacity"
#    cell_voltage_overvoltage_protection:
#      name: "${bms1} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms1} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms1} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms1} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms1} balance starting voltage"
#    voltage_calibration:
#      name: "${bms1} voltage calibration"
#    current_calibration:
#      name: "${bms1} current calibration"
#    power_off_voltage:
#      name: "${bms1} power off voltage"
#    max_balance_current:
#      name: "${bms1} max balance current"
#    max_charge_current:
#      name: "${bms1} max charge current"
#    max_discharge_current:
#      name: "${bms1} max discharge current"

sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    min_cell_voltage:
#      name: "${bms0} min cell voltage"
#    max_cell_voltage:
#      name: "${bms0} max cell voltage"
#    min_voltage_cell:
#      name: "${bms0} min voltage cell"
#    max_voltage_cell:
#      name: "${bms0} max voltage cell"
#    delta_cell_voltage:
#      name: "${bms0} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms0} average cell voltage"
#    cell_voltage_1:
#      name: "${bms0} cell voltage 01"
#    cell_voltage_2:
#      name: "${bms0} cell voltage 02"
#    cell_voltage_3:
#     name: "${bms0} cell voltage 03"
#   cell_voltage_4:
#      name: "${bms0} cell voltage 04"
#    cell_voltage_5:
#      name: "${bms0} cell voltage 05"
#    cell_voltage_6:
#      name: "${bms0} cell voltage 06"
#    cell_voltage_7:
#      name: "${bms0} cell voltage 07"
#    cell_voltage_8:
#      name: "${bms0} cell voltage 08"
#    cell_voltage_9:
#      name: "${bms0} cell voltage 09"
#    cell_voltage_10:
#      name: "${bms0} cell voltage 10"
#    cell_voltage_11:
#      name: "${bms0} cell voltage 11"
#    cell_voltage_12:
#      name: "${bms0} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms0} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms0} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms0} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms0} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms0} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms0} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms0} cell resistance 07"
#    cell_resistance_8:
#     name: "${bms0} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms0} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms0} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms0} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms0} cell resistance 12"
#    total_voltage:
#      name: "${bms0} total voltage"
#    current:
#      name: "${bms0} current"
#    power:
#      name: "${bms0} power"
#    charging_power:
#      name: "${bms0} charging power"
#    discharging_power:
#      name: "${bms0} discharging power"
#    temperature_sensor_1:
#     name: "${bms0} temperature sensor 1"
#     id: temp_sensor_1
#    temperature_sensor_2:
#      name: "${bms0} temperature sensor 2"
#      id: temp_sensor_2
#    power_tube_temperature:
#      name: "${bms0} power tube temperature"
#    state_of_charge:
#      name: "${bms0} state of charge"
#    capacity_remaining:
#      name: "${bms0} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms0} total battery capacity setting"
#    charging_cycles:
#      name: "${bms0} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms0} total charging cycle capacity"
#    total_runtime:
#      name: "${bms0} total runtime"
#    balancing_current:
#      name: "${bms0} balancing current"
#    errors_bitmask:
#      name: "${bms0} errors bitmask"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    min_cell_voltage:
#      name: "${bms1} min cell voltage"
#    max_cell_voltage:
#      name: "${bms1} max cell voltage"
#    min_voltage_cell:
#      name: "${bms1} min voltage cell"
#    max_voltage_cell:
#      name: "${bms1} max voltage cell"
#    delta_cell_voltage:
#      name: "${bms1} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms1} average cell voltage"
#    cell_voltage_1:
#      name: "${bms1} cell voltage 01"
#    cell_voltage_2:
#      name: "${bms1} cell voltage 02"
#    cell_voltage_3:
#      name: "${bms1} cell voltage 03"
#    cell_voltage_4:
#      name: "${bms1} cell voltage 04"
#    cell_voltage_5:
#      name: "${bms1} cell voltage 05"
#    cell_voltage_6:
#      name: "${bms1} cell voltage 06"
#    cell_voltage_7:
#      name: "${bms1} cell voltage 07"
#    cell_voltage_8:
#      name: "${bms1} cell voltage 08"
#    cell_voltage_9:
#      name: "${bms1} cell voltage 09"
#    cell_voltage_10:
#      name: "${bms1} cell voltage 10"
#    cell_voltage_11:
#      name: "${bms1} cell voltage 11"
#    cell_voltage_12:
#      name: "${bms1} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms1} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms1} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms1} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms1} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms1} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms1} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms1} cell resistance 07"
#    cell_resistance_8:
#      name: "${bms1} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms1} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms1} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms1} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms1} cell resistance 12"
#    total_voltage:
#      name: "${bms1} total voltage"
#    current:
#      name: "${bms1} current"
#    power:
#      name: "${bms1} power"
#    charging_power:
#      name: "${bms1} charging power"
#    discharging_power:
#      name: "${bms1} discharging power"
#    temperature_sensor_1:
#      name: "${bms1} temperature sensor 1"
#      id: temp_sensor_3
#    temperature_sensor_2:
#      name: "${bms1} temperature sensor 2"
#      id: temp_sensor_4
#    power_tube_temperature:
#      name: "${bms1} power tube temperature"
#    state_of_charge:
#      name: "${bms1} state of charge"
#    capacity_remaining:
#      name: "${bms1} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms1} total battery capacity setting"
#    charging_cycles:
#      name: "${bms1} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms1} total charging cycle capacity"
#    total_runtime:
#      name: "${bms1} total runtime"
#    balancing_current:
#      name: "${bms1} balancing current"
#    errors_bitmask:
#      name: "${bms1} errors bitmask"

#  - platform: template
#    name: "Avg BMS Temp"
#    id: avg_bms_temp
#    update_interval: 10s
#    lambda: |-
#     float sum = 0.0;
#     int count = 0;

#     if (!isnan(id(temp_sensor_1).state)) {
#       sum += id(temp_sensor_1).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 1: %f", id(temp_sensor_1).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 1 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_2).state)) {
#       sum += id(temp_sensor_2).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 2: %f", id(temp_sensor_2).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 2 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_3).state)) {
#       sum += id(temp_sensor_3).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 3: %f", id(temp_sensor_3).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 3 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_4).state)) {
#       sum += id(temp_sensor_4).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 4: %f", id(temp_sensor_4).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 4 ist ungültig");
#     }

#     if (count == 0) {
#       ESP_LOGD("Avg Temp", "Keine gültigen Temperatursensoren gefunden");
#       return NAN;
#     } else {
#       float avg = sum / count;
#       ESP_LOGD("Avg Temp", "Durchschnittstemperatur: %f", avg);
#       return avg;
#     }

  - platform: uptime
    type: seconds
    name: Uptime

  - platform: debug
    free:
      name: "Debug_Heap Free"
#    fragmentation:
#      name: "Debug_Heap Fragmentation"
    block:
      name: "Debug_Heap Max Block"
#    loop_time:
#      name: "Debug_Loop Time"
#    psram:
#      name: "Debug_Free PSRAM"

#climate:
#  - platform: thermostat
#    name: "heat_mat"
#    sensor: avg_bms_temp
#    heat_overrun: 1 °C
#    min_idle_time: 60s
#    min_heating_off_time: 1s
#    min_heating_run_time: 60s
#    heat_action:
#      - switch.turn_on: heat_mat
#    idle_action:
#      - switch.turn_off: heat_mat
#    visual:
#      min_temperature: 0 °C
#      max_temperature: 20 °C
#      temperature_step: 0.5 °C
#    default_preset: Lower bound
#    id: climate_heat_mat
#    preset:
#      - name: Lower bound
#        default_target_temperature_low: 10 °C

switch:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    balancer:
#      name: "${bms0} balancer"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    balancer:
#      name: "${bms1} balancer"

  - platform: ble_client
    ble_client_id: client0
    id: ble_client_switch0
    name: "${bms0} enable bluetooth connection"
#  - platform: ble_client
#    ble_client_id: client1
#    id: ble_client_switch1
#    name: "${bms1} enable bluetooth connection"

  - platform: gpio
    name: "heat_mat"
    pin: GPIO14
    id: heat_mat

text_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    errors:
#      name: "${bms0} errors"
#    total_runtime_formatted:
#      name: "${bms0} total runtime formatted"
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    errors:
#      name: "${bms1} errors"
#    total_runtime_formatted:
#      name: "${bms1} total runtime formatted"
  - platform: debug
    device:
      name: "Device Info"
    reset_reason:
      name: "Reset Reason"
syssi commented 3 weeks ago

Correct!

peff74 commented 3 weeks ago

uploaded image

now we got 132kb free heap and the biggest block is ~90kb. And very few changes to the heap. I therefore now log every value and not just the changes

peff74 commented 3 weeks ago

image almost 24 hours without anything...

What would be the next steps?

syssi commented 3 weeks ago

Re-add a single BMS sensor f.e. total voltage.

peff74 commented 3 weeks ago
substitutions:
  name: jk-bms
  bms0: "${name}"
#  bms1: "${name}1"
  device_description: "Monitor and control a JK-BMS via bluetooth"
  external_components_source: github://syssi/esphome-jk-bms@main
# Akku gross
  bms0_mac_address: 20:22:09:27:7c:44
# Akku klein
# mac_address: 20:22:08:25:0f:a9
# Akku gross_2
# bms1_mac_address: 20:22:08:25:26:8b
# Please use "JK02_24S" if you own a old JK-BMS < hardware version 11.0 (hardware version >= 6.0 and < 11.0)
# Please use "JK02_32S" if you own a new JK-BMS >= hardware version 11.0 (f.e. JK-B2A8S20P hw 11.XW, sw 11.26)
# Please use "JK04" if you have some old JK-BMS <= hardware version 3.0 (f.e. JK-B2A16S hw 3.0, sw. 3.3.0)
  bms0_protocol_version: JK02_32S
#bms1_protocol_version: JK02_32S

esphome:
  name: ${name}
  comment: ${device_description}
  min_version: 2024.6.0
  project:
    name: "syssi.esphome-jk-bms"
    version: 2.1.0
#  on_boot:
#    priority: 600
#    then:
#      - climate.control:
#          id: climate_heat_mat
#          mode: HEAT

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

external_components:
  - source: ${external_components_source}
    refresh: 0s

#web_server:
#  local: false

#wifi:
#  ssid: !secret wifi_ssid
#  password: !secret wifi_password

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

ota:
  - platform: esphome
    password: ""
    on_begin:
      then:
        - switch.turn_off: ble_client_switch0
#        - switch.turn_off: ble_client_switch1
        - logger.log: "BLE connection suspended for OTA update"

logger:
#  level: DEBUG
  level: INFO

debug:
  update_interval: 5s

# If you don't use Home Assistant please remove this `api` section and uncomment the `mqtt` component!
# api:

mqtt:
   broker: !secret mqtt_host
   username: !secret mqtt_username
   password: !secret mqtt_password
   id: mqtt_client
   discovery: false

esp32_ble_tracker:
  scan_parameters:
   active: false
  on_ble_advertise:
    then:
      - lambda: |-
          if (x.get_name().rfind("JK-", 0) == 0 || x.get_name().rfind("JK_", 0) == 0) {
            ESP_LOGI("ble_adv", "New JK-BMS found");
            ESP_LOGI("ble_adv", "  Name: %s", x.get_name().c_str());
            ESP_LOGI("ble_adv", "  MAC address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
              ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
          }

ble_client:
  - mac_address: ${bms0_mac_address}
    id: client0
#  - mac_address: ${bms1_mac_address}
#    id: client1

jk_bms_ble:
  - ble_client_id: client0
    protocol_version: ${bms0_protocol_version}
    throttle: 5s
    id: bms0
#  - ble_client_id: client1
#    protocol_version: ${bms1_protocol_version}
#    throttle: 5s
#    id: bms1

binary_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balancing:
#      name: "${bms0} balancing"
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    online_status:
#      name: "${bms0} online status"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balancing:
#      name: "${bms1} balancing"
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    online_status:
#      name: "${bms1} online status"

button:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    retrieve_settings:
#      name: "${bms0} retrieve settings"
#    retrieve_device_info:
#      name: "${bms0} retrieve device info"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    retrieve_settings:
#      name: "${bms1} retrieve settings"
#    retrieve_device_info:
#      name: "${bms1} retrieve device info"

number:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balance_trigger_voltage:
#      name: "${bms0} balance trigger voltage"
#    cell_count:
#      name: "${bms0} cell count"
#    total_battery_capacity:
#      name: "${bms0} total battery capacity"
#   cell_voltage_overvoltage_protection:
#      name: "${bms0} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms0} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms0} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms0} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms0} balance starting voltage"
#    voltage_calibration:
#      name: "${bms0} voltage calibration"
#    current_calibration:
#      name: "${bms0} current calibration"
#    power_off_voltage:
#      name: "${bms0} power off voltage"
#    max_balance_current:
#      name: "${bms0} max balance current"
#    max_charge_current:
#      name: "${bms0} max charge current"
#    max_discharge_current:
#      name: "${bms0} max discharge current"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balance_trigger_voltage:
#      name: "${bms1} balance trigger voltage"
#    cell_count:
#      name: "${bms1} cell count"
#    total_battery_capacity:
#      name: "${bms1} total battery capacity"
#    cell_voltage_overvoltage_protection:
#      name: "${bms1} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms1} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms1} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms1} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms1} balance starting voltage"
#    voltage_calibration:
#      name: "${bms1} voltage calibration"
#    current_calibration:
#      name: "${bms1} current calibration"
#    power_off_voltage:
#      name: "${bms1} power off voltage"
#    max_balance_current:
#      name: "${bms1} max balance current"
#    max_charge_current:
#      name: "${bms1} max charge current"
#    max_discharge_current:
#      name: "${bms1} max discharge current"

sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
#    min_cell_voltage:
#      name: "${bms0} min cell voltage"
#    max_cell_voltage:
#      name: "${bms0} max cell voltage"
#    min_voltage_cell:
#      name: "${bms0} min voltage cell"
#    max_voltage_cell:
#      name: "${bms0} max voltage cell"
#    delta_cell_voltage:
#      name: "${bms0} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms0} average cell voltage"
#    cell_voltage_1:
#      name: "${bms0} cell voltage 01"
#    cell_voltage_2:
#      name: "${bms0} cell voltage 02"
#    cell_voltage_3:
#     name: "${bms0} cell voltage 03"
#    cell_voltage_4:
#      name: "${bms0} cell voltage 04"
#    cell_voltage_5:
#      name: "${bms0} cell voltage 05"
#    cell_voltage_6:
#      name: "${bms0} cell voltage 06"
#    cell_voltage_7:
#      name: "${bms0} cell voltage 07"
#    cell_voltage_8:
#      name: "${bms0} cell voltage 08"
#    cell_voltage_9:
#      name: "${bms0} cell voltage 09"
#    cell_voltage_10:
#      name: "${bms0} cell voltage 10"
#    cell_voltage_11:
#      name: "${bms0} cell voltage 11"
#    cell_voltage_12:
#      name: "${bms0} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms0} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms0} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms0} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms0} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms0} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms0} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms0} cell resistance 07"
#    cell_resistance_8:
#     name: "${bms0} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms0} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms0} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms0} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms0} cell resistance 12"
    total_voltage:
      name: "${bms0} total voltage"
#    current:
#      name: "${bms0} current"
#    power:
#      name: "${bms0} power"
#    charging_power:
#      name: "${bms0} charging power"
#    discharging_power:
#      name: "${bms0} discharging power"
    temperature_sensor_1:
     name: "${bms0} temperature sensor 1"
     id: temp_sensor_1
    temperature_sensor_2:
      name: "${bms0} temperature sensor 2"
      id: temp_sensor_2
#    power_tube_temperature:
#      name: "${bms0} power tube temperature"
#    state_of_charge:
#      name: "${bms0} state of charge"
#    capacity_remaining:
#      name: "${bms0} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms0} total battery capacity setting"
#    charging_cycles:
#      name: "${bms0} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms0} total charging cycle capacity"
#    total_runtime:
#      name: "${bms0} total runtime"
#    balancing_current:
#      name: "${bms0} balancing current"
#    errors_bitmask:
#      name: "${bms0} errors bitmask"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    min_cell_voltage:
#      name: "${bms1} min cell voltage"
#    max_cell_voltage:
#      name: "${bms1} max cell voltage"
#    min_voltage_cell:
#      name: "${bms1} min voltage cell"
#    max_voltage_cell:
#      name: "${bms1} max voltage cell"
#    delta_cell_voltage:
#      name: "${bms1} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms1} average cell voltage"
#    cell_voltage_1:
#      name: "${bms1} cell voltage 01"
#    cell_voltage_2:
#      name: "${bms1} cell voltage 02"
#    cell_voltage_3:
#      name: "${bms1} cell voltage 03"
#    cell_voltage_4:
#      name: "${bms1} cell voltage 04"
#    cell_voltage_5:
#      name: "${bms1} cell voltage 05"
#    cell_voltage_6:
#      name: "${bms1} cell voltage 06"
#    cell_voltage_7:
#      name: "${bms1} cell voltage 07"
#    cell_voltage_8:
#      name: "${bms1} cell voltage 08"
#    cell_voltage_9:
#      name: "${bms1} cell voltage 09"
#    cell_voltage_10:
#      name: "${bms1} cell voltage 10"
#    cell_voltage_11:
#      name: "${bms1} cell voltage 11"
#    cell_voltage_12:
#      name: "${bms1} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms1} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms1} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms1} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms1} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms1} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms1} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms1} cell resistance 07"
#    cell_resistance_8:
#      name: "${bms1} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms1} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms1} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms1} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms1} cell resistance 12"
#    total_voltage:
#      name: "${bms1} total voltage"
#    current:
#      name: "${bms1} current"
#    power:
#      name: "${bms1} power"
#    charging_power:
#      name: "${bms1} charging power"
#    discharging_power:
#      name: "${bms1} discharging power"
#    temperature_sensor_1:
#      name: "${bms1} temperature sensor 1"
#      id: temp_sensor_3
#    temperature_sensor_2:
#      name: "${bms1} temperature sensor 2"
#      id: temp_sensor_4
#    power_tube_temperature:
#      name: "${bms1} power tube temperature"
#    state_of_charge:
#      name: "${bms1} state of charge"
#    capacity_remaining:
#      name: "${bms1} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms1} total battery capacity setting"
#    charging_cycles:
#      name: "${bms1} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms1} total charging cycle capacity"
#    total_runtime:
#      name: "${bms1} total runtime"
#    balancing_current:
#      name: "${bms1} balancing current"
#    errors_bitmask:
#      name: "${bms1} errors bitmask"

#  - platform: template
#    name: "Avg BMS Temp"
#    id: avg_bms_temp
#    update_interval: 10s
#    lambda: |-
#     float sum = 0.0;
#     int count = 0;

#     if (!isnan(id(temp_sensor_1).state)) {
#       sum += id(temp_sensor_1).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 1: %f", id(temp_sensor_1).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 1 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_2).state)) {
#       sum += id(temp_sensor_2).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 2: %f", id(temp_sensor_2).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 2 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_3).state)) {
#       sum += id(temp_sensor_3).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 3: %f", id(temp_sensor_3).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 3 ist ungültig");
#     }

#     if (!isnan(id(temp_sensor_4).state)) {
#       sum += id(temp_sensor_4).state;
#       count += 1;
#     ESP_LOGD("Avg Temp", "Sensor 4: %f", id(temp_sensor_4).state);
#     } else {
#       ESP_LOGD("Avg Temp", "Sensor 4 ist ungültig");
#     }

#     if (count == 0) {
#       ESP_LOGD("Avg Temp", "Keine gültigen Temperatursensoren gefunden");
#       return NAN;
#     } else {
#       float avg = sum / count;
#       ESP_LOGD("Avg Temp", "Durchschnittstemperatur: %f", avg);
#       return avg;
#     }

  - platform: uptime
    type: seconds
    name: Uptime

  - platform: debug
    free:
      name: "Debug_Heap Free"
#    fragmentation:
#      name: "Debug_Heap Fragmentation"
    block:
      name: "Debug_Heap Max Block"
#    loop_time:
#      name: "Debug_Loop Time"
#    psram:
#      name: "Debug_Free PSRAM"

#climate:
#  - platform: thermostat
#    name: "heat_mat"
#    sensor: avg_bms_temp
#    heat_overrun: 1 °C
#    min_idle_time: 60s
#    min_heating_off_time: 1s
#    min_heating_run_time: 60s
#    heat_action:
#      - switch.turn_on: heat_mat
#    idle_action:
#      - switch.turn_off: heat_mat
#    visual:
#      min_temperature: 0 °C
#      max_temperature: 20 °C
#      temperature_step: 0.5 °C
#    default_preset: Lower bound
#    id: climate_heat_mat
#    preset:
#      - name: Lower bound
#        default_target_temperature_low: 10 °C

switch:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    balancer:
#      name: "${bms0} balancer"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    balancer:
#      name: "${bms1} balancer"

  - platform: ble_client
    ble_client_id: client0
    id: ble_client_switch0
    name: "${bms0} enable bluetooth connection"
#  - platform: ble_client
#    ble_client_id: client1
#    id: ble_client_switch1
#    name: "${bms1} enable bluetooth connection"

  - platform: gpio
    name: "heat_mat"
    pin: GPIO14
    id: heat_mat

text_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    errors:
#      name: "${bms0} errors"
#    total_runtime_formatted:
#      name: "${bms0} total runtime formatted"
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    errors:
#      name: "${bms1} errors"
#    total_runtime_formatted:
#      name: "${bms1} total runtime formatted"
  - platform: debug
    device:
      name: "Device Info"
    reset_reason:
      name: "Reset Reason"

done, but I took three sensor^^

now we got 130kb free heap and the biggest block is ~86kb.

peff74 commented 3 weeks ago

image the current status. I had to activate my thermo function yesterday because it was getting too cold. Since I was unable to set the thermostat via MQTT, it always reset itself to the value I had set on the website, I also had to activate the web server. Nevertheless, it seems to be stable. So it seems to be the number of BMS sensors, or one of them has a problem?

What I found noteworthy is that opening the website has such a strong effect on the max block size. I don't know that from Arduino

syssi commented 3 weeks ago

It's too early to make assumptions but we are on a good track.

peff74 commented 3 weeks ago

What should I do next to continue testing? Can you tell me why the thermostat always gets the values that were last set on the website, even if the web server is no longer active? Do you save the settings on the ESP?

syssi commented 3 weeks ago

Let's stick to two sensors (per BMS) but add the second BMS again.

I'm on the road and cannot provide answers to your other questions ATM.

peff74 commented 3 weeks ago

I didn't get around to expanding it today. The system as last described is now running 24 hours stable :-)

I think tomorrow I will add the second BMS again

syssi commented 3 weeks ago

Please keep in mind, we have changed a lot of parameters and a lot of components are running faster now. It's possible the issue occurs on heavy load only.

peff74 commented 2 weeks ago

yes I understand, I think we will then add the components back in bit by bit and see what the problem is. Right?

syssi commented 2 weeks ago

Correct!

peff74 commented 2 weeks ago

This morning I finally got round to adding the second BMS.

image

now we got 102kb free heap and the biggest block is ~60kb.

You can now clearly see how the largest block of the heap fluctuates and when the BMS went online, the free memory dropped further.

What I also noticed is that something about ‘cell resistance’ first appeared in the logs, although I didn't even have it active.

peff74 commented 2 weeks ago

This config has now also been running for 24 hours. First of all, it contains the most important data:

substitutions:
  name: jk-bms
  bms0: "${name}"
  bms1: "${name}1"
  device_description: "Monitor and control a JK-BMS via bluetooth"
  external_components_source: github://syssi/esphome-jk-bms@main
# Akku gross
  bms0_mac_address: 20:22:09:27:7c:44
# Akku klein
  bms1_mac_address: 20:22:08:25:0f:a9
# Akku gross_2
# bms1_mac_address: 20:22:08:25:26:8b
# Please use "JK02_24S" if you own a old JK-BMS < hardware version 11.0 (hardware version >= 6.0 and < 11.0)
# Please use "JK02_32S" if you own a new JK-BMS >= hardware version 11.0 (f.e. JK-B2A8S20P hw 11.XW, sw 11.26)
# Please use "JK04" if you have some old JK-BMS <= hardware version 3.0 (f.e. JK-B2A16S hw 3.0, sw. 3.3.0)
  bms0_protocol_version: JK02_32S
  bms1_protocol_version: JK02_32S

esphome:
  name: ${name}
  comment: ${device_description}
  min_version: 2024.6.0
  project:
    name: "syssi.esphome-jk-bms"
    version: 2.1.0
  on_boot:
    priority: 600
    then:
      - climate.control:
          id: climate_heat_mat
          mode: HEAT

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

external_components:
  - source: ${external_components_source}
    refresh: 0s

web_server:
  local: false

#wifi:
#  ssid: !secret wifi_ssid
#  password: !secret wifi_password

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO0_IN
  phy_addr: 1
  power_pin: GPIO16

ota:
  - platform: esphome
    password: ""
    on_begin:
      then:
        - switch.turn_off: ble_client_switch0
#        - switch.turn_off: ble_client_switch1
        - logger.log: "BLE connection suspended for OTA update"

logger:
#  level: DEBUG
  level: INFO

debug:
  update_interval: 5s

# If you don't use Home Assistant please remove this `api` section and uncomment the `mqtt` component!
# api:

mqtt:
   broker: !secret mqtt_host
   username: !secret mqtt_username
   password: !secret mqtt_password
   id: mqtt_client
   discovery: false

esp32_ble_tracker:
  scan_parameters:
   active: false
  on_ble_advertise:
    then:
      - lambda: |-
          if (x.get_name().rfind("JK-", 0) == 0 || x.get_name().rfind("JK_", 0) == 0) {
            ESP_LOGI("ble_adv", "New JK-BMS found");
            ESP_LOGI("ble_adv", "  Name: %s", x.get_name().c_str());
            ESP_LOGI("ble_adv", "  MAC address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
              ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
          }

ble_client:
  - mac_address: ${bms0_mac_address}
    id: client0
  - mac_address: ${bms1_mac_address}
    id: client1

jk_bms_ble:
  - ble_client_id: client0
    protocol_version: ${bms0_protocol_version}
    throttle: 5s
    id: bms0
  - ble_client_id: client1
    protocol_version: ${bms1_protocol_version}
    throttle: 5s
    id: bms1

binary_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balancing:
#      name: "${bms0} balancing"
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    online_status:
#      name: "${bms0} online status"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balancing:
#      name: "${bms1} balancing"
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    online_status:
#      name: "${bms1} online status"

button:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    retrieve_settings:
#      name: "${bms0} retrieve settings"
#    retrieve_device_info:
#      name: "${bms0} retrieve device info"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    retrieve_settings:
#      name: "${bms1} retrieve settings"
#    retrieve_device_info:
#      name: "${bms1} retrieve device info"

number:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balance_trigger_voltage:
#      name: "${bms0} balance trigger voltage"
#    cell_count:
#      name: "${bms0} cell count"
#    total_battery_capacity:
#      name: "${bms0} total battery capacity"
#   cell_voltage_overvoltage_protection:
#      name: "${bms0} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms0} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms0} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms0} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms0} balance starting voltage"
#    voltage_calibration:
#      name: "${bms0} voltage calibration"
#    current_calibration:
#      name: "${bms0} current calibration"
#    power_off_voltage:
#      name: "${bms0} power off voltage"
#    max_balance_current:
#      name: "${bms0} max balance current"
#    max_charge_current:
#      name: "${bms0} max charge current"
#    max_discharge_current:
#      name: "${bms0} max discharge current"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    balance_trigger_voltage:
#      name: "${bms1} balance trigger voltage"
#    cell_count:
#      name: "${bms1} cell count"
#    total_battery_capacity:
#      name: "${bms1} total battery capacity"
#    cell_voltage_overvoltage_protection:
#      name: "${bms1} cell voltage overvoltage protection"
#    cell_voltage_overvoltage_recovery:
#      name: "${bms1} cell voltage overvoltage recovery"
#    cell_voltage_undervoltage_protection:
#      name: "${bms1} cell voltage undervoltage protection"
#    cell_voltage_undervoltage_recovery:
#      name: "${bms1} cell voltage undervoltage recovery"
#    balance_starting_voltage:
#      name: "${bms1} balance starting voltage"
#    voltage_calibration:
#      name: "${bms1} voltage calibration"
#    current_calibration:
#      name: "${bms1} current calibration"
#    power_off_voltage:
#      name: "${bms1} power off voltage"
#    max_balance_current:
#      name: "${bms1} max balance current"
#    max_charge_current:
#      name: "${bms1} max charge current"
#    max_discharge_current:
#      name: "${bms1} max discharge current"

sensor:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
#    min_cell_voltage:
#      name: "${bms0} min cell voltage"
#    max_cell_voltage:
#      name: "${bms0} max cell voltage"
#    min_voltage_cell:
#      name: "${bms0} min voltage cell"
#    max_voltage_cell:
#      name: "${bms0} max voltage cell"
    delta_cell_voltage:
      name: "${bms0} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms0} average cell voltage"
    cell_voltage_1:
      name: "${bms0} cell voltage 01"
    cell_voltage_2:
      name: "${bms0} cell voltage 02"
    cell_voltage_3:
     name: "${bms0} cell voltage 03"
    cell_voltage_4:
      name: "${bms0} cell voltage 04"
    cell_voltage_5:
      name: "${bms0} cell voltage 05"
    cell_voltage_6:
      name: "${bms0} cell voltage 06"
    cell_voltage_7:
      name: "${bms0} cell voltage 07"
    cell_voltage_8:
      name: "${bms0} cell voltage 08"
    cell_voltage_9:
      name: "${bms0} cell voltage 09"
    cell_voltage_10:
      name: "${bms0} cell voltage 10"
    cell_voltage_11:
      name: "${bms0} cell voltage 11"
    cell_voltage_12:
      name: "${bms0} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms0} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms0} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms0} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms0} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms0} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms0} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms0} cell resistance 07"
#    cell_resistance_8:
#     name: "${bms0} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms0} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms0} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms0} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms0} cell resistance 12"
    total_voltage:
      name: "${bms0} total voltage"
    current:
      name: "${bms0} current"
    power:
      name: "${bms0} power"
    charging_power:
      name: "${bms0} charging power"
    discharging_power:
      name: "${bms0} discharging power"
    temperature_sensor_1:
     name: "${bms0} temperature sensor 1"
     id: temp_sensor_1
    temperature_sensor_2:
      name: "${bms0} temperature sensor 2"
      id: temp_sensor_2
#    power_tube_temperature:
#      name: "${bms0} power tube temperature"
    state_of_charge:
      name: "${bms0} state of charge"
#    capacity_remaining:
#      name: "${bms0} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms0} total battery capacity setting"
#    charging_cycles:
#      name: "${bms0} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms0} total charging cycle capacity"
#    total_runtime:
#      name: "${bms0} total runtime"
#    balancing_current:
#      name: "${bms0} balancing current"
#    errors_bitmask:
#      name: "${bms0} errors bitmask"

  - platform: jk_bms_ble
    jk_bms_ble_id: bms1
#    min_cell_voltage:
#      name: "${bms1} min cell voltage"
#    max_cell_voltage:
#      name: "${bms1} max cell voltage"
#    min_voltage_cell:
#      name: "${bms1} min voltage cell"
#    max_voltage_cell:
#      name: "${bms1} max voltage cell"
    delta_cell_voltage:
      name: "${bms1} delta cell voltage"
#    average_cell_voltage:
#      name: "${bms1} average cell voltage"
    cell_voltage_1:
      name: "${bms1} cell voltage 01"
    cell_voltage_2:
      name: "${bms1} cell voltage 02"
    cell_voltage_3:
      name: "${bms1} cell voltage 03"
    cell_voltage_4:
      name: "${bms1} cell voltage 04"
    cell_voltage_5:
      name: "${bms1} cell voltage 05"
    cell_voltage_6:
      name: "${bms1} cell voltage 06"
    cell_voltage_7:
      name: "${bms1} cell voltage 07"
    cell_voltage_8:
      name: "${bms1} cell voltage 08"
    cell_voltage_9:
      name: "${bms1} cell voltage 09"
    cell_voltage_10:
      name: "${bms1} cell voltage 10"
    cell_voltage_11:
      name: "${bms1} cell voltage 11"
    cell_voltage_12:
      name: "${bms1} cell voltage 12"
#    cell_resistance_1:
#      name: "${bms1} cell resistance 01"
#    cell_resistance_2:
#      name: "${bms1} cell resistance 02"
#    cell_resistance_3:
#      name: "${bms1} cell resistance 03"
#    cell_resistance_4:
#      name: "${bms1} cell resistance 04"
#    cell_resistance_5:
#      name: "${bms1} cell resistance 05"
#    cell_resistance_6:
#      name: "${bms1} cell resistance 06"
#    cell_resistance_7:
#      name: "${bms1} cell resistance 07"
#    cell_resistance_8:
#      name: "${bms1} cell resistance 08"
#    cell_resistance_9:
#      name: "${bms1} cell resistance 09"
#    cell_resistance_10:
#      name: "${bms1} cell resistance 10"
#    cell_resistance_11:
#      name: "${bms1} cell resistance 11"
#    cell_resistance_12:
#      name: "${bms1} cell resistance 12"
    total_voltage:
      name: "${bms1} total voltage"
    current:
      name: "${bms1} current"
    power:
      name: "${bms1} power"
    charging_power:
      name: "${bms1} charging power"
    discharging_power:
      name: "${bms1} discharging power"
    temperature_sensor_1:
      name: "${bms1} temperature sensor 1"
      id: temp_sensor_3
    temperature_sensor_2:
      name: "${bms1} temperature sensor 2"
      id: temp_sensor_4
#    power_tube_temperature:
#      name: "${bms1} power tube temperature"
    state_of_charge:
      name: "${bms1} state of charge"
#    capacity_remaining:
#      name: "${bms1} capacity remaining"
#    total_battery_capacity_setting:
#      name: "${bms1} total battery capacity setting"
#    charging_cycles:
#      name: "${bms1} charging cycles"
#    total_charging_cycle_capacity:
#      name: "${bms1} total charging cycle capacity"
#    total_runtime:
#      name: "${bms1} total runtime"
#    balancing_current:
#      name: "${bms1} balancing current"
#    errors_bitmask:
#      name: "${bms1} errors bitmask"

  - platform: template
    name: "Avg BMS Temp"
    id: avg_bms_temp
    update_interval: 10s
    lambda: |-
     float sum = 0.0;
     int count = 0;

     if (!isnan(id(temp_sensor_1).state)) {
       sum += id(temp_sensor_1).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 1: %f", id(temp_sensor_1).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 1 ist ungültig");
     }

     if (!isnan(id(temp_sensor_2).state)) {
       sum += id(temp_sensor_2).state;
       count += 1;
     ESP_LOGD("Avg Temp", "Sensor 2: %f", id(temp_sensor_2).state);
     } else {
       ESP_LOGD("Avg Temp", "Sensor 2 ist ungültig");
     }

     if (count == 0) {
       ESP_LOGD("Avg Temp", "Keine gültigen Temperatursensoren gefunden");
       return NAN;
     } else {
       float avg = sum / count;
       ESP_LOGI("Avg Temp", "Durchschnittstemperatur: %f", avg);
       return avg;
     }

  - platform: uptime
    type: seconds
    name: Uptime

  - platform: debug
    free:
      name: "Debug_Heap Free"
#    fragmentation:
#      name: "Debug_Heap Fragmentation"
    block:
      name: "Debug_Heap Max Block"
#    loop_time:
#      name: "Debug_Loop Time"
#    psram:
#      name: "Debug_Free PSRAM"

climate:
  - platform: thermostat
    name: "heat_mat"
    sensor: avg_bms_temp
    heat_overrun: 1 °C
    min_idle_time: 60s
    min_heating_off_time: 1s
    min_heating_run_time: 60s
    heat_action:
      - switch.turn_on: heat_mat
    idle_action:
      - switch.turn_off: heat_mat
    visual:
      min_temperature: 0 °C
      max_temperature: 20 °C
      temperature_step: 0.5 °C  
    default_preset: Lower bound
    id: climate_heat_mat
    preset:
      - name: Lower bound
        default_target_temperature_low: 10 °C

switch:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    charging:
#      name: "${bms0} charging"
#    discharging:
#      name: "${bms0} discharging"
#    balancer:
#      name: "${bms0} balancer"

#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    charging:
#      name: "${bms1} charging"
#    discharging:
#      name: "${bms1} discharging"
#    balancer:
#      name: "${bms1} balancer"

  - platform: ble_client
    ble_client_id: client0
    id: ble_client_switch0
    name: "${bms0} enable bluetooth connection"
  - platform: ble_client
    ble_client_id: client1
    id: ble_client_switch1
    name: "${bms1} enable bluetooth connection"

  - platform: gpio
    name: "heat_mat"
    pin: GPIO14
    id: heat_mat

text_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    errors:
#      name: "${bms0} errors"
#    total_runtime_formatted:
#      name: "${bms0} total runtime formatted"
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms1
#    errors:
#      name: "${bms1} errors"
#    total_runtime_formatted:
#      name: "${bms1} total runtime formatted"
  - platform: debug
    device:
      name: "Device Info"
    reset_reason:
      name: "Reset Reason"
syssi commented 2 weeks ago

Is the used menory still constant or do you see peaks?

peff74 commented 2 weeks ago

image the line is relatively smooth

image but when I open the website, you can clearly see something

peff74 commented 2 weeks ago

image I have now added the “cell resistance” to both BMS, i.e. 24 additional sensors. The memory is shrinking more and more.

Now we got 97kb free heap and the biggest block is ~55kb.

I wonder why adding the sensors eats up so much memory. I only know Arduino. If I take a look at how the data is processed there, then only the data stream that comes via Bluetooth is actually analyzed. Then it doesn't really matter whether I pull 10 or 50 pieces of data information from the data stream, the data is already there anyway.

syssi commented 2 weeks ago

Just a guess: The combination of sensor objects and the mqtt component is probably heavy because a topic must be assembled and measurements must be transfromed etc. You could remove mqtt once just for testing and look up the heap at the log to have a comparison.

peff74 commented 2 weeks ago

I have tested it out of curiosity. That makes a clear difference!

image

Just a thought from someone who is not familiar with ESP Home... Would it be possible to run only some sensors/settings through MQTT and make others only visible via the web browser.

syssi commented 2 weeks ago

Would it be possible to run only some sensors/settings through MQTT and make others only visible via the web browser.

Yes. You can declare sensors as internal: true. In this case the state isn't passed to third parties. The web_server component has a special feature to show interal sensors nevertheless:

web_server:
  include_internal: true
peff74 commented 2 weeks ago

I have now set the cell resistance as internal: true and for the web server include_internal: true. The result is no difference, except that the cell resistance not arrives via MQTT^^

peff74 commented 2 weeks ago

by the way, here is the strange picture of the startup that I mentioned before... But this only happens sometimes image

syssi commented 2 weeks ago

Okay. In this case the implementation is not as efficient as hoped for.

syssi commented 2 weeks ago

The screenshot above shows the log output of the settings frame:

https://github.com/syssi/esphome-jk-bms/blob/main/components/jk_bms_ble/jk_bms_ble.cpp#L971-L1006

The frame is retrieved once on established connection and every time if you press the retrieve settings frame button.

peff74 commented 2 weeks ago

Well... what else can we do to get ahead?

syssi commented 2 weeks ago

Just add new stuff to your YAML step by step and try to get an idea which piece causes the crash.

peff74 commented 2 weeks ago

O.K. I'll go on

peff74 commented 2 weeks ago

A question for understanding. When I have the switches active.

switch:
  - platform: jk_bms_ble
    jk_bms_ble_id: bms0
    charging:
      internal: true
      name: "switch ${bms0} charging"
    discharging:
      internal: true
      name: "switch ${bms0} discharging"
    balancer:
      internal: true
      name: "switch ${bms0} balancing"

Then I don't need the binary sensors.

#binary_sensor:
#  - platform: jk_bms_ble
#    jk_bms_ble_id: bms0
#    balancing:
#      internal: true
#      name: "switch ${bms0} balancing"
#    charging:
#      internal: true
#      name: "switch ${bms0} charging"
#    discharging:
#      internal: true
#      name: "switch ${bms0} discharging"
#    online_status:
#      name: "switch ${bms0} online status"

Wouldn't that be double? Because the switches display On/Off

Or are they linked to each other?

syssi commented 2 weeks ago

There is a difference between switch.balancing is turned ON and the BMS is balancing at the moment indicated by binary_sensor.balancing. The same applies to switch.charging. If charging is enabled in general this doesn't mean the protection board allows charging at the moment (indicated by binary_sensor.charging).

peff74 commented 2 weeks ago

adding the switches seems to have been too much. or something is wrong with the switches. I will now leave the switches in and remove the ‘cell resistance’. image Let's see what happens

What always catches my eye is the message of the long loop time of the esp32_ble ~200ms is really a lot. I know this from my Arduino projects, where I split up functions to run them in different loops to reduce the runtime as much as possible. An ESP32 is not as sensitive as an ESP8266, but it's just a thought

peff74 commented 2 weeks ago

Perhaps it makes sense to split up the Bluetooth query. The important data more frequently and the unimportant data less frequently.

syssi commented 2 weeks ago

This is a good idea in general but let's check first at some point blocking is really an issue: We will reduce the number of sensor to three pieces again (per BMS) and add a blocking sleep of ~200ms to the loop.

Please keep in mind: The BMS pushs the complete status frame two times per second. We have to discard the traffic because the interval is fix and cannot be changed.

peff74 commented 2 weeks ago

O.K. I didn't know that, I thought you had to ask the BMS I haven't looked at the scripts yet, because I know that if I start I'll build my own Arduino version, or make the one from the ‘Akkudoktor’ forum work ^^

At the moment I'm running a version as written above with switch: and binary_sensor: and less sensor:

syssi commented 2 weeks ago

How did you retrieve this log:

[16:22:17][D][sensor:094]: 'Avg BMS Temp': Sending state 17.05000  with 1 decimals of accuracy
[16:22:17][D][climate:396]: 'heat_mat' - Sending state:
[16:22:17][D][climate:399]:   Mode: HEAT
-----------------------------REBOOT--------------------------------
[16:22:28][W][component:170]: Component mqtt cleared Warning flag
[16:22:28][I][mqtt:286]: MQTT Connected!
[16:22:29][I][app:062]: setup() finished successfully!

Via network? Did you try to retrieve the log using the serial line / the USB connection? You should see the exception + stack trace here which will provide some more insights probably.

txubelaxu commented 2 weeks ago

I had a similar issue during this year. ESP restarted several times randomly (?). I started commenting sensors/switches but nothing. At least, I created a custom component "switch" (JkRS485BmsSwitch) and a custom component "number" (JkRS485BmsNumber) and everything went OK (with all sensors uncommented).

I cannot undestand why the problem dissapeared using custom components...

Now, I have a similar issue with sensors. I have tried to create a new custom component "sensor" (JkRS485BmsSensor) but I have not got it to know if this way the problem goes away for ever. :-(

peff74 commented 2 weeks ago

How did you retrieve this log:

[16:22:17][D][sensor:094]: 'Avg BMS Temp': Sending state 17.05000  with 1 decimals of accuracy
[16:22:17][D][climate:396]: 'heat_mat' - Sending state:
[16:22:17][D][climate:399]:   Mode: HEAT
-----------------------------REBOOT--------------------------------
[16:22:28][W][component:170]: Component mqtt cleared Warning flag
[16:22:28][I][mqtt:286]: MQTT Connected!
[16:22:29][I][app:062]: setup() finished successfully!

Via network? Did you try to retrieve the log using the serial line / the USB connection? You should see the exception + stack trace here which will provide some more insights probably.

I received the logs via the network. Because the ESP runs outside in a small cabinet, it's a bit difficult to connect it serially. But if it becomes necessary, I could build it.

To get exception and stack trace logger level: DEBUG must be active? I don't know ESP-Home very well.

peff74 commented 2 weeks ago

I had a similar issue during this year. ESP restarted several times randomly (?). I started commenting sensors/switches but nothing. At least, I created a custom component "switch" (JkRS485BmsSwitch) and a custom component "number" (JkRS485BmsNumber) and everything went OK (with all sensors uncommented).

I cannot undestand why the problem dissapeared using custom components...

Now, I have a similar issue with sensors. I have tried to create a new custom component "sensor" (JkRS485BmsSensor) but I have not got it to know if this way the problem goes away for ever. :-(

JkRS485BmsSwitch Sounds like you are connected over cable, I use BLE. I am not sure if this is comparable.