You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raspberry Pi4使用PCAN Canable读取CAN总线时出现读取超时错误求助

Raspberry Pi 4下PCAN适配器读取CAN总线数据时出现*"The CAN controller was read too late"*错误的解决思路

我正在开发一个基于Raspberry Pi 4的项目,技术栈包含Python、Kivy GUI及python-can库,通过PCAN Canable适配器读取车辆CAN总线数据并实现可视化。该项目在Windows PC上运行完全正常,但切换到Raspberry Pi 4后,应用可正常运行一段时间并正确展示数据,随后出现延迟并抛出如下错误:

File "/home/admin/.local/lib/python3.11/site-packages/can/notifier.py", line 124, in _rx_thread
if msg := bus.recv(self.timeout):
^^^^^^^^^^^^^^^^^^^^^^
File "/home/admin/.local/lib/python3.11/site-packages/can/bus.py", line 126, in recv
msg, already_filtered = self._recv_internal(timeout=time_left)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/admin/.local/lib/python3.11/site-packages/can/interfaces/pcan/pcan.py", line 558, in _recv_internal
raise PcanCanOperationError(self._get_formatted_error(result))
can.interfaces.pcan.pcan.PcanCanOperationError: The CAN controller was read too late

相关代码片段

import can
# 其他导入语句省略

''' 其他类定义 '''

class Can_data(can.Listener):
    print("reading can messages")

    def on_message_received(self, msg):
        # print(f"data: {msg}")
        if msg.arbitration_id == 0x316 and msg is not None:
            Dash_Board.rpm = msg.data[3] * 7000 / 110
            Dash_Board.arrow_rpm = Dash_Board.rpm
            print("rpm: ", Dash_Board.rpm)
            Dash_Board.rpm = round(Dash_Board.rpm / 50) * 50

        elif msg.arbitration_id == 0x1F1 and msg is not None:
            Dash_Board.speed = int(msg.data[4] * 220 / 110)
            Dash_Board.arrow_speed = Dash_Board.speed * 260 / 220
            print("t: ", Dash_Board.speed)
            # 取消注释可启用数据过滤
        elif msg.arbitration_id == 0x0A0 and msg is not None:
            Dash_Board.t = msg.data[1] - 40
            print("t: ", Dash_Board.t)
        elif msg.arbitration_id == 0x0A1 and msg is not None:
            Dash_Board.boost = msg.data[4]
            print("boost: ", Dash_Board.boost)
        elif msg.arbitration_id == 0x0350 and msg is not None:
            Dash_Board.fuel = msg.data[3] * 0.75
            print("tank: ", Dash_Board.fuel)
        else:
            print("no message recieved")

    def stop(self):
        print("stoped")


class Read_bus_data():

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        print("reading bus data")

        self.filter = [
            {"can_id": 0x316, "can_mask": 0x7FF, "extended": False},
            {"can_id": 0x1F1, "can_mask": 0x7FF, "extended": False},
            {"can_id": 0x0A0, "can_mask": 0x7FF, "extended": False},
            {"can_id": 0x0A1, "can_mask": 0x7FF, "extended": False},
            {"can_id": 0x350, "can_mask": 0x7FF, "extended": False}
        ]

        self.bus = None
        self.notifier = None

        self.start_bus()

    def start_bus(self):
        try:
            self.bus = can.Bus(interface='pcan', channel='PCAN_USBBUS1', can_filters=self.filter, timeout=2)

            listen = Can_data()
            self.notifier = can.Notifier(self.bus, [listen], timeout=2)

            # 以下为注释掉的备用读取逻辑
            # with self.bus as bus:
            # msg = self.bus.recv(0.1)
            # for msg in bus:
            # if msg.arbitration_id == 0x316 and msg is not None:
            # Dash_Board.rpm = msg.data[3]*7000/110
            # Dash_Board.arrow_rpm = Dash_Board.rpm
            # print("rpm: ", Dash_Board.rpm)
            # Dash_Board.rpm = round(Dash_Board.rpm/50)*50

            # elif msg.arbitration_id == 0x1F1 and msg is not None:
            # Dash_Board.speed = int(msg.data[4]*220/110)
            # Dash_Board.arrow_speed = Dash_Board.speed*260/220
            # print("t: ", Dash_Board.speed)
            # # #取消注释可启用数据过滤
            # if msg.arbitration_id == 0x0A0 and msg is not None:
            # Dash_Board.t = msg.data[1] - 40
            # print("t: ", Dash_Board.t)
            # elif msg.arbitration_id == 0x0A1 and msg is not None:
            # Dash_Board.boost = msg.data[4]
            # print("boost: ", Dash_Board.boost)
            # elif msg.arbitration_id == 0x0350 and msg is not None:
            # Dash_Board.fuel = msg.data[3]*0.75
            # print("tank: ", Dash_Board.fuel)
            # else:
            # print("no message recieved")

        except Exception as e:
            print("error", e)
            # self.cleanup()


class Dashboard_project(MDApp):

    def build(self):
        sm = MDScreenManager()
        sm.add_widget(Classic_style_dash_board())
        sm.add_widget(Sport_style_dash_board())
        sm.add_widget(Engine())
        Read_bus_data()
        return sm

if __name__ == '__main__':
    Dashboard_project().run()

已尝试的解决方案

  • 使用PEAK系统的PCANBasic库(运行缓慢,未解决问题)
  • 更新树莓派系统、驱动并优化硬件配置
  • 更换高效电源,排除供电不足问题
  • 用Arduino+MCP2515 CAN模拟器测试PCAN适配器,适配器工作正常
  • 使用threading.queue传递CAN数据到GUI线程,问题依旧

故障无固定触发规律,应用可运行10秒至10分钟不等,现寻求新的解决思路。

内容的提问来源于stack exchange,提问作者Dima Panasenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:50:55