本帖最后由 grhr 于 2020-12-29 18:08 编辑
#申请原创# @21小跑堂
背景如果你是一位产品经理,老板跟你说,我们想要做伺服电机控制器,你负责这个产品。你会怎么规划? 如果是我,我首先想到的肯定是产品标准化。这在交付给客户使用的时候,就是一个标准品。所有拿到产品的客户,都按照某个国际都认同的一个标准去使用,客户按照这个标准去用,我们按照这个标准去开发,就能完美契合了呢? 这就有了今天的主题,CANopen。 CANopen相关的介绍在网上已经有了很多,这里就不重复去讲他的由来了。 通俗的说,他将一些CAN报文做了格式和内容的规定,使用方和开发方都按照这个规定进行开发,就比较契合了,产品做出来以后,供应商就可以推广各种不同的客户,降低开发周期。 CANopen是一个比较大的概念,会分为不同的系列,通用的为DS301就是一个通讯协议栈。在此基础上进行二次开发,DS402是建立在DS301的基础上,专注在伺服控制。
本人不才,之前实际负责过CANopen的开发工作,将自己的一些见解以及实测报告截图分享给各位。
就通信而言,我们一般会想到这几个问题: (1) 系统如何和驱动器建立通信; (2) 系统实时知道总线上有没有驱动器掉线; (3) 驱动器一旦发生紧急情况,需要及时告诉系统:我有异常! (4) 直接复位和重启驱动器; (5) 可以配置驱动器,给驱动器下发指令,系统和驱动器都知道报文是什么意思; (6) 可以一条发送一条返回,也可以同时交互大量数据,以便交互更全面的信息。 (7) 我发送的报文如果没有在驱动器内部定义其含义,驱动器会告诉我吗? 针对上述问题,CANopen均给出了答案。
问题1: 系统如何和伺服驱动器建立通信? 说白了,三个过程,匹配ID → 主动上报我通信状态 → 不断主动发心跳报文刷存在感
1.匹配ID 一般而言,一个大型的运动机构,不止一个轴,需要一个系统配上很多个伺服电机驱动器,共同完成大型设备的运转。他们都是挂在同一个CAN总线上的,通过CANopen DS402协议完成信息交互。
通俗的说,CAN报文的通信格式为:CAN-ID+数据长度(DLC)+报文内容、 下图是我调试CAN通信的界面,无论是发送还是接收区,均按照这三个元素表征CAN通信的属性。 为了区分不同的驱动器,将每个驱动器都进行编码(NodeID),这样就能区分不同轴了。 CAN-ID在CANopen中的概念是COB-ID。他包含node ID的,不同报文类型,COB-ID也是不同的。
比如你正在控制的驱动器的node ID为D,而系统想发SDO类型报文,那发送报文的CAN-ID为60D,驱动器返回的ID为58D。 一旦正确返回了,表征ID匹配好了。
2.主动上报我通信状态 COB-ID的内容大致就这样。 数据长度,一般说来都是8个byte,除非有特定的功能,为了减小通信时间,一般会少于8个byte。 根据CANopen标准,通信状态流程图如下:
上述状态转移(1~6)的实现方式,是在报文的内容中如下规定: 1;start remote node(0x01) 2:stop remote node(0x02) 3:enter pre-operational(0x80) 4:reset node(0x81) 5;reset communication(0x82) 6:设备初始化结束,走动进入pre operational模式,发送boot-up状态。 由上文表述,初始化完成后,驱动器会先boot-up,自动进入pre-operation模式。 还是以node-ID为D举例,详细说明过程。 Boot- up:当驱动器上电以后,为了提示系统它已经加入网络(便于热插拔),或者避免与其他从站Node-ID冲突。这个从站必须发出节点上发报文。节点上线报文的ID为为700h+Node-ID,数据为1个字节0。本控制器的Node-ID为D,因此报文此时CAN-id为70d。 这时候,相当于伺服驱动器和系统说,我来啦!
3.不断主动发心跳报文刷存在感 第一次上报以后,CANopen开始进行心跳报文的发送,数据为1个字节,代表节点目前的状态,04h为停止状态,05h为操作状态,7Fh为预操作状态。
当发送进入start remote node(ox01)报文时,驱动器进入operation状态,心跳报文的值为05
01的后面,本例为node-ID,即专门控制某个驱动器,如果这是00,则表征广播报文,控制所有驱动器。 至此,通信就建立以来了。
问题2: 系统实时知道总线上有没有驱动器掉线——心跳报文 驱动器需要定时的项系统上发送心跳报文,告诉系统,我还活着,系统如果时间长了收不到心跳报文,则表征可能掉线了。 还是以刚刚的例子。后面驱动器就不断周期性(40ms)向系统发送心跳报文,内容为7F(表征状态为preoperational),表征自己还活着。
问题3: 驱动器一旦发生紧急情况,需要及时告诉系统:我有异常!——紧急报文 紧急报文,驱动器在断电后会发送一条紧急报文,告诉系统其状态。这里要注意,驱动器外部断电后,其电容电量能保证其发送该条报文。由于各家定义可能有点区别,不再实际举例。
问题4:直接复位和重启驱动器 本条在刚刚的状态切换流程中也有体现。可以复位单个驱动器,也可以全部一起复位。一般的格式为:
问题5:可以一条发送然后一条返回,驱动器也可以同时反馈大量数据,以便系统知道驱动器更全面的信息——SDO/PDO SDO比较简单,类似串口通信时一发一回,系统发送请求帧,驱动器回复应答帧。 而PDO分为TX-PDO,RX-PDO,就相对复杂一些,他是同时发送或者接受一堆报文。为了提升效率,他是没有返回报文的。 发送和接收的一堆报文,具体的含义(PDO的报文是哪个对象字典映射出来的)和传输方式(同步还是异步?),都需要提前使用SDO命令设置好。 由前文的图,PDO和SDO的COB-ID完全不同,ID值更小一些。
规定好映射方式,即PDO传输的是哪个对象字典的内容,加上是以什么方式进行传输(同步还是异步?),PDO就能传输大量的数据了。
问题6:可以配置驱动器,给驱动器下发指令,系统和驱动器都知道报文是什么意思——对象字典 这里就设计到对象字典(object dictionary,OD)的概念了。 通俗的说,就是将一般数据的报文(8个byte)进行具体的定义,前4个byte作为属性,即表征发的数据准确含义是什么,后4个byte是实际数据。 前4个byte中的第一个byte表示发送有效数据的属性,包括是发送还是接收,发送或接收的数据长度,一般说来,例如0x23表示是发送数据,发送4个byte。2b表示发送2个byte,2f为1个byte。 前4个byte中的后三个byte,指的是本报文具体对象的具体含义,就像查字典一样,查目录就能找到具体含义,这也就是对象字典这个名字的由来。 于是这描述属性的三个byte称之为index(前两个byte)即subindex(后一个byte)。 再最后,表示的是具体内容。
说这些有点没概念,举个例子:从DS402的对象字典列表中看到有6040的index,这是一个OD。他是一个uint16类型的。
CAN报文的发送和接收为:
报文具体解析如下: (1)发出去60D,返回的COB-ID为58D。 (2)2b表示类型为uint16,即只有2个byte的有效位。正确的返回值为0x60 (3)604000是对象字典,即index为6040,subindex为00. (4)后面的08073412,为数据。通过观测界面看实际得到的数据为下图。可以看到尽管写入的数据较长,但是实际上只有0x3412是有效数据,因为他是uint16类型
问题7:我发送的报文如果没有在驱动器内部定义其含义,驱动器会告诉我吗?——诊断报文 当然可以了。 如果你发送的报文数据类型和规定的类型不一致,则会报错; 显著的特点是:第一个byte为0x80,后面为索引和自索引,再后面就是故障码。例如下文中的就是06070013的故障码。
一般而言,也会有一个表格,详细阐述通信的故障码的。例如:
总结
好啦,全部讲完了。怎么建立通信的,通信后主要干嘛,通信的诊断,全部讲完了。
|
请问系统向驱动器发送命令到驱动器响应,这个传输过程的时间周期能计算出来嘛?