软件架构
控制算法是驱动系统中最容易进行理论分析、却最难保持简洁的部分。它只是几百行算术运算,不涉及任何 I/O——但在大多数固件中,它最终会被紧密耦合到厂商 SDK、定点库、RTOS 和显示栈上,此时若想在没有电机的试验台上对其进行测试已变得不可能。
本页介绍了一种避免上述问题的软件架构,它并非抽象的理论构想,而是提炼自一台实际运行的驱动器:由 MCX-N947 驱动 Teknic PMSM,在逐步从 NXP SDK 示例中剥离出独立于厂商的控制库的过程中,每一步之间电机都保持正常运转。
三层架构,以及关于依赖方向的铁律
依赖关系的箭头全部指向内部,正是这一条约束条件支撑起了其他所有部分。核心代码不能包含厂商提供的头文件,因此不会引入对芯片的依赖。它没有I/O接口,所以可以在任何地方运行——包括在你的笔记本电脑上以实际速度的一万倍进行单元测试。
这并非一种假设性的优势。本网站本身就是这一测试的实例。 此处的每一幅交互图表都在浏览器中对电机模型运行着完全相同的闭环控制算法,因为控制代码与它通常所驱动的硬件是完全解耦的。标有 port/sim 的模块并非示意图,而是这些网页实际正在执行的模块。
在试验台上 迁移顺序比最终架构更重要。试图一次性剥离出整个控制库,只会得到一份从未跑通的固件。分步推进——先抽离纯数学变换,再定义硬件接口契约,接着迁移电流环,最后迁移状态机——每完成一步都在实验台上实测运行,这样一旦出现回归问题,可疑原因就只有一个。在上述实验台上,第 3 步先在后台证明了新调制器与厂商原版调制器的输出偏差不超过 0.009%,随后才允许它真正接管逆变桥驱动。
端口契约就是整个设计
所有与平台相关的内容都归结为少数几个操作:
| 操作 | 核心层所需内容 |
|---|---|
| 测量 | 来自当前周期的两相电流与直流母线电压 |
| 驱动 | 三个占空比,以相干方式施加 |
| 位置 | 编码器计数及索引,若存在的话 |
| 时间 | 控制周期,以数值表示 |
仅此而已。无需初始化,无需时钟配置,无需中断优先级——这些都属于应用程序的职责范围,将它们排除在接口之外,才能防止端口层膨胀成第二个 SDK。
在移植任何代码之前,先明确这个接口规范。这也是实现第二个版本几乎无需额外成本的地方:通过一个基于电机模型的仿真端口为核心模块提供输入,从而无需搭建硬件平台即可验证控制算法。
两个时钟域,以及它们各自的职责
驱动器中有两个时钟,混淆它们是导致神秘行为的常见原因。
快速路径:每个 PWM 周期在中断服务程序中执行一次。 依次采集电流、执行 Clarke 与 Park 变换、运行两个电流 PI、解耦、逆 Park 变换、调制并写入占空比。仅做这些;不要在中断里分配内存、记录日志或等待。实测这部分耗时约 12 µs,而 PWM 周期为 62.5 µs;这是在该硬件上测得的数值,不是模型估计。
慢速路径:在任务或主循环中执行,周期通常为 1–10 ms。 速度环与位置环、斜坡发生器、故障处理策略、用户界面、遥测。这些模块的运行频率只需与机械系统的实际响应能力相匹配,它们都不应放在 16 kHz 的高频中断中执行。
两者通过简单的共享状态进行通信——一方传递命令,另一方传递测量值的小型结构体。如果这一边界需要互斥锁,则说明划分的位置不当。
同一套控制律,两种调度方式
这里有一个常被当作个人偏好来讨论的部分,但事实并非如此。在实时操作系统(RTOS)下和在裸机超循环中,快速控制环路完全相同:两者都是通过中断实现的,在两种情况下都会抢占所有其他任务,并且包含完全一致的计算逻辑。磁场定向控制中没有任何部分需要调度器。
不同之处在于底层结构,而且这种差异并非仅是形式上的。
最后一句话道出了全部权衡,且这一权衡是可测量的,而非主观争论的问题。给两个模型分配相同的中断、相同的慢速任务以及相同的后台处理块,观察它们各自的表现:
在默认设置下——16 kHz 开关频率、12 µs 中断耗时、1 kHz 慢速环路以及 3 ms 的后台任务块——两种模型下中断均占用 19.2% 的 CPU 资源。RTOS 准确交付了 1 kHz 的慢环频率;而超循环实际仅交付了约 266 Hz,因为主循环跑完一圈的 3.04 ms 工作量被高频中断拉长到了 3.76 ms 的实际挂钟时间。系统并没有坏,只是这个速率从一开始就不存在调度保障。
在试验台上 这并非思想实验。在本页面所描述的试验台上,转速 参考信号发生器 在用户界面任务中以标称 10 Hz 运行。 实测表明,在图表绘制负载下,该任务的实际运行频率仅为 2–3 Hz,因此,当指令要求 500 rpm/s 的加速度时,实际输出约为 80 rpm/s——驱动系统的响应显得迟缓,而这与电机、控制参数或机械本身无关。
解决方案并非加快 UI 任务,而是将参考信号生成及外环控制移入控制中断内,使执行频率成为硬件定时器的固有属性,而不再受显示任务繁忙程度的影响。在动念引入 RTOS 之前,这一点值得深思:提升任务的执行层级,往往比升级调度器更为经济。
因此:只有当产品中的其他部分确实需要时才使用实时操作系统——比如网络栈、文件系统,或者那些会阻塞的图形库。不要为了使控制环路具有确定性而引入 RTOS。控制环路本来就是确定的,而且这种确定性是由中断向量而非调度器决定的。
逆变器的唯一所有者
本页面背后那台设备上最难解决的 bug 就是因为违反了这一规则: 两段代码在同一中断中写入占空比寄存器,而硬件的重新加载机制决定了哪个写操作生效。表现出来的现象是根本不可能发生的物理现象;原因在于所有权问题,而非算术错误。
因此,应将其设计为结构化方式。仅有一个函数负责写入占空比。所有希望影响逆变器的模块都向该函数返回数值,而非直接操作外设。对于存在两个写入者的驱动系统,仅靠合理安排两者的执行顺序并不能保证正确性——请参阅 外设页面,其中逐周期展示了相关机制,您可以观察是硬件而非您的代码决定了最终结果。
掌管状态转换的状态机
驱动器的故障往往出现在模式切换时,因为真正值得关注的失效发生在状态之间的过渡阶段,而不是稳定状态下:比如在ADC仍在校准时就进行对齐,在错误的角度从开环切换到闭环,或者在电机高速运转时断开接触器并产生再生电流。
一个小型的显式模型,所有状态转移都集中在一个文件中,其价值远胜于任何单一模式的复杂性。标题中提到的两次故障实际上都是状态转移错误,而非控制错误,且在任何一个单独状态的代码中都无法发现。
异常防护与独立见证
有两件事值得在一开始就予以实现,而不是在出现问题后再添加。
异常防护(Guards)。 带有观测器的驱动系统可能会发生“自我投毒”:在试验台上,一次停滞的无感启动曾在观测器中产生了一个 NaN(非数值),该值随后传播到电压指令中,导致驱动器悄无声息地死锁,直到重新上电才恢复。在快速环路中增加非有限值(NaN/Inf)检查,一旦发现便立即清零 PI 积分器并强制触发故障状态——这只需寥寥数条指令,却能将一起离奇的死机转化为明确的故障码。
独立见证(Witness)。 保留一项控制律完全不使用的独立测量值。在无位置传感器驱动器中,编码器就是最天然的见证者——当观测器自信满满地报告电角速度为健康的 435 rad/s,而编码器计数值却纹丝不动时,你立刻就能判断是谁在撒谎。未被控制环使用的“真值”绝非浪费;它是唯一能够拆穿一个过度自信的估算器的铁证。
要点回顾
- 使所有依赖关系均指向内部,这样控制律便可在无需硬件的情况下进行测试。
- 保持端口契约:测量、驱动、定位、计时。
- 快速环仅执行电流环控制,其余较慢的任务则交由一个任务或循环处理。
- 电流环无需RTOS。真正需要RTOS的是那些耗时较长的任务,而且只有当某些操作确实会导致环路周期过长时才需使用——在超循环模式下,慢周期就是环路周期,而非一个单独的设置。
- 占空比寄存器有且仅有一个写入者,并从软件结构上强制保证这一点。
- 将状态切换逻辑集中处理,防范非有限值,并保留一项虽未使用但必要的测量数据。