LoginSignup
3
4

More than 5 years have passed since last update.

Raspberry Pi > pySerial 2.6 > [CR]はreadline()のdelimiterに使えない | [CR]まで読込む実装

Last updated at Posted at 2017-08-25
動作環境
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終端文字列の受信を実装してみた。

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)

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4