daelon-docs/docs/LiquidCore15/telemetry-interface.md
Andreas Johannsen 2f1b63aeb5 docs: write LiquidCore15 telemetry interface reference
Replaces the stale JSON error with accurate documentation derived
from telemetry.h / telemetry.c — frame layout, payload field table,
FSM/fault enums, UART/UDP transmission details, and integration checklist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 16:06:42 +02:00

92 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Telemetry Interface
The LiquidCore15 firmware streams a continuous binary telemetry frame over **UART** and **UDP** at **100 Hz**, giving a host controller or operator GUI a real-time view of all monitored control variables.
---
## Frame Format
Every frame is exactly **63 bytes**:
| Byte(s) | Field | Value |
|---------|-------|-------|
| `[0]` | Sync low | `0x55` |
| `[1]` | Sync high | `0xAA` |
| `[2]` | Length | `0x3A` (58 decimal = payload size) |
| `[3..60]` | Payload | `TelemetryPayload_t` — 58 bytes, packed |
| `[61]` | CRC low | CRC16-CCITT low byte |
| `[62]` | CRC high | CRC16-CCITT high byte |
Sync bytes form the little-endian word `0xA55A` — check both bytes before decoding.
**CRC:** CRC16-CCITT (polynomial `0x1021`, init `0xFFFF`) computed over bytes `[2..60]` (59 bytes: length byte + full payload). No output inversion.
---
## Payload Fields
`TelemetryPayload_t` is `__attribute__((packed))`, 58 bytes. Field order is stable — the host decoder assumes this exact layout.
| Offset | Type | Field | Description |
|--------|------|-------|-------------|
| 0 | `float` | `Vdc` | DC bus voltage (V) |
| 4 | `float` | `Ia` | Phase A current (A) |
| 8 | `float` | `Ib` | Phase B current (A) |
| 12 | `float` | `Ic` | Phase C current (A) |
| 16 | `float` | `Va` | Phase A grid voltage (V) |
| 20 | `float` | `Vb` | Phase B grid voltage (V) |
| 24 | `float` | `Vc` | Phase C grid voltage (V) |
| 28 | `float` | `Id` | d-axis current feedback (A) |
| 32 | `float` | `Iq` | q-axis current feedback (A) |
| 36 | `float` | `Id_ref` | d-axis current reference (A) |
| 40 | `float` | `Iq_ref` | q-axis current reference (A) |
| 44 | `float` | `theta` | PLL grid angle (rad, 0 .. 2π) |
| 48 | `float` | `omega` | PLL angular frequency (rad/s) |
| 52 | `uint8_t` | `pll_locked` | `1` = locked, `0` = searching |
| 53 | `uint8_t` | `mode` | FSM state (see below) |
| 54 | `uint32_t` | `fault_flags` | Active fault bitmask (see below) |
All floats are IEEE 754 single-precision, little-endian (Cortex-M native byte order).
### `mode` — FSM State
| Value | State |
|-------|-------|
| `0x00` | `FSM_INIT` |
| `0x01` | `READY` |
| `0x02` | `RUNNING` |
| `0x03` | `FAULT` |
### `fault_flags` — Fault Bitmask
| Bit | Fault |
|-----|-------|
| 0 | Over-voltage (OV) |
| 1 | Under-voltage (UV) |
| 2 | Over-current (OC) |
| 3 | Frequency high |
| 4 | Frequency low |
---
## Transmission
**UART:** USART3 (`hcom_uart[COM1]`), 115200 baud, GPDMA1 Channel 0 (DMA mode).
- Cadence: every 160th control tick → **100 Hz**.
- If UART DMA is busy when a frame is ready, the frame is **dropped silently**. At 100 Hz × 63 bytes = 6 300 bytes/s versus 11 520 bytes/s line capacity, collision probability is low.
- Double-buffering: two 63-byte buffers swap between fill and DMA-in-flight roles.
**UDP:** The same 63-byte frame is forwarded to `eth_send_telem()` (implemented in `eth.c`) on every tick, independent of UART DMA state.
---
## Integration Checklist
- [ ] Open a 115200-baud serial connection to USART3 (or listen on the UDP socket).
- [ ] Scan the byte stream for the two-byte sync sequence `0x55 0xAA`.
- [ ] Read the next 61 bytes (length + payload + CRC).
- [ ] Verify CRC16-CCITT over bytes `[2..60]`; discard frame on mismatch.
- [ ] Deserialize `TelemetryPayload_t` in the field order above (little-endian floats).
- [ ] Check `pll_locked` before using `theta` / `omega` for phase-sensitive calculations.
- [ ] Check `fault_flags != 0` and handle `mode == 0x03` (FAULT) before commanding.