Python自动选择串口(用于Arduino)

30 投票
4 回答
48801 浏览
提问于 2025-04-18 09:44

目前,Python程序必须知道设备(Arduino)连接在哪个端口上,才能与设备进行通信。

问题:每当设备拔掉再插上时,它的COM端口就会改变,因此必须再次告诉Python正确的串口,才能让它找到设备。

那么,Python(使用pySerial库)怎么才能自动搜索到正确的串口呢?Python能否正确识别串口上的设备是Arduino呢?

4 个回答

-3

试试这段代码(仅适用于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())
2

在编程中,有时候我们需要让程序在特定的条件下执行某些操作。比如说,当用户输入一个数字时,我们希望程序能判断这个数字是正数、负数还是零。这个过程就叫做“条件判断”。

条件判断的基本思路是:程序会检查一个条件,如果这个条件成立(也就是“真”),那么就执行某个操作;如果条件不成立(也就是“假”),那么就执行另一个操作。这样,程序就能根据不同的情况做出不同的反应。

在代码中,我们通常会用“if”语句来实现条件判断。比如:

"""
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()

在这个例子中,程序会先检查用户输入的数字。如果这个数字大于零,程序就会告诉用户“这是一个正数”;如果数字小于零,程序会说“这是一个负数”;如果数字等于零,程序则会说“这是零”。

通过这种方式,程序能够根据用户的输入做出相应的反馈,这就是条件判断的基本用法。

24

使用 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')
45

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

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!"

撰写回答