12

pySerial を使用して Eddie にコマンドを送信しています。readline でキャリッジ リターンを指定する必要がありますが、pySerial 2.6 ではそれが削除されました...回避策はありますか?

Eddie コマンド セットは、この PDF の 2 ページ目と 3 ページ目にリストされています。PDF にアクセスできない場合のバックアップ イメージを次に示します。

一般的なコマンド形式:

Input:              <cmd>[<WS><param1>...<WS><paramN>]<CR>
Response (Success): [<param1>...<WS><paramN>]<CR>
Response (Failure): ERROR[<SP>-<SP><verbose_reason>]<CR> 

ご覧のとおり、すべての応答は\r. pySerial に停止するように指示する必要があります。

私が今持っているもの:

def sendAndReceive(self, content):
  logger.info('Sending {0}'.format(content))
  self.ser.write(content + '\r')
  self.ser.flush();
  response = self.ser.readline() # Currently stops reading on timeout...
  if self.isErr(response):
    logger.error(response)
    return None
  else:
    return response
4

5 に答える 5

20

私は同じ問題を抱えており、pyserial パッケージにある serialutil.py ファイルからコピーして変更した独自の readline() 関数を実装しました。

シリアル接続は、この関数が属するクラスの一部であり、属性「self.ser」に保存されます

def _readline(self):
    eol = b'\r'
    leneol = len(eol)
    line = bytearray()
    while True:
        c = self.ser.read(1)
        if c:
            line += c
            if line[-leneol:] == eol:
                break
        else:
            break
    return bytes(line)

これは、タイムアウトを待つよりも安全で優れた高速なオプションです。

編集: io.TextIOWrapper メソッドを機能させようとしたときに、この投稿に出くわしました ( zmoに感謝します)。したがって、上記のようにカスタム readline 関数を使用する代わりに、次を使用できます。

self.ser = serial.Serial(port=self.port,
                         baudrate=9600,
                         bytesize=serial.EIGHTBITS,
                         parity=serial.PARITY_NONE,
                         stopbits=serial.STOPBITS_ONE,
                         timeout=1)
self.ser_io = io.TextIOWrapper(io.BufferedRWPair(self.ser, self.ser, 1),  
                               newline = '\r',
                               line_buffering = True)
self.ser_io.write("ID\r")
self_id = self.ser_io.readline()

に引数を渡すようにしてください1BufferedRWPairそうしないと、シリアル接続が再度タイムアウトする原因となるバイトごとにデータが TextIOWrapper に渡されません。

に設定line_bufferingすると、書き込みのたびTrueに関数を呼び出す必要がなくなりますflush(書き込みが改行文字で終了する場合)。

編集: TextIOWrapper メソッドは実際には小さなコマンド文字列に対して機能しますが、その動作は定義されておらず、2 バイト以上を送信するとエラーが発生する可能性があります。実際に行う最も安全な方法は、独自のバージョンの を実装することですreadline

于 2013-06-06T12:17:16.510 に答える
4

pyserial のドキュメントから:

(原文のまま)

ノート:

モジュールが利用可能な新しいバージョンの Python (V2.6+) で pySerial を実行する場合、パラメーター for はサポートされなくなりましeolた。EOLreadline()io

EOLユニバーサル改行モードの文字を指定readline()または使用するには、次を使用することをお勧めしますio.TextIOWrapper

import serial
import io
ser = serial.serial_for_url('loop://', timeout=1)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

sio.write(unicode("hello\n"))
sio.flush() # it is buffering. required to get the data out *now*
hello = sio.readline()
print hello == unicode("hello\n")
于 2013-06-06T12:28:09.850 に答える
-3

送信しないシリアルデバイスから文字が来るのをreadline()待つため、タイムアウトが発生するようです。'\n'

pyserial documentationによると、行末文字を指定できます。

response = self.ser.readline(eol='\r')

それは動作しますか?

于 2013-05-10T00:11:28.330 に答える