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

python-can接收CAN数据存在3-5秒延迟,寻求解决方案

问题排查与解决方案

核心延迟原因

  1. 频繁磁盘I/O:每次循环都调用df.to_csv()写入CSV,磁盘操作远慢于内存处理,直接阻塞CAN消息接收与处理流程。
  2. 低效DataFrame更新:重复使用df.loc[df['Name']=="..."]遍历整个DataFrame查找目标行,增加不必要的计算开销。
  3. 冗余监听器:_get_message函数无实际作用,却占用Notifier的处理资源。

修复后的代码

import can
import logging
import pandas as pd
from time import time

class PCANBus(object):
    def __init__(self):
        logging.info("Initializing CANbus")
        self.bus = can.interface.Bus(interface='vector', app_name='EA7B', channel='0,1', receive_own_messages=True)
        self.buffer = can.BufferedReader()
        # 移除无用的_get_message监听器
        self.notifier = can.Notifier(self.bus, [self.buffer])

    def read_input(self):      
        return self.buffer.get_message()

    def cleanup(self):
        self.notifier.stop()
        self.bus.shutdown()
           
pcan = PCANBus() 
fileName = "c:\\Data\\Can.csv"
df = pd.read_csv(fileName)

# 预计算目标行索引,避免每次遍历整个DataFrame
try:
    target_row_idx = df[df['Name'] == "ADAS_CAM_EGO_LANE_HI_ACCU_POSX"].index[0]
except IndexError:
    logging.error("CSV中未找到目标行'ADAS_CAM_EGO_LANE_HI_ACCU_POSX'")
    exit(1)

# 配置批量写入参数
WRITE_INTERVAL = 1  # 每1秒写入一次CSV
last_write_time = time()
update_count = 0

try:
    while True: 
        msg = pcan.read_input()
        
        if msg.arbitration_id == 780:  # IDAS_30C
            print("Message value", msg)
            # 使用预计算索引快速更新单元格
            df.at[target_row_idx, 'value'] = str(msg.data[3] >> 1) 
            update_count += 1
        
        # 仅在达到时间间隔且有更新时写入CSV
        current_time = time()
        if (current_time - last_write_time >= WRITE_INTERVAL) and update_count > 0:
            try:   
                df.to_csv(fileName, index=False)
                last_write_time = current_time
                update_count = 0  # 重置更新计数器
            except PermissionError:
                print("无法打开文件,跳过本次写入")

except KeyboardInterrupt:
    # 退出时写入剩余更新
    if update_count > 0:
        try:
            df.to_csv(fileName, index=False)
        except PermissionError:
            print("退出时无法写入最终更新到CSV")
    print("Program Exited")
    pcan.cleanup()

修复说明

  1. 移除冗余监听器:删除无实际作用的_get_message函数,减少Notifier的处理负载。
  2. 预计算目标行索引:启动时一次性找到目标行的索引,后续使用df.at[]直接更新单元格,效率远超重复遍历DataFrame。
  3. 批量写入CSV:设置固定时间间隔(1秒),仅当有更新且达到间隔时才写入磁盘,彻底解决频繁I/O导致的阻塞。
  4. 退出时收尾:确保程序中断时,未写入的更新能被保存。

额外优化建议

  • 如果需要更低延迟,可将CSV写入逻辑放到单独线程,避免阻塞CAN消息接收线程。
  • 生产环境中可替换print()为logging模块,减少控制台输出带来的微小延迟。
  • 检查Vector接口的接收缓冲区配置,确保硬件数据能及时传递到软件层。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:31:07