22. 读懂 CiA 402 电机状态
CANopen 的 NMT Heartbeat 告诉我们“节点是否处于 Pre-operational 或 Operational”。它没有告诉我们电机功率级是否已经使能。
电机能不能接受运动命令,要读取 CiA 402 的 0x6041:00 Statusword。
两套状态不要混在一起
| 状态系统 | 从哪里观察 | 它回答什么 |
|---|---|---|
| CANopen NMT | 0x701 Heartbeat DATA | 通信节点处于哪个网络管理状态 |
| CiA 402 FSA | 0x6041:00 Statusword | 驱动器功率和控制状态处于哪一步 |

图中两条路线互不替代。收到 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 | 掩码 | 含义 |
|---|---|---|
| 0 | 0x0001 | Ready to switch on |
| 1 | 0x0002 | Switched on |
| 2 | 0x0004 | Operation enabled |
| 3 | 0x0008 | Fault |
| 4 | 0x0010 | Voltage enabled |
| 5 | 0x0020 | Quick stop |
| 6 | 0x0040 | Switch on disabled |
| 7 | 0x0080 | Warning |
| 9 | 0x0200 | Remote |
| 10 | 0x0400 | Target reached |
| 11 | 0x0800 | Internal 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:

绿色格子表示该位为 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

0x0027 对应 Operation enabled。因此 0x0637 不需要和 0x0027 完全相等,也能判定状态机处于 Operation enabled。
按位与可以理解成一排开关:掩码中为 1 的位置允许原始位通过,掩码中为 0 的位置被清掉。它不会修改电机,只是 ESP32 在本地计算一个更容易查表的数值。
常见状态模式
| 掩码后的值 | 状态 |
|---|---|
0x0040 | Switch on disabled |
0x0021 | Ready to switch on |
0x0023 | Switched on |
0x0027 | Operation enabled |
0x0007 | Quick stop active |
0x000F | Fault reaction active |
0x0008 | Fault |
这些是状态模式,不是电机必须返回的完整 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)
逐项解释:
0x0637 & 0x006F = 0x0027,驱动处于 Operation enabled;0x6061 = 1,当前显示 Profile Position 模式;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,不写模式和目标位置。