Logiciel embarque LilyGO T-A7670G : gestion BLE double (OBD + SUNKENET), PIDs BMW M57 standard et UDS proprietaires, communication 4G, deep sleep.
PIDs standard OBD-II et PIDs proprietaires BMW via protocole UDS.
| PID | Donnee | Formule | Unite | Frequence |
|---|---|---|---|---|
010C | Regime moteur (RPM) | (A*256 + B) / 4 | tr/min | 2 Hz |
010D | Vitesse vehicule | A | km/h | 2 Hz |
0104 | Charge moteur | A * 100 / 255 | % | 2 Hz |
0105 | Temperature liquide refroidissement | A - 40 | C | 0.1 Hz |
015C | Temperature huile moteur | A - 40 | C | 0.1 Hz |
010B | Pression collecteur admission | A | kPa | 0.5 Hz |
012F | Niveau de carburant | A * 100 / 255 | % | 0.1 Hz |
0142 | Tension module controle | (A*256 + B) / 1000 | V | 0.1 Hz |
Les PIDs proprietaires BMW necessitent des requetes UDS (Unified Diagnostic Services) avec des headers CAN specifiques. L'OBDLink CX supporte ces requetes via des commandes AT configurees pour le mode etendu.
| Requete UDS | Donnee | Description | Unite | Frequence |
|---|---|---|---|---|
22 1233 | Pression common rail | Pression dans la rampe d'injection diesel M57. Valeur nominale : 250-1600 bar. | bar | 0.5 Hz |
22 1237 | Pression turbo (boost) | Pression de suralimentation du turbocompresseur. Le M57 utilise un turbo a geometrie variable. | bar | 0.5 Hz |
22 123B | Charge de suie DPF | Niveau de charge en suie du filtre a particules diesel. Declenchement regeneration a ~45g. | g | 0.05 Hz |
22 1241 | Temperature DPF | Temperature du filtre a particules. En regeneration : 500-600C. Normal : 200-300C. | C | 0.1 Hz |
22 124B | Debit d'air massique (MAF) | Debit massique d'air admis. Indicateur de performance moteur et calibration turbo. | kg/h | 0.5 Hz |
22 1250 | Position vanne EGR | Position de la vanne de recirculation des gaz d'echappement. 0% ferme, 100% ouvert. | % | 0.1 Hz |
22 1255 | Pression differentielle DPF | Difference de pression avant/apres DPF. Indique le niveau de colmatage. | mbar | 0.1 Hz |
Initialisation UDS : Avant d'envoyer des requetes proprietaires BMW, il faut ouvrir une session de diagnostic etendue via la commande UDS 10 03 (Extended Diagnostic Session). Sans cela, l'ECU rejettera les requetes avec un code NRC 0x7F.
Architecture non-bloquante basee sur millis().
Le firmware fonctionne sur une boucle non-bloquante avec trois niveaux de frequence d'acquisition :
| Niveau | Frequence | Donnees capturees | Action locale |
|---|---|---|---|
| Haute frequence | 2 Hz (500ms) | RPM, vitesse, charge moteur | Mise a jour couleur SUNKENET (bleu < 2500 RPM, orange 2500-4000, rouge > 4000) + envoi vers ecran local |
| Frequence moyenne | 0.5 Hz (2s) | Pression common rail, pression turbo, debit air (MAF) | PIDs BMW UDS proprietaires |
| Basse frequence | 0.1 Hz (10s) | Temperature huile, carburant, tension batterie, suie DPF, temperature DPF, position EGR | Monitoring et diagnostics |
En parallele, un upload cloud s'effectue toutes les 5 secondes, compilant les dernieres valeurs capteurs avec la position GPS en un payload JSON envoye via HTTPS POST a l'API Symfony.
Priorite batterie : La surveillance de la tension batterie est prioritaire sur toute autre operation. Si Vbatt < 11.8V, le firmware envoie un SMS d'alerte, coupe le modem et entre en deep sleep permanent.
Constantes et seuils du systeme — adaptes au BMW M57.
| Categorie | Parametre | Valeur | Description |
|---|---|---|---|
| Alimentation | Vbatt critique | 11.8V | Declenchement deep sleep permanent |
| Alimentation | Vbatt warning | 12.2V | Alerte SMS preventive |
| Moteur M57 | RPM seuil haut | 4000 tr/min | Fibre SUNKENET rouge (redline M57 ~5000) |
| Moteur M57 | RPM seuil moyen | 2500 tr/min | Fibre SUNKENET orange |
| Moteur M57 | Temperature huile warning | 120C | Temperature huile M57 elevated |
| Moteur M57 | Temperature huile critique | 130C | Temperature huile M57 dangereuse |
| Moteur M57 | Suie DPF warning | 40g | Regeneration bientot necessaire |
| Moteur M57 | Pression common rail min | 200 bar | Pression minimum acceptable |
| Fibre SUNKENET | Couleurs | Bleu, orange, rouge, vert, blanc, violet | Codes couleur RGBW predefinis |
| Timings | Upload cloud | 5000ms | Frequence d'envoi vers l'API Symfony |
Controle du kit fibre optique SUNKENET 20W RGBW Meteor via BLE.
Le controleur BLE du SUNKENET utilise un service BLE generique (FFE0) avec une characteristique de controle (FFE1). La LilyGO se connecte au controleur en tant que second peripherique BLE (en parallele de l'OBDLink CX).
| Fonction | Description |
|---|---|
| Changement couleur | Envoi des valeurs RGBW (rouge, vert, bleu, blanc) au controleur. Permet toute couleur du spectre visible. |
| Mode d'animation | Statique, pulsation, ou meteor. Vitesse d'animation configurable. |
| Luminosite | Reglage de 0 a 255 de l'intensite lumineuse globale. |
UUIDs BLE : Les UUIDs du service et de la characteristique du controleur SUNKENET (FFE0/FFE1) sont des valeurs typiques pour les controleurs LED BLE generiques. A confirmer par un scan BLE du controleur reel installe dans la BMW E90.
Connexion BLE a l'OBDLink CX et lecture des PIDs standard + BMW UDS.
Recherche d'un peripherique advertisant le service FFF0 (OBDLink CX).
Connexion BLE, decouverte du service FFF0, recuperation des characteristiques TX (FFF1) et RX (FFF2).
Envoi des commandes AT d'initialisation : ATZ (reset), ATE0 (echo off), ATSP6 (protocole CAN 500kbps).
Configuration du header CAN BMW (AT SH 7E0) et ouverture de la session diagnostic etendue (10 03).
Envoi des commandes PID standard (ex: "010C\r" pour RPM) et UDS BMW (ex: "22 12 33\r" pour la pression common rail).
Surveillance de la tension batterie BMW E90 et logique de survie.
Le module lit en permanence la tension de la batterie BMW via un pont diviseur resistif sur le GPIO 34. Un ADC 12 bits convertit la tension reduite (max 3.3V) puis la formule de calibration reconstitue la tension reelle (ratio 4.03).
| Seuil | Tension | Action |
|---|---|---|
| Normal | > 12.2V | Fonctionnement normal |
| Warning | < 12.2V | Envoi SMS d'alerte preventive |
| Critique | < 11.8V | SMS d'alerte, coupure modem, deep sleep permanent |
| Reveil | — | Uniquement par GPIO 33 (SMS entrant) ou reset physique (demarrage vehicule) |
Communication avec le modem SIMCom A7670 via commandes AT. SIM FREE 100GB/mois.
| Commande | Action | Reponse attendue |
|---|---|---|
AT | Test de presence | OK |
AT+CPIN? | Etat carte SIM FREE | +CPIN: READY |
AT+CSQ | Qualite signal | +CSQ: 15,0 (0-31) |
AT+CGPS=1 | Activer GPS | OK |
AT+CGPSINFO | Position GPS | +CGPSINFO: lat,N,lon,E... |
AT+CMGS="num" | Envoyer SMS | +CMGS: id |
AT+HTTPINIT | Init HTTP | OK |
AT+HTTPPARA="URL","..." | Set URL | OK |
AT+HTTPACTION=1 | POST HTTP | +HTTPACTION: 1,200,... |
Liaison ultra-rapide vers l'ecran Sunton (optionnel, nice-to-have).
Le protocole ESP-NOW d'Espressif permet une communication directe entre la LilyGO et l'ecran Sunton ESP32-S3 sans routeur WiFi. Le module envoie un paquet de telemetrie contenant les valeurs essentielles : RPM, vitesse, charge moteur, temperature huile, pression turbo, pression common rail, suie DPF, tension batterie et couleur fibre actuelle.
Performance : ESP-NOW fonctionne sans routeur WiFi, avec une latence typique de < 5ms. Ideal pour l'affichage temps reel embarque des donnees M57.
Update du firmware a distance via le modem 4G.
Precaution : Toujours verifier Vbatt > 12.5V avant de lancer un OTA. Utiliser une partition OTA double (app0/app1) pour pouvoir rollback en cas d'echec.
Le module interroge GET /api/firmware/latest a chaque boot. Compare avec la version locale.
Telechargement du binaire par chunks via HTTPS (SIM FREE). Ecriture progressive sur la partition OTA inactive.
Verification du hash SHA256 du binaire. Si OK, bascule sur la nouvelle partition et reboot.
Si le nouveau firmware ne repond pas dans les 30s apres reboot, rollback automatique vers l'ancienne version.
Protection des secrets et des communications.
Le X-Device-Token et les credentials sont stockes dans la partition NVS chiffree de l'ESP32. Jamais en clair dans le code. Hash bcrypt valide cote Symfony.
Le certificat SSL du serveur CarTrack est verifie par empreinte SHA256. Protection contre les attaques MITM meme sans CA chain complete.
HTTPSTimer watchdog hardware a 30s. Si le firmware freeze (crash BLE, modem bloque), reboot automatique propre. Les donnees non envoyees sont bufferisees en NVS.
FiabiliteArborescence du projet firmware avec descriptions des fichiers.
firmware/
├── platformio.ini # Configuration PlatformIO (board, libs, flags)
├── src/
│ ├── main.cpp # Point d'entree — setup() + loop()
│ ├── config.h # Constantes, seuils, pins, URLs
│ ├── obd_manager.h/.cpp # Connexion BLE OBDLink CX + lecture PIDs
│ ├── fiber_manager.h/.cpp # Connexion BLE SUNKENET + controle couleur
│ ├── modem_manager.h/.cpp # Modem A7670 — AT commands, HTTP, SMS, GPS
│ ├── power_manager.h/.cpp # Surveillance Vbatt, deep sleep, survie
│ ├── telemetry.h/.cpp # Compilation payload JSON + upload cloud
│ ├── ota_manager.h/.cpp # Mise a jour OTA via 4G
│ └── espnow_sender.h/.cpp # Envoi telemetrie vers ecran Sunton (optionnel)
├── data/
│ ├── ca_cert.pem # Certificat CA du serveur CarTrack
│ └── nvs_keys.csv # Template cles NVS (token, wifi, etc.)
├── test/
│ ├── test_pid_parser.cpp # Tests unitaires parsing PIDs OBD
│ ├── test_power_logic.cpp # Tests logique de survie batterie
│ └── test_telemetry_json.cpp # Tests compilation payload JSON
├── lib/
│ └── README # Librairies locales (si necessaire)
└── include/
└── README # Headers partages
Commandes PlatformIO pour compiler et flasher le firmware sur la LilyGO T-A7670G.
| Commande | Description |
|---|---|
pio run | Compile le firmware (verifie la syntaxe, les dependances et genere le binaire) |
pio run -t upload | Compile et flash le firmware sur la carte connectee via USB |
pio device monitor -b 115200 | Ouvre le moniteur serie a 115200 baud (debug output) |
pio run -t uploadfs | Upload le contenu du dossier data/ vers la partition SPIFFS (certificats, config) |
pio test | Lance les tests unitaires (natifs sur la machine de dev, pas sur la carte) |
pio run -t clean | Nettoie les fichiers de build |
pio lib list | Liste les librairies installees et leurs versions |
pio lib install "NimBLE-Arduino" | Installe une librairie (ex: NimBLE pour le BLE) |
platformio.ini : La configuration cible la carte lilygo-t-a7670g avec le framework Arduino. Les flags de compilation incluent -DBOARD_HAS_PSRAM pour activer la PSRAM et -DCONFIG_BT_NIMBLE_MAX_CONNECTIONS=2 pour deux connexions BLE simultanees.
Details d'implementation des requetes OBD standard et UDS proprietaires BMW.
Avant de pouvoir lire les PIDs BMW proprietaires, le firmware doit executer la sequence suivante sur l'OBDLink CX :
// 1. Reset ELM327
sendATCommand("ATZ\r"); // Reset complet
waitForResponse("ELM327", 3000);
// 2. Configuration de base
sendATCommand("ATE0\r"); // Echo OFF
sendATCommand("ATL0\r"); // Linefeeds OFF
sendATCommand("ATS0\r"); // Spaces OFF (reponses compactes)
sendATCommand("ATH1\r"); // Headers ON (pour voir les CAN IDs)
sendATCommand("ATSP6\r"); // Protocole ISO 15765-4 CAN 500kbps
// 3. Configuration header CAN BMW
sendATCommand("AT SH 7E0\r"); // Header CAN ECU BMW (requete)
// Reponses viendront avec header 7E8 (ECU response)
// 4. Ouverture session diagnostic etendue
sendATCommand("10 03\r"); // UDS: Extended Diagnostic Session
// Reponse attendue: 50 03 (positive response)
// Si 7F 10 12: session non supportee — verifier le header CAN
// 5. Maintien session (toutes les 2s)
// La session UDS expire apres 5s sans activite
// Envoyer periodiquement: "3E 00\r" (TesterPresent)
Les reponses UDS BMW suivent le format 62 XX XX DD DD ou 62 est le positive response code de ReadDataByIdentifier, XX XX est le DID demande, et DD DD sont les octets de donnees.
// Exemple: Pression common rail (DID 1233)
// Requete: "22 1233\r"
// Reponse: "62 1233 05 DC"
// Parsing: pressure = (0x05 * 256 + 0xDC) = 1500 bar
//
// Exemple: Charge suie DPF (DID 123B)
// Requete: "22 123B\r"
// Reponse: "62 123B 00 1E"
// Parsing: soot = (0x00 * 256 + 0x1E) / 10 = 3.0 g
//
// Chaque DID a sa propre formule de conversion.
// Les formules sont definies dans config.h sous forme de macros.
TesterPresent : La session UDS etendue expire apres 5 secondes d'inactivite. Le firmware doit envoyer 3E 00 (TesterPresent) au moins toutes les 2 secondes pour maintenir la session ouverte. Si la session expire, les requetes 22 XX XX retourneront un NRC 7F 22 31 (requestOutOfRange).
Format des commandes BLE envoyees au controleur fibre optique SUNKENET.
Les commandes sont envoyees via write without response sur la characteristique FFE1 du service FFE0. Le format est un tableau d'octets :
| Commande | Format (hex) | Description |
|---|---|---|
| Couleur statique | 7E 07 05 03 RR GG BB WW EF | RR=rouge, GG=vert, BB=bleu, WW=blanc (0x00-0xFF chacun) |
| Luminosite | 7E 04 01 LL EF | LL = luminosite (0x00 = eteint, 0xFF = maximum) |
| Mode statique | 7E 04 03 01 EF | Couleur fixe (pas d'animation) |
| Mode pulsation | 7E 04 03 02 EF | Pulsation lente (fade in/out) |
| Mode meteor | 7E 04 03 03 EF | Effet meteor (fibres qui s'allument en sequence) |
| Power OFF | 7E 04 04 00 EF | Eteindre la source lumineuse |
| Power ON | 7E 04 04 01 EF | Allumer la source lumineuse |
| Etat | Couleur | RGBW | Condition |
|---|---|---|---|
| Repos | Bleu | 00 00 FF 00 | RPM < 2500 |
| Medium | Orange | FF 80 00 00 | RPM 2500-4000 |
| High | Rouge | FF 00 00 00 | RPM > 4000 |
| Jarvis action | Violet | 80 00 FF 00 | Jarvis execute une action |
| Alerte batterie | Blanc clignotant | 00 00 00 FF | Vbatt < 12.2V (mode pulsation) |
| DPF regen | Vert | 00 FF 00 00 | Regeneration DPF en cours |
A confirmer : Le format des commandes ci-dessus est base sur le reverse-engineering de controleurs LED BLE generiques similaires. Les octets de header (7E) et de footer (EF) ainsi que les opcodes peuvent varier. Un sniffing BLE avec nRF Connect sera necessaire pour confirmer le protocole exact du controleur SUNKENET installe.
Implementation detaillee de la mise a jour Over-The-Air via le modem 4G.
# Partition Table (partitions.csv)
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x5000 # NVS chiffre (token, config)
otadata, data, ota, 0xe000, 0x2000 # Metadata OTA (partition active)
app0, app, ota_0, 0x10000, 0x1E0000 # Firmware slot A
app1, app, ota_1, 0x1F0000,0x1E0000 # Firmware slot B
spiffs, data, spiffs, 0x3D0000,0x30000 # Certificats, fichiers config
GET /api/firmware/latest retourne {"version": "1.2.0", "url": "https://..../firmware-1.2.0.bin", "sha256": "abc123...", "size": 1245184}. Le firmware compare avec FIRMWARE_VERSION dans config.h.
Verification Vbatt > 12.5V. Si insuffisant, l'OTA est reportee au prochain boot. Un OTA interrompu par coupure de courant peut bricker le module (meme avec dual partition, le flash partiel est corrompu).
Le modem A7670 telecharge le binaire par morceaux de 4096 octets via HTTPS. Chaque chunk est ecrit sur la partition OTA inactive via esp_ota_write(). Progression loguee en serie.
Apres ecriture complete, calcul du hash SHA256 de la partition ecrite et comparaison avec le hash retourne par l'API. Si mismatch : abort, la partition active reste inchangee.
esp_ota_set_boot_partition() bascule la partition active. esp_restart() redemarrage. Le bootloader charge la nouvelle partition.
Le nouveau firmware doit appeler esp_ota_mark_app_valid() dans les 30 premieres secondes. Si le watchdog expire avant (crash, freeze), le bootloader rollback automatiquement vers l'ancienne partition.
Outils et techniques pour diagnostiquer les problemes firmware.
Le firmware emet des logs structures sur le port serie a 115200 baud. Format : [timestamp_ms] [MODULE] message.
[1234] [BOOT] CarTrack Firmware v1.0.0 — LilyGO T-A7670G
[1240] [POWER] Vbatt = 12.65V (OK)
[1890] [MODEM] AT OK — SIM READY — Signal: 18/31
[2100] [GPS] Fix acquired: 48.8566, 2.3522
[3200] [BLE] OBDLink CX connected (FFF0)
[3400] [OBD] ATZ OK — ELM327 v2.3
[3500] [OBD] UDS session opened (10 03 -> 50 03)
[4000] [BLE] SUNKENET connected (FFE0)
[4500] [LOOP] RPM=2800 Speed=95 OilTemp=98 Boost=1.2
[4500] [FIBER] Color -> ORANGE (RPM 2500-4000)
[5000] [UPLOAD] POST /api/telemetry -> 200 OK (312ms)
| Application | Plateforme | Usage |
|---|---|---|
| nRF Connect | Android / iOS | Scanner BLE, decouverte services, ecriture characteristiques. Outil de reference. |
| LightBlue | iOS / Mac | Scanner BLE simplifie. Bon pour les tests rapides de connexion. |
| Wireshark + nRF Sniffer | Desktop | Capture des paquets BLE bruts. Necessaire pour reverse-engineer le protocole SUNKENET. |
| Symptome | Cause probable | Solution |
|---|---|---|
| BLE OBDLink deconnecte apres 30s | Timeout BLE — pas d'activite | S'assurer que le firmware envoie des requetes PID regulierement (au moins toutes les 2s) |
UDS repond 7F 22 31 | Session diagnostic expiree | Verifier que 3E 00 (TesterPresent) est envoye toutes les 2s |
| Modem ne repond pas aux AT | Power Key non pulse | Pulse GPIO 4 pendant 1.5s pour allumer le modem A7670 |
| GPS pas de fix | Antenne obstruee (coffre metallique) | Placer l'antenne GPS pres de la lunette arriere ou utiliser une antenne externe |
| Reboots aleatoires | Parasites alimentation | Verifier les condensateurs de filtrage. Ajouter un condensateur 470uF supplementaire si necessaire. |
| SUNKENET ne change pas de couleur | Mauvais UUIDs BLE | Scanner le controleur avec nRF Connect pour verifier les UUIDs reels |