Je lis des données en série comme ceci:
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()
Le problème est que cela empêche toute exécution, y compris le framework web bottle py. Ajouter sleep()
ne vous aidera pas.
Changer "While True" "en" While ser.readline (): "n'imprime pas" test ", ce qui est étrange, car cela fonctionnait dans Python 2.7. Des idées sur ce qui pourrait ne pas être correct?
Idéalement, je ne devrais être capable de lire des données série que si elles sont disponibles. Les données sont envoyées toutes les 1 000 ms.
Mettez-le dans un fil séparé, par exemple:
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()
L'utilisation d'un thread séparé est totalement inutile. Faites simplement ceci pour votre boucle while infinie à la place (testé en 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.
De cette façon, vous ne lisez et n'imprimez que s'il y a quelque chose. Vous avez dit: "Idéalement, je devrais pouvoir lire les données série uniquement lorsqu'elles sont disponibles." C'est exactement ce que le code ci-dessus fait. Si rien n’est disponible pour la lecture, il passe au reste de votre code dans la boucle while. Totalement non bloquant.
(Cette réponse a été posté et débogué ici: Lecture non bloquante de Python 3 avec pySerial (Impossible d'obtenir la propriété "in_waiting" de pySerial) )
documentation pySerial: http://pyserial.readthedocs.io/en/latest/pyserial_api.html
METTRE À JOUR:
in_waiting
vs inWaiting()
. Merci à @ FurkanTürkal pour l'avoir signalé dans les commentaires ci-dessous. Voir la documentation ici: https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting .Même si la lecture de données série, comme indiqué ci-dessus, not ne nécessite pas l'utilisation de plusieurs threads, la lecture au clavier d'une manière non bloquante ne. Par conséquent, pour obtenir une lecture d’entrée au clavier non bloquante, j’ai écrit cette réponse: Comment lire une entrée au clavier? .
Utilisez un événement piloté par une horloge pour tester et lire le port série . Exemple non testé:
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