【问题标题】:Python to automatically select serial ports (for Arduino)Python 自动选择串口(适用于 Arduino)
【发布时间】:2014-08-04 13:31:27
【问题描述】:

目前,python 程序必须知道设备 (Arduino) 在哪个端口上,然后 Python 才能与设备通信。

问题: 每当设备被拔出和重新插入时,它的 COM 端口都会发生变化,因此必须再次将正确的串行端口提供给 Python 才能找到设备。

Python(使用pySerial)如何自动搜索要使用的正确串口? python是否可以正确地将串口上的设备识别为Arduino?

【问题讨论】:

  • 如果您的问题是 USB 设备断开并重新连接时计算机中的端口发生变化,那么答案可能取决于操作系统。你在使用 pySerial 吗?
  • @user3735428 是的,我正在使用 pySerial。希望有一个适用于 Windows/Mac/Linux 的解决方案

标签: python python-2.7 serial-port arduino pyserial


【解决方案1】:

使用以下代码查看所有可用的串口:

import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
    print p

这给了我以下信息:

('COM4', 'Arduino Due Programming Port (COM4)', 'USB VID:PID=2341:003D SNR=75330303035351300230')
('COM11', 'RS-232 Port (COM11)', 'FTDIBUS\\VID_0856+PID_AC27+BBOPYNPPA\\0000')

要确定它是否是 Arduino,您可以执行以下操作:

    if "Arduino" in p.description:
        print "This is an Arduino!"

【讨论】:

  • 如果您插入 Arduino Due 上的 Native USB 端口,这也可以工作。我还没有在任何其他 Arduino 上测试过它。
  • p[1] 拼写更好p.description
  • 如果您检查 p.hwid 的“VID:PID=2341:0043”,那是一个 arduino uno,它也适用于仿冒品。您需要使用不同的 PID(只需像在帖子中那样扫描您的端口以找到正确的)。
  • 这也适用于 Linux,即使端口具有不同的名称并且“Arduino”不在 p.description 中。相反,p.manufacturer 包含“Arduino”,p.serial_number 告诉我哪个是哪个 :-)
  • 您也可以使用serial.tools.list_ports.grep('Arduino') 过滤掉不需要的设备。可以按字符串或正则表达式搜索pyserial.readthedocs.io/en/latest/…
【解决方案2】:

使用serial.tools.list_ports.comports,我们可以找到并连接到一个arduino:

import warnings
import serial
import serial.tools.list_ports

arduino_ports = [
    p.device
    for p in serial.tools.list_ports.comports()
    if 'Arduino' in p.description  # may need tweaking to match new arduinos
]
if not arduino_ports:
    raise IOError("No Arduino found")
if len(arduino_ports) > 1:
    warnings.warn('Multiple Arduinos found - using the first')

ser = serial.Serial(arduino_ports[0])

如果您知道每次都在寻找完全相同的 arduino,则可以改为过滤 p.serial_number

import serial.tools.list_ports

def find_arduino(serial_number):
    for pinfo in serial.tools.list_ports.comports():
        if pinfo.serial_number == serial_number:
            return serial.Serial(pinfo.device)
    raise IOError("Could not find an arduino - is it plugged in?")

ser = find_arduino(serial_number='85430353531351B09121')

【讨论】:

  • 效果很好,但仅适用于原始 Arduino。非原装 Arduinos 会以不同的方式报告,例如“通用 CDC”...最终最好的解决方案是列出所有可能的 USB 设备,然后允许用户使用运行时标志选择一个。
  • @dust:是的,但是对于您在多个 USB 端口和计算机之间弹跳一个硬件的常见情况,这种技术是最方便的。如果您希望检测以前未见过的类似 arduino 的设备,您将遇到困难,并且按照您提到的方式强制用户选择可能是最好的路径
  • 是否可以对 Arduino 给出的描述进行编程?然后每个 python 都会找到并连接到它需要的确切 Arduino。
【解决方案3】:
"""
Written on a Windows 10 Computer, Python 2.7.9 Version.

This program automatically detects and lists ports.  If no ports are found, it simply shells out.  In the printout below "list(serial.tools.list_ports.comports())" finds two ports and the program lists them out - a listout shown below:

     COM5 - USB-SERIAL CH340 (COM5)
     Found Arduino Uno on COM5
     COM4 - Microsoft USB GPS Port (COM4)

As each port is found, "CH340," (the name of the Adruino Uno) is searched for in the listed port with the "while int1 < 9:" loop.  The first "If" statement looks for "CH340" and when found the integer value "int1" will be the same as the com port #. With a concatination,  the operation "str1 = "COM" + str2" gives the com port name of the Adruino, eg. "COM5."  The next "IF" statement looks for both "CH340" AND str1, ("COM5") in the above case.  The statement "Found Arduino Uno on COM5" prints out, and "str1" is used in setting up the com port:

ser = serial.Serial(str1, 9600, timeout=10)

This program goes on to open the com port and prints data from the Adruino.

The modules "serial, sys, time, serial.tools.list_ports" must all be imported.

Written by Joseph F. Mack 01/29/2016.  "A BIG Thank you" to all the individuals whose programs I "borrowed" from that are available in the many forums for Python and PYGame users!
"""

import serial
import sys
import time
import serial.tools.list_ports

serPort = ""
int1 = 0
str1 = ""
str2 = ""

# Find Live Ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
   print p # This causes each port's information to be printed out.
           # To search this p data, use p[1].

   while int1 < 9:   # Loop checks "COM0" to "COM8" for Adruino Port Info. 

      if "CH340" in p[1]:  # Looks for "CH340" in P[1].
            str2 = str(int1) # Converts an Integer to a String, allowing:
            str1 = "COM" + str2 # add the strings together.

      if "CH340" in p[1] and str1 in p[1]: # Looks for "CH340" and "COM#"
         print "Found Arduino Uno on " + str1
         int1 = 9 # Causes loop to end.

      if int1 == 8:
         print "UNO not found!"
         sys.exit() # Terminates Script.

      int1 = int1 + 1

time.sleep(5)  # Gives user 5 seconds to view Port information -- can be   changed/removed.

# Set Port
ser = serial.Serial(str1, 9600, timeout=10) # Put in your speed and timeout value.

# This begins the opening and printout of data from the Adruino.

ser.close()  # In case the port is already open this closes it.
ser.open()   # Reopen the port.

ser.flushInput()
ser.flushOutput()

int1 = 0
str1 = ""
str2 = ""

while int1==0:

   if "\n" not in str1:        # concatinates string on one line till a line feed "\n"
      str2 = ser.readline()    # is found, then prints the line.
      str1 += str2
   print(str1)
   str1=""
   time.sleep(.1)

print 'serial closed'
ser.close()

【讨论】:

  • 我假设这个程序是在插入 Arduino 的计算机上运行的。那正确吗?用什么扩展名来保存这个文件?
  • 这是写得很糟糕的代码。 int&lt;n&gt; 不是一个明智的变量名,8 和 9 是很神奇的数字
  • 此代码不适用于正版 Arduinos。正版 Arduino 使用 FTDI USB 串行桥接器,而 CH340/CH341 串行端口是江苏勤恒芯片,仅在廉价的中国 Arduino“克隆”上找到。
【解决方案4】:

试试这个代码(仅适用于windows用户。MAC用户可以退出这个概念)

import serial
import time
list=['COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9','COM10','COM11','COM12','COM13','COM14','COM15','COM16','COM17','COM18',]



COM1='COM1'
COM2='COM2'
COM3='COM3'
COM4='COM4'
COM5='COM5'
COM6='COM6'
COM7='COM7'
COM8='COM8'
COM9='COM9'
COM10='COM10'
COM11='COM11'
COM12='COM12'
COM13='COM13'
COM14='COM14'
COM15='COM15'
COM16='COM16'
COM17='COM17'
COM18='COM18'
COM19='COM19'
time.sleep(1)
ser = serial.Serial()

ser.baudrate = 9600

i=1

while True:
    time.sleep(.2)
    print(i)
    ser.port = list[i]
    try:

        ser.open()
        if ser.isOpen()==True:
            print('connected')
            #print('arduino is on COMPORT'.join(i))
            break
        break

    except:
        print('waiting')
        i=i+1
        if i==18:
            print('Kindly remove usb cable and try again')
            break


print('here we go')
while True:
    print(ser.readline())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2017-06-26
    相关资源
    最近更新 更多