摘要:最近用到python-can,发现网上参考资料实在不多,也缺乏一定的系统性,特此进行一番整理。——by catmemo
注:
抱歉一段时间以来没有时间和精力去更新这份博文,在这段时间以来,主要基于python-can这个库,开发了一个CAN节点模拟仿真工具,有需要的可以去下载来用,当然也欢迎二次开发。后面,时间会相对宽裕些,会继续更新这篇博文。
(当然也包括CAN收发、诊断、图形化显示等功能,详细内容可以在抖音搜索:47:/ 复制打开抖音,看看【一夜春风的作品】CAN 仿真神器——QX工具链之UltraSim… ЭmAELbZr5bntmw8ππ )。
python-can库为Python提供了控制器局域网的支持,为不同的硬件设备提供了通用的抽象,并提供了一套实用程序,用于在CAN总线上发送和接收消息。
python-can可以在Python运行的任何地方运行; 从具有商用CAN的高功率计算机到USB设备,再到运行Linux的低功率设备(例如BeagleBone或RaspberryPi)。
更具体地说,该库的一些示例用法如下:
连接到CAN总线,创建和发送消息的简单实例:
#!/usr/bin/env python
# coding: utf-8
"""
This example shows how sending a single message works.
"""
from __future__ import print_function
import can
def send_one():
# this uses the default configuration (for example from the config file)
# see https://python-can.readthedocs.io/en/stable/configuration.html
bus = can.interface.Bus()
# Using specific buses works similar:
# bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000)
# bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
# bus = can.interface.Bus(bustype='ixxat', channel=0, bitrate=250000)
# bus = can.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
# ...
msg = can.Message(arbitration_id=0xc0ffee, data=[0, 25, 0, 1, 3, 1, 4, 1], is_extended_id=True)
try:
bus.send(msg)
print("Message sent on {}".format(bus.channel_info))
except can.CanError:
print("Message NOT sent")
if __name__ == '__main__':
send_one()
可以使用pip命令进行安装:
$ pip install python-can
由于您很可能与某些硬件连接,因此可能还必须安装对应的平台依赖项。
许多接口可以像安装python依赖项一样,通过如下命令进行安装:
$ pip install python-can[serial]
理论上来说,现代Linux内核(2.6.25或更新版本)有一个socketcan的实现。如果用Python3.3或更高版本调用,此版本的python can将直接使用socketcan,否则将通过ctypes的类型来判断。
使用Kvaser CANLib SDK作为后端安装python-can:
安装Kvaser最新的Windows CANLib驱动程序。
测试Kvaser自己的工具是否正常工作,以确保驱动程序安装正确,以及硬件是否能正常工作。
为您的接口下载并安装最新的驱动:
Windows (also supported on Cygwin)
Linux(also works without, see also Linux installation)
macOS
请注意,PCANBasic API时间戳从系统启动开始计算秒数。要将这些时间转换为纪元时间,请使用uptime库。否则,时间将以系统启动后的秒数返回。要安装uptime库,请运行pip install python can[pcan]
。
如果安装了Python for Windows Extensions库,此库将可以很好的被用于获得新消息的通知,而不是不得不使用的CPU密集型轮询。
使用IXXAT VCI V3 或者 V4 SDK 作为后端安装python-can:
(1)安装IXXAT’s latest Windows VCI V3 SDK or VCI V4 SDK (Win10) drivers
(2)测试IXXAT自己的工具(例如MiniMon)是否正常工作,以确保驱动程序安装正确,以及硬件是否能正常工作。
下载并安装National Instruments
当前该驱动在Windows平台只支持32位python。
查看neoVI
使用XL Driver Library作为后端安装python-can:
(1)为Vector硬件接口安装最新的驱动程序。
(2)安装XL Driver Library或复制vxlapi.dll和/或vxlapi64.dll到您的工作目录中。
(3)使用Vector Hardware Configuration为您的应用程序分配通道。
Linux、Windows和macOS均支持CANtact。要使用CANtact driver作为后端安装python-can,请执行以下操作:
(1)python3 -m pip install "python-can[cantact]"
(2)如果已经安装了python-can,则可以单独安装CANtact后端:
python3 -m pip install cantact
(3)更多相关的文档,请查看cantact.io
当前python-can已经支持通过运行python -m can.viewer 命令显示一个简单的CAN查看器终端应用程序。(类似于CANalyzer的trace)
在Windows上,需要运行如下命令安装库依赖:
python -m pip install "python-can[viewer]"
此软件包的“开发版本”安装允许您在本地进行更改,或从Git存储库中获取更新并使用它们,而无需重新安装。下载或克隆源存储库,然后:
python setup.py develop
通常,此库与特定的CAN接口一起使用,可以在代码中指定,也可以从配置文件或环境变量中读取。
can对象暴露了一个rc字典,该字典可用于在从can.interfaces导入之前设置接口和通道。
import can
can.rc['interface'] = 'socketcan'
can.rc['channel'] = 'vcan0'
can.rc['bitrate'] = 500000
from can.interface import Bus
bus = Bus()
您还可以为每个Bus实例指定接口和通道:
import can
bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=500000)
在Linux系统上,将在以下路径中搜索配置文件:
在Windows系统上,将在以下路径中搜索配置文件:
配置文件设置默认接口和通道:
[default]
interface = <the name of the interface to use>
channel = <the channel to use by default>
bitrate = <the bitrate in bits/s to use by default>
该配置还可以包含其他部分(或上下文):
[default]
interface = <the name of the interface to use>
channel = <the channel to use by default>
bitrate = <the bitrate in bits/s to use by default>
[HS]
# All the values from the 'default' section are inherited
channel = <the channel to use>
bitrate = <the bitrate in bits/s to use. i.e. 500000>
[MS]
# All the values from the 'default' section are inherited
channel = <the channel to use>
bitrate = <the bitrate in bits/s to use. i.e. 125000>
from can.interfaces.interface import Bus
hs_bus = Bus(context='HS')
ms_bus = Bus(context='MS')
可以从以下环境变量中获取配置:
Name | Documentation |
---|---|
“socketcan” | SocketCAN |
“kvaser” | Kvaser’s CANLIB |
“serial” | CAN over Serial |
“slcan” | CAN over Serial / SLCAN |
“ixxat” | IXXAT Virtual CAN Interface |
“pcan” | PCAN Basic API |
“usb2can” | USB2CAN Interface |
“nican” | NI-CAN |
“iscan” | isCAN |
“neovi” | NEOVI Interface |
“vector” | Vector |
“virtual” | Virtual |
“canalystii” | CANalyst-II |
“systec” | SYSTEC interface |
主要对象是BusABC和Message。
Bus为物理或者虚拟CAN 总线提供了一个包装器。
接口特定实例是通过使用特定接口实例化Bus类来创建的,例如:
vector_bus = can.Bus(interface='vector', ...)
然后,创建的总线能够处理特定于接口的软/硬件交互,同时为用户提供最高层级API。
当前,也可以使用线程安全总线包装器,请参阅Thread safe bus。
我们可以调用send()方法并传过去一个Message类型的参数将message发送到CAN总线上,如下所示:
with can.Bus() as bus:
msg = can.Message(
arbitration_id=0xC0FFEE,
data=[0, 25, 0, 1, 3, 1, 4, 1],
is_extended_id=True
)
try:
bus.send(msg)
print(f"Message sent on {bus.channel_info}")
except can.CanError:
print("Message NOT sent")
周期型信号的发送则通过boradcast manager控制。
通过调用recv()方法或者直接在bus上进行迭代可以读取总线上的messages:
with can.Bus() as bus:
for msg in bus:
print(msg.data)
此外,我们也可以通过Listener api来接收和处理来自Notifier的消息。
can.detect_available_configs(interfaces=None)
检测接口当前可以连接的所有配置/通道。
这可能相当耗时。
并非每个平台上的每个接口都可以实现自动配置检测。在这种情况下,此方法不会引发错误,而是返回该接口的空列表。
interfaces (Union[None, str, Iterable[str]])
- None:在所有已知接口中搜索
- string:在字符串名称的接口中搜索
- 在可迭代的接口名称中搜索
can.BusABC
的构造函数中使用。Notifier对象用作总线的消息分发器。
classcan.Notifier(bus, listeners, timeout=1.0, loop=None)
管理can.Message实例向侦听器的分发。
支持多个总线和侦听器。
待续…