View Categories

BMS LC30 Power Board – exemple API

9 min read

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/bms pour les données complètes,
  • une API /api/bms/diag pour 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 :

  1. vérifier que la carte est alimentée correctement,
  2. vérifier que le signal d’activation BMS est fonctionnel,
  3. vérifier le câblage SDA / SCL,
  4. vérifier que le bus I²C isolé côté système est bien accessible depuis l’hôte,
  5. 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())
Attention : ne pas utiliser l’écriture registre ou Data Flash sans connaître précisément l’effet attendu sur le BMS et sans disposer d’une procédure de récupération.

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/diag avant 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}

Powered by BetterDocs

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut