4. 通信对象概述:PDO、SDO、NMT、SYNC、EMCY、TIME、LSS等通信对象简介

好,咱们进入正题。CANopen 协议里,设备之间怎么说话?靠的就是这些通信对象。说白了,它们就是一套标准化的“信使”,每种信使干不同的活。

我个人习惯把 CANopen 的通信对象分成两类:一类是“实时数据”的搬运工,另一类是“管理控制”的传令兵。你想想看,一个电机驱动器,既要实时上报转速,又要能远程修改参数,这两件事对实时性的要求完全不同。所以协议把它们分开了。

4.1 PDO(过程数据对象)—— 快车道上的数据

PDO 是 Process Data Object 的缩写。它的特点就一个字:快。

为什么快? 因为 PDO 报文里没有协议索引,直接就是数据。一个 CAN 帧最多 8 个字节,PDO 可以塞满这 8 个字节,不浪费一点带宽。

我在项目中遇到过这样一个坑:有个同事把电机的位置、速度、电流三个值都映射到一个 PDO 里,结果发现数据更新频率上不去。后来一查,这三个值加起来超过 8 个字节了,被拆成了两个 PDO。嗯,这里要注意,PDO 的映射长度不能超过 8 字节。

PDO 的两种传输方式:

  • 同步 PDO: 收到 SYNC 消息后,统一发送。适合需要严格同步的场景,比如多轴联动。
  • 异步 PDO: 事件触发或定时发送。比如温度超过阈值就发,或者每 100ms 发一次。

我的小技巧: 调试阶段,我习惯把 PDO 设为事件触发模式,这样每次数据变化都能抓到。量产时再改成定时发送,减少总线负载。

4.2 SDO(服务数据对象)—— 慢车道上的配置

SDO 是 Service Data Object 的缩写。它跟 PDO 正好相反,特点是:慢,但可靠。

SDO 采用“请求-应答”模式。你发一个请求,设备回一个应答。如果没收到应答,主站会重发。这种机制保证了数据不会丢,但代价就是慢。

SDO 的典型应用场景:

  • 设备上电后,通过 SDO 配置参数(比如 PID 系数、限位值)。
  • 读取设备版本号、序列号等非实时信息。
  • 修改对象字典里的任意条目。

我曾经犯过一个错误:在电机高速运转时,通过 SDO 修改了电流环的 PI 参数。结果电机当场抖动了一下,差点撞机。后来我学乖了,改参数前先让设备进入 Pre-Operational 状态。

警告: 不要在设备运行时频繁使用 SDO 修改关键参数。SDO 的响应时间不确定,可能造成系统不稳定。

4.3 NMT(网络管理)—— 设备的“生老病死”

NMT 是 Network Management 的缩写。它负责控制设备的状态机。

CANopen 设备有四个状态:

状态 说明 能干啥
Initialisation 初始化 上电后自动进入,完成后自动跳转
Pre-Operational 预运行 只能 SDO 通信,不能 PDO
Operational 运行 PDO 和 SDO 都可以用
Stopped 停止 只能响应 NMT 命令,其他都不行

NMT 命令由主站发出,从站必须响应。比如主站发一个“启动远程节点”的命令,从站就从 Pre-Operational 进入 Operational。

我记得有一次调试,设备怎么都进不了 Operational 状态。查了半天,发现是心跳报文没配置好,主站以为从站死了,一直不给启动命令。嗯,NMT 和心跳是绑定的,这个后面会细讲。

4.4 SYNC(同步对象)—— 大家一起动

SYNC 是一个特殊的 CAN 报文,它的 COB-ID 是 0x80。主站定期发送 SYNC,所有从站收到后,同时更新输出或采集输入。

为什么需要 SYNC? 你想想看,如果三个电机各自按自己的节奏发 PDO,那它们的位置数据就不是同一时刻的。用 SYNC 同步后,所有电机在同一时刻锁存数据,然后一起发上来。这样上位机拿到的就是“快照”。

我在做多轴同步控制时,SYNC 周期设成了 1ms。结果总线负载飙到了 80% 以上。后来把不重要的 PDO 改成异步发送,只让关键数据走同步,问题就解决了。

SYNC 的注意事项:

  • SYNC 的发送周期要合理,太短会占用大量带宽。
  • 所有从站的时钟偏差要尽量小,否则同步效果会打折扣。
  • 如果某个从站没收到 SYNC,它会用上次的数据继续运行,直到超时。

4.5 EMCY(紧急对象)—— 出事了!

EMCY 是 Emergency 的缩写。当设备检测到严重错误时,它会主动发一个紧急报文。

紧急报文的格式很简单:

COB-ID: 0x80 + Node-ID
数据: 错误码 (2字节) + 错误寄存器 (1字节) + 制造商特定 (5字节)

比如电机过流了,错误码是 0x2310。主站收到后,可以立即采取行动,比如切断电源。

我曾经遇到过一个问题:设备频繁发 EMCY,但错误码是 0x0000(无错误)。后来发现是硬件干扰导致报文被误触发。嗯,EMCY 的触发条件一定要设置好,别让噪声也来凑热闹。

4.6 TIME(时间对象)—— 对表

TIME 对象用于同步所有设备的时间。它基于 CANopen 的时间戳协议,精度可以达到微秒级。

说实话,TIME 对象在工业现场用得不多。大多数应用靠 SYNC 就够了。但在一些需要精确时间戳的场景,比如数据采集系统,TIME 就派上用场了。

我记得有个项目,客户要求记录每个报警发生的时间,精度到 1ms。我们就是用 TIME 对象来同步所有从站的时钟,然后在报警时打上时间戳。

4.7 LSS(层设置服务)—— 改节点 ID 不求人

LSS 是 Layer Setting Services 的缩写。它的作用很简单:在线修改设备的节点 ID 和波特率。

你想想看,如果设备已经装到机柜里了,要改节点 ID 还得拆开外壳拨 DIP 开关,多麻烦。LSS 允许主站通过 CAN 总线直接修改这些参数。

LSS 的典型流程:

  1. 主站发送 LSS 请求,询问“谁是供应商 ID 为 0x123,产品代码为 0x456 的设备?”
  2. 匹配的设备应答。
  3. 主站发送“把你的节点 ID 改成 5”。
  4. 设备保存新 ID,然后重启。

避坑指南: 我曾经在批量配置设备时,忘了检查 LSS 的应答超时。结果有一台设备没收到命令,节点 ID 没改过来,导致总线冲突。后来我加了个重试机制,连续三次没应答就报错。

4.8 总结一下

这些通信对象各有各的用途:

  • PDO: 快,用于实时数据交换。
  • SDO: 慢但可靠,用于参数配置。
  • NMT: 控制设备状态。
  • SYNC: 同步所有设备。
  • EMCY: 报告紧急错误。
  • TIME: 时间同步。
  • LSS: 在线修改节点参数。

实际项目中,PDO 和 SDO 用得最多,NMT 和 EMCY 是标配,SYNC 看需求,TIME 和 LSS 属于锦上添花。你根据应用场景选就行。

下一章,我会详细讲 PDO 的映射和配置,这是 CANopen 开发中最容易出问题的地方。到时候咱们再细聊。