ESP32 BMS JIKONG 8S OUT 2 PARAMETER MAC MANUAL INPUT PLUS RESET LCD TAMPIL IP , AP ,SSID , STATUS BLUTUT
esphome:
name: "bms-monitoring"
min_version: 2025.9.1
build_path: build/dara-tes-esp
on_boot:
priority: -10
then:
- lambda: |-
id(apply_hysteresis).execute();
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
api:
ota:
- platform: esphome
# =========================
# KONFIGURASI WIFI
# =========================
wifi:
ap:
ssid: "PUTU@TEKNO"
password: "rejeki88"
captive_portal:
# Web Server aktif SETELAH perangkat terhubung ke WiFi.
web_server:
port: 80
# =========================
# PENGATURAN MAC ADDRESS MANUAL
# =========================
text:
- platform: template
name: "BMS MAC Address"
id: bms_mac_address
mode: text
pattern: "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$"
optimistic: true
restore_value: true
on_value:
then:
- lambda: |-
auto mac_str_to_uint64 = [](std::string mac_str) -> uint64_t {
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end());
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), '-'), mac_str.end());
if (mac_str.length() != 12) {
ESP_LOGW("custom", "Format MAC address tidak valid (panjang salah): %s", mac_str.c_str());
return 0;
}
char *end;
const char *start = mac_str.c_str();
uint64_t mac_addr = strtoull(start, &end, 16);
if (end != start + 12) {
ESP_LOGW("custom", "Karakter tidak valid di MAC address: %s", mac_str.c_str());
return 0;
}
return mac_addr;
};
uint64_t new_mac = mac_str_to_uint64(x);
if (new_mac != 0) {
ESP_LOGD("custom", "Mengatur MAC address BLE baru ke: %s", x.c_str());
id(client0).set_address(new_mac);
} else {
ESP_LOGE("custom", "Gagal mengatur MAC address baru karena format salah.");
}
# =========================
# BUTTONS (SATU BLOK)
# =========================
button:
# Tombol SAVE MAC
- platform: template
name: "Save and Apply MAC Address"
on_press:
then:
- logger.log: "Menyimpan dan menerapkan MAC address yang tersimpan..."
- lambda: |-
id(bms_mac_address).publish_state(id(bms_mac_address).state);
# Factory Reset (hapus preferences: WiFi & nilai restore_value)
- platform: factory_reset
id: factory_reset_btn
name: "Factory Reset (Erase Prefs)"
# Opsional: Restart
- platform: restart
id: restart_device
name: "Restart ESP"
# =========================
# RESET PIN FISIK (LONG-PRESS 5s)
# =========================
binary_sensor:
- platform: gpio
id: reset_pin
name: "Reset Pin (Hold ≥5s)"
pin:
number: GPIO25
mode:
input: true
pullup: true
inverted: true
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
- logger.log: "Reset pin: PRESS (start 5s timer)"
- script.execute: reset_longpress
on_release:
- logger.log: "Reset pin: RELEASE (cancel timer)"
- script.stop: reset_longpress
# Komponen JK-BMS
external_components:
- source: github://syssi/esphome-jk-bms@main
refresh: 0s
esp32_ble_tracker:
scan_parameters:
active: false
# Placeholder; atur via web
ble_client:
- mac_address: "00:00:00:00:00:00"
id: client0
# === Tambahan: publish status BLE ke text_sensor ===
on_connect:
then:
- logger.log: "BLE connected"
- text_sensor.template.publish:
id: ble_status
state: "Connected"
on_disconnect:
then:
- logger.log: "BLE disconnected"
- text_sensor.template.publish:
id: ble_status
state: "Not Connected"
jk_bms_ble:
- ble_client_id: client0
protocol_version: JK02_32S
throttle: 8s
id: bms0
# --- I2C / OLED 0.96" + FONT ---
i2c:
sda: GPIO21
scl: GPIO22
scan: true
font:
- id: font_14
file: "gfonts://Roboto"
size: 14
# Text sensor Wi-Fi + BLE untuk OLED
text_sensor:
- platform: wifi_info
ip_address:
name: "Device IP"
id: device_ip
ssid:
name: "Connected SSID"
id: connected_ssid
# === Tambahan: text sensor template untuk status BLE ===
- platform: template
name: "BLE Status"
id: ble_status
update_interval: never
icon: "mdi:bluetooth"
# =========================
# SENSORS
# =========================
sensor:
- platform: jk_bms_ble
jk_bms_ble_id: bms0
total_voltage:
name: "JK Total Voltage"
id: jk_total_voltage
capacity_remaining:
name: "JK SOC"
id: jk_soc
min_cell_voltage:
name: "JK Min Cell V"
max_cell_voltage:
name: "JK Max Cell V"
min_voltage_cell:
name: "JK Min Voltage Cell #"
max_voltage_cell:
name: "JK Max Voltage Cell #"
average_cell_voltage:
name: "JK Avg Cell V"
delta_cell_voltage:
name: "JK Delta Cell V"
# ====== 8S ONLY ======
cell_voltage_1:
name: "JK Cell V1"
cell_voltage_2:
name: "JK Cell V2"
cell_voltage_3:
name: "JK Cell V3"
cell_voltage_4:
name: "JK Cell V4"
cell_voltage_5:
name: "JK Cell V5"
cell_voltage_6:
name: "JK Cell V6"
cell_voltage_7:
name: "JK Cell V7"
cell_voltage_8:
name: "JK Cell V8"
# (cell_voltage_9..15 dihapus untuk konfigurasi 8S)
# =========================
# Kontrol GPIO
# =========================
output:
- platform: gpio
pin: GPIO32
id: out_gpio32
- platform: gpio
pin: GPIO33
id: out_gpio33
switch:
# Output fisik
- platform: output
name: "SOC Output GPIO32"
id: soc_output_32
output: out_gpio32
restore_mode: RESTORE_DEFAULT_OFF
- platform: output
name: "SOC Output GPIO33"
id: soc_output_33
output: out_gpio33
restore_mode: RESTORE_DEFAULT_OFF
# Toggle Auto Control per pin
- platform: template
name: "Auto Control by SOC (GPIO32)"
id: auto_soc_enable_32
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
turn_on_action: []
turn_off_action: []
- platform: template
name: "Auto Control by SOC (GPIO33)"
id: auto_soc_enable_33
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
turn_on_action: []
turn_off_action: []
number:
# Ambang untuk GPIO32
- platform: template
name: "SOC Ah Min (ON) - GPIO32"
id: soc_ah_min_on_32
unit_of_measurement: "Ah"
min_value: 0
max_value: 100
step: 0.1
optimistic: true
restore_value: true
initial_value: 19.9
- platform: template
name: "SOC Ah Max (OFF) - GPIO32"
id: soc_ah_max_off_32
unit_of_measurement: "Ah"
min_value: 0
max_value: 100
step: 0.1
optimistic: true
restore_value: true
initial_value: 25.5
# Ambang untuk GPIO33
- platform: template
name: "SOC Ah Min (ON) - GPIO33"
id: soc_ah_min_on_33
unit_of_measurement: "Ah"
min_value: 0
max_value: 100
step: 0.1
optimistic: true
restore_value: true
initial_value: 19.2
- platform: template
name: "SOC Ah Max (OFF) - GPIO33"
id: soc_ah_max_off_33
unit_of_measurement: "Ah"
min_value: 0
max_value: 100
step: 0.1
optimistic: true
restore_value: true
initial_value: 25.5
# =========================
# SCRIPTS
# =========================
script:
# Histeresis SOC → kontrol GPIO32/33
- id: apply_hysteresis
mode: queued
then:
# Kontrol untuk GPIO32
- if:
condition:
lambda: |-
return id(auto_soc_enable_32).state &&
(id(jk_soc).state <= id(soc_ah_min_on_32).state);
then:
- switch.turn_on: soc_output_32
- if:
condition:
lambda: |-
return id(auto_soc_enable_32).state &&
(id(jk_soc).state >= id(soc_ah_max_off_32).state);
then:
- switch.turn_off: soc_output_32
# Kontrol untuk GPIO33
- if:
condition:
lambda: |-
return id(auto_soc_enable_33).state &&
(id(jk_soc).state <= id(soc_ah_min_on_33).state);
then:
- switch.turn_on: soc_output_33
- if:
condition:
lambda: |-
return id(auto_soc_enable_33).state &&
(id(jk_soc).state >= id(soc_ah_max_off_33).state);
then:
- switch.turn_off: soc_output_33
# Timer long-press reset (tanpa menunggu tombol dilepas)
- id: reset_longpress
mode: restart
then:
- delay: 5s
- if:
condition:
binary_sensor.is_on: reset_pin
then:
- logger.log: "Long press ≥5s terdeteksi → factory reset!"
- text.set:
id: bms_mac_address
value: ""
- lambda: |-
id(client0).set_address(0);
- button.press: factory_reset_btn
else:
- logger.log: "Tombol dilepas <5s → batal reset."
# Evaluasi berkala
interval:
- interval: 5s
then:
- script.execute: apply_hysteresis
# --- OLED 0.96" (SSD1306 128x64) ---
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
update_interval: 5s
lambda: |-
it.clear();
// Jika sudah terhubung Wi-Fi (punya IP) → tampilkan SSID terhubung & IP
if (id(device_ip).has_state()) {
if (id(connected_ssid).has_state()) {
it.printf(0, 0, id(font_14), "WiFi: %s", id(connected_ssid).state.c_str());
} else {
it.printf(0, 0, id(font_14), "WiFi: -");
}
it.printf(0, 20, id(font_14), "IP: %s", id(device_ip).state.c_str());
} else {
// Mode AP aktif → tampilkan SSID AP & password
it.printf(0, 0, id(font_14), "AP: %s", "PUTU@TEKNO-BMS-JK");
it.printf(0, 20, id(font_14), "PASS: %s", "rejeki88");
}
// SOC (Ah)
if (id(jk_soc).has_state()) {
it.printf(0, 40, id(font_14), "SOC: %.2f Ah", id(jk_soc).state);
} else {
it.printf(0, 40, id(font_14), "SOC: -");
}
// === Tambahan: Status Bluetooth ===
if (id(ble_status).has_state()) {
it.printf(0, 56, id(font_14), "BT: %s", id(ble_status).state.c_str());
} else {
it.printf(0, 56, id(font_14), "BT: -");
}
Comments
Post a Comment