私は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:
そしてそれは永遠に続きます。読み取りデータなどはありません。
どこが間違っているのですか?
どうやらもっと単純なバージョンのコードが問題を解決したようです。
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
_ser.timeout = None
_が原因で問題が発生しているようです。 while
ループの最初のサイクルは正常に終了したようですが、プログラムが2回目にser.readline()
を試行するとハングします。
これを解決するにはいくつかの方法があります。私が好む方法は、None
以外のタイムアウト(おそらく1秒)を指定することです。これにより、デバイスがエンドライン文字を送信しない場合でも、ser.readline()
が値を返すことができます。
もう1つの方法は、ser.readline()
をser.read(ser.in_waiting)
またはser.read(ser.inWaiting())
のように変更して、バッファーで使用可能なすべての文字を返すことです。
このコードを試してください
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