У меня есть MCU, подключенный к компьютеру через последовательный интерфейс. MCU может отправлять данные с регулярными интервалами или очень редко, в зависимости от типа подключенного к нему датчика. Поэтому я хочу иметь функцию python, которая вызывается всякий раз, когда из последовательного порта поступают данные, вместо постоянного опроса.
После прочтения множества похожих вопросов ( Маленький пример для pyserial используя Threading . PySerial / Arduino , PySerial / interrupt mode , Python Serial listener и так далее), я пришел к выводу, что решение этой проблемы - многопоточность. Итак, я придумал 3 разных кода , которые работают :
Первый:
import time
import serial
import threading
ser = serial.Serial("/dev/ttyUSB0", 19200)
datos = ""
class SerialReaderThread(threading.Thread):
'''
The class with the method that reads the serial port in the backgroud.
'''
def __init__(self):
super().__init__()
self._stop_event = threading.Event()
def run(self):
'''
The method that actually gets data from the port
'''
global ser, datos
while not self.stopped():
datos = ser.readline().decode('ascii').strip()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
serial_thread = SerialReaderThread()
serial_thread.start()
i = 0
while i < 5:
if datos != "":
print(datos)
datos = ""
i += 1
serial_thread.stop()
while serial_thread.isAlive():
pass
print("Thread stopped.")
ser.close()
Второй:
import serial
import threading
import time
ser = serial.Serial("/dev/ttyUSB0", 19200)
read = True
datos = ""
def serialEvent():
global ser, read, datos
while read is True:
datos = ser.read_until().decode('ascii').strip()
return
t = threading.Thread(target=serialEvent)
t.start()
i = 0
while i < 5:
if datos != "":
print(datos)
datos = ""
i += 1
read = False
t.join()
while t.isAlive():
pass
print("Thread stopped.")
ser.close()
Третий:
import serial
import concurrent
ser = serial.Serial("/dev/ttyUSB0", 19200)
datos = ""
readData = True
def serialReadEvent():
global ser, readData, datos
while readData is True:
datos = ser.read_until().decode('ascii').strip()
return
executor = concurrent.futures.ThreadPoolExecutor()
serialData = executor.submit( serialReadEvent )
i = 0
while i < 5:
if datos != "":
print(datos)
datos = ""
i += 1
readData = False
while serialData.running():
pass
print('Thread stopped.')
ser.close()
Вопрос 1: Один из этих кодов лучше других?
Вопрос 2: использует глобальную переменную как лучший способ передать данные между потоком и основным процессом?
Я также читал, что PySerial API обеспечивает способ работы с потоками , но я не понимаю документацию.
Вопрос 3: Может ли кто-нибудь дать мне пример потока чтения с использованием PySerial API?
Наконец, я прочитал, что Последовательный порт Qt также предоставляет способ обработки входящих данных в потоке ( пример ).
Вопрос 4: - это лучший способ решить мою проблему, если я собираюсь иметь a GUI также написано на PyQt5?