4. 运动控制软件分层架构设计

运动控制软件的分层架构,本质上是在回答一个问题:当上层希望“以 1 kHz 周期、每周期 1 ms 内完成一次插补与输出”时,这个时间承诺由谁保证、在哪一层兑现、又怎样逐层传递下去。如果所有代码混在一起,轨迹规划的一次浮点运算抖动就可能直接破坏伺服环的周期;反之,若分层清晰,实时约束就能被逐层“翻译”为可验证的接口契约。

本节采用五层划分:硬件抽象层(HAL)、实时内核层(RTK)、运动规划层(MPL)、任务调度层(TSL)、应用接口层(API)。它们不是简单的调用栈,而是一条“约束自上而下分解、状态自下而上反馈”的双向通道。

五层架构:约束下行分解 · 状态上行反馈 实时约束下行分解 状态/误差上行反馈 应用接口层 API 职责:指令下发、状态查询、参数配置、报警订阅 约束:非实时线程,调用不得阻塞实时域;接口超时 50 ms 任务调度层 TSL 职责:周期任务编排、优先级分配、时间片与同步点管理 约束:伺服环 1 ms 硬实时,规划任务 4 ms 软实时,抖动 ≤ 50 μs 运动规划层 MPL 职责:轨迹插补、速度规划、多轴协调、前瞻与限幅 约束:每 4 ms 输出一组插补点,位置误差 ≤ 1 个脉冲当量 实时内核层 RTK 职责:时钟基准、中断管理、实时任务调度、内存锁定 约束:中断延迟 ≤ 10 μs,上下文切换 ≤ 5 μs,禁止动态分配 硬件抽象层 HAL 职责:编码器读取、PWM/DAC 输出、IO 映射、总线驱动 约束:寄存器级访问,单次读写 ≤ 2 μs,无操作系统依赖 指令 / 参数 / 模式切换 周期任务注册 / 优先级 / 同步信号 插补点 / 速度前馈 / 限幅状态 定时中断 / 时钟节拍 / 任务唤醒 编码器计数 / 电流反馈 / 故障标志

各层职责与接口契约

硬件抽象层是唯一直接触碰寄存器和外设的层。它把“读编码器”“写 PWM 占空比”“读限位开关”封装为固定签名的函数,例如 hal_encoder_read(axis) 返回 32 位计数值,hal_pwm_set(axis, duty) 写入比较寄存器。这一层不调用任何操作系统服务,也不做浮点运算,保证最坏执行时间可静态分析。以某 17 位增量编码器为例,四倍频后每转 131072 计数,若机械分辨率要求 0.001°,则每计数约 0.00275°,HAL 只需保证计数不丢、读取原子即可。

实时内核层提供时钟基准与中断框架。它把硬件定时器配置为 1 ms 周期中断,在中断服务程序里置位软件标志或释放信号量,唤醒伺服环任务。RTK 的关键约束是“中断延迟”和“调度抖动”:前者指从中断触发到 ISR 第一条指令的时间,后者指任务从就绪到实际运行的时间。工程上通常要求中断延迟 ≤ 10 μs、调度抖动 ≤ 50 μs。为达成这一点,RTK 需要锁定关键代码段内存、关闭不必要的动态内存分配,并把中断优先级分组配置正确。

运动规划层接收上层下发的目标位置、速度、加速度,按 4 ms 周期计算插补点。它内部通常包含前瞻缓冲、S 形速度规划和多轴插补。以两轴直线插补为例,若合成速度 100 mm/s、插补周期 4 ms,则每周期步长 0.4 mm;再按各轴方向余弦分解为 Δx、Δy,输出给 RTK 的伺服环。MPL 的实时约束是“软实时”:偶尔超时不会立即造成机械冲击,但连续超时会耗尽前瞻缓冲,导致速度骤降。

任务调度层是约束传递的枢纽。它把 MPL 的 4 ms 规划任务、RTK 的 1 ms 伺服任务、API 的非实时任务统一编排,明确优先级:伺服环最高,规划次之,通信与日志最低。调度层还要处理同步点——例如每 4 个伺服周期执行一次规划,用计数信号量或时间戳对齐,避免规划与伺服之间的相位漂移。

应用接口层面向工艺工程师和上位机,提供 move_linear()、set_velocity()、get_axis_status() 等接口。它必须把非实时调用转换为实时域可消费的消息,常用无锁环形缓冲或双缓冲实现,避免 API 线程直接操作实时数据结构。

实时约束的传递方式

约束传递不是“把 1 ms 写在文档里”,而是逐层转化为可测量的指标。API 层承诺“指令下发后 50 ms 内生效”,TSL 将其翻译为“规划任务在下一个 4 ms 周期读取指令队列”,MPL 再翻译为“插补器在 4 ms 内完成一次轨迹更新”,RTK 最终翻译为“伺服任务每 1 ms 读取一次插补结果并输出”。每一层都只对自己那一段负责,层间通过固定周期和缓冲深度解耦。

设计要点:层间接口应尽量“窄而稳定”。HAL 只暴露寄存器级读写,RTK 只暴露任务创建与同步原语,MPL 只暴露插补点流。接口越窄,实时约束越容易验证,替换硬件或算法时影响面越小。

一个可落地的分层配置示例

假设一台三轴直角坐标机器人,控制器采用 ARM Cortex-A 双核 + FPGA 方案。可参考如下分层参数配置:

层级周期/触发关键参数验证方式
HAL被调用编码器 17 位,PWM 20 kHz示波器测读写时序
RTK1 ms 中断中断延迟 ≤ 10 μsGPIO 翻转 + 示波器
MPL4 ms 任务前瞻 32 段,S 形加减速记录插补点时间戳
TSL事件驱动伺服优先级 90,规划 80跟踪任务切换次数
API异步环形缓冲 256 条压力测试丢包率

配置完成后,用示波器同时观察“定时器中断引脚”和“伺服输出更新引脚”,若两者间隔稳定在 1 ms ± 50 μs,说明 RTK 与 TSL 的约束传递有效;再让 MPL 连续执行 1000 段小线段插补,记录每 4 ms 规划任务的执行时间,若最大值不超过 2 ms,则前瞻缓冲不会耗尽。这些观察量就是分层架构是否真正落地的判断依据。

常见误区:把运动规划放在实时中断里执行。规划涉及浮点运算和循环,执行时间随轨迹复杂度变化,一旦超过中断周期就会丢步。正确做法是规划在独立任务中运行,中断只做数据搬运和输出更新。

分层架构的价值最终体现在可替换性和可验证性上:更换伺服驱动器只需重写 HAL;更换插补算法只需替换 MPL;调整任务周期只需修改 TSL 配置。每一层都有明确的输入、输出和实时指标,约束才能从“口头承诺”变成“可测量、可回归”的工程事实。