linux下CANopen for python的使用
0前言
本专题相关教程:
本文代码链接:https://pan.baidu.com/s/1YOAX8ljUP_zERSAMQ9asbg?pwd=famm
提取码:famm
1. linux下配置VScode的python3环境
此节与本教程关系不大,要看CANopen的同学可以直接跳到下一节。
只是本人有时候习惯用VScode运行程序,所以顺带配置一下。
参考博文如下:
vscode 配置 python3开发环境的方法 / 张生荣 (zhangshengrong.com)
其中2.4步骤之后略有区别,如下
点击这个图标变成代码界面
可以看到,名字并不是User Settings,而是serttings.json,也没博主里那么多东西(就算东西很多的也没关系)。可能是版本不一样。我们不管,把它东西都复制过来
在第四行后插入下面这句话:
"python.defaultInterpreterPath": "/usr/bin/python3", // python3路径 新版本调用方法
并且如果觉得它字体过大,自己调整一下即可。
它的配置里面有一些软件可能我们还没有安装。我们在桌面开启一个终端安装一下。
sudo apt install python3-pip #如果没有pip3,先安装pip3
# flake8安装到特定版本
sudo python3.6 -m pip install flake8 #python版本与自己的一致就行 我的是3.6
#安装yapf
pip3 install yapf
有一说一,这个配置确实挺好看的~~~~。
要运行python程序,在右边选择 Run Python File(使用Run Code依然默认是python而不是python3)
有时候,提示包找不到,这时候我们需要在setting里添加路径。
来到文件最末尾,添加下面语句
"python.autoComplete.extraPaths": [
"~/.local/lib/python3.6/site-packages/canopen",
//在这里添加包路径 上一句是我的canopen的路径
2. 安装canopen
使用很简单,因为我是python3版本,使用的是pip3。相关文档链接CANopen for Python — canopen 1.2.2.dev41+gff8b5ca documentation。里面写了很多使用例子,建议瞧瞧。
pip3 install canopen
3. 创建虚拟CAN设备
为了方便验证代码,我们新建一个虚拟CAN设备,名字为vcan0,类型是socketCAN。似乎每次启动都得新建一次。
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan #添加设备
sudo ip link set up vcan0 #启动设备
4. 词典准备
CANopen最重要的文件就是词典了。python下,只需要建立属于子节点的词典就行,主机不需要。
我们为节点建立一个词典,主要三点:
(1)添加心跳报文,间隔1000ms
(2)添加一个变量,用于访问测试。
(3)词典新建一个SDO服务器,用于主机访问(如默认有就可以忽略)。
添加词典需要使用Objdictedit.py。该文件及使用教程之前博客有,这里不过多赘述。基于STM32F4的CANOpen移植教程(超级详细)
(1)新建一个Slaver节点
(2)设置心跳间隔1000ms(0x3E8)
(3)添加一个服务器
如果已经有就把多的删掉。 内容不需要修改(我们也改不了)。
(4)添加变量test
在0x2000处添加一个变量test,类型为16位整形,内容为3。用于快速sdo访问测试。
生成eds文件
python使用的是eds格式的词典。
5. 编写Python代码
因为需要一个主机和一个节点,所以需要2份代码。
主机:使用快速SDO读取节点的test变量,并让该值+1之后重新赋值回去。
节点:id为0x02。发送上线报文。然后就啥都不用做了。
我们建立一个文件夹canopentest(取名随意),取名master.py和slaver.py。再把上边的词典放进来。
master.py
import time
import canopen
# 创建一个网络用来表示CAN总线
network = canopen.Network()
# 添加slave节点,其id是2(需要与slaver.py里一致),对象字典为Slaver.eds
slaver_node = canopen.RemoteNode(2, 'Slaver.eds')
network.add_node(slaver_node)
# 连接到CAN总线 CAN波特率1000K
network.connect(bustype='socketcan', channel='vcan0', bitrate=1000000)
# 全局广播,id为0x00,内容为0x01,0x00 让节点都进入操作状态
network.send_message(0x0, [0x01, 0])
# 使用快速sdo读取节点0x2000地址数据,适用于没有定义变量的区域
test = slaver_node.sdo[0x2000].raw # 使用快速sdo读取节点0x2000地址数据
print("test value=" + str(test))
while 1:
temp = slaver_node.sdo['test'].raw # 使用快速sdo读取节点test地址数据
print("temp value=" + str(temp))
slaver_node.sdo['test'].raw = temp + 1 # 使用快速sdo设置节点test地址数据
time.sleep(1)
里面用到了一个NMT命令,介绍如下
slaver.py
import canopen
import time
# 创建一个网络用来表示CAN总线
network = canopen.Network()
# 连接到CAN总线
network.connect(bustype='socketcan', channel='vcan0', bitrate=1000000)
# 创建slaver节点,其id是2(需要与master.py里一致),对象字典为Slaver.eds
slaver_node = network.create_node(2, 'Slaver.eds')
# 向CAN总线上发送启动报文 帧 cob id:0x700+节点id 内容:0
slaver_node.nmt.send_command(0)
# 发送心跳报文,每隔1s发送一次 词典里面虽然配置了心跳,但需要下边代码启动
slaver_node.nmt.start_heartbeat(1000) # 1000ms
# 循环
while 1:
time.sleep(1)
print("slaver work")
6. 监听心跳报文
我们打开两个终端。
一个打开can监听(如果提示命令没有安装就安装)
sudo modprobe vcan #新建虚拟设备,如果已有则忽略。(注意,该设备重启后就不见了,需要重新建立)
sudo ip link add dev vcan0 type vcan #添加设备
sudo ip link set up vcan0 #启动设备
candump -t d vcan0 #带绝对时间戳 (-t a) 带相对时间戳 (-t d)
一个执行slaver.py
python3 slaver.py
效果如下:
比较奇怪的是,确实每秒都发了一帧报文,但是,发的是上线报文…有一种可能应该是:只有当主机也在线时,节点才正常发送心跳报文,不然发的就会是上线报文(我的主机呢?我的主机呢?) 上线报文和心跳报文介绍如下:
7. 快速SDO使用
在上边程序运行的基础。我们再打开一个终端。执行master.py
python3 master.py
master的运行正常。右边监听的终端,可以看到相应的CAN通信内容。第一个框是读取与反馈,第二个框是写入与反馈。
备注:实验过程中的发现
(1):写入变量的值,关闭slaver.py程序之后再打开。发现变量的值又是最开始的3。也就是说,词典没有保存。
(2):slaver.py关闭之后,还是能监听到心跳报文。再执行一次slaver.py,将会1秒收到两个心跳报文。再关闭再打开,将会1秒收到三个心跳报文。疑似之前关闭程序不完全,导致心跳报文遗留而产生的bug。