博文

开源连载③|ST_AxisMessage —— 读懂轴的'心跳'

ST/PLC / 轴控

开源连载 ③ | 共 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 定义了标准的轴状态机,用数字编号表示轴的当前阶段:

状态含义
0Disabled(未使能)
1Standstill(静止就绪)
2Running(运动中)
3ErrorStop(故障停止)
4Homing(回零中)

只用 11 个布尔位来覆盖所有状态是不够的——比如”运动中”这个状态,点动和定位都在跑,但布尔位只有 bJogBusybVelBusy,没有”正在绝对定位中”的位。

所以加一个 iPLCOpenState,把轴的主状态机固化进来:

IF iPLCOpenState = 2 THEN
    // 轴正在运动,具体是哪种运动看 bJogBusy / bVelBusy
END_IF

布尔位负责”精细状态”,iPLCOpenState 负责”大阶段”,两者互补。

要点三:实时数据的工程单位

rActPosrActVelrActTor 这三个 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?留言聊聊 👇

← 返回博文列表