Files
Francesco Zanin db6d5aca63 Doc: README allineati (no MSP/BOOT, modo MAVLINK, my_config gitignored)
README top + 02_telemetry_bridge: cambio modo via comando seriale (non BOOT),
4o modo = MAVLINK (non piu' MSP), nota su terseCRSF/mavlink vendorizzate e su
my_config.h in .gitignore (+ my_config.h.example da copiare).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:55:41 +02:00

114 lines
5.4 KiB
Markdown

# Telemetry Bridge — firmware unico multi-modo
ESP32 DevKit che riceve la telemetria CRSF dal **TX Backpack ELRS** via ESP-NOW e
la espone in **4 modalità selezionabili a runtime** (comando seriale, scelta
salvata in NVS). Un solo firmware da compilare; nessuna ricompilazione per
cambiare uso.
## Modalità
| # | Nome | USB | Cosa fa |
|---|-----------|------------|------------------------------------------------------------------|
| 0 | HUMAN | testo | Dashboard leggibile (GPS, batteria, assetto, link) a 1 Hz |
| 1 | CRSF_DUMP | testo | Dump esadecimale grezzo di ogni frame CRSF (debug/reverse) |
| 2 | LTM | binario | Traduce CRSF → **LTM v2** per **mwptools** (monitoraggio volo) |
| 3 | MAVLINK | binario | Traduce CRSF → **MAVLink v2** per mwptools (include corrente in A)|
## Selezione della modalità (comando seriale)
La scelta è persistente (NVS). Dal **monitor seriale @115200** digita:
- `!` seguito da `0`..`3` → seleziona quel modo direttamente;
- `!` seguito da `m` → passa al modo successivo (ciclico).
La board salva la scelta in NVS e si riavvia nel nuovo modo. Senza comando,
riparte sull'ultimo modo salvato.
> **Perché un comando seriale e non il pulsante BOOT.** BOOT è GPIO0, *strapping
> pin* del bootloader: tenerlo premuto al reset manda l'ESP32 in download mode
> invece di eseguire il firmware, quindi il cambio modo via BOOT non era
> affidabile. Il prefisso `!` è obbligatorio perché mwp in modo INAV interroga via
> MSP (byte `$M<...`): senza prefisso la `M` verrebbe interpretata come comando e
> farebbe cambiare modo da sola.
## Uso con mwptools
Entrambi i modi LTM e MAVLink sono **downlink unidirezionale** — perfetti per il
path downlink-only del backpack. In mwp: *Connect***porta USB** dell'ESP32 →
protocollo **INAV**, baud **115200**.
- **Modo LTM (#2):** posizione, assetto, batteria (V, mAh). LTM in INAV è opera di
Jonathan Hudson, lo stesso autore di mwp.
- **Modo MAVLINK (#3):** come LTM **più la corrente istantanea in Ampere**
(`SYS_STATUS`/`BATTERY_STATUS`), RSSI (`RADIO_STATUS`) e % batteria — campi che
LTM non trasporta. Messaggi emessi: HEARTBEAT, SYS_STATUS, GPS_RAW_INT,
ATTITUDE, VFR_HUD, BATTERY_STATUS, RADIO_STATUS.
> **Problema noto (aperto):** mwp mostra la corrente come ~0.12 A invece di 1.2 A
> (fattore ÷10). La codifica del firmware è spec-corretta (`current_battery` in cA:
> 120 cA = 1.2 A, verificato a byte). Sembra un'interpretazione non standard lato
> mwp; da indagare.
> Cosa **non** fa: missioni, lettura/scrittura parametri, qualunque cosa MSP
> request/response (bidirezionale). Vedi i limiti qui sotto.
## Limiti uplink (importante, verificato)
Il backpack ELRS via ESP-NOW è **downlink-only by design**. I maintainer ELRS
(discussion #3510, gen 2026) confermano che il backpack **non** inietta pacchetti
arbitrari nell'uplink OTA, e che l'uplink verso l'FC è possibile **solo** dal
flusso CRSF dell'handset (radio → TX → OTA → RX → FC), con telemetria attiva.
Conseguenza: **MSP bidirezionale verso l'FC attraverso il backpack non è
realizzabile** con ELRS stock (per questo il vecchio modo MSP sperimentale è stato
rimosso). Per vero MSP bidirezionale con mwp serve un link seriale trasparente
dedicato (coppia SiK/3DR 433-915 MHz, oppure mLRS con MSPX): architettura separata,
non questo ESP32 sul backpack.
## Struttura del codice
```
platformio.ini
src/
main.cpp # dispatcher: comando seriale '!' + NVS, loop sui modi
my_config.h # UID (bind phrase), in .gitignore <-- DA COMPILARE
my_config.h.example # modello da copiare in my_config.h
modes.h # interfaccia Mode {begin,onFrame,tick}
mode_human.cpp # modo 0
mode_crsfdump.cpp # modo 1
mode_ltm.cpp # modo 2 (usa lib/Ltm)
mode_mavlink.cpp # modo 3 (usa lib/mavlink)
lib/
EspNowCrsf/ # init ESP-NOW + ring buffer dei frame CRSF (condiviso)
Ltm/ # encoder LTM v2 (layout fedele a inav/ltm.c)
terseCRSF/ # parser CRSF VENDORIZZATO e patchato (vedi sotto)
mavlink/ # libreria MAVLink ufficiale (c_library_v2, vendorizzata)
```
Aggiungere un nuovo modo = nuovo `mode_xxx.cpp` che esporta un `Mode`, più una
riga nell'array `MODES[]` in `main.cpp`.
### Librerie vendorizzate
`terseCRSF` e `mavlink` sono copiate in `lib/` (non più via `lib_deps`) così le
patch locali sono permanenti e versionate:
- **terseCRSF** — patch documentate in cima a `lib/terseCRSF/src/terseCRSF.h`:
(1) disattivati i `#define SHOW_*` di debug, che stampavano testo dentro lo
stream binario LTM/MAVLink corrompendolo; (2) corretto `bat_fuel_drawn`
(leggeva 4 byte includendo il byte percent → mAh consumati errati).
- **mavlink** — dialetti `minimal`+`common`+`standard` di `c_library_v2`; include
base `-I lib/mavlink` in `platformio.ini` (si include come `<common/mavlink.h>`).
## Build / upload
Apri la cartella in VSCode/PlatformIO, **Build → Upload → Monitor** (115200).
Le librerie sono già in `lib/` (la prima build scarica solo il core 2.0.17).
Copia `src/my_config.h.example` in `src/my_config.h` e mettici il tuo **UID**
(il file reale è in `.gitignore` perché contiene un dato derivato dalla bind
phrase).
> Upload: questa board entra in download mode solo tenendo **BOOT premuto** durante
> il `Connecting...` di esptool (poi rilascia). Non tenerlo premuto fino al reset
> finale.