Zeilengepufferter serieller Eingang

Ich habe ein serielles Gerät, von dem ich Eingaben lesen möchte. Ich habe ihm eine Zeichenfolge "ID \ r" gesendet und sie gibt "ID XX \ r" zurück (wobei \ r ein ASCII-Wagenrücklauf ist, hexadezimal 0x0d).

Da die Option eol für serial.readline nicht mehr unterstützt wird, verwende ich TextIOWrapper, um vom seriellen Anschluss zu lesen und jeweils eine Zeile zurückzugeben.

Mein Problem ist, dass der String nicht zurückgegeben wird, sobald er den Wagenrücklauf sieht, sondern bis zu dem doppelten Zeitlimit gewartet wird, das ich beim Öffnen der seriellen Schnittstelle festgelegt habe. Ich möchte, dass die Zeichenfolge sofort zurückgegeben wird, sobald eine ganze Zeile gelesen wird, da ich möglicherweise Hunderte dieser Befehle an das Gerät senden muss und nicht jedes Mal auf das Timeout warten möchte. Wenn ich das Zeitlimit auf 0 setze, wird überhaupt keine Ausgabe ausgegeben (vermutlich, weil mein Skript nicht mehr wartet, bis das Gerät die Möglichkeit hat, etwas auszugeben). Wenn ich das Zeitlimit auf Keine setze, wird das Skript für immer blockiert.

Hier ist ein einfaches Testskript:

<code>import serial
import io
import time

ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
                    bytesize=8, parity='N', stopbits=1,
                    xonxoff=0, rtscts=1, timeout=5)

sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser),
                       newline=None)


sio.write(unicode("ID\r"))
sio.flush()

print "reading..."

x = sio.readline()

print len(x)
print x
</code>

Das Skript benötigt immer 10 Sekunden von der Meldung "Lesen" bis zum Ausdruck der Zeichenfolge "ID XX", die von der seriellen Schnittstelle gelesen wurde.

Ich bin sicher, dass das Gerät den Wagenrücklauf ausgibt, da ich strace verwendet habe, um die Lesungen zu beobachten:

<code>select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 991704})
read(3, "I", 8192)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999267})
read(3, "D", 8191)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999420})
read(3, " ", 8190)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999321})
read(3, "X", 8189)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999355})
read(3, "X", 8188)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999171})
read(3, "\r", 8187)                     = 1
select(4, [3], [], [], {5, 0})          = 0 (Timeout)
select(4, [3], [], [], {5, 0})          = 0 (Timeout)
</code>

Sie können die 2 Zeitüberschreitungen select () sehen, die die Verzögerung von 10 Sekunden angeben, aber Sie können auch deutlich sehen, wie der Wagenrücklauf gelesen wird. Ich habe versucht, den newline-Parameter auf 'None' und '' (was automatisch \ r, \ n und \ r \ n zulassen sollte) und auf '\ r' zu setzen, aber jedes Mal mit demselben Ergebnis.

Ich habe auch versucht, die buffer_size im BufferedRWPair () -Aufruf auf '1' zu setzen, um zu verhindern, dass Eingaben zwischengespeichert werden, aber das machte keinen Unterschied.

Irgendeine Idee, was ich falsch mache?

Wenn ich das nicht zum Laufen bringen kann, besteht mein nächster Schritt darin, mit serial.read () ein Zeichen nach dem anderen zu lesen und meine eigenen Zeilen zu puffern, aber ich wollte versuchen, es mit textiowrapper "richtig" zu machen zuerst.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage