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

Python读取串口时cal数据随机停止写入文件问题求助

串口读取cal数据异常问题

我正在从串口读取数据并写入文本文件,但无论如何设置cal,程序总会在几秒后停止读取cal数据或停止写入其输出,mm和light相关数据运行完全正常。

我已经尝试过:

  • 移除延迟
  • 提高波特率
  • 在循环中添加打印语句排查卡顿(看起来一切正常)
    单独编写仅处理cal数据的相似程序时运行正常,不清楚问题出在哪里。

相关代码

with open(path + r"\mm_response.txt", "w") as f, open(path + r"\cal_response.txt", "w") as h, open(path + r"\light_response.txt", "w") as g:
        while main.a == 1:
            #continuosly send 89 hex command to receive data back from mm
            ser_mm.write(serial.to_bytes([0x89]))
            #read serial data
            if lux == 1 and cal == 1: 
                response_mm = ser_mm.readline(12)
                response_light = ser_light.read(16)
                response_cal = ser_cal.readline()
            elif lux == 1 and cal == 0: 
                response_mm = ser_mm.readline(12)
                response_light = ser_light.read(16)
                response_cal = 0
            elif lux == 0 and cal == 1: 
                response_mm = ser_mm.readline(12)
                response_light = 0
                response_cal = ser_cal.readline()
            elif lux == 0 and cal == 0: 
                response_mm = ser_mm.readline(12)
                response_light = 0
                response_cal = 0
            else: 
                response_mm = ser_mm.readline(12)
                response_light = 0
                response_cal = 0
            #remove special characters from multimeter data
            response_mm = str(response_mm)
            response_mm = ''.join(letter for letter in response_mm if letter.isalnum())
            #remove special characters from light data
            response_light = str(response_light)
            response_light = ''.join(letter for letter in response_light if letter.isalnum())
            #remove special characters from multimeter data
            response_cal = str(response_cal)
            response_cal = ''.join(letter for letter in response_cal if letter.isalnum())
            #record null value from light meter as zero reading
            response_light = response_light.replace("x19", "0")
            #remove special characters from light data
            response_cal = response_cal.replace("b", "0")
            #record values
            g.write(response_light)
            g.flush()
            f.write(response_mm)
            f.flush()
            h.write(response_cal)
            h.flush()
            #add delay so there aren't thousands of data points
            time.sleep(0.0001)

可能的原因及修复方案

1. 串口读取阻塞导致同步异常

当前代码中三个串口的读取操作是同步串行执行的,一旦某一个读取未及时返回,会阻塞后续操作。多串口同时运行时,cal的串口读取可能被其他操作抢占资源,导致缓冲区堆积后无法正常读取。

修复: 给cal串口添加超时设置,避免永久阻塞。初始化串口时指定超时时间:

# 示例:初始化cal串口时添加timeout参数
ser_cal = serial.Serial(port='COMx', baudrate=9600, timeout=0.1)

2. cal数据处理逻辑存在漏洞

当response_cal为空字节串时,str(response_cal)会转为"b''",经过isalnum()过滤后变成空字符串,后续的replace("b", "0")不会生效,写入文件的是空内容,看起来像是停止了输出。单独运行时数据量小,问题未暴露;多串口运行时,空数据被高频写入,掩盖了正常数据。

修复: 优化cal的数据处理逻辑,先判断数据有效性:

# 替换原cal数据处理代码
if isinstance(response_cal, bytes):
    # 先解码为字符串,忽略编码错误
    cal_str = response_cal.decode('utf-8', errors='ignore').strip()
    # 空值或无效值转为0,否则保留有效字符
    response_cal = cal_str if cal_str.isalnum() else '0'
else:
    response_cal = '0'

3. 循环频率过高耗尽CPU资源

time.sleep(0.0001)意味着每秒执行10000次循环,CPU占用过高会导致串口驱动无法及时处理cal的数据。单独运行时CPU资源充足,问题不明显;多串口同时运行时,资源不足导致cal的串口处理被延迟。

修复: 适当提高延迟时间,比如改为time.sleep(0.01)(每秒100次循环),既控制数据量,也给串口驱动留出处理时间。

4. 文件写入的隐性冲突

尽管调用了flush(),但高频同时写入三个文件可能导致文件句柄的隐性阻塞。可以调整写入顺序,或者给cal的文件写入单独设置缓冲策略。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:23:21