web-dev-qa-db-ja.com

Python3双方向シリアル通信:データの読み取り

私はPython3を介して双方向通信を確立しようとしています。レーザーレンジファインダーがUSBポートの1つに接続されていますが、それにコマンドを送信または受信したいと思います。送信できるコマンドと返されるコマンドのシートがあるので、この部分はすでにあります。

必要なのは、リアルタイムでそれを行うための便利な方法です。これまでのところ、私は次のコードを持っています:

import serial, time

SERIALPORT = "/dev/ttyUSB0"
BAUDRATE = 115200

ser = serial.Serial(SERIALPORT, BAUDRATE)
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = None          #block read
ser.xonxoff = False     #disable software flow control
ser.rtscts = False     #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False       #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 0     #timeout for write

print ("Starting Up Serial Monitor")

try:
    ser.open()
except Exception as e:
    print ("Exception: Opening serial port: " + str(e))

if ser.isOpen():
    try:
        ser.flushInput()
        ser.flushOutput()
        ser.write("1\r\n".encode('ascii'))
        print("write data: 1")
        time.sleep(0.5)
        numberOfLine = 0
        while True:
            response = ser.readline().decode('ascii')
            print("read data: " + response)
            numberOfLine = numberOfLine + 1
            if (numberOfLine >= 5):
                break
        ser.close()
    except Exception as e:
        print ("Error communicating...: " + str(e))
else:
    print ("Cannot open serial port.")

したがって、上記のコードでは、レーザーファインダーの「getDistance()」関数をトリガーして距離をmmで返す「1」を送信しています。私はこれをPuTTYで試してみましたが、機能し、最大4桁の距離を返します。ただし、上記のPythonスクリプトを起動すると、出力は次のようになります。

Starting Up Serial Monitor
Exception: Opening serial port: Port is already open.
write data: 1
read data: 

そしてそれは永遠に続きます。読み取りデータなどはありません。

どこが間違っているのですか?

4
Schütze

どうやらもっと単純なバージョンのコードが問題を解決したようです。

import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 115200, timeout = 1) # ttyACM1 for Arduino board

readOut = 0   #chars waiting from laser range Finder

print ("Starting up")
connected = False
commandToSend = 1 # get the distance in mm

while True:
    print ("Writing: ",  commandToSend)
    ser.write(str(commandToSend).encode())
    time.sleep(1)
    while True:
        try:
            print ("Attempt to Read")
            readOut = ser.readline().decode('ascii')
            time.sleep(1)
            print ("Reading: ", readOut) 
            break
        except:
            pass
    print ("Restart")
    ser.flush() #flush the buffer

必要に応じて出力:

Writing:  1
Attempt to Read
Reading: 20
Restart
Writing:  1
Attempt to Read
Reading:  22
Restart
Writing:  1
Attempt to Read
Reading:  24
Restart
Writing:  1
Attempt to Read
Reading:  22
Restart
Writing:  1
Attempt to Read
Reading:  26
Restart
Writing:  1
Attempt to Read
Reading:  35
Restart
Writing:  1
Attempt to Read
Reading:  36
2
Schütze

_ser.timeout = None_が原因で問題が発生しているようです。 whileループの最初のサイクルは正常に終了したようですが、プログラムが2回目にser.readline()を試行するとハングします。

これを解決するにはいくつかの方法があります。私が好む方法は、None以外のタイムアウト(おそらく1秒)を指定することです。これにより、デバイスがエンドライン文字を送信しない場合でも、ser.readline()が値を返すことができます。

もう1つの方法は、ser.readline()ser.read(ser.in_waiting)またはser.read(ser.inWaiting())のように変更して、バッファーで使用可能なすべての文字を返すことです。

0
Alton Campbell

このコードを試してください

try:
  ser = serial.Serial("/dev/ttyS0", 9600) #for COM3
  ser_bytes = ser.readline()
  time.sleep(1)
  inp = ser_bytes.decode('utf-8')
  print (inp)
except:
  pass
0
Reyhaneh Trb