CANopen协议的理解

本文的重点是对CANopen协议的理解,不是编程实现

参考链接

canopen快速入门 1cia301协议介绍_哔哩哔哩_bilibili

CANopen是什么? CANopen通讯基础(上)_哔哩哔哩_bilibili

CANopen概述

 

图1. CAN报文标准帧的格式

CAN的报文可简单的被分为帧ID和数据部分,由于其灵活性,在CAN通讯刚出来时,各个厂家一般根据自己的喜好进行编写协议,这最终导致了很混乱的局面。因此诞生CANopen协议,CANopen是由CIA组织提出的CAN的应用层协议,包含CIA301、CIA401、CIA402…,其中CIA301是CANopen中最基础的协议,规定基于帧ID和报文的分类用法,相当于定义了一个CAN报文框架。CIA401、CIA402…则是基于CIA301基础协议,针对不同类型的通讯器件,所制定的更具体的协议,比如CIA402就是驱动器协议,全球通用,很多驱动器厂商都会支持CIA402这种协议。

注意:CAN通信有标准帧和扩展帧的区别,本文仅考虑标准帧的情况。

CIA301基于帧ID的功能划分

CAN报文主要分为帧ID和数据两部分,CIA301协议,对ID部分进行了划分,把从低到高的各个ID划分成了不同区域,每个区域实现不同功能,根据ID的不同,决定CAN报文的类型,每种类型有不同的格式,所以后面的数据会根据格式进行拆解。

图2. CIA301协议基于帧ID的功能划分

在CANopen协议中,定义了一个概念,通讯标识符 Communication Object Indentifier,后续简写为COB_ID,COB_ID是CAN报文的唯一标识符,COB_ID本质上就是CAN报文中的帧ID。根据图1可知,标准帧的帧ID共有11位,也就是COB_ID有11位。CANopen协议将COB_ID分成了功能码(FUNCTION)和NodeID两个部分。其中功能码占4位,NodeID占7位,如图3所示,(图2的第2列的功能码ID位搞错了,应该是bits10~7)

图3. COB_ID格式

功能码的作用就是字面意思,不同的码值代表不同的功能,而NodeID代表的是CAN网络中的各个网络节点的编号,范围是1~127。这个NodeID号是设备自己定义的,比如我是一个驱动器,我可以给我自己定一个NodeID号,比如1。甚至我可以提供上位机的配置接口,去配置我的NodeID号。根据我的理解,同一个CAN网络中所有设备,NodeID号应不要重复。比如我是主控平台(Master),我要通过CAN网络分别去控制三个轴系的电机驱动器。那么这三个电机驱动器的NodeID不能一样,否则主控平台根据NodeID发送的指令不知道最终发给了谁。NodeID是用来辨识从设备的。

下面根据功能码,以从小到大的顺序,对CANopen的报文做一个分类。

图4. 基于功能码的CANopen报文分类

基于图4的内容,CANopen协议主要需要学习的报文为下表中的8种。

序号

报文分类

COD_ID

学习难度
简单 < 正常 < 地狱

是否重点学习

1

NMT

000H

简单

2

SYNC

080H

正常

3

EMCY

080H+NodeID

简单

-

4

PDO

从节点发送

TxPDO1~TxPDO4

180H+NodeID

280H+NodeID

380H+NodeID

480H+NodeID

从节点接收

RxPDO1~RxPDO4

200H+NodeID

300H+NodeID

400H+NodeID

500H+NodeID

地狱

5

SDO

主节点发送

600H+NodeID

主接点接收

580H+NodeID

正常

6

节点保护报文

700H+NodeID

简单

有的资料也把这3节点状态监控相关的报文统一在NMT这类报文中,本文也会

7

心跳报文

700H+NodeID

简单

8

Boot-UP启动报文

700H+NodeID

简单

 

CANopen协议报文详解

图5. CANopen协议报文的基本格式

图5是CANopen协议报文的基本格式,主要包含COB_ID和最多8个字节的数据部分。下面根据前文的分类对每一种报文进行详解。 在CAN网络中,存在主节点和从节点之分。在本文中,我们以单片机通过CAN连接驱动器控制电机为例。单片机为主节点,驱动器为从节点。

0 OD对象字典

在正式介绍CANopen协议报文之前,我们需要了解一个CANopen中用到的极其重要的一个概念,不得不吐槽网上很多资料对此部分不够重视。Object Dictionary,对象字典本质上就是一个表格,表格里面的内容都有其独特的含义作用。在CANopen编程中,我们大部分的时间都是在编写配置这个对象字典,来达到我们的目的。

以单片机通过CANopen和驱动器通信来控制电机为例,单片机是CAN网络的主节点,它有它的对象字典。驱动器是CAN网络的从节点,它也有它的对象字典。这两个对象字典都是需要编写配置的。

  1. 单片机的对象字典,一般是使用开源的对象字典工具软件(objdictedit)生成,我们需要学习该软件的使用,同时还须学习移植CanFestival开源库到单片机,CanFestivalobjdictedit要配合起来使用。
  2. 驱动器的对象字典,一般驱动器厂商会默认配置好。然后局部的内容,可以通过单片机通过SDO通信进行配置 或者 使用驱动器的上位机进行配置。

如果我们要读/写表格里面的内容,是不是需要知道它在表格的第几行第几列啊。 对象字典里面是用索引index和子索引sub-index来唯一确定这个表格每个数据的地址的。 有时候你还会发现对象字典里面某个索引/子索引对应的数据,竟然存放的是另外一个数据的索引/子索引。用C语言的话来说,它存的是指针,那存这个指针数据它本身的索引/子索引是什么?指针的指针。指针、地址、索引/子索引含义是一样的。怎么说?有没有被我成功的绕进去。 但对于对象字典的理解,本就是这么绕的,提前做好心理准备。

图6. 对象字典举例

图6所示是一个对象字典的局部内容。这里面有索引/子索引,有名称,有含义,还有位宽和读写属性。这里所展示的对象字典的局部,其实是CIA402协议里面所规定的内容,也就是说,所有使用CANopen协议的驱动器,它的对象字典里面,都是这样定义的。

图7. CANopen对象字典通用结构

图7所示为CANopen对象字典的通用结构,其中特别填充的部分是我们用的最多的。

  1. 1000h-1FFFh这个索引段,是用来配置通讯的。
  2. 6000h-9FFFh这个索引段是标准设备字协议区。解释一下,比如CIA401、CIA402…这些协议都是针对的是不同类型的设备。CIA402是针对驱动器设备的,CIA406是针对编码器设备的。 什么叫做标准设备子协议区,这个标准说明是意思就是固定。前面对图6的解释也讲过,所有支持CIA402的驱动器的对象字典索引为6040h、6060 h、607A h都固定是这个含义。
  3. 2000h-5FFFh这个索引段是制造商特定子协议区, 从两个层面去理解:
    1. 如果我是一个驱动器(从节点),这里面的内容由我驱动器的厂商自己去定义什么意思,自己去定义怎么用。我们在做单片机开发的时候,基本上不用管驱动器这部分的协议。
    2. 如果我是一个单片机(主节点),这里面的内容也是由我单片机自己去定义。

这么说可能有点抽象,比如我在配置PDO的时候,我可以配置2000h-5FFFh这里面的某个地址里面存储的内容是目标速度。然后在配置PDO通讯参数的时候,我把这个地址放在通讯参数里面,这里就是刚刚提到的指针的指针了,PDO后配置好之后就不用管了,往从机发PDO的时候,CANopen就会自动找到这个地址来把目标速度发送给驱动器。同时呢,我单片机的主程序,只需要修改这个地址里面的数据就可以,就等价于修改了目标速度。 这部分内容会在后文中进一步详细讲,如果没有理解透,通读一遍全文后再来读这里。

1 NMT网络管理报文

在开始正式介绍NMT网络管理报文之前,需要先介绍一个概念,CANopen协议的状态机。

图8. CANopen协议的状态机

如图8所示,CAN网络中的每一个从设备,都有会有一个状态,在不同状态下,可以执行不同的操作,有些操作比如e就只能在Operational这个状态才能执行。 下面我们来看abcdef分别代表什么。

a

NMT

网络管理

b

Node Guard

节点保护

c

SDO

服务数据报文

d

Emergency

紧急报文

e

PDO

过程数据报文

f

Boot-up

启动报文

另外,图8中有1,2,3,4,5,6,6种状态转移

1: Start Remote node (0x01)

2:Stop Remote Node (0x02)

3:Enter Pre-Operational State (0x80)

4:Reset Node(0x81)

5:Reset Communication (0x82)

6:Boot up

1.1 NMT状态转移报文 [ COB_ID:  000H ]

其中1~5的NMT报文只能从主节点(单片机)发送,所有从节点(驱动器)必须支持 NMT 服务。NMT报文不需要应答。NMT 报文格式如下:

图9 .NMT报文格式

其中CS是命令字,不同命令字代表不同的含义,Node-ID表示从节点的ID。 当Node-ID = 0时,则代表该指令是针对所有的从节点。 如果Node-ID≠0,则该命令仅针对该Node-ID。CS的取值及含义如下:

图10. NMT报文CS命令字的含义 

1.2 NMT BOOT-UP报文 [ COB_ID:  700H + NodeID ]

图8中的“6”状态转移,是Boot-UP, 是由从节点(驱动)发布Boot-UP报文通知主节点(单片机)它已经从initialising状态进入pre-operational状态。

图11. NMT Boot-UP报文

这个报文我们只需要做个了解,在实际编程的过程中,应该用不到。

1.3 NMT节点保护报文 [ COB_ID:  700H + NodeID ]

NMT节点保护报文的机制是,主节点(单片机)可以监视每个从节点(驱动器)的当前状态。主节点周期性的发送报文去询问从节点的状态,从节点收到主节点的问询后将自己的状态回复给主节点,在设定的时间内如果主节点没有收到从节点的信息或信息错误都会判断从节点通讯故障。下面给出主节点的询问报文和从节点的回复报文。

图12. NMT 节点保护报文

从图12中我们可以看出,主节点的询问报文只有COB_ID没有数据, 而从节点的回复报文是有一个字节的数据的。该字节又分成了Bit7 和 Bits6-0两个部分。 Bit7为触发位,在每次节点保护应答中交替“0”和“1”,在第一次节点保护时置0。下面给出Bit0 - Bit6状态表:

图13. 节点保护报文,从节点回复报文,Bit0-Bit6的状态表

图13中,有两个标记,第一个0x0被划掉了,因为这个状态0x0不会在NMT节点保护报文中出现,从节点一般是自己初始化后,发送Boot-UP报文到主节点,它自己呢,就会进入Pre-operational状态。 而不是我们通过NMT节点保护报文去询问得到。 第二个红色方框框住的是扩展帧才有的状态,我们不必去关注。 最后只剩下0x4 0x5 0x7F,即 Stoped / Operational / Pre-operational三个状态,是我们需要关注的。 不过节点保护报文是一问一答,效率不高,下面介绍心跳报文。

1.4 NMT心跳报文 [ COB_ID:  700H + NodeID ]

从节点还可被配置为产生周期性的被称作心跳报文(Heartbeat)的报文,从节点周期将该报文为发送给主节点,主节点可以通过报文中的状态值得知从节点的状态。

图14. 心跳报文的格式

其状态如下,与NMT节点保护报文是一样的。

图15. 心跳报文的状态表

简单说就是主节点你不用发询问报文了,我从节点直接周期性的发送状态过来,显然,心跳报文的效率更高,但从节点应该需要做一个配置,在后文中,我们会讲SDO通信,SDO通信主要就是用来配置从节点的。

2 SYNC同步报文 [ COB_ID:  080H ]

根据我的理解, SYNC同步报文应该是由主节点(单片机)发给从节点(驱动器)的,是广播式的,所有从节点都能收到同步报文,且不需要应答。SYNC是由主节点周期性地发送,每发送一个SYNC相当于一拍,所以可以实现整个从节点网络一拍一拍的进行,同步各个从节点的时钟。

图16. SYNC同步报文

如图16所示,同步报文只有个COB_ID,没有数据。

那么主节点(单片机)的同步报文是以什么样的周期发送给从节点(驱动器)呢? 这个就需要对主节点(单片机)的对象字典进行配置了。

对象字典中,有三个和同步报文相关的索引1005H、1006H、1007H

  1. 1005H索引规定了SYNC报文的COB-ID,这个一般不需要更改。
  2. 1006H索引规定了同步帧的循环周期,注意:单位是us
  3. 1007H索引规定了约束了同步帧发送后,从节点发送PDO的时效,即在这个时间窗口内发送的PDO才有效,超过时间的PDO将被丢弃。注意:单位也是us

3 EMCY紧急报文 [ COB_ID:  080H + NodeID ]

紧急报文一般来讲,也是CAN网络中从节点发给主节点的,比如从节点中驱动器,有编码器,当这些设备内部出现的致命错误的时候就会触发紧急报文的发送,以最高优先级发送到主节点。适用于中断类型的错误报警信号。一个紧急报文包含8个字节,报文格式如下:

图17.EMCY紧急报文格式

紧急报文和同步报文的功能码都是080H,但是他们的区别是很多的,很容易区分。

  1. 同步报文一般是主节点发给从节点的,紧急报文是从设备发给主节点的。
  2. 同步报文没有NodeID,而紧急报文有NodeID,这个NodeID可以指示是哪一个从设备发生了故障。
  3. 同步报文是不带数据的,但是紧急报文是带8个字节的数据的,8个字节拉满。其目的是通过这8个字节的信息让主节点能够分析出从设备到底发生了什么故障。

如图17所示,紧急报文的8个字节数据被分为了3个部分

第一个部分包含两个字节,Byte0-1,表示应急错误代码。错误代码表格如下图所示。

 

图18.EMCY紧急报文的错误代码及含义

图18所示的错误代码及含义应该是由CANopen的基础协议CIA301所定义,也就是是固定不变的。 另外,错误代码中“XX”部分是由相应的标准设备子协议规定。 什么意思呢? 就是如果我是一个驱动器,那么“XX”部分是由CANopen中的CIA402协议去规定。如果我是个编码器呢,那么“XX”部分是由CANopen中的CIA406协议去规定。总的来说呢,就是这个错误代码及含义是固定不变的,通过查询CIA301和CIA402/CIA406/其他设备子协议,就可以查到错误代码的含义。

第二个部分包含1字节,Byte2,表示错误寄存器的数据。前面我们提到了OD对象字典。也提到过无论是主节点(单片机),还是从节点(驱动器/编码器/其他类型的设备),都有一个属于它们自己的对象字典。 那么在CIA301协议中我们规定,索引1001H,就是错误寄存器,位宽为8位。 假设我们CAN网络中有个驱动器出问题了, 那么驱动器它本身(如果驱动器它自己实现了错误寄存器这部分协议的话,有些驱动器不会实现完整的协议的),它会自己判断到底是什么错误,然后呢,把这个错误信息,写到它自己的对象字典的1001H索引里面。随后发送EMCY紧急报文到CAN网络中,并且紧急报文中的第3个字节Byte2就会自动去拷贝对象字典里面索引为1001H里面的数据。当我们主节点收到这个报文的时候,就可以做更细致的错误分析。如下图所示,为错误寄存器1001H的8个位的数据每一位的含义。

图19.EMCY紧急报文的错误寄存器每个位的含义

第三个部分,共5个字节,Byte3-7,制造商特定的错误区域,这部分就不是标准的CIA301和CIA402/CIA406/其他设备子协议所规定的内容啦。 所以假设有两个驱动器的制造商,那么这两个驱动器的制造商在Byte3-7的定义很大概率是不同的。这部分内容有驱动器制造商自己去定义错误区域的含义。这部分的定义呢,应该出现在该驱动器的规格书里面,以便于用户去查询/定位错误的具体信息。

在以下这个参考链接中,有一个EMCY紧急报文的举例说明,可以看看。

canopen快速入门10emcy_哔哩哔哩_bilibili

4 SDO服务数据报文 [COB_ID: 580H+NodeID (RxSDO) | 600H+NodeID (TxSDO)]

原本想着根据COB_ID的大小,以从小到大的顺序来安排本文的内容,然而我还是发现,SDO的内容还是放在PDO的内容之前好一些,PDO更难理解是一方面,另外,对于PDO通讯参数和映射参数的配置,是需要使用SDO这部分内容的前置知识的,所以我们先讲SDO,再讲PDO。

如标题所示,SDO报文有两种COB_ID,一个发送一个接收。 SDO通讯是一种一问一答的方式,一般是由主节点发起一个对从节点的对象字典的某个索引/子索引的读或写的操作,然后从节点反馈主节点,你的写操作是否成功或你要读的数据。这个RxSDO和TxSDO是我本人为了便于理解,自己提的说法,都是针对主节点而言。

我们来看SDO的COB_ID具体的定义规则:

图20. SDO COB_ID的具体定义

 

图20的SDO COB_ID具体定义这里就不细讲了,一目了然。 下面我们将SDO分为读操作和写操作分别展开具体的通讯协议。(再次强调,我们是主节点去读/写操作从节点对象字典,主语是主节点

读操作

图21. SDO读操作主节点发送报文

由主节点发送给从节点

图22.SDO读操作从节点回应报文

由从节点发送给主节点

下面做一个举例说明

图23. 驱动器设备CIA402协议的对象字典的局部内容

图23中的数值都是十六进制,注意一下08,10,20,分别表示8位,16位,32位。

图24.SDO读操作示例

如图24所示,示例中是主节点现在先要读取驱动器1号(NodeID=1)的伺服实际位置6063 00(索引 子索引,图23最后一行)。CANopen是低字节在前高字节在后的小端格式,所以图24中的6360,实际上6063。

从节点回应的报文,43代表我回的是4个字节(图22有写),63 60/00表示6063索引/00子索引。最后13 D1 FF FF就是具体的实际位置的数据啦。由于CANopen是小端格式,所以反过来是FF FF FD 13,转换成10进制为-12013。

写操作

图25. SDO写操作主节点发送报文

由主节点发送给从节点

图26.SDO写操作从节点回应报文

由从节点发送给主节点

同样的,下面也给出一个SDO写操作的示例。

图27. SDO写操作示例(写成功)

如图27所示,我们先看发送报文,23H表示写4个字节,7A 60 00表示607A索引/00子索引, 回顾刚才的图23,607A/00表示的是目标位置。 A0 86 01 00 是 00 01 86 A0的小端格式 = 100000d。 再看回应报文,60表示写操作成功了,后面索引和数据回来的是一样的。说明我们把目标位置100000写到NodeID = 1的驱动器的对象字典里面去啦。 如果驱动器正常工作的话, 就会把电机转到100000这个位置去啦。

那么有成功也会有失败,失败的报文是怎样的呢?

图28. SDO通讯失败(读/写操作)

如图28所示,无论的读还是写,如果SDO通讯失败,返回的命令字都是80。数据中最后4个字节表示错误代码。其定义如下:

图29.SDO通讯失败错误代码

如图29所示,红色框住的部分是比较常见的SDO通讯错误。第一个可能是索引搞错了,大小端没注意。第二个可能是位宽搞错了,比如往8位宽的字典里面写32位宽的数据。

5 PDO过程数据报文 [ COB_ID : 180H+NodeID ~500H+NodeID]

终于到达了地狱级难度的PDO啦,哈哈,其实也没有那么难,如果前文的所有内容你都理解了,那么PDO也不过是水到渠成的事情,只不过就是步骤多一些,多绕几个弯子。

PDO相比于SDO而言,它的优势在于它不需要应答信号,效率高,因此用于传输实时性要去高的数据。但缺点也比较明显,就是在运行PDO之前,需要进行一些地狱级难度的配置工作。大家不必担心和心急,请耐心的看后文,我们一层一层的破开云雾见月明。遇到有疑惑的地方,带着疑惑往下看,你得疑惑应该都会对应的解答。

知识点1

下面讲第一个我认为在学习PDO的时候比较重要的事情,我们在网上所看到的资料,所说的TxPDO和RxPDO基本是都是针对从节点而言的。所谓的传输Tx,是说从节点传输PDO报文到主节点。 所谓的接收Rx,是说从节点接收主节点发过来的PDO报文。 每一个PDO都有两组参数要配置,通讯参数和映射参数(后面细讲),说的也是去配置从节点的对象字典。SDO的读写操作是指主节点去读写操作从节点。 PDO的Tx和Rx指的是从节点的传输和接收。网上的资料很少去强调这个,导致很多时候理解起来有点困难。

知识点2

第二个比较重要事情也需要进一步提前说明, 之前我们也提到了,无论主节点还是从节点,都是存在一个对象字典的。PDO的通讯是需要提前进行一些配置工作的, 网上很多资料的重点是去讲 如何利用SDO通讯,去配置从节点的PDO的通讯参数和映射参数。但是忽略了主节点也需要配置PDO相关的对象字典,我们主节点对于PDO参数的配置,主要是用开源的对象字典工具软件(objdictedit)生成。但这也是一个重要的事情,不能忽视。 可能这时候有点绕了, 我们从节点是不是存在TxPDO和RxPDO。对于从节点的TxPDO和RxPDO,都需要对他们的通讯参数和映射参数进行配置。 那么从节点的TxPDO配置完了是不是要发送报文给主节点。 那么主节点的RxPDO是不是也需要做一个对于的配置。有点像串口通信,从节点的TxPDO对于主节点的RxPDO。从节点的RxPDO对于主节点的TxPDO。 总结来讲,就是从节点的TxPDO和RxPDO,主节点的TxPDO和RxPDO都需要进行配置。 从节点的PDO配置主要通过主节点发送SDO通讯去配置从节点PDO的通讯参数和映射参数的对应的对象字典。 主节点的PDO配置主要通过开源的objdictedit软件直接生成。

知识点3

是不是感觉上面两个比较重要的事情有点绕了, 哈哈,下面我讲第三个重要的事情,前面我们提到无论是TxPDO和RxPDO,每一个PDO都有两组参数要配置,这两组参数分别叫做通讯参数映射参数。注意一我的用词,是两组参数。为什么用,而不用。因为通讯参数和映射参数中包含的配置项都不止一项。举个例子,从节点的第一个TPDO1,它所对应的通讯参数和映射参数在其对象字典中的索引分别是1800H和1A00H。 好,这还没完,TPDO1的通讯参数,包含7个配置项。其具体的实现方式,就是子索引。之前大家可能对子索引还比较疑惑,为什么索引下面还有个子索引呢,其实就是有时候索引是不够用的,因此同一功能的索引下面还包含很多个子索引。比如TPDO1的通讯参数索引是1800H,它的子索引分别是00H 01H 02H…06H。每个子索引代表的含义,位宽,值的含义如图30所示。

图30. 从节点 – TxPDO1 – 通讯参数- 索引/子索引,以及每个子索引的含义,位宽,值的含义

 

同理,TPDO1的映射参数的1A00H对应的子索引也不止一个,如图31所示。

图31.从节点-TPDO1-映射参数-索引/子索引,以及每个子索引的含义,位宽,值的含义

 

映射参数的子索引还不是固定的个数,这主要取决于第一个子索引00H,它代表的映射参数数目。如图31所示,当它的值为2的时候,后面就还有01 02两个子索引。以此类推,如果它的值是4呢,后面可以有01 02 03 04四个子索引。 但是这里有一个约束,就是你所有的映射参数的位宽,加起来不能超过64位。可以这么说,就是你后面可以最多8个子索引,每个子索引的位宽都是8位,8*8=64位。

知识点4

怎么样? 信息量是不是上来了?所以叫地狱难度。接下来,我们说第四个重要的事情。一般标准的CANopen协议里面,无论是从节点还是主节点。 它的TxPDO和RxPDO都是4个,即TxPDO1、TxPDO2、TxPDO3、TxPDO4、RxPDO1、RxPDO2、RxPDO3、RxPDO4,总共8个PDO。每个PDO都会有对应的通讯参数映射参数。那就是16个索引,不知道多少个子索引了。 那有的人就会觉得,啊?我配置从节点的一个TPDO1都费劲了,我还要配从节点8个PDO,主节点8个PDO,那不是得废老大劲啦? 这里给一个回答,就是真实的使用场景,这些PDO可能未必会全部使用。大家按照需要去配置。 下面给出从节点所有PDO的COB_ID和通讯参数/映射参数的索引,(子索引定义都一样的,如图30和31所示)

图32. 从节点 TPDO/RPDO的COB_ID以及通讯参数/映射参数索引

 

前面我们第二个重要的事情提到,主节点是需要配置TPDO/RPDO的,那主节点的COB_ID以及通讯/映射参数的索引是怎样的呢?请看图33。

图33. 主/从节点的PDO COB_ID以及通讯/映射参数索引

注意到图33中主机的COB_ID是个大的范围,是因为一个CAN网络中可以允许有127个从Node。这些Node的ID是不一样的。在一个有多个从节点的CAN网络中,主节点的TPDO和RPDO的使用率应该是较大的,甚至有可能8个都用完。而从节点的TPDO和RPDO有可能的只使用一组。从图33还有另外的关键信息,即主机的TPDO/RPDO的COB_ID与从机相反

  1. 主机的TPDO和从机的RPDO的COB_ID号是一样的;
  2. 主机的RPDO和从机的TPDO的COB_ID号是一样的。

知识点5

紧接上文,我们讲5个重要的问题, 想象一个场景,如果CAN网络中,有3个驱动器, 我主机需要通过TPDO分别发送3个目标速度给3个驱动器。 由于驱动器的NodeID号不一样,所以主机需要用3个TPDO,配置3个不同的COB_ID。但在配置映射参数的时候,问题来啦,我这3个目标速度应该放在哪个索引里面。我主机的TPDO应该去哪些索引里面去取3个目标速度呢? 有的熟悉CIA402协议的同学可以立马反应过来了,马上举手站起来就回答。目标速度的索引/子索引是60 FF/00。 记忆力很好哈,可惜,这个不是老师要的答案哈,秀儿你坐下。 对于驱动器而言,它遵循CIA402协议,目标速度的索引确实是在60 FF/00这个位置。  但!对于CAN网络中的主机(单片机)而言,它是不遵循CIA402协议,这一点很重要。  如果目标速度是在索引60 FF/00这个地址,那岂不是我主机发给3个驱动器的目标速度,都是一样的值啦。 正确的做法应该是把的3个电机的目标速度的索引放在 2000H~5FFFH这个区域,如图7所示,这个索引区域是什么?是制造商特定子协议区。换成大白话就是,这部分索引,我想怎么定义就怎么定义。这部分的配置,还是在objdictedit工具里面配置。

请仔细阅读上述文字后,再继续阅读下文。


 

通讯参数和映射参数的配置以及报文格式

随着信息量越来越大,所产生的疑惑可能会越来越多,主要的疑惑可能是我的通讯参数和映射参数具体应该怎么配置,参数里面各个子索引分别的什么含义?我们RxPDO报文和TxPDO报文它的格式到底是怎么样的? 下面以配置主节点的TPDO和配置从节点的RPDO为例进行进一步的讲解。

例子:假设现在我们要用主节点的TxPDO1给从节点驱动器发送目标速度,从节点用RxPDO1来进行接收。

网上的资料经常会忽略或不重视,主节点的TxPDO1的配置,因为这步的操作是在objdictedit工具里面完成的。下面我们就先来讲主节点TxPDO1的配置。

主节点TxPDO1的配置

TxPDO1的需要配置三个东西

      1、在制造商特定子协议区自己定义一个目标速度的索引

       2、TxPDO1的通讯参数配置

       3、TxPDO1的映射参数配置

我们先看第1点如何实现。

 

面我们来看第2点,TPDO1的通讯参数配置

0x00 Highest Sublndex Supported

最大子索引支持个数,只读的,我们不需要配置。6就代表,后面0x00子索引后面还有0x01、0x02、0x03、0x04、0x05、0x06 6个子索引。

0x01 COB_ID used by PDO

指的是主节点在发送TPDO报文的时候的COB_ID。 这里由0x180 + NodeID组成。比如我主节点想通过TPDO1发送目标速度个驱动器,驱动器的NodeID是1,那么这里的COB_ID就要写0x180+1 = 0x181。

0x02 Transmission Type

TPDO的传输类型,这个子索引对于的数据位宽的8位, 不同的值代表着TPDO不同的传输方式。如下图所示:

 

当TPDO传输类型的值为0时,代表同步/非循环模式,如果映射数据发生改变,且接收到一个同步帧,则发送该TPDO。可是同步帧一般情况下都是由主节点发送给从节点的。所以在主节点用TPDO发送数据给从节点的时候,我感觉一般不用这个类型。

当TPDO传输类型的值为1~240时,代表同步/循环模式,比如值为2,那么该TPDO报文将在接收到两个同步帧之后,但还是同样一个问题,同步帧一般情况下都是由主节点发送给从节点的。主节点发送同步帧的时候,不知道主节点会对同步帧计数吗?

241~253这一段值,保留,暂时不管

当TPDO传输类型的值为为254、255时,代表异步/制造商特定事件和设备子协议特定事件。 网上很多资料说当映射数据改变或事件计时器到,就会发送PDO。但有人测试过,254或者255的情况下,如果映射数据改变的时候,不会发送PDO,只有事件计时器到才会发送PDO。 我的理解是254代表映射数据改变的触发TPDO,这个不靠谱。所以,这里可能靠谱的做法是选255,然后配合0x05 Event Timer做事件定时触发。

 

0x03 Inhibit Time

       禁止时间,这一项对异步传输类型的TPDO才有用,用来规定TPDO发送的最小时间间隔。这其实就是流量控制,防止TPDO狂发,占用大量CAN总线带宽。CIA301协议规定,禁止时间的分辨率是100us,精度是2毫秒。比如你要禁止1毫秒,你这个数值得写10d。你要禁止2毫秒,这个数值得写20。注意,有些设备可能把这个分辨率改成1ms什么的,使用的时候注意。

0x04 Compatibility Entry,这个参数不管

0x05 Event Timer

       事件定时器,这个应该是和传输类型为 254/255的异步传输类型配合使用。 这个参数名很容易让人误解,这里要这么去理解这个参数,这个参数代表的是TPDO定时周期,在移植CANopen协议开源库到单片机的时候,它是需要实现带定时器功能,也就是说CANopen协议内部是自带定时器的。 这就可以解释这个参数了。 这个参数的单位的1ms。 比如你填入一个1,那么CANopen应该就会每隔1ms触发一次TPDO。 配合0x03禁止时间使用。

0x06 SYNC start value

       TPDO同步帧的起始值,这个容易理解,这个是配合传输类型为1~240使用,比如传输类型值是2。 同步帧起始值这里我配置的是1,那么我第一次出发TPDO报文,应该是只需要收到1个同步帧就可以了。 后续第2帧开始以后的TPDO报文,我猜测应该还是要接到2同步帧才能触发发送。目前来讲,没什么卵用。

那么总结一下,主机发送TPDO的方式,无非就两种

  1. 一种是传输类型为1~240,当收到从节点的n个同步帧之后触发TPDO。
  2. 一种是传输类型为255,结果0x05的Event Timer,主机不需要接收从节点的同步帧,而是采用自己内部的定时器进行周期性的触发。

具体选择哪一种呢? 需要做一个验证,我有一个设想,如果主节点往从节点发送的同步帧,也算是主机自己接到的同步帧的话,也就是说主节点在发送同步的是同时,也会触发自己的TPDO,这样就美滋滋了。 这就果断选同步循环方式。 否则,就选择第二种,定时器触发方式。本文中,稳妥起见,我暂时认为我的设想是错误的,即如果我配置主机的TPDO是同步循环模式,则从节点必须发送同步帧到主机,才能触发主机的TPDO。 所以我选择定时器触发

那么我们通讯参数配置则如下

 

下面来看第3点 ,TxPDO1的映射参数配置

映射参数我们也简单来理解一下,这个比通讯参数简单多了。

 

这里我认为这个软件少显示了一些信息,这里只简化显示了变量名,没有显示 子索引 和 位宽。不过生成对象字典的时候应该会自动生成,标准的映射参数配置,我们来看下图。

你看【值】的部分, 是存在 7100H(索引)  / 01H(子索引) / 10H(16位宽)3个部分的。

从节点RxPDO1的配置

前面提到了,从节点,比如说驱动器,它的对象字典,可能有两种配置方式,一种是通过驱动器本身的上位机软件进行配置,一种是通过主节点给从节点发送SDO指令来配置。 上位机配置的方式和上面主节点用objdictedit配置方式估计大同小异,而有些驱动器是不支持上位机配置的方式的。所以关于从节点RxPDO1的配置,我们用SDO指令的方式讲解,而且里面还有一些其他的东西需要注意。

假设我们使用RPDO1来接收主机发过来的信息。那么我们需要配置RPDO1的通讯参数映射参数。即:1400H和1600H两个索引。RPDO1的通讯参数和映射参数的索引是1400H和1600H。 由于它一个索引号,不止要配置一个参数。所以还有子索引。每个子索引呢,代表不同的含义。

 

上面这两张图是有点不严谨的,不必在意,可以看到是抄了以前的图,然后稍微改了改。

使用SDO的配置方式,是由固定流程的。

 

SDO指令如果搞忘了可以倒回去看第4小节。

0x22是通用的写,驱动器未必都支持这种协议,建议还是使用下面这种方式。

2f:写入1个;

2b:写入2个;

27:写入3个;

23:写入4个

 

下面对上述指令进行一一解析。

第一条指令

第二条指令

第三条指令

 

 

注意一下,这里追加映射参数的时候,所有参数的总长度不能超过8个字节。

比如我01子索引映射参数长度20H=32d位
          02 子索引映射参数长度20H=32d位

前面两个参数已经64位 = 8字节了, 后面03 04就不能再加了。

第四条指令

 

第5条指令。

前面5条配置完,RPDO1的配置就结束了,但是它并不代表现在PDO就能运行了。 因为CANopen协议规定,PDO服务必须只能在operational操作状态下在能运行。 另外驱动器本身还需要做一些设置,也是通过SDO服务。

第6~9条命令

这时候我们可以用SDO发送速度,也可以用PDO发送目标速度了。前面第1~5条指令,就为了配置驱动器的RPDO1的。就是为了让主机通过PDO把目标速度发过去。 如果你不用PDO,前面的配置反而没意义了。而且PDO发送效率更高,不需要应答。

第10条指令

PDO的配置结束时候,还需要发送应NMT网络管理指令。将从机驱动器NODE-ID假设=0x01的CANopen状态机的状态,切换成operational操作状态。

第11~∞条

大家有没有发现我们在配置从节点RxPDO的时候,COB_ID配置的是201,但是前面主节点TxPDO的配置却是配置的181。 这是objedit个坑,它会提示你180+NodeID,我在截图的时候没注意,就搞成181了。 前面知识点4提到过的。主节点的RxPDO和TxPDO的COB_ID和 从节点的COB_ID是反的。所以应该是这样:

 

总结:学习一个新东西,最好还是要做一个笔记整理,整理的过程中你会发现以前以为明白的地方,其实并没有理解透彻,这个时候能继续查漏补缺进一步完善。 下集预告,CANopen开源库移植,欢迎关注/阅订。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/879306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker-compose 部署 flink

下载 flink 镜像 [rootlocalhost ~]# docker pull flink Using default tag: latest latest: Pulling from library/flink 762bedf4b1b7: Pull complete 95f9bd9906fa: Pull complete a880dee0d8e9: Pull complete 8c5deab9cbd6: Pull complete 56c142282fae: Pull comple…

Redis搭建集群

功能概述 Redis Cluster是Redis的自带的官方分布式解决方案&#xff0c;提供数据分片、高可用功能&#xff0c;在3.0版本正式推出。 使用Redis Cluster能解决负载均衡的问题&#xff0c;内部采用哈希分片规则&#xff1a; 基础架构图如下所示&#xff1a; 图中最大的虚线部分…

路由器WAN口和LAN口有什么不一样?

“ 路由器WAN口和LAN口的区别&#xff0c;WAN是广域网端口&#xff0c;LAN是本地网端口。WAN主要用于连接外部网络&#xff0c;而LAN用来连接家庭内部网络&#xff0c;两者主要会在标识上面有区别。以往大部分路由器的WAN只有一个&#xff0c;LAN口则有四个或以上&#xff0c;近…

《深度学习》—— 神经网络基本结构

前言 深度学习是一种基于神经网络的机器学习算法&#xff0c;其核心在于构建由多层神经元组成的人工神经网络&#xff0c;这些层次能够捕捉数据中的复杂结构和抽象特征。神经网络通过调整连接各层的权重&#xff0c;从大量数据中自动学习并提取特征&#xff0c;进而实现预测或…

Banana Pi BPI-SM9 AI 计算模组采用算能科技BM1688芯片方案设计

产品概述 香蕉派 Banana Pi BPI-SM9 16-ENC-A3 深度学习计算模组搭载算能科技高集成度处理器 BM1688&#xff0c;功耗低、算力强、接口丰富、兼容性好。支持INT4/INT8/FP16/BF16/FP32混合精度计算&#xff0c;可支持 16 路高清视频实时分析&#xff0c;灵活应对图像、语音、自…

Python面试宝典第48题:找丑数

题目 我们把只包含质因子2、3和5的数称作丑数&#xff08;Ugly Number&#xff09;。比如&#xff1a;6、8都是丑数&#xff0c;但14不是&#xff0c;因为它包含质因子7。习惯上&#xff0c;我们把1当做是第一个丑数。求按从小到大的顺序的第n个丑数。 示例 1&#xff1a; 输入…

基于MinerU的PDF解析API

基于MinerU的PDF解析API - MinerU的GPU镜像构建 - 基于FastAPI的PDF解析接口支持一键启动&#xff0c;已经打包到镜像中&#xff0c;自带模型权重&#xff0c;支持GPU推理加速&#xff0c;GPU速度相比CPU每页解析要快几十倍不等 主要功能 删除页眉、页脚、脚注、页码等元素&…

uniapp使用高德地图设置marker标记点,后续根据接口数据改变某个marker标记点,动态更新

最近写的一个功能属实把我难倒了,刚开始我请求一次数据获取所有标记点,然后设置到地图上,然后后面根据socket传来的数据对这些标记点实时更新,改变标记点的图片或者文字, 1:第一个想法是直接全量替换,事实证明这样不行,会很卡顿,有明显闪烁感,如果标记点比较少,就十几个可以用…

【网络安全】-rce漏洞-pikachu

rce漏洞包含命令执行漏洞与代码执行漏洞 文章目录 前言 什么是rce漏洞&#xff1f; 1.rce漏洞产生原因&#xff1a; 2.rce的分类&#xff1a; 命令执行漏洞&#xff1a; 命令拼接符&#xff1a; 常用函数&#xff1a; 代码执行漏洞&#xff1a; 常用函数&#xff1a; 分类&…

信号与线性系统综合实验

文章目录 一、实验目的二、实验内容及其结果分析&#xff08;一&#xff09;基础部分&#xff08;二&#xff09;拓展部分&#xff08;三&#xff09;应用设计部分 三、心得体会 一、实验目的 1、掌握连续时间信号与系统的时域、频域综合分析方法&#xff1b;   2、掌握运用M…

SAP B1 单据页面自定义 - 用户界面编辑字段

背景 接《SAP B1 基础实操 - 用户定义字段 (UDF)》&#xff0c;在设置完自定义字段后&#xff0c;如下图&#xff0c;通过打开【用户定义字段】可打开表单右侧的自定义字段页。然而再开打一页附加页面操作繁复&#xff0c;若是客户常用的定义字段&#xff0c;也可以把这些用户…

JMM 指令重排 volatile happens-before

在单线程程序中&#xff0c;操作系统会通过编译器优化重排序、指令级并行重排序、内存系统重排序三个步骤对源代码进行指令重排&#xff0c;提高代码执行的性能。 但是在多线程情况下&#xff0c;操作系统“盲目” 地进行指令重排可能会导致我们不想看到的问题&#xff0c;如经…

2024第三届大学生算法大赛 真题训练2 解题报告 | 珂学家 | FFT/NTT板子

前言 题解 D是FFT板子题&#xff0c;这么来看&#xff0c;其实处于ACM入门题&#xff0c;哭了T_T. D. 行走之谜 思路: FFT 如果你知道多项式乘法&#xff0c;继而知道FFT&#xff0c;那题纯粹就是板子题&#xff0c;可惜当时比赛的时候&#xff0c;无人AC。 这题来简单抽象…

物联网之PWM呼吸灯、脉冲、LEDC

MENU 前言原理硬件电路设计软件程序设计analogWrite()函数实现呼吸灯效果LEDC输出PWM信号 前言 学习制作呼吸灯&#xff0c;通过LED灯的亮度变化来验证PWM不同电压的输出。呼吸灯是指灯光在单片机的控制之下完成由亮到暗的逐渐变化&#xff0c;感觉好像是人在呼吸。 原理 脉冲宽…

【中秋月饼系列】2024年立体月饼新鲜出炉----python画月饼(1)附完整代码

【中秋月饼系列】2024年立体月饼新鲜出炉 ----python画月饼&#xff08;1&#xff09;附完整代码 本文目录&#xff1a; 零、时光宝盒 一、2024年中秋节立体逼真月饼&#xff08;效果展示&#xff09; 二、Python 海龟画图主要方法 &#xff08;1&#xff09;海龟画图的主…

学习大数据DAY56 业务理解和第一次接入

作业1 1 了解行业名词 ERP CRM OA MES WMS RPA SAAS 了解每个系统的功能和应用 ERP 系统&#xff0c;&#xff08;Enterprise Resource Planning&#xff0c;企业资源计划系统&#xff09;&#xff1a;ERP 系统 是一种用于管理企业各类资源的软件系统&#xff0c;包括生产管理…

攻防世界 ics-05

ics-05 隐藏的变量传参&#xff0c;php弱类型比较 只有设备维护中心可以点击进去 查看源码&#xff0c;发现有个隐藏的超链接变量传参 看到变量传参&#xff0c;有可能存在文件包含漏洞读取源码&#xff0c;这个站是php的站&#xff0c;所以可以使用php伪协议读取源码 index.p…

Docker Swarm管理(Docker技术集群与应用)

如上图所示&#xff0c; 三台主机&#xff1a;恢复到docker的快照&#xff1b; 然后上传到三台服务器所需的镜像&#xff1b; 同步会话。执行导入脚本将镜像导入到系统中&#xff1b; 然后取消会话的同步&#xff0c;设置各个主机的主机名&#xff1b; 然后同步会话修改hosts…

Java JUC(一) 线程概念与常用方法

Java JUC&#xff08;一&#xff09; 线程概念与常用方法 一. JUC 基本概念 Java JUC&#xff08;Java Util Concurrent&#xff09; 是Java平台提供的一个并发编程工具包&#xff08;java.util.concurrent&#xff09;&#xff0c;全称为Java Concurrency Utilities。这个工具…

深入剖析 MQTT 协议:物联网通信的核心力量

摘要&#xff1a; 本文全面深入地探讨了 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;协议。详细阐述了 MQTT 协议的起源与发展背景&#xff0c;介绍其基本概念、特点及工作原理。深入分析了 MQTT 的架构组成&#xff0c;包括客户端、代理服务器及主题的作…