Data Format
Both the SD log and the UDP stream carry the same thing: the telemetry snapshot serialized to CSV. The serializer lives in telemetry_csv_line() in telemetry.c, and the matching column names are in telemetry_csv_header().
One source of truth
The header string and the line serializer are two separate hand-written lists in telemetry.c. Their column order must stay in lockstep. If you add, remove, or reorder a field, edit both, and re-check the format specifiers (%u, %.3f, %d, %s): a mismatch silently corrupts every downstream parser.
Message types
The same function produces three different lines depending on telemetry_msg_type_t. This lets the fast link send only the high-rate data while the slow link carries the bulky, slow-changing data.
| Type | Contents | Used by |
|---|---|---|
MSG_TYPE_FULL | Everything: fast block and slow block | SD logging |
MSG_TYPE_FAST | Timestamps + high-rate block (dynamics, powertrain, GPS, LVSOC) | UDP fast (20 Hz) |
MSG_TYPE_SLOW | Timestamps + slow block (BMS pack detail, flow/temps, dashboard) | UDP slow (5 Hz) |
Every line, regardless of type, begins with the timestamps:
time,time_unix,...time: a free-running counter read from TIM2 (__HAL_TIM_GET_COUNTER).time_unix: the RTC's Unix time, kept in sync from GPS (see GPS).
The FAST block
Present in FULL and FAST. After the timestamps it carries the last CAN ID, the SD filename, and then the high-rate signals grouped by source:
- Gateway front: wheel speeds, suspension travel, APPS, steering, R2D, software state
- Gateway rear: wheel speeds, suspension travel, brake, junction-box currents, SDC, software state
- ECU: inverter enables/percentages, state machines (main / R2D / control), UKF outputs, torque-vectoring outputs
- Left & right inverters (GI): PWM, voltage, current, RPM, temps, software state
- IMU: acceleration, angular velocity, Euler angles
- GPS: fix, sats, lat/lon/alt, speed, course, yaw
- LVSOC: battery voltage, current, SoC, peak current (10s), capacity, state of operation, time remaining, avg current (10s), OCV
The SLOW block
Present in FULL and SLOW. Mostly the full BMS picture plus a few extras:
- Flow sensor, coolant temps
- A subset of dashboard debug flags
- BMS: internal temp, the full DTC fault set, multi-purpose outputs, balancing/charge flags, pack voltages, SoC estimates, cell resistances, open-cell voltages, per-cell min/max voltages and IDs, currents, DOD/DCL, charger safety
can_programming
Wire framing (UDP)
The UDP sender prefixes each datagram with a single digit so the pit software can tell fast from slow lines apart on the same socket:
| Prefix | Payload |
|---|---|
1, | a FAST line |
2, | a SLOW line |
The SD log writes FULL lines with no prefix. See Networking and SD Logging.
Reading a line
Every line ends with \n. Split on commas, and map columns positionally against telemetry_csv_header(). Because the fast and slow blocks are concatenated for FULL, a full log line's columns are exactly [timestamps] + [fast block] + [slow block], in that order.
