为何树莓派4B与执行器的CAN FD连接后通信异常?
我用Raspberry Pi 4B搭配Waveshare CAN HAT和一台执行器做CAN FD通信。分开测试时,用测试器能读到两台设备发出的正确帧,但把树莓派和执行器连起来后,树莓派收到的帧ID、数据、长度全是异常的。
运行代码
import time import os import can import cantools def startBus(): os.system('sudo ip link set can0 up type can bitrate 500000 dbitrate 5000000 restart-ms 1000 berr-reporting on fd on') time.sleep(0.1) global can0 can0 = can.interface.Bus(bustype='socketcan', channel='can0', bitrate=500000, dbitrate=5000000 receive_own_messages=False, local_loopback=True, fd=True, can_filters=None, ignore_rx_error_frames=False) def shutDownBus(): os.system('sudo ifconfig can0 down') print('shut down') def periodicSend(): print('sendPeriodic') messageID1 = 0xC0FFEE data1 = [0, 1, 2, 3, 4, 5, 6, 7] msg1 = can.Message(arbitration_id=messageID1, is_fd=True, data=data1, is_extended_id=False) messageID2 = 0xC0FFFF data2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] msg2 = can.Message(arbitration_id=messageID2, is_fd=True, data=data2, is_extended_id=False) task1 = can0.send_periodic(msg1, 0.01) if not isinstance(task1, can.ModifiableCyclicTaskABC): task1.stop() return task2 = can0.send_periodic(msg2, 0.01) if not isinstance(task2, can.ModifiableCyclicTaskABC): task2.stop() return def listen(): print("listening") for message in can0: print(message) # Calling the functions: shutDownBus() time.sleep(1) startBus() periodicSend() listen() x = False while not x: time.sleep(0.1)
接收的异常帧内容
Timestamp: 1667826218.955793 ID: 0088 S Rx E DL: 8 00 00 94 00 00 00 00 00 Channel: can0 Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 90 00 00 00 00 00 Channel: can0 Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 04 00 00 00 00 00 Channel: can0 Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 02 00 00 00 00 00 Channel: can0
这类帧会不断重复,其中第三个字节持续变化,和测试器显示的正确帧完全不符。
已尝试的操作
- 调整过比特率(500kbit/s和5000kbit/s),确认当前设置正确
- 排除硬件问题,分开测试两台设备都能发送正常帧
- 把
ignore_rx_error_frames设为False会让消息消失,但这不是根本解决办法 - 修改
local_loopback参数没有明显效果 - 查到类似问题可能和ACK位有关,但不知道怎么操作,而且总线上第一帧就不符合预期
排查方向与解决建议
检查CAN总线终端电阻
CAN总线两端必须接120Ω终端电阻,否则会出现信号反射导致帧异常。确认树莓派的CAN HAT和执行器是否都接了终端电阻,或者总线上是否有多余的终端电阻(总线上只能保留两个)。修正代码参数错误
你的startBus函数中,创建can.interface.Bus时dbitrate=5000000后面少了逗号,导致参数传递混乱,同时local_loopback建议关闭:can0 = can.interface.Bus(bustype='socketcan', channel='can0', bitrate=500000, dbitrate=5000000, receive_own_messages=False, local_loopback=False, fd=True, can_filters=None, ignore_rx_error_frames=False)验证CAN FD配置一致性
确认执行器的CAN FD配置和树莓派完全匹配:包括仲裁比特率、数据比特率、FD模式开关,以及帧格式(标准/扩展ID)。你发送的帧用了is_extended_id=False,如果执行器用的是扩展ID,会直接导致解析异常。用系统命令抓包排查
用candump直接抓取总线数据,排除Python库的问题:candump can0,0:0,#FFFFFFFF如果
candump抓到的也是异常帧,问题出在总线配置或硬件连接;如果candump能抓到正确帧,那就是Python代码或python-can库的配置问题。降低总线负载测试
你当前以100Hz发送两个帧,总线负载可能过高。先暂停发送逻辑,只监听执行器的帧,看是否能正常接收,排除发送导致的总线冲突。
内容的提问来源于stack exchange,提问作者Tawhiri

