Непрерывный цикл считывания PySerial
Я читаю серийные данные следующим образом:
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()
Проблема заключается в том, что она предотвращает выполнение каких-либо других функций, включая флеш-флеш-память. Добавление sleep()
не поможет.
Изменение "while True" "до", в то время как ser.readline(): "не печатает" тест ", что странно, поскольку он работал в Python 2.7. Любые идеи, что может быть неправильным?
В идеале я должен иметь возможность читать последовательные данные только тогда, когда они доступны. Данные отправляются каждые 1000 мс.
Ответы
Ответ 1
Поместите это в отдельную ветку, например:
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()
http://docs.python.org/3/library/threading
Ответ 2
Использование отдельного потока совершенно не нужно. Просто сделайте это для своего бесконечного цикла 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. Полностью неблокируемый.
(Этот ответ первоначально был опубликован и отлажен здесь: неблокирующее чтение Python 3 с помощью pySerial (не удается заставить работать свойство inSwaiting) pySerial))
Документация pySerial: http://pyserial.readthedocs.io/en/latest/pyserial_api.html
ОБНОВИТЬ:
Примечание по многопоточности:
Хотя чтение последовательных данных, как показано выше, не требует использования нескольких потоков, чтение неблокируемого ввода с клавиатуры делает это. Поэтому, чтобы выполнить неблокирующее чтение с клавиатуры, я написал такой ответ: Как читать ввод с клавиатуры? ,
Ответ 3
Используйте управляемое таймером событие для тестирования и чтения последовательного порта. Непроверенный пример:
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
Ответ 4
Я бы предостерег от использования блокировки ввода-вывода в потоке. Помните, что в Python есть GIL, и одновременно может выполняться только один поток. Теперь обратите внимание, что модуль pyserial является оболочкой для реализации ОС доступа к последовательному порту. Это означает, что он вызывает код, внешний по отношению к Python. Если этот код блокируется, то интерпретатор также блокируется, и в программе Python ничего не будет выполняться, даже основной поток.
Это может даже произойти при использовании неблокирующего ввода-вывода или опроса на основе тайм-аута, если базовый драйвер устройства не реализует тайм-аут хорошо.
Более надежный подход заключается в использовании многопроцессорного модуля с очередью. Запустите последовательный код чтения в отдельном процессе. Это позволит убедиться, что основной и другие потоки не блокируются, и программа может выйти чистым способом.