如何检查设备是否连接Pyserial

12
我通过USB端口连接我的Arduino,并使用PySerial模块向其发送数据。首先,我可以使用以下代码检查设备是否已连接:

我通过USB端口连接我的Arduino,并使用PySerial模块向其发送数据。首先,我可以使用以下代码检查设备是否已连接:

try:
    ser = serial.Serial("COM3", 9600)
except serial.serialutil.SerialException:
    print "Arduino not connected"
现在我想定期检查一下Arduino是否仍然连接到电脑上。我尝试了ser.isOpen(),但是即使Arduino断开连接,它也会返回true。我还想知道如何重新连接设备。我的意思是,一旦你断开设备,程序就无法再向Arduino发送任何数据了。
6个回答

16

大部分答案提出了2个方法:

  1. 在代码的某个点,通过串行发送某种消息来检查设备是否仍然存活
  2. 启动一个单独的线程,并通过打开通信来不断检查设备是否存活

第一种解决方案的问题在于,您并不总是检查连接,而只在某些特定点上进行检查:这种解决方案不太优雅,如果编写不当甚至可能无法正常工作。

第二种解决方案解决了第一种解决方案的问题,但引入了一个新问题:在线程循环中检查连接,或者更糟的是发送消息,将会导致问题,甚至可能中断来自其他函数对设备的连接。

一种允许您在不垄断通信的情况下不断检查连接的解决方案涉及读取现有的COM:

import serial.tools.list_ports
myports = [tuple(p) for p in list(serial.tools.list_ports.comports())]
print myports

输出:

[(u'COM3', u'Arduino Due Programming Port (COM3)', u'some more data...'),
(u'COM6', u'USB Serial Port (COM6)', u'some more data...'),
(u'COM100', u'com0com - serial port emulator (COM100)', u'some more data...')]

然后我们保存包含端口的元组:

arduino_port = [port for port in myports if 'COM3' in port ][0]

然后我们创建一个函数来检查此端口是否仍然存在:

import time

def check_presence(correct_port, interval=0.1):
    while True:
        myports = [tuple(p) for p in list(serial.tools.list_ports.comports())]
        if arduino_port not in myports:
            print "Arduino has been disconnected!"
            break
        time.sleep(interval)

最后,我们将该函数作为守护进程线程运行:

import threading
port_controller = threading.Thread(target=check_presence, args=(arduino_port, 0.1,))
port_controller.setDaemon(True)
port_controller.start()

这样,您将每0.1秒检查一次Arduino是否仍然连接,当Arduino断开连接或所有其他活动结束时,该线程将结束。


@JonnyHenly 是的!你发现了一个复制粘贴错误!已经修复,谢谢。 - Gsk

9

您可以设置一个超时时间。

import serial

ser = serial

try:
  ser = serial.Serial("COM3", 9600, timeout=10)

  while ser.read():
    print 'serial open'

  print 'serial closed'
  ser.close()

except serial.serialutil.SerialException:
  print 'exception'

4

很不幸,我找到的最好方法是尝试一些沟通并查看是否失败。一个相当安全的方法是:

try:
   ser.inWaiting()
except:
   print "Lost connection!"

虽然你可能需要将ser.close()放在“try:except”块中,但在连接丢失后仍然需要关闭连接。


2
 import serial
 import time

 ser = serial.Serial()
 ser.braudrate = 115200
 ser.port = "/dev/ttyUSB0"
 ser.open()

 print(ser.name)
 if ser.isOpen():
    print("serial is open!")

 ser.close()

is_open() 已经被弃用,请使用:is_open() - creeser

1
例如,要检测ttyUSB0:
import os

x=os.system("ls /dev/ttyUSB0")

if x==0:
    print "connected"
else:
    print "disconnected"

7
建议使用 os.path.exists('/dev/ttyUSB0') 更好。 - goetz
os.path.exists确实更好。我在Windows(COM3)和Ubuntu(ttyACM0)上进行了测试,运行得非常顺畅。 - Marcos

0
我建议使用Python线程类来实例化串行连接,在run方法中放置while循环,设置一个变量用于在结束时终止它,第二个公共变量用于存储接收到的数据并在主方法中加载数据。很快会贴出一个示例。
   class Arduino():
    def __init__(self,Port='/dev/ttyUSB0',Boud=9600,connState=0): 
    self.parent=self
    self.port=Port
    self.boud=Boud
    self.connState=connState
    self.timeount=1
    self.ser=None
    self.connect()
    def connect(self): 
        try:
            self.ser=serial.Serial(self.port,self.boud,timeout=0.0001)
            self.connState=1
            return [1,'connect']
        except:
            self.connState=0
            return [0,'no hardware found']


    def loadData(self):     
        self.buffer=self.ser.read(1)        
        if (self.buffer!=''):
            try:
            print self.buffer
            except Exception, e:
            pass

    ard=Arduino()
       while True:
    if ard.connState:
        ard.loadData()
    else:
        print "Arduino not found"
        break

并且从以下内容开始:

import threading
class ThController( threading.Thread ):

   # Override Thread's __init__ method to accept the parameters needed:
    def __init__( self,parent):
        self.parent = parent
        threading.Thread.__init__ ( self )

    def run ( self ):
        while self.parent.ctrlattive:
            j=json.loads(data)
            self.parent.data=j

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接