Ich habe ein Python-Programm, das Daten von einem seriellen Port über das PySerial
-Modul liest. Die zwei Bedingungen, die ich berücksichtigen muss, sind: Ich weiß nicht, wie viele Daten entstehen werden, und ich weiß nicht, wann ich mit Daten rechnen muss.
Darauf basierend habe ich die folgenden Code-Snipets gefunden:
#Code from main loop, spawning thread and waiting for data
s = serial.Serial(5, timeout=5) # Open COM5, 5 second timeout
s.baudrate = 19200
#Code from thread reading serial data
while 1:
tdata = s.read(500) # Read 500 characters or 5 seconds
if(tdata.__len__() > 0): #If we got data
if(self.flag_got_data is 0): #If it's the first data we recieved, store it
self.data = tdata
else: #if it's not the first, append the data
self.data += tdata
self.flag_got_data = 1
Daher wird dieser Code für immer in einer Schleife ausgeführt, um Daten von der seriellen Schnittstelle zu erhalten. Wir erhalten bis zu 500 Zeichen, um die Daten zu speichern, und alarmieren Sie die Hauptschleife, indem Sie ein Flag setzen. Wenn keine Daten vorhanden sind, schlafen wir einfach weiter und warten.
Der Code funktioniert, aber ich mag das 5s-Timeout nicht. Ich brauche es, weil ich nicht weiß, wie viele Daten zu erwarten sind, aber es gefällt mir nicht, dass es alle 5 Sekunden aufwacht, selbst wenn keine Daten vorhanden sind.
Gibt es eine Möglichkeit zu überprüfen, wann Daten verfügbar sind, bevor Sie das read
-Objekt ausführen? Ich denke so etwas wie den select
-Befehl in Linux.
BEARBEITEN:
Ich dachte nur, ich würde feststellen, dass ich die inWaiting()
-Methode gefunden habe, aber wirklich scheint es, als würde ich meinen "Schlaf" in eine Umfrage umwandeln. Ich möchte einfach nur schlafen, bis Daten eingehen, und dann gehen Sie los.
Ok, ich habe tatsächlich etwas zusammengestellt, das mir gefällt. Verwenden einer Kombination aus read()
ohne Timeout und der inWaiting()
-Methode:
#Modified code from main loop:
s = serial.Serial(5)
#Modified code from thread reading the serial port
while 1:
tdata = s.read() # Wait forever for anything
time.sleep(1) # Sleep (or inWaiting() doesn't give the correct value)
data_left = s.inWaiting() # Get the number of characters ready to be read
tdata += s.read(data_left) # Do the read and combine it with the first character
... #Rest of the code
Dies scheint die Ergebnisse zu liefern, die ich wollte. Ich glaube, diese Art von Funktionalität existiert in Python nicht als einzelne Methode
Sie können timeout = None
setzen, dann wird der Aufruf read
blockiert, bis die angeforderte Anzahl von Bytes vorhanden ist. Wenn Sie warten möchten, bis Daten eingehen, führen Sie einfach eine read(1)
mit Timeout None
aus. Wenn Sie Daten ohne Blockierung prüfen möchten, führen Sie eine read(1)
mit Timeout Null durch und prüfen Sie, ob Daten zurückgegeben werden.
(siehe Dokumentation http://pyserial.sourceforge.net/pyserial_api.html )
def cmd(cmd,serial):
out='';prev='101001011'
serial.flushInput();serial.flushOutput()
serial.write(cmd+'\r');
while True:
out+= str(serial.read(1))
if prev == out: return out
prev=out
return out
nenne es so:
cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000))