動作環境
Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
Python 2.7.9
pySerial 2.6-1.1
$ pip show pyserial
---
Name: pyserial
Version: 2.6
Location: /usr/lib/python2.7/dist-packages
Requires:
注意点
Python 2.6 以降だと PySerial で '\r' が readline の delimiter に使えない
PySerial では Python 2.6 以降の場合には、'\r' (CR) が readline のときの delimiter に使えません。つまり、装置側の出力に '\r' が delimiter として使われている場合、次の code だと '\n' (LF) を待ってしまうために time out してしまいます。
ということで、readline()は用途によっては使えない。
実装
CR終端文字列の受信を実装してみた。
- 参考1: https://stackoverflow.com/questions/16470903/pyserial-2-6-specify-end-of-line-in-readline
- 参考2: pyserialでreadしたデータの文字比較
CRコード自身は受信文字列から除外するように実装した。
タイムアウトなし
test_recv_170825b.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import serial
import datetime
def recvCommand_CRterminated():
if con1.inWaiting() == 0:
return
EOL_CODE = '\r'
buf = ""
while True:
c = con1.read(1) # 1: byte
if c:
if c == EOL_CODE:
break
buf += c
print(datetime.datetime.today(), end='')
print("recvd:", end='')
print(buf)
with serial.Serial('/dev/ttyUSB1', 9600, timeout=10) as con1:
recvCommand_CRterminated()
#con1.flushOutput()
#con1.flushInput()
#time.sleep(.1)
タイムアウトあり
- 受信ありかどうかは10msecごとにチェックしている
test_recv_170825.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import serial
import datetime
def recvCommand_CRterminated(tmout_sec):
EOL_CODE = '\r'
buf = ""
start_time = time.time()
while True:
# print('.', end='')
if con1.inWaiting() == 0:
if (time.time() - start_time > tmout_sec):
return
time.sleep(0.01)
continue
code = con1.read(1) # 1: byte
if code:
if code == EOL_CODE:
break
buf += code
print(datetime.datetime.today(), end='')
print("recvd:", end='')
print(buf)
with serial.Serial('/dev/ttyUSB1', 9600, timeout=10) as con1:
recvCommand_CRterminated(0.1) # [sec]
#con1.flushOutput()
#con1.flushInput()
#time.sleep(.1)
関連
Raspberry Pi > pySerial 2.6 > bug? > 受信バッファにデータが残る場合がある
import用
- import用に変更
- LFコードは無視
util_recv_170825.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import serial
import datetime
def recvCommand_CRterminated(acon, tmout_sec):
CR_CODE = '\r'
LF_CODE = '\n'
buf = ""
start_time = time.time()
while True:
# print('.', end='')
if acon.inWaiting() == 0:
if (time.time() - start_time > tmout_sec):
return
time.sleep(0.01)
continue
code = acon.read(1) # 1: byte
if code:
if code == LF_CODE: # ignore LF
continue
if code == CR_CODE:
break
buf += code
print(datetime.datetime.today(), end='')
print("recvd:", end='')
print(buf)
if __name__ == '__main__':
print('start receiving')
with serial.Serial('/dev/ttyUSB1', 9600, timeout=10) as con1:
recvCommand_CRterminated(con1, 0.1) # [sec]
#con1.flushOutput()
#con1.flushInput()
#time.sleep(.1)