技术博客

30/03/2018 作者 Dynamic

用Python处理CAN数据库

这是介绍如何用Kvaser数据库(kvadblib)和Python管理DBC数据库的博客第一部分(总计为2部分):

  1. 在Python里处理CAN数据库
  2. 发送和接收数据库信号

随着CANlib SDK软件开发包v5.22的发布, 数据库(kvaDbLib) 性能增强,同时Python canlib 包装函数包(v1.5) 通过kvadblib 模块加强了对数据处理的支持。此 kvaDbLib数据库是用来生成,书写,读取和修改DBC 数据库。[1] 在这第一篇博客里,我们先介绍怎样用Python canlib包装函数包生成和检验一个DBC 数据库。 这个Python canlib包是以Python Wheel文件发布的,以便 using pip install安装。如果你还没安装它,请参阅博客 ‘Python samples are now bundled in a package[2] (Python 范例现在已包含在一个软件包里)’了解更多这方面的介绍。


生成一个数据库

我们需要一个数据库来把原始 CAN 数据转换为人工可读信号。在本范例中我们使用一个假设的汽车数据库。

让我们先从头开始生成数据。首先,我们从canlib python包引进kvadblib,生成一个名为“Histogram”[3] 的数据库, 加上一个标识符为id “402”报文, dlc “8” 并命名此报文为 “LIM_002”。

from canlib import kvadblib

# 生成一个数据库
db = kvadblib .Dbc(name=’Histogram ’ )

# 加上报文
message = db.new_message(name=’LIM_002’ ,
			 id=402,
			 dlc=8)

下一步是在我们刚刚生成的报文上加一个信号。让我们加一个名为“Load” 的float (浮标)信号,此信号附带了一个单位和评论文字。

message . new_signal(
       name=’Load ’ ,
       type=kvadblib . SignalType .FLOAT,
       byte_order=kvadblib . SignalByteOrder .INTEL, # 预设值
       mode=kvadblib . SignalMultiplexMode .MUX_INDEPENDENT, # 预设值
       size=kvadblib . ValueSize( startbit=0, length=32) ,
       scaling=kvadblib . ValueScaling( factor=1, offset=0) ,
       limits=kvadblib . ValueLimits(min=0, max=100) ,
       unit=’ metric ton ’ ,
       comment=’Measured load in system . ’ )

在生成一个信号时,我们要限定很多方面的信息,现在我们来快速看一下这些选项:

名字给此信号一个特别的字串。这个名字必须是在整个数据库里独一无二的。

类型此信号可被设为 SIGNEDUNSIGNED, (DOUBLE[4] ), 或 FLOAT。 这个信号也可为列举信号,那样我们就在Python包里把信号设为 ENUM_SIGNED 或ENUM_UNSIGNED

模式 The signal byte order can be either INTEL or MOTOROLA, defaults to INTEL.

模式 信号的预设模式是 MUX_INDEPENDENT, 也就是说这是一个普通信号。[5] 在一个CAN 报文中,如果将模式设为 MUX_SIGNAL,一个信号也可被定义为数据选择器。现在这个数据选择器在这个报文帧里选择传输哪个多路数据。此多路数据应被设为它应有的正整数值,这样这个多路数据信号才能被使用。kvadblib目前只支持简单的多路数据。对简单多路传输来说,只有多路数据器信号能在一个报文里被定义,对每个多路数据信号来说,只能定义一个多录数据器值。

大小这个信号的起始位 (又称为startbit), 和它的长度,以bit数来度量。

比例比例有一个系数和一个调整量。一个原始CAN值乘以这个系数,然后再由调整量增值,就被转换为一个物理值。

限制此信号的最小和最大物理值。

单位 一个字串代表这个信号的单位。

注释 一个字串用来记录此信号。

让我们以定义另外三个报文和信号来完成这个数据库。

message = db.new_message(name=’ECM_004’ ,
                         id=504,
                         dlc=8)

message . new_signal(name=’Fuel ’ ,
                     type=kvadblib . SignalType .FLOAT
                     size=kvadblib . ValueSize( startbit=0, length=32) ,
                     limits=kvadblib . ValueLimits(min=0, max=300) ,
                     unit=’ l /100 km’ ,
                     comment=’Current fuel consumption . ’ )

message = db.new_message(name=’ECM_003’ ,
                         id=503,
                         dlc=8)

message . new_signal(name=’EngineTemp ’ ,
                     type=kvadblib . SignalType .FLOAT,
                     size=kvadblib . ValueSize( startbit=0, length=32) ,
                     limits=kvadblib . ValueLimits(min=-60, max=200) ,
                     unit=’ Celsius ’ ,
                     comment=’System temperature consumption . ’ )

message = db.new_message(name=’ECM_001’ ,
                         id=501,
                         dlc=8)

message . new_signal(name=’EngineSpeed ’ ,
                     type=kvadblib . SignalType .UNSIGNED,
                     size=kvadblib . ValueSize( startbit=0, length=32) ,
                     limits=kvadblib . ValueLimits(min=0, max=6000) ,
                     unit=’rpm’ ,
                     comment=’Current engine speed . ’ )

最后一步是把我们的新数据库存到一个文件里并关上它。

# 写数据库文件
db. write_file ( ’db_histogram . dbc ’ )
db. close ()

检测我们的数据库

让我们来看一下我们刚刚生成的DBC 数据库。我们从Python书写内容开始:

import textwrap
from canlib import kvadblib

with kvadblib .Dbc( filename=’db_histogram . dbc ’ ) as db:
    print (db)
    for message in db:
        print ( ’\n {} ’ . format(message) )
        for signal in message :
            print (textwrap . f i l l ( ’ {} ’ . format( signal ) , 80))

使用textwrap模块来生成一个简洁的80字宽输出:

Dbc db_histogram: flags:0, protocol:CAN, messages:4

 Message(name=’LIM_002’, id=402, flags=<MessageFlag.0: 0>, dlc=8, comment=’’)
  Signal(name=’Load’, type=<SignalType.FLOAT: 3>,
byte_order=<SignalByteOrder.INTEL: 0>, mode=-1, size=ValueSize(startbit=0,
length=32), scaling=ValueScaling(factor=1.0, offset=0.0),
limits=ValueLimits(min=0.0, max=100.0), unit=’metric ton’, comment=’Measured
load in system.’)

  Message(name=’ECM_004’, id=504, flags=<MessageFlag.0: 0>, dlc=8, comment=’’)
   Signal(name=’Fuel’, type=<SignalType.FLOAT: 3>,
byte_order=<SignalByteOrder.INTEL: 0>, mode=-1, size=ValueSize(startbit=0,
length=32), scaling=ValueScaling(factor=1.0, offset=0.0),
limits=ValueLimits(min=0.0, max=300.0), unit=’l/100 km’, comment=’Current fuel
consumption.’)

  Message(name=’ECM_003’, id=503, flags=<MessageFlag.0: 0>, dlc=8, comment=’’)
   Signal(name=’EngineTemp’, type=<SignalType.FLOAT: 3>,
byte_order=<SignalByteOrder.INTEL: 0>, mode=-1, size=ValueSize(startbit=0,
length=32), scaling=ValueScaling(factor=1.0, offset=0.0),
limits=ValueLimits(min=-60.0, max=200.0), unit=’Celsius’, comment=’System
temperature consumption.’)

  Message(name=’ECM_001’, id=501, flags=<MessageFlag.0: 0>, dlc=8, comment=’’)
   Signal(name=’EngineSpeed’, type=<SignalType.UNSIGNED: 2>,
byte_order=<SignalByteOrder.INTEL: 0>, mode=-1, size=ValueSize(startbit=0,
length=32), scaling=ValueScaling(factor=1.0, offset=0.0),
limits=ValueLimits(min=0.0, max=6000.0), unit=’rpm’, comment=’Current engine
speed.’)

希望这里不要有什么不正常,所以让我们看一下我们的数据库在Kvaser 数据库编辑器里是怎么样。

图1:在Kvaser 数据库编辑器里看我们的数据库。

在Kvaser数据库编辑器的中间框里,我们能看到4个已定义的报文。在图1中1, 报文“LIM_002”被选择,该报文的内容显示在此报文下面。在我们的例子里,有一个名为“Load”的信号,它的单位unit被设为“metric ton”。在右边的方框中,当前报文的数据bits以一个布局(有阴影的格子)显示。 在图中 1, 我们能看到被选中的信号是从第一个byte 的bit 0 到第三个byte的bit 7, 这和开始位置0和给出的长度32相对应。

这样我们就结束了此博客的第一部分,介绍怎样生成一个数据库。在下一个部分我们将看一下在发送和接收信号时怎样使用数据。


注释

DBC 数据库描述CAN 总线的属性,各连接节点,和CAN 报文及信号。.

 https://www.kvaser.com/developer-blog/python-samples-now-bundled-package/

如果你看过CANlib SDK 软件开发包的t 范例CANlib SDK,你可能见过这个特别的数据库,因为你可以在文件夹folder Samples\tScript\Learn more\Misc\histogram 那里看到它。

4 kvadblib目前不支持DOUBLE 型信号。

5 我们只在此博客里介绍普通(非选择数据) 信号。

Author Image

whind gutr