2
4

More than 3 years have passed since last update.

PythonでSerialポートを調べて受信する(Port check)

Last updated at Posted at 2020-01-23

PythonでSerialからのデータを受信する場合、SerialPortを指定する必要がありますが、Serialが1つのみでボーレートもわかっている場合は

from serial.tools import list_ports
import serial
ports = list_ports.comports()
ser = serial.Serial(ports[0].device,9600,timeout=0.1)

のようにしてポートを開くことができます。

これではあまりにも乱暴だという場合は、シリアルのボーレートと送られてくるデータのフォーマットが既知であれば、利用可能なポート全について流れてくるデータのフォーマットをチェックしてポートを開くことができます。

例えばPCに繋いだArduinoから9600bpsで定期的に

test:data=***

のようなデータが送られてくる場合は

from datetime import datetime as dt
from serial.tools import list_ports
import serial
import re

#---------------------------
def ReceiveSerial(_ser):
    _dataStr = ""
    if(_ser!=None):
        _data = _ser.readline()
        if(len(_data)>0):
            try:
                tmpDataStr = _data.decode('utf-8') # 'temp,24.5,hum,50.0'
            except:
                pass
            else:
                _dataStr = re.sub(r'\r|\n|','',tmpDataStr)
    return _dataStr
#---------------------------

def ScanUsingSerialPortName(_reg="^", _baudrate = 115200):
    devName = ""
    ckSer = serial.Serial()
    ckSer.baudrate = _baudrate
    ckSer.timeout = 0.1
    ports = list_ports.comports()
    print("find " + str(len(ports))+"ports")
    if len(ports) > 0:
        deviceNames = []
        for info in ports:
            deviceNames.append(info.device) # ポートの名前を取得
            isReady = SerialPortCheck(ckSer,info.device,_reg)
            if (isReady):
                devName = info.device
                break;
    return devName

def SerialPortCheck(_serial, _portName, _reg):
    ret = False
    _serial.port = _portName    # ポートを指定

    try:
        _serial.open()
    except:
        pass
    else:
        print("SerialPortCheck " + _serial.port )
        startDt = dt.now()
        while True:
            # 1行読み込む
            s = ReceiveSerial(_serial)
            if(len(s)>0):
                print(">" + s)
                matchOB = re.match(_reg,s)
                if matchOB:
                    print("match")
                    ret = True
                    break

            tickTime = (dt.now() - startDt).seconds
            if ((_serial.is_open==False) or (tickTime > 3)):
                print("TimeOut" + s)
                break
        _serial.close()
    return ret

#---------------------------

def SetSerial(_serial, _reg="^", _baudrate=115200):
    if((_serial!=None)and(_serial.is_open)):
        _serial.close()
    tmpSer = None
    usingPortName = ScanUsingSerialPortName(_reg,_baudrate)
    if(usingPortName!=""):
        tmpSer = serial.Serial()
        tmpSer.baudrate = _baudrate
        tmpSer.timeout = 0.1
        tmpSer.port = usingPortName # ポートを指定

        try:
            tmpSer.open()
        except:
            tmpSer = None
        else:
            print("SetSerialOK")
    return tmpSer
#---------------------------
ser =SetSerial(ser,"^"+"test:data=",9600)

のようにすることでポートを特定できます。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4