三模冗余(TMR)架构:原理、设计与权衡

各位同学,今天我们来聊聊飞控系统里一个绕不开的话题——三模冗余,也就是TMR。

说实话,我第一次接触TMR是在十年前做无人机飞控的时候。当时客户要求飞控必须能扛住单点故障,我第一反应就是:那就上三份硬件呗。后来才发现,事情远没那么简单。

TMR的基本原理

三模冗余,说白了就是「三个臭皮匠,顶个诸葛亮」。我们把三个完全相同的模块并联在一起,让它们同时处理同样的输入数据。然后通过一个表决器,取其中两个或三个一致的结果作为最终输出。

为什么会这样?因为三个模块同时出错的概率,比一个模块出错的概率低得多。你想想看,如果单个模块的失效率是10⁻⁶,那三个模块同时失效的概率就是10⁻¹⁸——这几乎可以忽略不计了。

核心思想:用空间换时间,用硬件冗余换取系统可靠性。

我习惯把TMR的工作流程分成三步:

  1. 输入分发——把同一个输入信号同时送给三个模块
  2. 并行计算——三个模块各自独立处理,互不干扰
  3. 结果表决——三取二,输出多数一致的结果

这里有个关键点:三个模块必须是完全独立的。电源、时钟、复位信号都要分开。我在项目中见过有人把三个模块放在同一块PCB上,共用同一个电源轨——结果一个电源短路,三个模块全挂了。嗯,这教训挺深刻的。

输入信号 模块 A 模块 B 模块 C 三取二表决器 输出 并行计算 多数表决

三取二表决器设计

表决器是TMR的核心。它的任务很简单:看三个输入里,哪两个一样,就输出那个值。

我给大家看一个最简单的表决器逻辑。假设三个模块的输出分别是A、B、C,都是布尔值:

// 三取二表决器 - 组合逻辑实现
output = (A && B) || (B && C) || (A && C);

这个逻辑说白了就是:任意两个一致,就输出那个值。如果三个都一致,那更没问题。

但在实际飞控系统中,我们处理的不是简单的布尔值,而是传感器数据、控制指令这些复杂信号。这时候表决器就要做更多工作:

  • 数值比较——设定一个容差范围,比如角度误差在0.5度以内就算一致
  • 超时检测——某个模块如果迟迟不输出结果,直接把它踢出表决
  • 健康状态跟踪——记录每个模块的历史表现,频繁出错的模块降低权重

实战技巧:我建议在表决器里加一个「故障计数器」。每个模块每出错一次,计数器加1。当某个模块的计数器超过阈值,系统就把它标记为「永久故障」,不再参与表决。这样可以防止一个间歇性故障的模块反复干扰系统。

我曾经在一个项目中遇到过这样的问题:三个IMU模块,其中有一个偶尔会飘出异常值。如果只用瞬时表决,这个异常值有33%的概率被选为输出。后来我加了一个滑动窗口滤波,把每个模块过去10次的数据都纳入考量,才彻底解决了这个问题。

TMR的优缺点

聊完了原理和设计,咱们来客观地看看TMR的利弊。我这些年用下来,感受很深。

维度 优点 缺点
可靠性 能容忍任意一个模块失效,系统仍正常工作 表决器本身是单点故障,表决器坏了整个系统就瘫了
实时性 表决是组合逻辑,几乎没有延迟 三个模块必须同步,对时钟对齐要求高
成本 设计简单,不需要复杂的故障恢复逻辑 硬件成本是单模的3倍,功耗也是3倍
维护性 故障模块可以热插拔替换 三个模块的一致性维护很麻烦,固件升级要同步

注意:TMR并不能解决所有故障。比如共因故障——三个模块都用了同一款芯片,芯片本身有设计缺陷,那三个模块会同时出问题。还有电源浪涌、电磁干扰这些外部因素,也可能让三个模块同时失效。

我个人觉得,TMR最适合用在对安全性要求极高、但对成本和体积不太敏感的场景。比如载人飞行器、航天器、核电站控制系统。对于消费级无人机,用双冗余加看门狗就足够了,上TMR有点杀鸡用牛刀。

另外,TMR还有一个隐藏的坑:三个模块之间的同步问题。你想想看,三个模块各自独立运行,它们的时钟不可能完全一致。如果某个模块因为温度变化导致时钟漂移,它的输出就会比其他模块慢半拍。这时候表决器拿到的三个值,其实不是同一时刻的——这会导致表决结果出错。

我解决这个问题的方法,是在每个模块的输出端加一个FIFO缓冲,然后用一个统一的采样时钟去读取。这样就能保证三个模块的数据在时间上是对齐的。嗯,这个细节很多教材上不会讲,但实际项目中特别重要。

最后说一句:TMR不是银弹。它解决的是随机硬件故障,但对软件故障、设计缺陷无能为力。如果你的飞控代码本身有bug,那三份同样的bug只会让系统以三倍的效率崩溃。所以,TMR要和多样性的设计思路结合起来——比如三个模块用不同的编译器编译,或者用不同的编程语言实现——才能真正提高系统的鲁棒性。


公众号:蓝海资料掘金营,微信deep3321