Python中长期串行连接的IO错误[Errno 5]

Python中长期串行连接的IO错误[Errno 5],python,ubuntu,arduino,serial-port,ioerror,Python,Ubuntu,Arduino,Serial Port,Ioerror,我正在Ubuntu上运行一个相当简单的python代码,用于与Arduino进行通信。代码按预期工作约15分钟,然后抛出一个I/O错误[Errno 5]。我已经搜索了很多关于这个错误消息的线索,但似乎找不到适合我需要的解决方案 python代码通过串口向Arduino发送命令,Arduino执行该命令的任何操作。当抛出此错误时,Arduino将被迫退出其原始端口号。它从“/dev/ttyACM1”到“/dev/ttyACM2” 起初我认为这与Arduino的自动复位功能有关,我在复位和+5V引脚

我正在Ubuntu上运行一个相当简单的python代码,用于与Arduino进行通信。代码按预期工作约15分钟,然后抛出一个I/O错误[Errno 5]。我已经搜索了很多关于这个错误消息的线索,但似乎找不到适合我需要的解决方案

python代码通过串口向Arduino发送命令,Arduino执行该命令的任何操作。当抛出此错误时,Arduino将被迫退出其原始端口号。它从“/dev/ttyACM1”到“/dev/ttyACM2”

起初我认为这与Arduino的自动复位功能有关,我在复位和+5V引脚之间用一个120欧姆的电阻绕过了该功能。这并没有解决问题

接下来,我认为这是因为Ubuntu机器由于不活动而挂起,所以我禁用了省电功能,但没有改进

另外,我让终端会话保持打开状态,在那里最初运行python代码

我确信问题与串行端口号有关,因为错误是由失败的ser.write命令触发的

生成此错误的python代码的子例程如下所示:

def sc_loop(ptime,maxiter, file):

iter = 1              ## Initialize cycle count
totalvol = 0
cyclevol = 0
while iter < maxiter:
    ts = time.time()
    st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
    print >>file, st, " - pump cycle #", iter
    ## Tell the arduino to begin pumping
    ser.write("1".encode())
    pump = ser.readline()
    if pump == 'P':
        ts = time.time()
        st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
        print >>file, st, " - Sample chamber pump turned ON"
    ts = time.time()
    st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
    print >>file, st, " - Sample chamber pump turned ON"
    time.sleep(ptime)
    ser.write("2".encode())
    ts2 = time.time()
    st2 = datetime.datetime.fromtimestamp(ts2).strftime('%Y-%m-%d %H:%M:%S')
    print >>file, st2, " - Sample Chamber Pump turned OFF"
    print >>file, st2, " - Pump was on for",ts2-ts, "seconds"
    cyclevol = 0.0667*(ts2-ts)
    print >>file, st2, " - ", cyclevol," mL of sample were pumped this cycle"
    totalvol = totalvol+cyclevol
    print >>file, st2, " - ", totalvol, " mL of sample have been pumped so far"
    time.sleep(3)
    runcamera(file) ## Run camera
    ## imaged = raw_input("Sample is ready for imaging [Press any key once imaged] ")
    iter = iter+1
return
def sc_循环(ptime、maxiter、文件):
iter=1##初始化循环计数
totalvol=0
cyclevol=0
当iter>文件,st,“-泵循环”,iter
##告诉arduino开始抽水
ser.write(“1.encode())
泵=序列读取线()
如果泵=‘P’:
ts=时间。时间()
st=datetime.datetime.fromtimestamp(ts).strftime(“%Y-%m-%d%H:%m:%S”)
打印>>文件,st,“-样本室泵已打开”
ts=时间。时间()
st=datetime.datetime.fromtimestamp(ts).strftime(“%Y-%m-%d%H:%m:%S”)
打印>>文件,st,“-样本室泵已打开”
时间。睡眠(ptime)
ser.write(“2.encode())
ts2=时间。时间()
st2=datetime.datetime.fromtimestamp(ts2).strftime(“%Y-%m-%d%H:%m:%S”)
打印>>文件,st2,“-样本室泵关闭”
打印>>文件,st2,“-泵开启时间”,ts2 ts,“秒”
cyclevol=0.0667*(ts2 ts)
打印>>文件,st2,“-”,cyclevol,“本次循环泵送了mL样品”
totalvol=totalvol+cyclevol
打印>>文件,st2,“-”,totalvol,“到目前为止已泵送样本毫升”
时间。睡眠(3)
运行摄影机(文件)##运行摄影机
##imaged=原始输入(“样本已准备好成像[成像后按任意键]”)
国际热核实验堆=国际热核实验堆+1
返回
这段代码可以完美地工作,尽管只是暂时的。我的问题是,在python代码运行10-15分钟后,是什么导致了这个错误

提前谢谢

看看:

问题是由于udev为设备提供动态名称。一段时间后,机器重新注册arduino,并为其分配一个新的端口号。它被分配了一个新的端口号,因为驱动程序几乎同时“删除”和“添加”arduino时会打嗝


为udev创建一个新规则来为设备分配一个静态端口将有所帮助

我也遇到了同样的错误。我所做的真正有效的工作就是简单地用
connection.close()关闭串行连接,然后用
connection=serial.serial(port,baudrate=baudrate)
重新建立它。尤其是当发生IOError[Errno 5]时。您可以使用try-and-catch来处理这个问题。

让我知道是否有代码的其他部分,您可能需要查看串行连接的建立位置等。我试图尽可能简洁地回答这个问题,但可以在必要时进行编辑。如果设备被重命名,则可能涉及系统
udev
。运行udevadm monitor
并查看是什么触发了重命名。谢谢@tdelaney,我尝试了这个,并看到端口被“删除”。就好像从机器上拔下了插头一样。一旦发生这种情况,它就会“添加”到/dev/ttyACM2。我无法从udevadm监视器中提取任何原因,但这证实了它正在被删除和重命名。udev监视器有什么特别的部分我需要注意吗?
udev监视器--property--environment
将提供更多信息。系统日志应包含更多信息。问题可能出在arduino一侧。它断开了usb连接,这是启动UbuntuBox上udev操作的原因。很好的解决方案。我的猜测是,当设备被移除时,OP将出现IOError,并且需要以相同的名称重新打开(重试和睡眠,以便udev有机会完成)。谢谢@tdelaney!你帮了大忙!我将随时更新此线程的任何进度/问题