4. 软件架构设计:三余度软件分层模型、同步与异步机制、数据一致性保障
各位同学,今天我们来聊聊三余度飞控的软件架构。说实话,这部分内容是我个人觉得整个课程里最考验系统思维的地方。硬件搞了三套,软件要是没设计好,那三余度反而可能变成三倍麻烦。
我见过不少团队,硬件冗余做得挺扎实,一上电三套飞控各自为政,数据乱飞,表决结果比单机还差。嗯,问题就出在软件架构上。今天我把这些年踩过的坑和总结的经验,掰开了讲给你们听。
4.1 三余度软件分层模型
先说说分层。我习惯把三余度软件分成三层:应用层、同步管理层、硬件抽象层。为什么这么分?说白了,就是为了解耦。
核心思想:每一层只关心自己的事,不越界。应用层只管飞控算法,同步管理层管三机协同,硬件抽象层管传感器和舵机。这样哪一层出了问题,不会牵连全局。
我在项目中遇到过一件事:某次飞行测试,三套飞控的IMU数据总是对不上。查了两天,发现是硬件抽象层里,不同通道的SPI时钟相位设置差了那么一点点。如果当时没有分层,这种问题根本没法定位。
具体分层如下:
- 硬件抽象层(HAL):封装传感器、舵机、通信接口。每个通道独立运行,互不干扰。
- 同步管理层(SML):负责三机之间的时钟同步、数据交换、故障检测。这是三余度的灵魂。
- 应用层(APP):姿态解算、控制律计算、任务管理。跑的是单机飞控算法,但输入输出都经过同步管理层。
你想想看,如果应用层直接去读传感器,那三套飞控读到的数据天然就有差异,后面再怎么表决也白搭。所以,应用层只能读同步管理层处理过的数据,这是铁律。
我的建议:分层时,接口定义要严格。我一般用结构体+版本号的方式,确保各层之间的数据格式一致。别小看这个,版本号能救你命。
4.2 同步与异步机制
三余度系统里,同步是个大问题。三套飞控怎么对齐时间?怎么保证同一时刻执行同一段代码?
我常用的方案是混合同步机制:
- 帧同步:每个控制周期开始,三机通过CCDL交换同步帧头。谁先收到两帧,谁就发起同步。说白了,就是三机互相喊「1、2、3,开始!」
- 异步补偿:如果某通道因为中断延迟或任务抢占,没赶上同步窗口,那就进入异步模式。异步模式下,该通道用上一周期的数据继续运行,同时尝试重新同步。
为什么会这样设计?我记得有一次做半实物仿真,发现三机同步后,总有一台慢几十微秒。查到最后,是某款MCU的DMA传输占用了总线。从那以后,我就在同步机制里加了超时回退逻辑。
注意:异步模式不能一直跑。我曾经见过一个系统,某通道长期处于异步状态,结果表决时它的数据总是滞后,导致控制输出抖动。所以,异步模式必须有个计数器,连续异步超过N个周期,就要触发故障切换。
代码层面,我习惯这样实现同步逻辑:
// 伪代码:三余度同步管理器
void sync_manager_run() {
// 等待CCDL同步帧
if (ccdl_wait_sync_frame(SYNC_TIMEOUT_US)) {
// 同步成功,进入帧同步模式
current_mode = SYNC_MODE_FRAME;
// 执行应用层任务
app_task_run();
} else {
// 同步超时,进入异步模式
current_mode = SYNC_MODE_ASYNC;
async_counter++;
// 使用上一周期数据
app_task_run_with_old_data();
}
// 如果连续异步超过5个周期,上报故障
if (async_counter > 5) {
fault_report(CHANNEL_SYNC_LOST);
}
}
这段代码看着简单,但实际工程里要考虑的东西很多。比如同步超时时间设多少?我一般设成控制周期的10%,太短容易误报,太长影响实时性。
4.3 数据一致性保障(CCDL)
CCDL,全称Cross-Channel Data Link,是三余度系统的数据高速公路。它的核心任务就一个:让三套飞控看到同一份数据。
我刚开始做三余度时,觉得CCDL不就是个通信协议嘛,随便写写就行。结果第一次联调,三机数据对不上,有的通道读到的是旧数据,有的读到的是新数据,表决结果一塌糊涂。
后来我总结了一套CCDL设计原则:
- 数据版本化:每条数据都带时间戳和序列号。接收方根据序列号判断数据新旧,丢弃旧数据。
- 三机互传:每个通道把自己的数据广播给另外两个通道,同时接收另外两个通道的数据。形成全互联拓扑。
- 多数表决:收到三份数据后,取中间值或平均值。如果某通道数据与其他两通道偏差过大,标记为可疑。
关键点:CCDL的数据传输必须是确定性的。不能出现「这次传了,下次没传」的情况。我一般用固定时间片轮转,每个通道在固定的时隙发送数据。
下面这张图展示了CCDL的数据流和表决逻辑:
这张图里,每个通道都把自己的数据发给另外两个通道。三份数据汇集到多数表决器,最终输出一致的结果。注意看,数据链路是双向的,没有主从之分。
实际工程中,CCDL的物理层我常用CAN总线或高速串口。CAN总线天生支持多主通信,很适合三余度场景。但要注意,CAN的带宽有限,一个控制周期内要传完所有数据,得算好时间。
避坑指南:我曾经在CCDL里用过软件校验和,结果发现偶尔会漏检。后来全部改成CRC32,再没出过问题。数据一致性这事,硬件校验比软件靠谱。
最后说一句,数据一致性不是靠一次交换就能保证的。我习惯在每个控制周期结束时,再做一次交叉校验——三机互相确认对方的数据和自己的一致。如果不一致,下个周期重新交换。这样虽然多花点时间,但能确保万无一失。
好了,软件架构这部分就讲到这里。记住,分层是骨架,同步是节拍,CCDL是血管。三者缺一不可。