Saltar a contenido
← Volver a OPRobots.org

Comunicaciones

Interfaces

Interfaz Periférico Velocidad Dirección Propósito
CRSF RX USART6 420 000 bps ELRS → MCU Canales RC + estadísticas de enlace
CRSF TX USART6 420 000 bps MCU → ELRS Telemetría a la emisora
Consola USART1 115 200 bps MCU → PC Salida de debug en tiempo real

USART6 opera en modo TX/RX bidireccional (half-duplex a nivel lógico, aunque el hardware soporta full-duplex). El protocolo CRSF es asimétrico: el receptor envía tramas RC y link stats, el MCU envía tramas de telemetría.


Protocolo CRSF (CrossFire Serial Protocol)

CRSF es el protocolo serie usado por los receptores ExpressLRS (ELRS) y TBS CrossFire. Opera sobre UART a 420 000 bps con tramas delimitadas por un byte de sincronización y protegidas por CRC-8.

Formato de Trama

[SYNC 0xC8][LEN][TYPE][PAYLOAD…][CRC-8 DVB-S2]
Campo Bytes Descripción
SYNC 1 Byte 0xC8, delimita el inicio de trama
LEN 1 Longitud de TYPE + PAYLOAD + CRC (rango 2–64)
TYPE 1 Identificador del tipo de trama
PAYLOAD N Datos, formato dependiente de TYPE
CRC 1 CRC-8 DVB-S2 sobre TYPE + PAYLOAD

El CRC-8 usa el polinomio 0xD5 (DVB-S2) calculado byte a byte en utils.c:3-17.

sequenceDiagram
    participant ELRS as ELRS Receiver
    participant MCU as STM32F401
    participant TX as Radio Transmitter

    loop Cada ~4 ms
        ELRS->>MCU: Frame 0x16 (RC channels, 22B payload)
        ELRS->>MCU: Frame 0x14 (Link stats, 10B payload)
    end

    loop Cada 50 ms (rate-limited)
        MCU->>ELRS: Frame 0x08 (Battery)
        MCU->>ELRS: Frame 0x1E (Attitude)
        MCU->>ELRS: Frame 0x21 (Flight mode)
    end

    ELRS->>TX: Telemetría vía radio

Recepción CRSF (RX)

Tipos de Trama Recibidos

TYPE Nombre Payload Descripción
0x16 RC Channels 22 bytes 16 canales × 11 bits, little-endian
0x14 Link Statistics 10 bytes RSSI, Link Quality, SNR, modo RF, potencia TX

Implementado en crsf_rx.c:65-79 con las funciones auxiliares parse_channels() y parse_stats().

Decodificación de Canales RC

Cada canal ocupa 11 bits en little-endian (rango 172–1811):

Valor Pulso equivalente
172 ~1000 µs (mínimo)
992 ~1500 µs (centro)
1811 ~2000 µs (máximo)

La extracción se realiza con máscaras y desplazamientos en crsf_rx.c:27-44. Los 16 canales se empaquetan en 22 bytes (16 × 11 bits = 176 bits = 22 bytes exactos).

Estadísticas de Enlace

Campo Byte Tipo Rango
RSSI payload[0] uint8 → int8 (negado) 0 a -127 dBm
Link Quality payload[2] uint8 0–100 %
SNR payload[3] int8 -128 a 127 dB

Mapeo en crsf_rx.c:46-50.

Estructura de Datos

typedef struct {
    uint16_t channels[16];  // 172–1811 (~1000–2000 µs)
    uint8_t link_quality;   // 0–100 %
    int8_t signal_strength; // RSSI en dBm (negativo)
    int8_t signal_to_noise; // SNR en dB
    bool failsafe;          // true si no hay trama RC en > 500 ms
} crsf_data_t;

Definido en crsf_rx.h:20-26.

Detección de Failsafe

crsf_get_data() en crsf_rx.c:117-121 compara clock_ticks - last_data_ms > 500. Si han pasado más de 500 ms desde la última trama RC válida, se activa el flag failsafe.

⚠️ Advertencia: crsf_get_data() devuelve un puntero a datos volátiles que la ISR puede modificar concurrentemente. No es segura para usar desde otra ISR ni desde el bucle principal sin protección. Ver SW-02.


Transmisión CRSF (TX) — Telemetría

Tipos de Trama Transmitidos

TYPE Nombre Payload Sensores EdgeTX
0x08 Battery 8 bytes RxBt, Curr, Capa, Bat%
0x1E Attitude 6 bytes Ptch, Roll, Yaw
0x21 Flight Mode ≤ 16 bytes FM
0x09 Baro 4 bytes Alt, VSpd
0x02 GPS 15 bytes GPS, GSpd, Hdg, Alt, Sat

Implementado en crsf_tx.c.

Sistema Dirty + Round-Robin

Cada llamada a un setter marca el slot correspondiente como dirty. crsf_telemetry_update() recorre los 5 slots en round-robin buscando el siguiente dirty, con un intervalo mínimo de 50 ms entre tramas:

Índice Slot Setter
0 Battery crsf_telemetry_set_battery(voltage, current, capacity, pct)
1 Attitude crsf_telemetry_set_attitude(pitch, roll, yaw)
2 Flight Mode crsf_telemetry_set_flight_mode("MODE")
3 Baro crsf_telemetry_set_baro(altitude_cm, vspeed_cms)
4 GPS crsf_telemetry_set_gps(lat, lon, speed, heading, alt, sats)

Solo los slots actualizados generan tráfico. Los slots nunca modificados no consumen ancho de banda.

API de Telemetría

Función Parámetros
crsf_telemetry_set_battery() voltage_mv (uint16), current_ma (uint16), capacity_mah (uint24), remaining_pct (uint8)
crsf_telemetry_set_attitude() pitch, roll, yaw (int16 × 0.0001 rad)
crsf_telemetry_set_flight_mode() mode_str (ASCII, ≤ 15 chars + \0)
crsf_telemetry_set_baro() altitude_cm (int32), vspeed_cms (int16)
crsf_telemetry_set_gps() lat/lon (int32 × 1e7), speed (× 10 km/h), heading (× 100°), altitude (m), sats
crsf_telemetry_update() Sin parámetros; llamar en cada iteración del bucle principal

Demo de Telemetría

telemetry_demo() en main.c:11-24 genera valores sintéticos que varían con el tiempo:

  • Batería: voltaje oscilando 12.0–14.8 V, corriente variable, capacidad creciente
  • Actitud: pitch/yaw cíclicos, roll con rampa
  • Flight mode: rota entre IDLE → ARMED → SPINNING → BRAKING cada 4 s
  • Baro y GPS: comentados en el código

Gestión de Errores

Error Detección Recuperación
CRC inválido CRC-8 DVB-S2 Descartar trama silenciosamente
Byte de sync perdido Estado SYNC busca 0xC8 Resync automático
Longitud inválida LEN < 2 o LEN > 64 Volver a SYNC
Failsafe Timeout 500 ms sin trama RC Flag failsafe = true
Datos parciales Fin de trama esperado por longitud Ver CM-01

Documento generado el 2026-06-27. Ver también Hardware, Arquitectura Software, Debug.