本文档介绍了Betaflight的遥测系统架构,该系统使飞行控制器能够将飞行数据、传感器读数和状态信息传输到外部接收器、地面站和屏幕显示(OSD)系统。遥测系统支持多种协议,并管理数据调度、格式化和传输。
系统架构
遥测系统为多种遥测协议提供了一个统一的框架,每种协议都针对特定的接收机生态系统和应用场景而设计。该系统负责协议初始化、从各种飞行控制器子系统收集数据、根据协议规范进行数据格式化以及传输调度。

支持的协议
该遥测系统支持六种主要协议,每种协议都针对不同的接收器生态系统和带宽要求进行了优化:
| 协议 | 文件 | 波特率 | 用例 | 主要特点 |
|---|---|---|---|---|
| FrSky SmartPort | smartport.c | 57600 | FrSky接收机 | 传感器轮询,MSP 支持 |
| CRSF(Crossfire) | crsf.c | 420000+ | ExpressLRS,TBS | 高带宽,MSP隧道 |
| 格劳普纳HoTT | hott.c | 19200 | 格劳普纳系统 | 双向文本模式 |
| MAVLink | mavlink.c | 多变的 | 地面站 | 完整飞行数据 |
| 光遥测(LTM) | ltm.c | 1200-2400 | 低带宽 OSD | 最小数据集 |
| FlySky iBus | ibus.c | 115200 | FlySky接收器 | 传感器框架 |
协议初始化模式
每个协议都遵循由中央遥测系统管理的统一初始化模式:

CRSF遥测实施
CRSF(Crossfire)代表了 Betaflight 中最先进的遥测实现,支持高带宽数据传输、MSP 命令隧道以及波特率协商等高级功能。

CRSF帧调度
CRSF 使用轮询调度器来确定每个周期要发送的遥测帧:
// Scheduling array populated during initialization
static uint8_t crsfSchedule[CRSF_SCHEDULE_COUNT_MAX];
static uint8_t crsfScheduleIndex = 0;
// Frame types are scheduled based on sensor availability
if (sensors(SENSOR_ACC) && telemetryIsSensorEnabled(SENSOR_PITCH | SENSOR_ROLL | SENSOR_HEADING)) {
crsfSchedule[index++] = BIT(CRSF_FRAME_ATTITUDE_INDEX);
}
SmartPort遥测实现
SmartPort遥测技术采用轮询协议,接收器通过ID请求特定的传感器数据。飞行控制器在收到轮询请求后,会返回请求的数据。

SmartPort传感器管理
SmartPort维护着一个已启用传感器及其对应数据ID的表格:
// Sensor initialization adds enabled sensors to the table
#define ADD_SENSOR(dataId) frSkyDataIdTableInfo.table[frSkyDataIdTableInfo.index++] = dataId
static void initSmartPortSensors(void) {
if (telemetryIsSensorEnabled(SENSOR_VOLTAGE)) {
ADD_SENSOR(FSSP_DATAID_VFAS);
}
if (telemetryIsSensorEnabled(SENSOR_CURRENT)) {
ADD_SENSOR(FSSP_DATAID_CURRENT);
}
// Additional sensors...
}
通过遥测技术实现的MSP
多种遥测协议支持 MSP(MultiWii 串行协议)隧道,允许配置工具通过遥测链路与飞行控制器通信。

MSP帧处理
通过遥测技术接收到的MSP帧会被缓冲并异步处理:
// MSP frame buffering for CRSF
bool bufferCrsfMspFrame(uint8_t *frameStart, int frameLength) {
if (mspRxBuffer.len + CRSF_MSP_LENGTH_OFFSET + frameLength > CRSF_MSP_BUFFER_SIZE) {
return false;
}
uint8_t *p = mspRxBuffer.bytes + mspRxBuffer.len;
*p++ = frameLength;
memcpy(p, frameStart, frameLength);
mspRxBuffer.len += CRSF_MSP_LENGTH_OFFSET + frameLength;
return true;
}
配置和传感器管理
遥测系统可对传输哪些传感器数据进行精细控制,使用户能够优化带宽使用并自定义发送给接收器的数据。
遥测配置结构
typedef struct telemetryConfig_s {
int16_t gpsNoFixLatitude;
int16_t gpsNoFixLongitude;
uint8_t telemetry_inverted;
uint8_t halfDuplex;
uint8_t frsky_coordinate_format;
uint8_t frsky_unit;
uint8_t frsky_vfas_precision;
uint8_t hottAlarmSoundInterval;
uint8_t pidValuesAsTelemetry;
uint8_t report_cell_voltage;
uint8_t flysky_sensors[IBUS_SENSOR_COUNT];
uint16_t mavlink_mah_as_heading_divisor;
uint32_t disabledSensors; // bit flags
uint8_t mavlink_min_txbuff;
} telemetryConfig_t;
传感器启用/禁用系统
遥测系统使用位标志来控制哪些传感器处于活动状态:
// Sensor enumeration
typedef enum {
SENSOR_VOLTAGE = 1 << 0,
SENSOR_CURRENT = 1 << 1,
SENSOR_FUEL = 1 << 2,
SENSOR_MODE = 1 << 3,
SENSOR_ACC_X = 1 << 4,
SENSOR_ACC_Y = 1 << 5,
SENSOR_ACC_Z = 1 << 6,
SENSOR_PITCH = 1 << 7,
SENSOR_ROLL = 1 << 8,
SENSOR_HEADING = 1 << 9,
SENSOR_ALTITUDE = 1 << 10,
SENSOR_VARIO = 1 << 11,
SENSOR_LAT_LONG = 1 << 12,
SENSOR_GROUND_SPEED = 1 << 13,
SENSOR_DISTANCE = 1 << 14,
ESC_SENSOR_CURRENT = 1 << 15,
ESC_SENSOR_VOLTAGE = 1 << 16,
ESC_SENSOR_RPM = 1 << 17,
ESC_SENSOR_TEMPERATURE = 1 << 18,
SENSOR_TEMPERATURE = 1 << 19,
SENSOR_CAP_USED = 1 << 20,
} sensor_e;
// Sensor checking function
bool telemetryIsSensorEnabled(sensor_e sensor) {
return ~(telemetryConfig()->disabledSensors) & sensor;
}
港口共享和国家管理
遥测系统在共享串行端口时必须与接收器协议协调,特别是对于 CRSF 和 iBus 等协议,因为相同的物理连接既处理 RC 输入又处理遥测输出。
端口共享逻辑
bool telemetryCheckRxPortShared(const serialPortConfig_t *portConfig, const SerialRXType serialrxProvider) {
if (portConfig->functionMask & FUNCTION_RX_SERIAL &&
portConfig->functionMask & TELEMETRY_SHAREABLE_PORT_FUNCTIONS_MASK &&
(serialrxProvider == SERIALRX_SPEKTRUM1024 ||
serialrxProvider == SERIALRX_SPEKTRUM2048 ||
serialrxProvider == SERIALRX_SBUS ||
serialrxProvider == SERIALRX_SUMD ||
serialrxProvider == SERIALRX_SUMH ||
serialrxProvider == SERIALRX_XBUS_MODE_B ||
serialrxProvider == SERIALRX_XBUS_MODE_B_RJ01 ||
serialrxProvider == SERIALRX_IBUS)) {
return true;
}
return false;
}
遥测状态确定
bool telemetryDetermineEnabledState(portSharing_e portSharing) {
bool enabled = portSharing == PORTSHARING_NOT_SHARED;
if (portSharing == PORTSHARING_SHARED) {
if (isModeActivationConditionPresent(BOXTELEMETRY))
enabled = IS_RC_MODE_ACTIVE(BOXTELEMETRY);
else
enabled = ARMING_FLAG(ARMED);
}
return enabled;
}
1056

被折叠的 条评论
为什么被折叠?



