Lecture de données en série en temps réel en Python
j'utilise un script en Python pour collecter des données à partir d'un microcontrôleur PIC via un port série à 2Mbps.
LE PIC fonctionne avec un timing parfait à 2Mbps, le port USB-série FTDI fonctionne aussi très bien à 2Mbps (tous les deux vérifiés avec l'oscilloscope)
Im envoi de messages (de la taille d'environ 15 caractères) environ 100-150x fois par seconde et le nombre il y en incréments (pour vérifier si j'ai des messages de perdu et ainsi de suite)
sur mon ordinateur portable J'ai Xubuntu tournant comme virtuel machine, je peux lire le port série via Putty et via mon script (python 2.7 et pySerial)
Le problème:
- lors de l'ouverture du port série via Putty je vois tous les messages (le compteur dans le message augmente de 1 par 1). Parfait!
- lors de l'ouverture du port série via pySerial je vois tous les messages mais au lieu de recevoir 100-150x par seconde je les reçois à environ 5 par seconde (toujours les incréments de message 1 par 1) mais ils sont probablement stockés dans certains tampon comme quand j'éteins le PIC, je peux aller à la cuisine et revenir et je reçois toujours des messages.
voici le code (j'ai omis la plupart du code, mais la boucle est la même):
ser = serial.Serial('/dev/ttyUSB0', 2000000, timeout=2, xonxoff=False, rtscts=False, dsrdtr=False) #Tried with and without the last 3 parameters, and also at 1Mbps, same happens.
ser.flushInput()
ser.flushOutput()
While True:
data_raw = ser.readline()
print(data_raw)
Quelqu'un sait pourquoi pySerial prend autant de temps à lire depuis le port série jusqu'à la fin de la ligne? Toute aide?
je veux avoir ce en temps réel.
Merci
3 réponses
Vous pouvez utiliser inWaiting()
pour obtenir le nombre d'octets disponibles à l'entrée de la file d'attente.
alors vous pouvez utiliser read()
pour lire les octets, quelque chose comme ça:
While True:
bytesToRead = ser.inWaiting()
ser.read(bytesToRead)
Pourquoi ne pas utiliser readline()
dans ce cas à partir de Docs:
Read a line which is terminated with end-of-line (eol) character (\n by default) or until timeout.
vous attendez le temps mort à chaque lecture car il attend la fin de vie. l'entrée en série Q reste la même, juste beaucoup de temps pour arriver à la "fin" du buffer, pour mieux le comprendre: vous écrivez à l'entrée Q comme une voiture de course, et de la lecture comme une vieille voiture :)
vous devez configurer le timeout à "None" lorsque vous ouvrez le port série:
ser = serial.Serial(**bco_port**, timeout=None, baudrate=115000, xonxoff=False, rtscts=False, dsrdtr=False)
ceci est une commande de blocage, donc vous attendez de recevoir des données qui ont newline (\n ou \r\n) à la fin: ligne = ser.readline()
Une fois que vous avez les données, elles vous reviendront aussitôt que possible.
valeurs possibles pour le paramètre timeout: … x set timeout x secondes
et
readlines (sizehint=None, eol='\n') Lire une liste de lignes, jusqu'à ce que délai. sizehint est ignoré et n'est présent que pour L'API compatibilité avec les objets de fichier intégrés.
Notez que cette fonction ne renvoie que sur un timeouts.
readlines
reviendra au plus toutes les 2 secondes. Utilisez read()
comme Tim l'a suggéré.