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
相关产品推荐
相关产品推荐

