web-dev-qa-db-ja.com

PySerialを使用してデータを待つことは可能ですか?

Python PySerialモジュールを介してシリアルポートからデータを読み取るプログラムです。注意する必要がある2つの条件は次のとおりです。どのくらいの量のデータが到着するかわからないし、いつデータを受け取るかわからない。

これに基づいて、次のコードスニペットを作成しました。

_#Code from main loop, spawning thread and waiting for data
s = serial.Serial(5, timeout=5)  # Open COM5, 5 second timeout
s.baudrate = 19200

#Code from thread reading serial data
while 1:
  tdata = s.read(500)    # Read 500 characters or 5 seconds

  if(tdata.__len__() > 0):        #If we got data
    if(self.flag_got_data is 0):  #If it's the first data we recieved, store it
      self.data = tdata        
    else:                         #if it's not the first, append the data
      self.data += tdata
      self.flag_got_data = 1
_

したがって、このコードは、シリアルポートからデータを取得してループします。最大500文字でデータを保存し、フラグを設定してメインループに警告します。データが存在しない場合は、スリープ状態に戻って待機します。

コードは機能していますが、5秒のタイムアウトは好きではありません。必要なデータ量がわからないため必要です。ただし、データが存在しない場合でも、5秒ごとに目が覚めるのが気に入らないのです。

readを実行する前にデータが利用可能になったことを確認する方法はありますか? Linuxのselectコマンドのようなものを考えています。

注:inWaiting()メソッドを見つけましたが、実際には「スリープ」をポーリングに変更するだけなので、ここでは望んでいません。データが入るまでスリープ状態にしてから、取得します。

20
Mike

わかりました、私は実際に私がこれのために私が好む何かを得た。タイムアウトなしのread()inWaiting()メソッドの組み合わせを使用する:

#Modified code from main loop: 
s = serial.Serial(5)

#Modified code from thread reading the serial port
while 1:
  tdata = s.read()           # Wait forever for anything
  time.sleep(1)              # Sleep (or inWaiting() doesn't give the correct value)
  data_left = s.inWaiting()  # Get the number of characters ready to be read
  tdata += s.read(data_left) # Do the read and combine it with the first character

  ... #Rest of the code

これは私が望んでいた結果を与えているようです、私はこのタイプの機能はPythonの単一のメソッドとして存在しないと思います

18
Mike

_timeout = None_を設定すると、read呼び出しは、要求されたバイト数になるまでブロックされます。データが到着するまで待機する場合は、タイムアウトNoneを指定してread(1)を実行します。ブロックせずにデータを確認する場合は、タイムアウトゼロでread(1)を実行し、データが返されるかどうかを確認します。

(ドキュメントを参照してください http://pyserial.sourceforge.net/pyserial_api.html

12
TJD
def cmd(cmd,serial):
    out='';prev='101001011'
    serial.flushInput();serial.flushOutput()
    serial.write(cmd+'\r');
    while True:
        out+= str(serial.read(1))
        if prev == out: return out
        prev=out
    return out

次のように呼び出します:

cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000))
0
user5509884