Small BMS Status Screen code #19
Replies: 5 comments 8 replies
-
This is a great project. Could you write a code for a 18 cell battery with a larger display? I would love to use such a feature but I need a bigger display for more information. |
Beta Was this translation helpful? Give feedback.
-
@Zahnpasta83 Here's a more complete config stripped of my specific info. Adapt as needed substitutions:
name: jbd-bms
device_description: "Monitor and control a Xiaoxiang Battery Management System (JBD-BMS) via BLE"
external_components_source: github://syssi/esphome-jbd-bms@main
mac_address: YOURS:YOURS:YOURS:YOURS:YOURS
arial_font_file: 'fonts/arial.ttf'
bebas_font_file: 'fonts/BebasNeue-Regular.ttf'
battery_font_file: 'fonts/materialdesignicons-webfont.ttf'
esphome:
name: ${name}
comment: ${device_description}
project:
name: "syssi.esphome-jbd-bms"
version: 1.4.0
esp32:
board: esp32doit-devkit-v1
variant: ESP32
framework:
type: esp-idf
# version: latest
external_components:
- source: ${external_components_source}
refresh: 0s
logger:
api:
encryption:
key: "YOURSYOURSYOURSYOURS"
ota:
password: "YOURSYOURSYOURSYOURS"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: YOURSYOURSYOURSYOURS
gateway: YOURSYOURSYOURSYOURS
subnet: YOURSYOURSYOURSYOURS
dns1: YOURSYOURSYOURSYOURS
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${name} Fallback Hotspot"
password: "YOURSYOURSYOURSYOURS"
# The MQTT component is ESP-IDF compatible since ESPHome version 2022.4.0. If
# ESPHome suggests to use the arduino framework instead because of missing ESP-IDF
# framework support you should update your setup.
# mqtt:
# broker: !secret mqtt_host
# username: !secret mqtt_username
# password: !secret mqtt_password
# id: mqtt_client
#esp32_ble_tracker:
esp32_ble_tracker:
on_ble_advertise:
then:
- lambda: |-
if (x.get_name().rfind("xiaoxiang", 0) == 0) {
ESP_LOGI("ble_adv", "New JBD-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: ${mac_address}
id: client0
jbd_bms_ble:
- ble_client_id: client0
id: bms0
button:
- platform: safe_mode
name: Safe Mode Boot
entity_category: diagnostic
- platform: restart
name: "${name} Restart"
font:
- file: ${bebas_font_file}
id: font_bebas_44
size: 44
- file: ${arial_font_file}
id: font_arial_20
size: 20
- file: ${arial_font_file}
id: font_arial_18
size: 18
- file: ${battery_font_file}
id: battery_font
size: 60
glyphs: [
# Battery
'', # F007A mdi-battery-10
'', # F007B mdi-battery-20
'', # F007C mdi-battery-30
'', # F007D mdi-battery-40
'', # F007E mdi-battery-50
'', # F007F mdi-battery-60
'', # F0080 mdi-battery-70
'', # F0081 mdi-battery-80
'', # F0082 mdi-battery-90
'', # F0079 mdi-battery 100
]
- file: ${battery_font_file}
id: charger_font
size: 20
glyphs: [
# Battery
'', # F1A73 mdi-solar-power-variant
'', # F0F67 mdi-moon-waxing-crescent
]
binary_sensor:
- platform: jbd_bms_ble
balancing:
name: "${name} balancing"
charging:
name: "${name} charging"
discharging:
name: "${name} discharging"
sensor:
- platform: homeassistant
id: ha_battery_power
entity_id: sensor.battery_wattage
unit_of_measurement: 'W'
- platform: homeassistant
unit_of_measurement: 'W'
entity_id: sensor.solar_power
id: ha_solar_power
accuracy_decimals: 2
- platform: homeassistant
unit_of_measurement: 'W'
entity_id: sensor.total_daily_yield
id: ha_solar_daily
accuracy_decimals: 0
- platform: homeassistant
unit_of_measurement: 'a'
entity_id: sensor.battery_current
id: ha_battery_current
- platform: jbd_bms_ble
battery_strings:
name: "${name} battery strings"
current:
name: "${name} current"
id: current
power:
name: "${name} power"
id: power
charging_power:
name: "${name} charging power"
discharging_power:
name: "${name} discharging power"
state_of_charge:
name: "${name} state of charge"
id: state_of_charge
nominal_capacity:
name: "${name} nominal capacity"
charging_cycles:
name: "${name} charging cycles"
capacity_remaining:
name: "${name} capacity remaining"
battery_cycle_capacity:
name: "${name} battery cycle capacity"
total_voltage:
name: "${name} total voltage"
id: total_voltage
average_cell_voltage:
name: "${name} average cell voltage"
delta_cell_voltage:
name: "${name} delta cell voltage"
id: cell_voltage_delta
accuracy_decimals: 3
min_cell_voltage:
name: "${name} min cell voltage"
max_cell_voltage:
name: "${name} max cell voltage"
min_voltage_cell:
name: "${name} min voltage cell"
max_voltage_cell:
name: "${name} max voltage cell"
temperature_1:
name: "${name} temperature 1"
id: temperature_1
filters:
- lambda: return x * (9.0/5.0) + 32.0;
unit_of_measurement: "°F"
temperature_2:
name: "${name} temperature 2"
id: temperature_2
cell_voltage_1:
id: cell_voltage_1
name: "${name} cell voltage 1"
cell_voltage_2:
name: "${name} cell voltage 2"
id: cell_voltage_2
cell_voltage_3:
name: "${name} cell voltage 3"
id: cell_voltage_3
cell_voltage_4:
name: "${name} cell voltage 4"
id: cell_voltage_4
cell_voltage_5:
name: "${name} cell voltage 5"
id: cell_voltage_5
cell_voltage_6:
name: "${name} cell voltage 6"
id: cell_voltage_6
cell_voltage_7:
name: "${name} cell voltage 7"
id: cell_voltage_7
cell_voltage_8:
name: "${name} cell voltage 8"
id: cell_voltage_8
operation_status_bitmask:
name: "${name} operation status bitmask"
errors_bitmask:
name: "${name} errors bitmask"
balancer_status_bitmask:
name: "${name} balancer status bitmask"
software_version:
name: "${name} software version"
switch:
- platform: jbd_bms_ble
charging:
name: "${name} charging"
discharging:
name: "${name} discharging"
balancer:
name: "${name} balancer"
text_sensor:
- platform: homeassistant
name: "Charger State"
entity_id: sensor.charger
id: ha_charger_state
- platform: jbd_bms_ble
errors:
name: "${name} errors"
operation_status:
name: "BMS Status"
device_model:
name: "${name} device model"
spi:
clk_pin: 18
mosi_pin: 23
display:
- platform: waveshare_epaper
cs_pin: 5
dc_pin: 21
busy_pin: 19
reset_pin: 22
model: 1.54in
rotation: 90°
update_interval: 3s
reset_duration: 20ms
full_update_every: 60
id: bms_display
lambda: |-
it.printf(6, 5, id(font_arial_18), "CHARGE");
it.printf(5, 25, id(font_bebas_44), "%4.0f", id(state_of_charge).state);
it.printf(64, 30, id(font_arial_20), "%%");
it.printf(10, 73, id(font_arial_20), "%.1fv", id(total_voltage).state);
it.line(6, 97, 120, 97);
it.line(6, 98, 120, 98);
it.printf(6, 102, id(font_arial_18), "POWER");
it.printf(6, 121, id(font_bebas_44), "%7.0f", id(power).state);
it.printf(95, 141, id(font_arial_20), "W");
it.printf(10, 170, id(font_arial_20), "%3.0f°f", id(temperature_1).state);
it.printf(74, 170, id(font_arial_20), "%.1fa", id(current).state);
it.line(125, 5, 125, 195);
it.line(126, 5, 126, 195);
it.printf(133, 5, id(font_arial_18), "CELLS");
it.line(133, 26, 192, 26);
it.printf(130, 28, id(font_arial_18), "1 %3.3f", id(cell_voltage_1).state);
it.printf(130, 48, id(font_arial_18), "2 %3.3f", id(cell_voltage_2).state);
it.printf(130, 68, id(font_arial_18), "3 %3.3f", id(cell_voltage_3).state);
it.printf(130, 88, id(font_arial_18), "4 %3.3f", id(cell_voltage_4).state);
it.printf(130, 108, id(font_arial_18), "5 %3.3f", id(cell_voltage_5).state);
it.printf(130, 128, id(font_arial_18), "6 %3.3f", id(cell_voltage_6).state);
it.printf(130, 148, id(font_arial_18), "7 %3.3f", id(cell_voltage_7).state);
it.printf(130, 168, id(font_arial_18), "8 %3.3f", id(cell_voltage_8).state);
/* Battery Voltage */
if(id(state_of_charge).has_state()) {
if (id(state_of_charge).state >= 98) {
// 100 %
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 90) {
// 90 %
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 80) {
// 80%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 70) {
// 70%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 60) {
// 60%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 50) {
// 50%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 40) {
// 40%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 30) {
// 30%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 20) {
// 20%
it.print(70, 30, id(battery_font), "");
} else if (id(state_of_charge).state >= 10) {
// 10%
it.print(70, 30, id(battery_font), "");
}
} |
Beta Was this translation helpful? Give feedback.
-
Adapted for 12S batteries, on the Waveshare ESP32 Raw Panel Driver Board with a Waveshare 2.7in e-paper display. Hope that helps at least one other person! Thanks for laying the groundwork @the-butterfry and @syssi
|
Beta Was this translation helpful? Give feedback.
-
I am using 16 batterys, wemos_d1_mini32 and a wave share 4.20in Display :D Also from me a huge Thanks for laying the groundwork @the-butterfry and @syssi !!!
|
Beta Was this translation helpful? Give feedback.
-
Thought I'd contribute this for those that would like an easy to view local screen for their battery/bms. Easy to adapt to whatever screen - but the 1.54 e-paper is probably about as small as you should go. Adjust positioning accordingly in the display block. I'm running this on the jbd-bms esp32 that is housed with the battery so most of this code is in addition to whatever config you have on your device to make syssi's code run.
I'll be mounting it atop the battery housing. Keep in mind this is for an 8s BMS. Adapt the code/cells to your needs, just a matter of adding or removing it.print lines and moving them around. Lots of uploading tests to get the pixels right, but the result is quite satisfying.
Make sure to get the arial and BebasNeue-Regualar font files inside your esphome the fonts folder. The battery icons come from the mdi webfont found here: https://github.com/Templarian/MaterialDesign-Webfont/tree/master/fonts
Beta Was this translation helpful? Give feedback.
All reactions