Raspberry Pi > pySerial 2.6 > bug? > 受信バッファにデータが残る場合がある


動作環境
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: 

組込み用CPU基板のシリアル動作試験をするため、RPiをエミュレータとして使用していた。

上記と関連して、以下の配線をして送信プログラム、受信プログラムを試した。

現象

クロス変換接続の状態にて以下のようなことをした。

  • ttyUSB0からCRLF終端文字列を複数回送信
  • ttyUSB1にて送信文字列を受信

受信を断続的に実行しても受信できる状況があるようだ。
pySerialのバグなどにより、受信バッファが残った状態になっているのだろうか。

関連して以下を見つけた。
https://stackoverflow.com/questions/7266558/pyserial-buffer-wont-flush

試したコード

送信コード

test_send_170825.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import serial
import datetime

INTERVAL_SEC = 10
CMD='hello.this is serial send/recv test message'
CRLF='\r\n'

def sendCommand():
    con1.write(CMD)
    con1.write(CRLF)
    print(datetime.datetime.today())

con1=serial.Serial('/dev/ttyUSB0', 9600, timeout=10)  # 10sec
for loop in range(10):
        sendCommand()
        time.sleep(INTERVAL_SEC)

受信コード

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():
    str1 = con1.readline()
    if len(str1) > 0:
        print(datetime.datetime.today(), end='')
        print("recvd:", end='')
        print(str1)

con1=serial.Serial('/dev/ttyUSB1', 9600, timeout=10)  # 10 sec
recvCommand()

実行

$ python test_send_170825.py
2017-03-08 09:03:12.438025
2017-03-08 09:03:22.448712
2017-03-08 09:03:32.459271
2017-03-08 09:03:42.469883
2017-03-08 09:03:52.480480
2017-03-08 09:04:02.491071
2017-03-08 09:04:12.501665
2017-03-08 09:04:22.512637
2017-03-08 09:04:32.523239
2017-03-08 09:04:42.533843
$ python test_recv_170825.py 
2017-03-08 09:13:05.348017recvd:hello.this is serial send/recv test message

上記の受信を10回以上実行しても受信できてしまう。

ミスの修正

それぞれのプログラムの最後に以下を追加した。

con1.close()

状況が発生しなくなったようだ。

やはり再現した。

v0.2 > with構文使用 | カウンタ追加

test_send_170825.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import serial
import datetime

INTERVAL_SEC = 10
CMD='hello.this is serial send/recv test message'
CRLF='\r\n'

def sendCommand(idx):
    con1.write(CMD)
    con1.write(',')
    con1.write(str(idx))
    con1.write(CRLF)
    print(datetime.datetime.today())

with serial.Serial('/dev/ttyUSB0', 9600, timeout=10) as con1:
    for idx in range(10):
        sendCommand(idx)
        time.sleep(INTERVAL_SEC)
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():
    str1 = con1.readline()
    if len(str1) > 0:
        print(datetime.datetime.today(), end='')
        print("recvd:", end='')
        print(str1)

with serial.Serial('/dev/ttyUSB1', 9600, timeout=10) as con1:
    recvCommand()
    #con1.flushOutput()
    #con1.flushInput()
    #time.sleep(.1)

$ python test_send_170825.py 
2017-03-08 09:36:40.509165
2017-03-08 09:36:50.519969
2017-03-08 09:37:00.530643
2017-03-08 09:37:10.541294
2017-03-08 09:37:20.551964
2017-03-08 09:37:30.562632
2017-03-08 09:37:40.573283
2017-03-08 09:37:50.583933
2017-03-08 09:38:00.594673
2017-03-08 09:38:10.605407

30秒程度待つ

$ python test_recv_170825.py 
2017-03-08 09:39:27.002521recvd:hello.this is serial send/recv test message,8

$ python test_recv_170825.py 
2017-03-08 09:39:28.052986recvd:hello.this is serial send/recv test message,9

$ python test_recv_170825.py 
2017-03-08 09:39:28.868108recvd:hello.this is serial send/recv test message,9

$ python test_recv_170825.py 
2017-03-08 09:39:29.674223recvd:hello.this is serial send/recv test message,9

bug: idx=9の結果が複数回送信できてしまう。

タイミングの検討が必要であるが、受信側でflushInput()を実行するなど検討が必要だ。