重置打开的串行端口

时间:2016-04-26 15:29:22

标签: python serial-port pyserial

我正在读取arduino发送的串口数据。

我有两个文件,我分别使用它来编写一些代码并尝试不同的东西。在其中一个中,我读取数据并使用matplotlib图绘制它。使用完毕后,它仍然连接到我的计算机并发送数据。所以,我需要做的是“重置”端口。这样,关闭打开的端口并再次打开它,并阻止它发送数据,这样我就可以使用arduino在这个文件的代码中尝试一些修改。

所以为了实现这一点,我的意思是,为了重置端口,我创建了另一个文件并编写了这段代码:

import serial

print "Opening port"

try:
  serial_port = serial.Serial("com4", 9600)
  print "Port is open"

except serial.SerialException:
  serial.Serial("com4", 9600).close()
  print "Port is closed"
  serial_port = serial.Serial("com4",9600)
  print "Port is open again"

print "Ready to use"

但是这段代码似乎不起作用。端口仍然连接并发送数据。所以,这意味着我无法用我的代码关闭端口,然后再次重新打开它。

我做错了什么?如何阻止arduino发送数据?或者我怎么能重置arduino,也许?

希望你能帮助我。

-----编辑-----

我完成了识别我遇到的真正问题,而这不是我的想法。问题不是端口是开放的,尽管我使用Pyserial的close函数。真实的是端口正在关闭,但设备(arduino)仍在发送数据。所以,我改变了代码来重现这种情况。

这是代码:

print "Abriendo puerto"

ser = serial

try:
  ser = serial.Serial("com4", 9600, timeout = 1)
  serial_port = "Open"
  print "The port %s is available" %ser

except serial.serialutil.SerialException:
  print "The port is at use"

  ser.close()
  ser.open()

while ser.read():
  print "Sending data"

ser.setBreak(True)
time.sleep(0.2)

ser.sendBreak(duration = 0.02)
time.sleep(0.2)

ser.close()
time.sleep(0.2)
print "The port is closed"

exit()

使用此代码,我所做的是:

1)我打开串口

2)如果设备正在发送数据,我打印“发送数据”

3)1秒后,我尝试关闭端口并停止设备发送数据

我使用close函数尝试了最后两件事来关闭端口,并阅读我尝试使用setBreaksendBreak的文档,如上面的代码所示(i故意留下他们)。但是设备仍然在发送数据,这意味着代码不起作用。

那么,有没有办法告诉arduino“停止发送数据”,还是可以重置设备?

4 个答案:

答案 0 :(得分:1)

我做了一件非常相似的事情,有两种成功的方法。

第一种方法是让Arduino连续发送数据。这里的问题是当你的python代码唤醒并开始从串口读取时,Arduino可能在其程序中的任何地方。简单的解决方案是修改Arduino代码以发送某种"重启"线。在这种情况下,你需要做的所有python代码都是等待"重启",然后读取实际数据,直到它再次看到" restart"。我有嘈杂的行,所以我的代码通过多个循环读取(并解析),以确保它获得良好的数据。

resetCount = 0;
while resetCount < 3:
    line = s.readline().rstrip("\r\n")
    if string.find(line, "restart") != -1 :
        resetCount += 1
    elif resetCount > 0 :
        fields = string.split(line, " ")
        dict[fields[0]] = fields

第二种方法是使用Arduino实现命令响应协议,其中Arduino仅在请求时发送数据。在这种情况下,你的python代码向Arduino发送命令(&#34; RT&#34;在下面的例子中),然后从Arduino读取数据,直到它看到&#34;完成&#34;行或它超时。

        dict = {}
        regex = re.compile('28-[0-9A-Fa-f]{12}') # 28-000005eaa80e

        s = serial.Serial('/dev/ttyS0', 9600, timeout=5)
        s.write("RT\n");

        while True:
            line = s.readline().rstrip("\r\n")
            print line
            if string.find(line, "completed") != -1:
                break;

            fields = string.split(line)
            if (regex.match(fields[0]) != None and len(fields) == 4) :
                dict[fields[0]] = fields
        s.close()

答案 1 :(得分:0)

我认为您必须在创建后立即执行serial_port.open()以实际打开端口。

看起来它只是打开端口并在成功时退出。也许我在这里遗漏了一些东西。我从来没有使用过pySerial,我只是去了文档。

答案 2 :(得分:0)

尝试使用句柄关闭端口,而不是再次调用构造函数。 如果您打开端口并且调用serial.Serial(&#34; com4&#34;,9600),它将再次尝试重新打开端口并失败。

如果成功分配了serial_port,那么serial_port.close()应该关闭它。

答案 3 :(得分:0)

关闭端口时,数据仍可能来自arduino并被操作系统缓冲。在您的脚本调用close()与设备驱动程序实际关闭内容之间存在短暂的延迟。

立即重新打开可能会使驱动程序继续运行而不会重置其缓冲区。这是设备驱动程序缓冲区,而不是Python串行端口实例看到的缓冲区。

如果您在调用close()之后等待至少几秒钟,然后再尝试调用open(),则行为应与您希望的一样。

我一天中的大部分时间都在工作,这是导致我的代码无法正常工作的原因。