1. 为什么一台伺服上电之后,真正决定它"听不听话"的是CiA402
干了几年运动控制的人大概都有过这种体验:硬件接线没问题,总线能扫到节点,SDO 也能读写,可电机就是不转,或者一给使能就报警。折腾半天,最后发现是状态机里某个位没对上,或者模式切换的顺序不对。这类问题的根源,几乎都绕不开一套东西——CiA402 伺服协议。
CiA402 是 CANopen 体系里针对驱动与运动控制设备的一份设备行规(Device Profile),后来被纳入 IEC 61800-7-201/202 标准,成为工业伺服、变频器、步进驱动器之间事实上的"通用语言"。它规定了驱动器的状态机、对象字典、工作模式、控制字与状态字的位定义。换句话说,不管你是用 CANopen、EtherCAT(CoE)还是别的基于这套行规的实时以太网,只要驱动器标称"符合 CiA402",那么它的使能流程、模式切换、参数结构就是同一套逻辑。学会了它,你换一个品牌的驱动器,可能只需要改几个厂商特定的对象索引,核心操作几乎不用重学。
我写这篇东西的出发点很简单:网上讲 CiA402 的资料,要么是直接把标准文档翻译一遍,术语满天飞,看完比不看还懵;要么是某一家驱动器的说明书,只讲自己那个型号,换台设备就抓瞎。而真正在项目里踩过的坑——比如"为什么模式切换非要先失能再切"、"PP 模式里 target reached 到底什么时候置位"、"CSP 模式下不给同步信号电机为什么会飞车"——这些很少有人系统讲清楚。
这篇文章适合三类人:刚接触伺服调试、想搞懂状态机每一步在干嘛的新手;做过 CANopen 但不熟悉多模式切换的工程师;以及想从 PLC 逻辑控制转向运动控制、需要补这块知识的人。我不打算照本宣科地复述标准,而是按照一个真实项目的落地顺序,把状态机怎么走、对象字典要背哪些、九种工作模式怎么选、模式切换怎么实现、出问题怎么排查这几件事讲透。每一段我都会补上"为什么这么做"和"我当时是怎么做的",能直接抄作业的地方尽量给到参数和时序。
2. 状态机是整套协议的骨架,先把这台"变速箱"吃透再谈模式
2.1 八个状态与四条跃迁路径
CiA402 最核心、也是最容易被忽略的东西,不是工作模式,而是状态机。你可以把它理解成汽车的变速箱挡位:模式是"你要往哪个方向开",而状态机是"现在挂的是空挡、前进挡还是已经熄火"。挡位不对,方向再对车也不动。
标准定义了八个状态:
- Not Ready to Switch On:驱动器内部自检、初始化阶段,外部控制字此时无效。
- Switch On Disabled:初始化完成,等待上位机指令,此时功率级是断开的。
- Ready to Switch On:已经允许上电,但功率输出还没使能。
- Switched On:功率级已供电,但电机轴仍然处于自由状态(无力矩输出)。
- Operation Enabled:真正的工作状态,电机通电并跟随指令,这是所有运动模式运行的前提。
- Quick Stop Active:接收到快速停止命令后的减速状态。
- Fault Reaction Active:检测到故障后的处理状态,会执行厂商定义的停机动作。
- Fault:故障已锁定,必须通过复位命令才能退出。
这八个状态之间的迁移,全部由**控制字(Controlword,索引 0x6040)的位组合触发,而当前处于哪个状态,则通过状态字(Statusword,索引 0x6041)**读回。这就是为什么调试伺服时你总在写 0x6040、读 0x6041——它们俩就是你和驱动器对话的遥控器与反馈表盘。
很多人第一次看状态图会觉得线很多、很乱,其实抓住主干就够了:从上电到能跑,只有一条最短路径。Switch On Disabled → Ready to Switch On → Switched On → Operation Enabled,四步,对应四个控制字命令,我后面会给出具体的十六进制值。
2.2 控制字与状态字的位级对照
要能一眼看懂调试软件里那一串十六进制,必须把位的含义记牢。控制字 0x6040 里最常用的几位如下:
| 位 | 名称 | 含义 |
|---|---|---|
| bit0 | Switch On | 请求进入 Switched On |
| bit1 | Enable Voltage | 允许功率级上电 |
| bit2 | Quick Stop | 写 0 触发快速停止(低有效) |
| bit3 | Enable Operation | 使能运行,进入 Operation Enabled |
| bit4~bit6 | 模式相关 | 不同工作模式下含义不同 |
| bit7 | Fault Reset | 故障复位,上升沿有效 |
| bit8 | Halt | 暂停,按停机斜坡减速 |
| bit9 | 模式相关 | 例如 PV/CSP 下的"不减速停止" |
状态字 0x6041 里对应的关键位:
| 位 | 名称 | 含义 |
|---|---|---|
| bit0 | Ready to Switch On | 已准备好上电 |
| bit1 | Switched On | 已进入 Switched On |
| bit2 | Operation Enabled | 已使能运行 |
| bit3 | Fault | 故障标志 |
| bit4 | Voltage Enabled | 主回路电压已建立 |
| bit5 | Quick Stop | 快速停止未激活(正常时为 1) |
| bit6 | Switch On Disabled | 处于禁止上电状态 |
| bit7 | Warning | 警告 |
| bit9 | Remote | 远程控制有效 |
| bit10 | Target Reached | 目标到达 |
| bit11 | Internal Limit Active | 内部限制生效 |
| bit12/bit13 | 模式相关 | 见各模式说明 |
注意:状态字 bit5 是低有效的"反向逻辑"。正常情况下它应该读到 1,如果读成 0,说明 Quick Stop 被触发了,此时无论你怎么写控制字都使能不起来。我见过不止一个人卡在这里,盯着控制字看半天,问题出在状态字。
2.3 上电使能的完整时序推演
现在把上面两张表拼起来,走一遍最经典的使能流程。假设驱动器已经把状态字报回了0x0250(bit6 Switch On Disabled = 1,bit4 Voltage Enabled = 1),说明初始化完成、主回路已上电,等待指令。
第一步,发Shutdown,控制字写0x0006(bit1 + bit2)。bit2 Quick Stop 写 1 表示"取消快速停止",bit1 允许电压。执行后状态字应该变成0x0021,即 Ready to Switch On。
第二步,发Switch On,控制字写0x0007(bit0 + bit1 + bit2)。执行后状态字变成0x0023,进入 Switched On,功率级已供电但电机还没出力。
第三步,发Enable Operation,控制字写0x000F(bit0~bit3 全 1)。执行后状态字变成0x0027,此时 bit2 Operation Enabled 置位,电机开始跟随指令。
这三步之间的间隔,很多驱动器并不要求严格延时,但我在项目里习惯每步之间给 10~20ms 的余量。原因是有一次用某个品牌的驱动器,连续无延时下发这三个命令,偶发出现状态字还在过渡中就收到下一条命令,导致跳到 Fault。后来加了小延时,再没出现过。这是经验,不是标准要求,但值得留意。
如果中途要停机,正常停走Disable Operation(0x0007),回到 Switched On;要彻底断电走Disable Voltage(0x0000),回到 Switch On Disabled。
3. 对象字典三千条,真正要背下来的其实就十几个
3.1 通用对象与模式专属对象分层
CiA402 的对象字典条目很多,但按使用频率分,你会发现常用的就那么十几个。我把它们分成两层:通用层(所有模式都用)和模式专属层(只在特定模式下有意义)。
通用层里,你几乎每次通讯都要碰的:
0x6040Controlword、0x6041Statusword:状态机遥控器。0x6060Modes of Operation:写入,设定当前工作模式。0x6061Modes of Operation Display:读回,确认模式真的切过去了。0x6064Position Actual Value、0x606CVelocity Actual Value、0x6077Torque Actual Value:三个实际值反馈。0x603FError Code:故障码,报警时第一个要查的。0x607DSoftware Position Limit:软件限位,sub1 是最小值、sub2 是最大值,防止机械撞限位。0x6502Supported Drive Modes:读回驱动器支持哪些模式,选型时非常有用的一个对象。
模式专属层按模式分:PP 模式关心0x607A目标位置、0x6081轮廓速度、0x6083加速度、0x6084减速度;PV 模式关心0x60FF目标速度;PT 模式关心0x6071目标转矩、0x6087转矩斜坡;HM 回零关心0x6098回零方法、0x6099回零速度、0x609A回零加速度;CSP/CSV/CST 这几种周期同步模式则关心0x60C2插值周期以及各自的目标值对象。
提示:
0x6502这个对象在新设备上手时特别值钱。它用位掩码告诉你驱动器到底支持哪几种模式,比如 bit0 表示支持 PP,bit3 表示支持 PV,bit8 表示支持 CSP。有一次我拿到一台驱动器,怎么配 CSP 都不动,读了这个对象才发现它根本不支持 CSP,白折腾一下午。
3.2 用户单位换算:位置和速度到底怎么算
新手最容易栽的一个坑,是"我明明写了目标位置 10000,为什么电机转了好大一圈"。这背后就是**用户单位(User Unit)**的换算问题。CiA402 里位置、速度都用"用户单位"表达,而这个单位是由减速比0x6091和进给常数0x6092决定的。
0x6091Gear Ratio,sub1 是电机转数、sub2 是负载轴转数,也就是"电机转 sub1 圈,负载转 sub2 圈"。0x6092Feed Constant,sub1 是进给量、sub2 是负载轴转数,意思是"负载轴转 sub2 圈,负载移动 sub1 个单位"。
我拿一个具体例子算一遍。假设编码器是 20 位,即每圈 1048576 个计数(count);电机和负载之间减速比是 1:1;我用旋转台,我把进给常数设成"一圈对应 3600 个用户单位"(也就是每个单位 0.1 度)。
那么,每转一圈的用户单位数= 3600。每个用户单位对应多少计数= 1048576 / 3600 ≈ 291.3 个计数。反过来,如果你想让电机以 10 圈/秒转动,目标速度0x60FF或0x6081就应该写 36000 单位/秒。
这套换算看起来麻烦,但好处是:一旦设好,上层的控制器就完全按工程单位思考——角度用 0.1 度、直线轴用微米、速度用单位/秒,不用关心底层编码器分辨率。这也是 CiA402 设计用户单位的初衷:让机械工程师用机械的语言描述运动,让驱动器去做底层换算。我建议在项目一开始就把0x6091和0x6092按机械参数配好,后面所有目标值都按用户单位给,别中途改,否则所有已配好的数值都要重新算。
3.3 SDO 与 PDO 的分工,决定了系统的实时性
对象字典里的数据怎么读写?靠 SDO 和 PDO 两套机制。SDO 是"配置通道",一问一答,可靠但有握手开销;PDO 是"数据通道",周期广播,实时性高但不保证送达。原则很简单:参数配置用 SDO,实时指令用 PDO。
具体来说,模式选择0x6060、加减速0x6083/0x6084、限位0x607D这些改一次就长期不变的,全部走 SDO;而控制字0x6040、目标位置0x607A、目标速度0x60FF这些每个周期都要刷新的,必须走 PDO。控制字如果不走 PDO,靠 SDO 一条条发,那响应速度根本撑不起运动控制,一秒钟也就几条命令,电机只会一顿一顿的。
PDO 的映射在通信初始化阶段(Pre-Operational 状态)用 SDO 配置好,包括传输类型、映射对象、映射长度。映射长度尤其要小心,比如把0x6040(16 位)和0x607A(32 位)映射到同一个 TPDO,要清楚哪个在前哪个在后、总共占几个字节。有一次我做主站,PDO 映射顺序和从站预期的对不上,控制字和位置值错位,结果电机收到的"控制字"其实是位置的半个字,直接乱套。这个教训后面排查部分还会展开。
4. 九种工作模式逐一拆解,什么时候用哪种心里得有数
4.1 点位模式 PP 与插值模式 IP:定长运动选谁
PP 模式(Profile Position,模式号 1)是定长运动里用得最多的一种。上位机给一个目标位置,驱动器按照你设的轮廓速度、加速度、减速度自己规划一条梯形或 S 形速度曲线,走完置位 Target Reached。它最大的好处是运动规划下放到驱动器,主站只要发指令,不用每个周期算轨迹,总线负载低。
PP 模式下控制字 bit4 是 New Set-point,需要上升沿触发;bit5 是 Change Set Immediately,决定当前点走到一半时来了新点,是"停下来重新规划"还是"走到当前点再走新点";bit6 是绝对/相对位置选择。状态字 bit10 是 Target Reached,bit12 是 Set-point Acknowledge,这两个位的时序关系是判断驱动器有没有收到新点的关键——bit12 会随着你 bit4 的上升沿翻转,可以用来确认"我发的新点驱动器真的吃了"。
IP 模式(Interpolated Position,模式号 7)则是另一条路:主站把每个插值周期的位置点连续下发,驱动器做插值平滑。它适合轨迹已知、需要严格同步的场合,比如多轴联动的曲线插补。缺点是对主站周期性要求高,主站一卡,轨迹就抖。
选型逻辑很清楚:单轴定长、主站压力大选 PP;多轴联动、轨迹预先规划选 IP。我在做单轴模组上下料时一律用 PP,简单稳;做龙门双轴同步才会上 IP 或后面要讲的 CSP。
4.2 速度与转矩:PV、PT 各自的适用面
PV 模式(Profile Velocity,模式号 3)只有速度目标0x60FF,外加加减速0x6083/0x6084,速度本身靠驱动器做斜坡。它适合连续运转类应用,比如传送带、卷绕、风机。控制简单,但位置不闭环,不能停到确定位置。
PT 模式(Profile Torque,模式号 4)目标对象是0x6071,可以理解成"我要让电机输出多少力矩"。它常用于张力控制、压装、力控场合,比如拧螺丝、压合。用 PT 一定要慎重,因为转矩是直接控制量,参数给大了就是硬撞,机械上要有限位和缓冲保护。
我个人的经验是:能用位置控制就别用转矩控制,转矩模式对机械刚性和参数整定要求高得多。实在需要力控,也尽量在 PT 外面套一层位置或速度环做外环,让机器有"兜底"。
4.3 回零 HM:机器每次上电的起手式
增量式系统上电后不知道自己在哪,必须回零。HM 模式(Homing,模式号 6)就是干这个的。核心对象是0x6098回零方法,标准里定义了 1~35 号方法(还有负数是厂商特定方法),对应"往哪个方向找、找到哪个信号作为零点、要不要找 Z 相"等等组合。常见的比如方法 17 是往负方向找限位开关、方法 35 是以当前位置为零点。
0x6099是两段回零速度:sub1 是寻找开关时的速度,sub2 是找到开关后精找 Z 相的速度。0x609A是回零加速度。HM 模式下控制字 bit4 是 Start Homing,状态字 bit12 是 Homing Attained、bit13 是 Homing Error。
回零这块最常见的坑是速度太快。高速撞限位,机械冲击大,还有可能过冲导致 Z 相信号错过。我的习惯是:找开关速度设为额定速度的 1/5 左右,精找 Z 相速度再降到 1/20,宁可慢一点,稳。
4.4 周期同步 CSP、CSV、CST:真正意义上的实时运动
前面几种模式,驱动器都在做"自主规划",主站给的是"终点"或"段"。而CSP(Cyclic Synchronous Position,模式号 8)、CSV(模式号 9)、CST(模式号 10)是另一套哲学:主站每个同步周期下发一次目标值,驱动器只负责插值和执行,不做规划。
CSP 下,主站每个周期写0x607A目标位置,驱动器读0x6064实际位置,两者之间的偏差由驱动器内部的位置环去追。同步周期由0x60C2的插值周期决定,常见配置是 1ms。这类模式下,同步信号一旦中断,驱动器得不到新目标值,通常会按最后一次目标保持,或者报同步错误,具体行为看厂商实现。
CSP 是数控、机器人这类要求多轴严格插补场合的首选。但它对主站的实时性和总线抖动极其敏感。我踩过最惨的一次坑:主站因为一个任务调度问题,同步周期偶尔抖到 5ms,结果多轴插补出来的轨迹出现明显的接刀痕,肉眼就能看到。后来把通信任务优先级调到最高、用实时系统,才解决。
到这里九种模式过完了。我整理了一张对照表,方便选型时快速定位:
| 模式 | 编号 | 目标对象 | 典型场景 | 规划方 |
|---|---|---|---|---|
| PP | 1 | 0x607A | 单轴定点、上下料 | 驱动器 |
| PV | 3 | 0x60FF | 传送带、卷绕 | 驱动器 |
| PT | 4 | 0x6071 | 张力、压装 | 驱动器 |
| HM | 6 | 0x6098 | 上电回零 | 驱动器 |
| IP | 7 | 0x60C1 | 多轴插补 | 主站+驱动器 |
| CSP | 8 | 0x607A | 数控、机器人 | 主站 |
| CSV | 9 | 0x60FF | 速度同步轴 | 主站 |
| CST | 10 | 0x6071 | 力控协同、牵引 | 主站 |
5. 多模式切换实战:从状态机到 PDO 的完整落地
5.1 为什么模式切换必须"先失能、再改、后使能"
这是个新手最容易问的问题:"我能不能在 Operation Enabled 状态下直接改0x6060?"答案基本是不行,或者说,能做也千万别做。
原因在于状态机本身。0x6060写入只在特定状态下被驱动器接受生效,而且切换模式会改变目标对象(比如从0x607A变成0x60FF),如果电机还在使能状态运行,瞬间换了目标对象含义,驱动器内部的位置环/速度环会收到一个不连续的目标跳变,轻则电机猛窜、报警,重则伤机械。
我在标准里看到的是"模式切换应在 Operation Enabled 之前完成",落到实操上,稳妥的范式是这样:
- 发 Disable Operation(
0x0007),从 Operation Enabled 退回 Switched On; - 通过 SDO 写
0x6060目标模式; - 读回
0x6061,确认模式真的切过去了; - 切换与该模式相关的 PDO 映射(这一步在 Pre-Operational 阶段做,或者用动态映射);
- 发 Enable Operation(
0x000F),进入 Operation Enabled。
注意:第 3 步读
0x6061是必须的,不能写完就假设切成功。有些驱动器不支持某些模式,写0x6060会被忽略,0x6061还是旧值。不检查的话,你以为切到了 CSP,其实还在 PP,后面发目标值自然对不上。
5.2 一次 PP 到 CSP 的完整切换时序记录
我拿项目里一次真实的切换过程记录一下,场景是:设备上电先做 PP 模式的回零定位,然后切到 CSP 做多轴插补。
上电后状态字0x0250,走标准使能:0x0006→0x0021,0x0007→0x0023,0x000F→0x0027。此时0x6060写 1(PP),设0x6081为 36000、0x6083为 360000、0x6084为 360000,0x607D限位设 -360000 到 360000。写0x607A目标位置 18000,控制字发0x000F | 0x0030(bit4 New Set-point + bit5 Change Immediately),观察状态字 bit10 置位后,定位完成。
现在切 CSP。先0x0007失能,状态字回0x0023。SDO 写0x6060= 8,读回0x6061= 8,确认。此时如果 CSP 的 PDO 映射和 PP 不一样,就要重新配置。我把 RPDO 映射从"控制字 + 目标位置"保持不变(其实这俩对象两个模式共用),TPDO 加了"状态字 + 实际位置 + 实际速度"。重新进 Pre-Operational、配 PDO、回 Operational。然后写0x60C2sub1 = 1(插值周期 1ms),sub2 = -3(表示 10 的 -3 次方秒)。
最后0x000F使能,进入 CSP。从这一刻起,每个 1ms 周期,主站往0x607A写新目标位置。第一帧目标值我习惯写成"当前实际位置"(读0x6064),避免切换瞬间位置环有一个大偏差导致猛冲。这是个小技巧,但很管用。
5.3 PDO 映射的实操细节与动态切换
PDO 映射配置,英文叫 mapping,本质是告诉驱动器"这个 PDO 里按顺序装了哪几个对象、每个多长"。它在 Pre-Operational 状态下用 SDO 写0x1600(RPDO 映射)和0x1A00(TPDO 映射)完成。
配置顺序有个讲究:先把映射条目数0x1600sub0 写成 0(清空),再逐条写 sub1、sub2……,最后写回条目数。为什么?因为如果你先写了条目数、再改里面的对象,驱动器可能认为映射非法,或者实际生效的是旧的那一版。顺序反了,症状是"我明明映射了新对象,可 PDO 里传的还是旧的"。这个坑我踩过,后来养成习惯,先清零再配。
映射长度要自己算清楚。比如映射三个对象:0x6040(16 位)、0x607A(32 位)、0x60FF(32 位),总长度就是 2+4+4=10 字节。如果映射长度和实际对象长度对不上,或者各个 PDO 之间字节数冲突,驱动器会报映射错误。有些驱动器支持动态 PDO 映射(在 Operational 状态下也能改),有些不支持,配置前最好查手册。不支持动态映射的,就得走"CSP 用一套固定 PDO、所有模式共用同一套映射"的路子,把所有可能用到的对象都映射进来,虽然浪费几个字节,但省去了每次切换都要回 Pre-Operational 的麻烦。
6. 常见问题与排查技巧实录
6.1 问题速查表
调试这么久,问题看着五花八门,其实类型高度集中。我把最常遇到的整理成表:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 使能不起来,状态字停在 0x0040 | 主回路电压没建立 | 查 bit4 Voltage Enabled |
| 状态字 bit3 置位,跳 Fault | 过流、编码器、参数错误 | 读 0x603F 故障码 |
| 写完控制字状态字无变化 | PDO 没映射控制字或映射错位 | 抓总线看 PDO 原始字节 |
| 模式切了但行为没变 | 0x6061 没确认或驱动器不支持 | 读回 0x6061、读 0x6502 |
| PP 模式目标走了但 Target Reached 不置位 | 到位窗口、速度过冲 | 查到位窗口参数、减速设置 |
| CSP 下电机抖动或飞车 | 同步周期抖动、目标值跳变 | 用实际位置作为首帧目标 |
| 回零找不到开关 | 速度过快、方向反、信号极性 | 降 0x6099 速度、查信号 |
6.2 那些文档上不写的坑
第一个坑:控制字的"写一次"和"每周期写"是两回事。有些驱动器要求控制字即使在 Operation Enabled 下,也要每个同步周期都写一遍(哪怕是同样的值),否则会超时报警。这在大网关上做转发时特别容易被忽略。我的做法是,只要走 PDO,控制字固定挂在 RPDO 里,每个周期都刷,不做"变化才发"的优化。
第二个坑:状态字要"边沿采集",别只看当前值。Target Reached、Set-point Acknowledge 这类位是瞬时的,尤其是 Acknowledge,它会翻转。如果你的主站采样周期比总线周期慢,很可能漏掉一次翻转,就误判成"驱动器没收到新点"。稳妥的做法是在从站侧做边沿锁存,或者主站用比总线快得多的周期轮询。
第三个坑:故障复位的时序。Fault Reset 是 bit7,上升沿有效。很多人写0x008F(保持 bit7 为 1),结果故障复位不了,因为驱动器等的是"上升沿"——你要先写0x0080,再写0x0000,形成一次 0→1→0。而且复位命令最好在状态字确实显示 Fault 之后再发,有时候故障刚发生、状态字还没来得及更新,你提前复位等于没发。
第四个坑:不要轻易在运行中改软件限位和回零参数。这类对象属于"配置类",改了要断电重载或者重新初始化才生效(具体看厂商)。我见过有人在运行中改0x607D限位,以为能实时生效,结果不生效还差点撞机。配置类的参数,改完老老实实走一遍重新初始化。
最后分享一个我个人的排查套路:用一根 USB 转总线工具直接挂在驱动器上,绕过 PLC,用上位机软件逐条发 SDO、看状态字。这样能把问题定位到"到底是驱动器的问题,还是主站程序的问题"。程序里全是对的、但就是不转,九成是 PDO 映射或时序问题;手动发 SDO 都不转,那就是驱动器配置或硬件问题。左右一对比,方向立刻就清晰了。这个方法帮我在好几次数小时的死磕里快速找到了病根,比盯着程序日志猜要高效得多。