跳到主要内容

22. 读懂 CiA 402 电机状态

学习形式状态分析
硬件要求完整实验平台
配套 Demo沿用 lab_19
本课动作只读状态字

CANopen 的 NMT Heartbeat 告诉我们“节点是否处于 Pre-operational 或 Operational”。它没有告诉我们电机功率级是否已经使能。

电机能不能接受运动命令,要读取 CiA 402 的 0x6041:00 Statusword

两套状态不要混在一起

状态系统从哪里观察它回答什么
CANopen NMT0x701 Heartbeat DATA通信节点处于哪个网络管理状态
CiA 402 FSA0x6041:00 Statusword驱动器功率和控制状态处于哪一步

同一台电机同时具有 NMT 通信状态和 CiA 402 驱动状态

图中两条路线互不替代。收到 0x701 DATA 05 只能沿左边得出“通信节点是 Operational”;想知道驱动器能否接受运动目标,还要沿右边读取 0x6041

所以可能同时看到:

Heartbeat 0x701 DATA 05 -> NMT Operational
Statusword 0x6041 -> Switch on disabled

这并不矛盾:网络通信已经 Operational,但电机驱动还没使能。

Statusword 是一个位集合

0x6041 类型是 UNSIGNED16。16 个 bit 分别表达 Ready to switch on、Switched on、Operation enabled、Fault、Voltage enabled 等状态。

常用低位:

bit掩码含义
00x0001Ready to switch on
10x0002Switched on
20x0004Operation enabled
30x0008Fault
40x0010Voltage enabled
50x0020Quick stop
60x0040Switch on disabled
70x0080Warning
90x0200Remote
100x0400Target reached
110x0800Internal limit active

某一位是否为 1,用按位与检查:

// 这里分别检查两个独立 bit:bit 3 表示 Fault,bit 2 表示 Operation enabled。
// “某一位为 1”不等于已经得出完整状态机名称,完整状态要在下一步使用 0x006F 掩码。
bool fault = (statusword & 0x0008U) != 0U;
bool operation_enabled = (statusword & 0x0004U) != 0U;

bit 编号从最右边开始:最右边是 bit 0,再向左依次是 bit 1、bit 2。四位十六进制数正好表示 16 个 bit,因为每个十六进制数字对应 4 个二进制位。

把本项目实测的 0x0637 展开后,可以直接看到哪些位是 1:

把实测 Statusword 0x0637 展开成关键 bit

绿色格子表示该位为 1,但不能把所有绿色格子拼成一个状态名称。bit 9 的 Remote、bit 10 的 Target reached 属于附加信息;状态机名称只使用规范指定的那些位判断。

为什么判断状态要使用掩码

一次实测得到:

0x6041 Statusword = 0x0637

不能写成 statusword == 0x0027 来判断 Operation enabled,因为 bit 9、bit 10 等附加状态也可能为 1。

CiA 402 常用下面的状态掩码:

// 0x006F 只保留 CiA 402 状态机判定需要的 bit 0、1、2、3、5、6。
// Remote、Target reached 等附加位会被清零,因此它们变化时不会破坏状态名称判断。
uint16_t state = statusword & 0x006FU;

对实测值计算:

0x0637 & 0x006F = 0x0027

用 0x006F 从完整 Statusword 中保留状态机判断位

0x0027 对应 Operation enabled。因此 0x0637 不需要和 0x0027 完全相等,也能判定状态机处于 Operation enabled。

按位与可以理解成一排开关:掩码中为 1 的位置允许原始位通过,掩码中为 0 的位置被清掉。它不会修改电机,只是 ESP32 在本地计算一个更容易查表的数值。

常见状态模式

掩码后的值状态
0x0040Switch on disabled
0x0021Ready to switch on
0x0023Switched on
0x0027Operation enabled
0x0007Quick stop active
0x000FFault reaction active
0x0008Fault

这些是状态模式,不是电机必须返回的完整 16 位原值。

用第 19 课工程只读状态

第 19 课已经包含:

// 三项都通过 SDO 上传读取:0x6041 判断驱动状态,0x6061 确认当前模式,
// 0x6064 读取带符号实际位置;程序中没有 0x6040 写入接口。
{0x6041, 0x00, VALUE_U16, "Statusword"},
{0x6061, 0x00, VALUE_I8, "Mode display"},
{0x6064, 0x00, VALUE_I32, "Position actual"},

因此本课不需要新建另一个几乎相同的程序。先运行只读实验,记录三项:

对象观察问题
0x6041当前状态和 Fault 位是什么
0x6061当前显示的运行模式是什么
0x6064当前实际位置是多少 counts

从实测日志读出什么

已有一次真实运行记录为:

Motor 0x6041 Statusword = 0x0637 (Operation enabled)
Motor 0x6061 Mode display = 0x01 (1, Profile position)
Motor 0x6064 Position actual = 0x000116AB (71339)

逐项解释:

  1. 0x0637 & 0x006F = 0x0027,驱动处于 Operation enabled;
  2. 0x6061 = 1,当前显示 Profile Position 模式;
  3. 0x6064 = 71339,当时反馈的位置值是 71339 counts。

这份日志是特定时刻的状态,不是每次上电都必须完全相同。读者应以自己刚读取的结果决定下一步。

Fault 时不要自动复位

如果 bit 3 为 1,程序应停止使能流程并报告:

// Fault bit 一旦置位就终止后续使能步骤;这里只报告,不自动写 Fault reset。
// 自动复位会改变设备状态,并可能掩盖供电、机械卡滞或厂商报警原因。
if ((statusword & 0x0008U) != 0U) {
ESP_LOGE(TAG, "Motor is in Fault");
return;
}

故障复位会改变设备状态。没有先确认 LED、供电、机械卡滞和报警原因时,不应为了让演示继续而自动复位。

官方背景资料:CiA 402 drives and motion control

下一课只走到 Operation enabled,不写模式和目标位置。