开源连载③|ST_AxisMessage —— 读懂轴的'心跳'
开源连载 ③ | 共 5 篇
开源连载③|ST_AxisMessage —— 读懂轴的”心跳”
轴在想什么?看 Message 就知道了。
上一篇我们聊了怎么”发指令”。但指令发出去了,轴到底在干嘛?跑起来了还是报错了?到位了还是卡住了?
这就是 ST_AxisMessage 的事——把轴的实时状态翻译成程序能读懂的信号。
源码一览
TYPE ST_AxisMessage :
STRUCT
bOperational : BOOL ; (* 运行就绪:TRUE = 轴已使能且处于可运行状态 *)
bPositionRestored : BOOL ; (* 位置恢复:TRUE = 上电后编码器位置已恢复 *)
bPositionStored : BOOL ; (* 位置已存:TRUE = 当前位置已保存至非易失存储 *)
bPowerOn : BOOL ; (* 已上电:TRUE = 轴伺服已上电使能 *)
bHomeDone : BOOL ; (* 回零完成:TRUE = 回原点操作已成功完成 *)
bJogBusy : BOOL ; (* 点动运行中:TRUE = 正在执行点动运动 *)
bMotionDone : BOOL ; (* 运动完成:TRUE = 目标位置已到达 *)
bBackDone : BOOL ; (* 回退完成:TRUE = 回退运动已结束 *)
bVelBusy : BOOL ; (* 速度运行中:TRUE = 正在执行速度模式运动 *)
bErrorStop : BOOL ; (* 故障停止:TRUE = 轴因错误而停止 *)
bSetPosDone : BOOL ; (* 位置设定完成:TRUE = 位置设定操作已生效 *)
iPLCOpenState : INT ; (* PLCopen 轴状态:遵循 PLCopen 标准的状态机编号 *)
DwErrorID : DWORD ; (* 错误代码:当前轴故障/报警的错误码 *)
rActPos : REAL ; (* 实际位置:轴当前实际位置 [mm 或 deg] *)
rActVel : REAL ; (* 实际速度:轴当前实际速度 [mm/s 或 deg/s] *)
rActTor : REAL ; (* 实际扭矩:轴当前实际扭矩/力 [% 或 N] *)
END_STRUCT
END_TYPE
三个设计要点
要点一:状态位按优先级排列
看上面的结构体,你有没有注意到一个细节——布尔状态位全部排在最前面。
这不是随意的排列,而是刻意的设计:
高频 → 低频 排列
bOperational ← 最常用,第一个
bErrorStop ← 故障信号,越早看到越好
rActPos / rActVel ← 数值排在最后
为什么这样排?
因为 HMI 和调试界面通常只看灯。灯绿了再去看具体数值。把布尔位集中在前部,工程师扫一眼结构体内存视图,就能判断轴的”大健康”状态。
内存中一眼扫过去:
Byte 0: Operational | PosRestored | PosStored | PowerOn | HomeDone | ...
↑
扫到这里就知道状态正常
要点二:PLCopen 状态机
iPLCOpenState 这个字段是整个 Message 的”定海神针”。
PLCopen 定义了标准的轴状态机,用数字编号表示轴的当前阶段:
| 状态 | 含义 |
|---|---|
| 0 | Disabled(未使能) |
| 1 | Standstill(静止就绪) |
| 2 | Running(运动中) |
| 3 | ErrorStop(故障停止) |
| 4 | Homing(回零中) |
只用 11 个布尔位来覆盖所有状态是不够的——比如”运动中”这个状态,点动和定位都在跑,但布尔位只有 bJogBusy 和 bVelBusy,没有”正在绝对定位中”的位。
所以加一个 iPLCOpenState,把轴的主状态机固化进来:
IF iPLCOpenState = 2 THEN
// 轴正在运动,具体是哪种运动看 bJogBusy / bVelBusy
END_IF
布尔位负责”精细状态”,iPLCOpenState 负责”大阶段”,两者互补。
要点三:实时数据的工程单位
rActPos、rActVel、rActTor 这三个 REAL 字段,最容易出现的问题是——单位不统一。
有人用 mm,有人用 μm,有人用 Pulse。同一个项目里混着用,调试的时候数值差三个数量级,排查半天才发现是单位问题。
我们的做法是在注释里强制约定工程单位:
rActPos : REAL ; (* 实际位置 [mm] *)
rActVel : REAL ; (* 实际速度 [mm/s] *)
rActTor : REAL ; (* 实际扭矩 [% 额定扭矩] *)
驱动层负责脉冲 → 工程单位的换算,上层应用只看统一单位。这样 AI 在理解数据时,也不需要猜单位。
Command ↔ Message 闭环
Command 和 Message 是一对请求-响应:
你发指令 轴回答
┌────────────┐ ┌────────────┐
│ bPower │──────▶ │ bPowerOn │
│ bHome │──────▶ │ bHomeDone │
│ bJogP │──────▶ │ bJogBusy │
│ bAbs/bRel │──────▶ │ iPLCOpenState│
│ bStop │──────▶ │ bErrorStop │
└────────────┘ └────────────┘
这套对应关系在调试时非常有用:
// 发指令
AxisCommand.bHome := TRUE;
// 等回应(超时保护)
TON_Wait(IN:=TRUE, PT:=T#5S);
IF AxisMessage.bHomeDone THEN
// 回零成功
ELSE
// 超时 → 报警
END_IF
小结
ST_AxisMessage 设计要点:
① 布尔状态位集中排列 → 快速扫视健康状态
② iPLCOpenState 定大阶段 → 状态机标准化
③ 布尔位补精细状态 → 两者互补
④ 实时数据统一单位 → 消灭单位混乱
⑤ Command ↔ Message 一一对应 → 可追溯可超时保护
下一篇聊 ST_AxisParameter——参数配好了,项目就稳了一半。
本文是「轴控三件套开源计划」连载第 3 篇。 代码已在笔记中同步,最终会在 Day 5 统一开源发布。
你的轴控项目里,出过哪些”状态理解错了”的bug?留言聊聊 👇