python收发can采坑总结 (jetson xavier)

项目原因需要使用python进行can的收发,将操作进行记录

之前在stm32和k60上用C收发过can,本来以为会很顺利,然而还是踩了很多坑

测试设备:

天准xavier Ubuntu18.04 python3.6

先给一个比较官方的链接(python_can)

SocketCAN — python-can 4.0.0 documentation

天准官方也给出了比较详细的命令行测试命令

python收发can采坑总结 (jetson xavier)_第1张图片

 sudo ip -details link show can0 可以查看can的详细信息

python收发can采坑总结 (jetson xavier)_第2张图片

python_can数据发送代码

import can
import time

def msg_send(bus,msg,state_byte,speed,speed_brush,speed_wind,life_count):
    speed_byte = speed.to_bytes(2,'big')
    # print(state_byte+speed_byte)
    speed_byte3 = speed_brush + 16*speed_wind
    byte3 = speed_byte3.to_bytes(1,'big')

    byte4 = (0).to_bytes(1,'big')
    byte5 = (0).to_bytes(1,'big')
    byte6 = (0).to_bytes(1,'big')

    byte7 = life_count.to_bytes(1,'big')
    msg.data = state_byte + speed_byte + byte3 + byte4 + byte5 + byte6 + byte7
    print(msg)
    bus.send(msg)

python 接收数据代码

import can

def msg_recive(bus):
    msg = bus.recv()
    print(msg)
    # msg = can.Message(arbitration_id=0x1808DA28, data=[1, 5, 6, 53, 4, 51, 6, 6], extended_id=False)

    # if(msg.arbitration_id == 0x1808DA28):
    if(msg.arbitration_id == 0x180828DA):
        data = msg.data
        print(msg.data)

        for i in range(8):
            print(data[i])

can_bus = can.interface.Bus(channel = 'can0', bustyp = 'socketcan_ctypes')

while(True):
    msg_recive(can_bus)

python收发can采坑总结 (jetson xavier)_第3张图片

python收发can采坑总结 (jetson xavier)_第4张图片

1. 采坑1 :循环发送的话会导致buffer问题

Traceback (most recent call last):
  File "/home/nvidia/.local/lib/python3.6/site-packages/can/interfaces/socketcan/socketcan.py", line 679, in _send_once
    sent = self.socket.send(data)
OSError: [Errno 105] No buffer space available

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/nvidia/can_test/socket_can.py", line 40, in 
    producer(10)
  File "/home/nvidia/can_test/socket_can.py", line 29, in producer
    bus.send(msg)
  File "/home/nvidia/.local/lib/python3.6/site-packages/can/interfaces/socketcan/socketcan.py", line 658, in send
    sent = self._send_once(data, msg.channel)
  File "/home/nvidia/.local/lib/python3.6/site-packages/can/interfaces/socketcan/socketcan.py", line 681, in _send_once
    raise can.CanError("Failed to transmit: %s" % exc)
can.CanError: Failed to transmit: [Errno 105] No buffer space available

改大buffer可以作为解决问题的一种暂时方案,但主要问题在于数据传输有问题,才会造成buffer阻塞。

(要注意在每次发送前,清空一次can buffer)

可以先尝试改大缓存,如果仍然报错,需要查找根本原因。
进入 root账户,在路径 /sys/class/net/can0下执行 echo 4096 > tx_queue_len

使用如下py脚本进行测试

python收发can采坑总结 (jetson xavier)_第5张图片

每次重启后,再发都会稳定死在 第11次发送

python收发can采坑总结 (jetson xavier)_第6张图片

 使用win10PC,pcan软件连接can卡分析can数据,发现接收端没有收到数据,换了个can卡之后问题解决。(排查硬件故障也是软件的一部分工作啦)

采坑2 :用python应该多探索库函数,而不是和C一样啥都想自己写

比如我最初写的这个很蠢的代码 (os.system是最初测试用的,小问题)

def byte2hex(byte):
    if(byte < 16):
        ret = '0' + hex(byte)[2:]
    else:
        ret = hex(byte)[2:]
    return ret


def send_can(distance,move_dis,life_count):
    time1 = time.time()
    byte1 = abs(int(distance) % 256)
    byte2 = int(abs(int(distance) / 256))
    if distance < 0:
        byte2 = int(byte2 + 128) #处理负数
    byte3 = abs(int(move_dis) % 256)
    byte4 = int(abs(int(move_dis) / 256))
    if move_dis < 0:
        byte4 = int(byte4 + 128)
    # byte5 = 
    # byte6 = 
    # byte7 = 
    can_id = '180828DA#'

    str0 = '0A'  #根据手册的状态分情况转一下十六进制
    # str1 = hex(byte1)[2:]
    # str2 = hex(byte2)[2:]
    # str3 = hex(byte3)[2:]
    # str4 = hex(byte4)[2:]
    str1 = byte2hex(byte1)
    str2 = byte2hex(byte2)
    str3 = byte2hex(byte3)
    str4 = byte2hex(byte4)
    str5 = '00'
    str6 = '00'
    str7 = hex(life_count)[2:]

    str_all = str7 + str6 + str5 + str4 + str3 +str2 + str1 +str0

    send_cmd = 'cansend can0 '+ can_id + str_all
    
    # os.system(send_cmd)
    #time1 = time.time()
    subprocess.call(send_cmd, shell=True)
    time2 = time.time()
    print("use subproces : ",time2 - time1)

    time1 = time.time()
    os.system(send_cmd)
    time2 = time.time()
    print("use system : ",time2 - time1)
  
while True:
	send_can(distance111,move_dis111,life_count111)

你可能感兴趣的:(深度学习实际部署,单片机,python)