跳到主要内容

排错专题:SDO Abort 与超时

SDO 失败主要有两类:电机明确返回 0x80 Abort,或者程序等到超时仍没有收到匹配响应。两者的排查方向不同。

Abort 和超时先分开

现象已经证明什么下一步
收到 0x581 DATA 80 ...CAN-ID、Node-ID 和位速率基本正确,电机主动拒绝本次访问解码 Abort Code
没有匹配 0x581,最终 timeout尚不能证明电机看到了请求查总线、Node-ID、接收过滤和并发

收到 Abort 其实比完全没响应更接近答案:通信路径已经通了。

Abort 帧怎样拆

示例:

CAN-ID 0x581
DLC 8
DATA 80 7D 60 00 00 00 02 06
字节内容
00x80,SDO Abort 响应
1~2Index 小端序:7D 600x607D
3Sub-index:0x00
4~7Abort Code 小端序:00 00 02 060x06020000

所以这帧表示:访问 0x607D:00 时,Server 返回“对象不存在”。

本课程常用 Abort Code

Abort Code常见含义应对
0x05040000SDO protocol timed out检查节点在线、处理循环和总线拥塞
0x06010001尝试读取只写对象查对象权限
0x06010002尝试写只读对象停止写入,查设备文档
0x06020000对象不存在设备可能没实现这个可选对象
0x06090011Sub-index 不存在核对记录/数组的子索引数量
0x06070010数据类型或长度不匹配核对 1、2、4 字节和有无符号类型
0x06090030参数值范围错误查允许范围和单位
0x08000022当前设备状态不能访问先核对 NMT/CiA 402 状态和厂家条件

同一数字在不同上下文中不要混淆:0x06020000 是 32 位 Abort Code,0x602 则可能被人看成一个 CAN-ID,日志应明确标签。

对象不存在不一定是电机故障

CiA 402 定义大量对象,但具体设备只需实现与其功能相关的部分。厂家没有实现 0x607D 时,返回 0x06020000 是规范化拒绝,不是总线损坏。

程序应:

  1. 打印对象地址和 Abort Code;
  2. 标记本对象不可用;
  3. 继续测试其他互不依赖的对象;
  4. 若它是当前功能必需对象,则停止该功能;
  5. 不用猜测的私有对象替代。

超时从四层排查

1. CAN 总线层

  • 是否能收到 0x701 Heartbeat;
  • 发送 0x601 是否得到 ACK;
  • TEC 是否持续增加;
  • 位速率是否都是 500 kbit/s。

2. Node-ID 和 CAN-ID

电机 Node 0x01 的默认 SDO:

请求 0x600 + 0x01 = 0x601
响应 0x580 + 0x01 = 0x581

若电机 Node-ID 已被厂家软件改成别的值,这两条编号也会一起改变。

3. 响应匹配

收到 0x581 还不够。客户端要核对 Index 和 Sub-index,不能把上一条请求或其他任务的响应当作当前结果。

同一时间只允许一个活动 SDO 请求,是本课程简化并发设计的重要规则。

4. 协议状态机是否持续运行

CANopenNode SDO API 返回大于 0 时,程序必须继续调用 CO_SDOclientUpload()CO_SDOclientDownload(),并给它正确的时间增量。只调用 Initiate 后就长时间阻塞,状态机不会自己完成。

写入超时后不要盲目重发

读取超时通常可以谨慎重试;控制字、目标位置等写入超时则存在不确定性:报文可能已经被设备执行,只是响应丢失。

运动写入超时后应:

  1. 停止自动重发;
  2. 读取 0x60410x6064
  3. 观察电机是否已经开始或完成动作;
  4. 根据真实状态决定后续操作。

对非幂等命令不停重发,可能造成重复动作。

一份有用的失败日志

TX 0x601 [8] 40 7D 60 00 00 00 00 00
RX 0x581 [8] 80 7D 60 00 00 00 02 06
SDO 0x607D:00 failed: abort=0x06020000 (object does not exist)

三行把请求、原始响应和程序解释连在一起。只有一句 read failed 几乎无法排错。

CANopenNode 官方 SDO Client 说明:SDO client