第三章 轴组状态机:状态机模型、状态转换条件、状态管理函数
各位工程师朋友,咱们今天聊聊轴组状态机。说实话,这东西是轴组控制的核心骨架。你想想看,一个多轴系统要协调运动,没有一套清晰的状态管理机制,那不乱套才怪。
我个人习惯把状态机比作一个「交通指挥系统」。每个轴组就是一个路口,状态机就是红绿灯和交警。什么情况下能走,什么情况下必须停,什么情况下要紧急刹车——都得有明确规则。
3.1 轴组状态机模型
PLCopen 标准定义了轴组的几个核心状态。我直接画了个图,方便你理解它们之间的关系。
这张图我建议你保存下来。每次写轴组程序前,先对照着看一遍,能少踩很多坑。
3.2 状态转换条件详解
每个状态之间的转换,都有明确的触发条件。我按实际项目中的使用频率,给你梳理一下。
| 当前状态 | 目标状态 | 触发条件 | 常用函数 |
|---|---|---|---|
| 未配置 | 空闲 | 轴组上电成功 | MC_Power(TRUE) |
| 空闲 | 运行 | 启动运动指令 | MC_MoveLinear, MC_MoveCircular |
| 运行 | 停止 | 收到停止指令或触发停止条件 | MC_Stop |
| 停止 | 空闲 | 停止动作完成 | MC_Stop.Done |
| 运行 | 错误停止 | 检测到严重错误 | 自动触发 |
| 错误停止 | 故障 | 错误确认 | MC_GroupReset |
| 故障 | 空闲 | 重新上电 | MC_Power(FALSE)→MC_Power(TRUE) |
核心要点:轴组状态机是「单向循环」结构。从空闲到运行,从运行到停止,再从停止回空闲。错误状态是「旁路」,一旦进入,必须手动复位才能回到正常流程。
3.3 状态管理函数
PLCopen 标准里,状态管理函数就那么几个。但每个函数怎么用、什么时候用,这里头有讲究。
3.3.1 MC_Power — 轴组上电/断电
这个函数是轴组控制的「总开关」。我个人习惯在程序启动时,先调用一次 MC_Power(TRUE),把轴组从「未配置」拉到「空闲」状态。
// 轴组上电示例
MC_Power_Instance(
AxisGroup := AxisGroup_1,
Enable := TRUE,
EnablePositive := TRUE,
EnableNegative := TRUE,
Status => PowerStatus,
Busy => PowerBusy,
Error => PowerError,
ErrorID => PowerErrorID
);
我的经验:上电时一定要检查 EnablePositive 和 EnableNegative 参数。我曾经在一个项目中,只使能了正方向,结果负方向运动时直接报错。后来我养成了习惯,只要不是特殊需求,两个方向都使能。
3.3.2 MC_Stop — 轴组停止
停止函数分两种:正常停止和紧急停止。正常停止用 MC_Stop,紧急停止我建议用硬件急停信号直接切断驱动器使能。
// 正常停止示例
MC_Stop_Instance(
AxisGroup := AxisGroup_1,
Execute := StopTrigger,
Deceleration := 1000, // 减速度,单位 mm/s²
Jerk := 5000, // 加加速度,单位 mm/s³
Done => StopDone,
Busy => StopBusy,
Error => StopError,
ErrorID => StopErrorID
);
这里要注意 Deceleration 和 Jerk 的取值。减速度太大,机械结构会「点头」;太小,停止距离过长。我一般先按额定值的 80% 设置,现场再微调。
3.3.3 MC_GroupReset — 错误复位
轴组进入「错误停止」状态后,必须调用 MC_GroupReset 才能回到「故障」状态。注意,它不能直接回到「空闲」。
避坑指南:我曾经在调试时,发现 MC_GroupReset 调用后轴组没反应。查了半天,原来是复位信号只维持了一个扫描周期。记住:Execute 输入必须保持为 TRUE,直到 Busy 变为 FALSE。
3.3.4 MC_GroupEnable / MC_GroupDisable — 轴组使能/禁能
这两个函数用于在「空闲」状态下,临时禁能轴组。比如你要手动点动某个单轴,可以先禁能轴组,操作完再使能。
// 轴组禁能示例
MC_GroupDisable_Instance(
AxisGroup := AxisGroup_1,
Execute := DisableTrigger,
Done => DisableDone,
Busy => DisableBusy,
Error => DisableError,
ErrorID => DisableErrorID
);
3.4 状态机编程实战要点
理论说完了,咱们聊聊实战中怎么用。我总结了几个关键点:
- 状态轮询不能停:每个扫描周期都要检查轴组当前状态。我习惯用一个 CASE 语句做状态分发。
- 状态转换要加互锁:比如从「运行」到「停止」,必须确认 MC_Stop 的 Done 信号为 TRUE,才能切到「空闲」。
- 错误处理要分级:轻微错误可以自动复位,严重错误必须人工介入。我在项目中用了一个错误计数器,连续 3 次自动复位失败就锁定为「故障」状态。
// 状态机轮询示例(结构化文本)
CASE GroupState OF
IDLE:
IF StartCommand THEN
MC_MoveLinear_Instance(Execute := TRUE);
GroupState := RUNNING;
END_IF
RUNNING:
IF StopCommand THEN
MC_Stop_Instance(Execute := TRUE);
GroupState := STOPPING;
END_IF
IF ErrorDetected THEN
GroupState := ERROR_STOP;
END_IF
STOPPING:
IF MC_Stop_Instance.Done THEN
MC_Stop_Instance(Execute := FALSE);
GroupState := IDLE;
END_IF
ERROR_STOP:
IF MC_GroupReset_Instance.Done THEN
GroupState := FAULT;
END_IF
FAULT:
IF MC_Power_Instance.Status THEN
GroupState := IDLE;
END_IF
END_CASE
最后说一句:状态机写得好不好,直接决定了轴组控制的稳定性和可维护性。我见过太多项目,状态机写得乱七八糟,出问题根本没法查。花点时间把状态机理清楚,后面能省十倍的时间。
好了,轴组状态机的内容就这些。记住那张状态转换图,记住那几个核心函数,再结合你自己的项目经验,很快就能上手。
公众号:蓝海资料掘金营,微信deep3321