- BMS LC30 – Prise en main logicielle
- 1. Principe de fonctionnement
- 2. Vérification matérielle avant test
- 3. Première lecture rapide
- 4. Diagnostic I²C
- 5. Configuration avancée
- 6. Calibration tension et courant
- 7. Lecture directe de registres
- 8. Écriture de registres
- 9. Profils de lecture
- 10. Routes “studio” pour l’exploration avancée
- 11. Gestion sécurité
- 12. Auto-shutdown batterie faible
- 13. Exemple minimal de script de supervision
- 14. Points d’attention
- 15. Résumé des routes utiles
BMS LC30 – Prise en main logicielle #
Cette page décrit la prise en main logicielle du BMS LC30 à travers le plugin Python utilisé dans le système. L’objectif est de permettre une mise en route rapide, la lecture des données principales, le diagnostic du bus I²C et les premières opérations de calibration et d’exploration.
Le plugin fournit notamment :
- une API
/api/bmspour les données complètes, - une API
/api/bms/diagpour le diagnostic I²C, - des routes avancées pour calibration, lecture de registres, profils, commandes MAC, cellules, statuts et Data Flash,
- une logique d’activation du BMS par GPIO avant démarrage du monitoring.
1. Principe de fonctionnement #
Au démarrage, le plugin active une ligne GPIO dédiée au BMS, attend la stabilisation du bus puis lance un moniteur périodique sur le bus I²C configuré. Les valeurs lues sont ensuite exposées via les routes API. Le code utilise par défaut le bus I²C 1, l’adresse 0x0B, un intervalle de polling de 2 s et un GPIO d’activation par défaut à 26. :contentReference[oaicite:3]{index=3} :contentReference[oaicite:4]{index=4}
| Paramètre | Valeur par défaut | Rôle |
|---|---|---|
| Adresse I²C | 0x0B | Adresse SMBus du BMS |
| Bus I²C | 1 | Bus utilisé pour la communication |
| Polling | 2.0 s | Fréquence de rafraîchissement |
| Nombre de cellules | 4 | Utilisé pour certaines lectures et estimations |
| Capacité nominale | 3000 mAh | Référence système |
| GPIO enable | 26 | Activation du BMS |
| Seuil SOC bas | 10 % | Alerte batterie faible |
| Seuil tension basse | 12.0 V | Seuil critique |
2. Vérification matérielle avant test #
Avant toute lecture logicielle :
- vérifier que la carte est alimentée correctement,
- vérifier que le signal d’activation BMS est fonctionnel,
- vérifier le câblage SDA / SCL,
- vérifier que le bus I²C isolé côté système est bien accessible depuis l’hôte,
- vérifier la configuration d’adresse et de bus dans l’application.
3. Première lecture rapide #
La route /api/bms renvoie les données consolidées du BMS. Lorsque le monitoring est actif,
la réponse inclut notamment l’état de connexion, les alarmes, l’état de charge, la tension, le courant
et d’autres informations issues du moniteur. :contentReference[oaicite:5]{index=5}
GET /api/bms
Exemple de réponse typique :
{
"connected": true,
"soc": 82,
"voltage": 15.84,
"current": -1.25,
"temperature": 27.4,
"remaining_capacity": 2460,
"full_charge_capacity": 3000,
"cycle_count": 18,
"charging": false,
"fully_charged": false,
"alarms": []
}
Exemple Python #
import requests
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms", timeout=5)
r.raise_for_status()
data = r.json()
print("Connecté :", data.get("connected"))
print("SOC :", data.get("soc"), "%")
print("Tension :", data.get("voltage"), "V")
print("Courant :", data.get("current"), "A")
print("Temp. :", data.get("temperature"), "°C")
print("Alarmes :", data.get("alarms", []))
4. Diagnostic I²C #
La route /api/bms/diag effectue un scan des bus disponibles, indique le bus cible,
l’adresse cible et tente plusieurs lectures directes de registres standard comme la tension, le courant,
le SOC, la température, le status, le compteur de cycles et le numéro de série. La connexion est considérée
valide si la lecture de tension réussit. :contentReference[oaicite:6]{index=6} :contentReference[oaicite:7]{index=7}
GET /api/bms/diag
Exemple Python #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/diag", timeout=10)
r.raise_for_status()
diag = r.json()
print(json.dumps(diag, indent=2, ensure_ascii=False))
Cette route est à utiliser en priorité si le BMS n’apparaît pas dans l’interface ou si aucune donnée temps réel ne remonte.
5. Configuration avancée #
Le plugin expose une configuration avancée avec :
- activation du mode avancé,
- choix de la source de SOC,
- tension cellule pleine / vide,
- gains et offsets de calibration tension et courant.
Deux sources de SOC sont prises en charge par le code : bms et voltage_estimated. :contentReference[oaicite:8]{index=8} :contentReference[oaicite:9]{index=9}
GET /api/bms/advanced-config
POST /api/bms/advanced-config
Exemple Python – lecture de configuration #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/advanced-config", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – mise à jour de configuration #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"advanced_mode": True,
"soc_source": "bms",
"full_cell_voltage": 4.2,
"empty_cell_voltage": 3.2,
"voltage_gain": 1.0,
"voltage_offset": 0.0,
"current_gain": 1.0,
"current_offset": 0.0
}
r = requests.post(f"{BASE_URL}/api/bms/advanced-config", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
6. Calibration tension et courant #
Le plugin propose deux routes dédiées :
/api/bms/calibration/voltage/api/bms/calibration/current
La calibration tension calcule un nouveau gain à partir d’une tension de référence. La calibration courant fait de même pour le courant, avec contrôle sur la validité de la mesure. Une route de remise à zéro est également disponible. :contentReference[oaicite:10]{index=10} :contentReference[oaicite:11]{index=11}
Exemple Python – calibration tension #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"reference_voltage": 15.92
}
r = requests.post(f"{BASE_URL}/api/bms/calibration/voltage", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
Exemple Python – calibration courant #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"reference_current": -1.48
}
r = requests.post(f"{BASE_URL}/api/bms/calibration/current", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
Exemple Python – reset calibration #
import requests
BASE_URL = "http://127.0.0.1:5000"
r = requests.post(f"{BASE_URL}/api/bms/calibration/reset", json={}, timeout=5)
r.raise_for_status()
print(r.json())
7. Lecture directe de registres #
La route /api/bms/register/read permet de lire un registre au format
byte, word ou block. Le code gère aussi
la conversion signée pour les mots 16 bits. :contentReference[oaicite:12]{index=12}
Exemple Python – lecture de la tension (0x09) #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"register": "0x09",
"mode": "word",
"signed": False
}
r = requests.post(f"{BASE_URL}/api/bms/register/read", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
Exemple Python – lecture du courant (0x0A signé) #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"register": "0x0A",
"mode": "word",
"signed": True
}
r = requests.post(f"{BASE_URL}/api/bms/register/read", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
Exemple Python – lecture bloc fabricant #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"register": "0x20",
"mode": "block",
"length": 20
}
r = requests.post(f"{BASE_URL}/api/bms/register/read", json=payload, timeout=5)
r.raise_for_status()
print(r.json())
8. Écriture de registres #
L’écriture est protégée par le code. Le mode avancé doit être activé, et
confirm_write=true est requis. Certains registres sont protégés en écriture par défaut,
notamment 0x00, 0x3E et 0x3F. Forcer ces écritures nécessite
force_unsafe=true. :contentReference[oaicite:13]{index=13} :contentReference[oaicite:14]{index=14}
Exemple Python – écriture d’un registre non protégé #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"register": "0x17",
"mode": "word",
"value": 12,
"confirm_write": True
}
r = requests.post(f"{BASE_URL}/api/bms/register/write", json=payload, timeout=5)
print(r.status_code, r.json())
9. Profils de lecture #
Le plugin définit déjà des profils par défaut, dont :
- sbs_monitoring pour les registres SBS principaux,
- manufacturer_strings pour les chaînes fabricant.
Il est aussi possible d’ajouter des profils personnalisés et de les appliquer en lecture ou écriture. :contentReference[oaicite:15]{index=15} :contentReference[oaicite:16]{index=16}
Exemple Python – lister les profils #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/register/profiles", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – appliquer le profil sbs_monitoring #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
payload = {
"profile": "sbs_monitoring",
"write_mode": False
}
r = requests.post(f"{BASE_URL}/api/bms/register/profile/apply", json=payload, timeout=10)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
10. Routes “studio” pour l’exploration avancée #
Le plugin expose un ensemble de routes proches d’un usage type “BQStudio” :
| Route | Usage |
|---|---|
/api/bms/studio/info |
Informations device et mode de sécurité |
/api/bms/studio/sbs |
Lecture de tous les registres SBS + cellules |
/api/bms/studio/cells |
Lecture des tensions cellules |
/api/bms/studio/status |
Lecture des flags safety / PF / operation / charging / gauging |
/api/bms/studio/mac_commands |
Liste des commandes MAC disponibles |
/api/bms/studio/mac |
Envoi d’une commande MAC |
/api/bms/studio/df_classes |
Liste des classes Data Flash |
/api/bms/studio/df_search |
Recherche par nom ou adresse |
/api/bms/studio/df_read |
Lecture d’une classe Data Flash |
/api/bms/studio/df_write |
Écriture Data Flash |
/api/bms/studio/security |
Seal / Unseal / Full Access |
Ces routes sont bien présentes dans le plugin et couvrent les fonctions avancées d’inspection et de configuration du BMS. :contentReference[oaicite:17]{index=17} :contentReference[oaicite:18]{index=18} :contentReference[oaicite:19]{index=19}
Exemple Python – lecture infos device #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/studio/info", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – lecture des cellules #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/studio/cells", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – lecture des statuts #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/studio/status", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – liste des commandes MAC #
import requests
import json
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/studio/mac_commands", timeout=5)
r.raise_for_status()
print(json.dumps(r.json(), indent=2, ensure_ascii=False))
Exemple Python – envoi d’une commande MAC #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"command": "0x0001",
"confirm": False
}
r = requests.post(f"{BASE_URL}/api/bms/studio/mac", json=payload, timeout=5)
print(r.status_code, r.json())
Le code impose explicitement une confirmation pour les commandes MAC considérées comme dangereuses. :contentReference[oaicite:20]{index=20}
11. Gestion sécurité #
Le plugin permet de lire le mode de sécurité courant, puis d’envoyer des actions seal, unseal ou full_access. Les clés sont passées dans la requête JSON. :contentReference[oaicite:21]{index=21}
Exemple Python – lecture du mode de sécurité #
import requests
BASE_URL = "http://127.0.0.1:5000"
r = requests.get(f"{BASE_URL}/api/bms/studio/security", timeout=5)
r.raise_for_status()
print(r.json())
Exemple Python – unseal #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"action": "unseal",
"key1": "0x0414",
"key2": "0x3672"
}
r = requests.post(f"{BASE_URL}/api/bms/studio/security", json=payload, timeout=5)
print(r.status_code, r.json())
Exemple Python – seal #
import requests
BASE_URL = "http://127.0.0.1:5000"
payload = {
"action": "seal"
}
r = requests.post(f"{BASE_URL}/api/bms/studio/security", json=payload, timeout=5)
print(r.status_code, r.json())
12. Auto-shutdown batterie faible #
Le code contient une logique optionnelle d’arrêt automatique si la batterie devient critique. Le déclenchement peut se faire sur tension basse ou SOC bas. En cas de déclenchement, l’évènement est journalisé et l’arrêt est lancé après un délai de 5 secondes. Les seuils par défaut sont 12.0 V et 10 %. :contentReference[oaicite:22]{index=22} :contentReference[oaicite:23]{index=23}
13. Exemple minimal de script de supervision #
import time
import requests
BASE_URL = "http://127.0.0.1:5000"
def read_bms():
r = requests.get(f"{BASE_URL}/api/bms", timeout=5)
r.raise_for_status()
return r.json()
while True:
try:
data = read_bms()
print(
f"SOC={data.get('soc')}% | "
f"V={data.get('voltage')}V | "
f"I={data.get('current')}A | "
f"T={data.get('temperature')}°C | "
f"connected={data.get('connected')}"
)
except Exception as e:
print("Erreur BMS :", e)
time.sleep(2)
14. Points d’attention #
- Valider d’abord le bus avec
/api/bms/diagavant d’utiliser les routes avancées. - Réserver l’écriture registre, MAC et Data Flash aux opérations maîtrisées.
- Activer le mode avancé uniquement pour les opérations de maintenance.
- Ne pas confondre valeur brute SMBus et valeur interprétée côté application.
- En cas de doute, commencer par les routes lecture seule :
/api/bms,/api/bms/diag,/api/bms/studio/info,/api/bms/studio/cells.
15. Résumé des routes utiles #
| Catégorie | Routes principales |
|---|---|
| Monitoring | /api/bms, /api/bms/diag |
| Configuration | /api/bms/advanced-config |
| Calibration | /api/bms/calibration/voltage, /api/bms/calibration/current, /api/bms/calibration/reset |
| Registres | /api/bms/register/read, /api/bms/register/write, /api/bms/register/profiles |
| Studio | /api/bms/studio/info, /api/bms/studio/sbs, /api/bms/studio/cells, /api/bms/studio/status |
| Sécurité | /api/bms/studio/security, /api/bms/studio/mac |
Documentation basée sur l’implémentation du plugin Python fourni. :contentReference[oaicite:24]{index=24}
