Add a Kconfig voltage-class choice (BMU_PACK_CLASS: 24V default / 48V) plus an sdkconfig.defaults.48v overlay, implementing lot 4 of the 48V design note. 48V class defaults: min 44600 mV (3.43 V/cell, same fleet policy as 24V), max 55200 mV (charger CV 54.6 V + 600 mV margin), imbalance 2000 mV (x13/7), VRM SOC window 44600-53500 mV. Blocking fixes found while implementing: - bmu_protection: plausibility guard rejected any reading above 35 V as an I2C glitch -> class macro BMU_V_PLAUSIBLE_MAX_MV. - bmu_ina237: BOVL/BUVL hardwired 30000/24000 -> programmed from runtime thresholds (NVS/Kconfig) at init; log real values. - bmu_ble control + display steppers: hardcoded 20-30/25-35 V setting bounds rejected any 48V config -> class-derived macros BMU_VMIN/VMAX_SET_FLOOR/CEIL_MV in bmu_config.h. - bmu_ui_detail: chart autoscale seeds 35000/15000 broke above 35 V -> neutral 65535/0. - bmu_ble_victron: SOC window hardcoded 24.0/28.8 -> reads the VRM Kconfig (class fallback when VRM disabled). - legacy firmware/src/config.h: BATTERY_PACK_CLASS_48V ifdef. Validated: idf.py build green for both classes (esp32s3, isolated sdkconfig; 48V generates 44600/55200/2000), no new warnings in touched files, legacy sim-host tests 13/13 pass. NVS erase needed when reflashing a board that has 24V thresholds persisted.
2.6 KiB
2.6 KiB
ESP-IDF Firmware (Production)
ESP-IDF 5.4 firmware pour ESP32-S3-BOX-3, 25 composants modulaires, LVGL display, NimBLE, MQTT, OTA.
Build & Flash
source ~/esp/esp-idf/export.sh
idf.py build # ~30-60s incremental
idf.py -p /dev/cu.usbmodem* flash monitor # flash + serial
idf.py menuconfig # configure sdkconfig
# Variante 48V (packs 13s, hardware BMU-v2-48v) — overlay Kconfig :
idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.48v" build
# (supprimer sdkconfig existant + erase NVS si seuils 24V déjà persistés)
Classe de tension : choix Kconfig BMU_PACK_CLASS (24V défaut / 48V).
Fixe les défauts des seuils (44600/55200 mV en 48V), les bornes de réglage
BLE/écran, le garde de plausibilité INA237 et la fenêtre SOC VRM.
Erase NVS (si config corrompue ou override sdkconfig) :
python3 -m esptool --chip esp32s3 -p /dev/cu.usbmodem* erase_region 0x9000 0x6000
Boot Sequence (14 étapes)
NVS → SPIFFS → Display → WiFi → BLE → FAT → SNTP → I2C scan → topology → protection → cloud → web → VE.Direct → OTA
Architecture clé
- bmu_protection : state machine 5 états (CONNECTED/DISCONNECTED/RECONNECTING/ERROR/LOCKED), lock après 5 reconnexions
- bmu_balancer : soft-balancing duty-cycling (3 ON / 2 OFF) + R_int opportuniste
- bmu_ble : NimBLE, 4 services GATT (battery/system/control/Victron SmartShunt),
bmu_ble_set_nb_ina()post-scan I2C - bmu_influx + _store : InfluxDB line-protocol + persistence offline FAT/SD (rotation 512KB)
- bmu_mqtt : ESP-MQTT auth user/password (NVS override possible)
- bmu_display : LVGL tabview, swipe detail, pack info line, R_int column
- bmu_storage : NVS, FAT (
/fatfs), SPIFFS (/spiffs), SD (/sdcardSPI PMOD2)
Offline Data Persistence
Si WiFi/InfluxDB down, télémétrie persistée :
- Primary :
/fatfs/influx/current.lp→ rotationrotated.lpà 512KB (max 1MB) - Fallback :
/sdcard/influx/ - Replay automatique au reconnect WiFi (cloud_telemetry_task, 10s)
Safety
- I2C : tout passe par
bmu_i2c_lock()/bmu_i2c_unlock() bmu_protectionskip les batteries oùbmu_balancer_is_off()(évite incrémentationnb_switch)- Tâches (priorités réelles du code) : protection (prio 8), balancer (prio 3), hotplug (prio 3), cloud (prio 2), ah_task (prio 1), display (esp_timer)
Anti-Patterns
- Ne pas lire
s_nb_inafigé — utiliserprot->nb_inadynamique post-scan - Ne pas oublier d'ajouter un nouveau composant aux REQUIRES de
main/CMakeLists.txt - Ne pas appeler
ble_gap_adv_set_fields()sansname— macOS/iOS perd la pub