私はこのようなシリアルデータを読んでいます:
_connected = False
port = 'COM4'
baud = 9600
ser = serial.Serial(port, baud, timeout=0)
while not connected:
#serin = ser.read()
connected = True
while True:
print("test")
reading = ser.readline().decode()
_
問題は、bottle py web frameworkを含む他のすべての実行を妨げることです。 sleep()
を追加しても役に立ちません。
「while True」を「while ser.readline():」に変更しても「test」は出力されません。これはPython 2.7。何が間違っているのでしょうか?
理想的には、シリアルデータが利用可能な場合にのみシリアルデータを読み取ることができるはずです。データは1,000ミリ秒ごとに送信されています。
たとえば、別のスレッドに入れます。
import threading
import serial
connected = False
port = 'COM4'
baud = 9600
serial_port = serial.Serial(port, baud, timeout=0)
def handle_data(data):
print(data)
def read_from_port(ser):
while not connected:
#serin = ser.read()
connected = True
while True:
print("test")
reading = ser.readline().decode()
handle_data(reading)
thread = threading.Thread(target=read_from_port, args=(serial_port,))
thread.start()
別のスレッドを使用する必要はまったくありません。代わりに無限のwhileループに対してこれを行ってください(Python 3.2.3)でテスト済み:
_import serial
import time # Optional (if using time.sleep() below)
while (True):
# NB: for PySerial v3.0 or later, use property `in_waiting` instead of function `inWaiting()` below!
if (ser.inWaiting()>0): #if incoming bytes are waiting to be read from the serial input buffer
data_str = ser.read(ser.inWaiting()).decode('ascii') #read the bytes and convert from binary array to ASCII
print(data_str, end='') #print the incoming string without putting a new-line ('\n') automatically after every print()
#Put the rest of your code you want here
time.sleep(0.01) # Optional: sleep 10 ms (0.01 sec) once per loop to let other threads on your PC run during this time.
_
この方法では、何かがある場合にのみ読み取りと印刷を行います。 「理想的には、シリアルデータは利用可能な場合にのみ読み取れるはずです。」これはまさに上記のコードが行うことです。読み込めるものがない場合は、whileループの残りのコードにスキップします。完全にノンブロッキング。
(この回答は元々ここに投稿され、デバッグされています: pySerialでのPython 3ノンブロッキング読み取り(pySerialの "in_waiting"プロパティを機能させることはできません) )
pySerialドキュメント: http://pyserial.readthedocs.io/en/latest/pyserial_api.html
更新:
in_waiting
_ vs inWaiting()
に関するコメントを追加しました。以下のコメントで指摘してくれた@FurkanTürkalに感謝します。次のドキュメントを参照してください: https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting 。上記のようにシリアルデータを読み取る場合でも、notは複数のスレッドを使用し、キーボード入力を非ブロッキング方式で読み取る必要がありますdoes。したがって、非ブロッキングキーボード入力読み取りを実現するために、この答えを書きました: キーボード入力の読み方 。
ブロッキングIOスレッドで使用することに対して警告します。覚えているPythonには [〜#〜] gil [〜#〜] =一度に1つのスレッドしか実行できませんpyserialモジュールは、シリアルポートにアクセスするOS実装のラッパーであることに注意してください。これは、Pythonの外部のコードを呼び出すことを意味します。ブロックされ、Pythonプログラム、メインスレッドでさえも実行されません。
基盤となるデバイスドライバーがタイムアウトを適切に実装していない場合、非ブロッキングIOまたはタイムアウトベースのポーリング)を使用している場合にも、これが発生する可能性があります。
より堅牢なアプローチは、 queue で multiprocessing モジュールを使用することです。別のプロセスでシリアル読み取りコードを実行します。これにより、メインおよび他のスレッドがブロックされず、プログラムが正常に終了できるようになります。
タイマー駆動のイベントを使用して、シリアルポートをテストおよび読み取ります。テストされていない例:
import threading
class serialreading():
def __init__(self):
self.active = True
self.test()
def test(self):
n_in =comport.in_waiting()
if n_in> 0:
self.data = self.data + comport.read(size=n_in)
if len(self.data) > 0:
print(self.data)
self.data=""
if self.active:
threading.Timer(1, test).start() # start new timer of 1 second
def stop(self):
self.active = False