Ich empfange Daten mit pySerial von einem Gerät, das ständig einen doppelten Datensatz mit konstanter Länge sendet. Ca. so:
DATA1\nDATA1\n
pause
DATA2\nDATA2\n
DATA1 kann gleich DATA2 sein
pause ist unterschiedlich lang
Auslesen der Schnittstelle mit readline() und Timeout bringt also max. die Hälfte eines Datensatzes.
Vielleicht sollte man ohne timeout zwei Datensätze mit read(n) lesen, aber das funktioniert nur, wenn man zufällig in pause den Eingangspuffer geleert hat. Und es könnten genausogut zwei halbe Datensatze gelesen werden.
Der Vergleich mit einem zweiten Lesevorgang bringt nichts, da das genausogut auch ein anderer Datensatz sein könnte (es sei denn, das timeout ist kürzer als pause).
Ha, das probiere ich mal - fallen Euch noch schönere Lösungen ein?
Auf empfangene Daten synchronisieren
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
Kannst du den Input vor dem Empfangen manipulieren (d.h. am Absender o.ä.)? Dann könntest du eine Art Hier-Ist-Ende-Signal anbringen.
Nee, am Format kann ich nix ändern. Auch das serielle Format ist lustig: 7 Datenbits, ungerade Parität (7O1) - pySerial und mein USB-RS232 Adapter mit FT232BM bekommen da regelmäßig Probleme:
Aber es funktioniert mit dem Vergleich von zwei readline() mit kleinem Timeout; das ist nur True, wenn zwei identische Zeilen unmittelbar hintereinander gelesen werden.
Code: Alles auswählen
ftdi_sio: ftdi_set_termios FAILED to set databits/stopbits/parity
ftdi_sio: ftdi_set_termios urb failed to set baudrate
ftdi_sio: urb failed to clear flow control
ftdi_sio: update_mctrl Error from MODEM_CTRL urb: DTR HIGH, RTS HIGH
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo whaeva!whaeva hat geschrieben:pause ist unterschiedlich lang
Vielleicht kannst du die Länge der Pause als Trenner verwenden. Wenn du z.B. von einer Mindestpausenlänge von einer halben Sekunde ausgehen kannst, dann könnte das Programm vielleicht wie folgt aussehen. ACHTUNG! Ungetestet --> soll nur als Denkanstoß dienen.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
import serial
import threading
import Queue
import datetime
import time
#DATA1\nDATA1\n
#pause
#DATA2\nDATA2\n
# Connection-Parameter
PORT = 0
BAUDRATE = 9600
BYTESIZE = serial.SEVENBITS
PARITY = serial.PARITY_ODD
STOPBITS = serial.STOPBITS_ONE
TIMEOUT = 1 # sec.
# Pause
MIN_PAUSE = datetime.timedelta(milliseconds = 500)
class MySerialConnection(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.cancel = threading.Event()
self.queue = Queue.Queue()
def run(self):
while True:
if self.cancel.isSet():
break
ser = serial.Serial(
port = PORT, baudrate = BAUDRATE, bytesize = BYTESIZE,
parity = PARITY, stopbits = STOPBITS, timeout = TIMEOUT
)
try:
while True:
if self.cancel.isSet():
break
if not ser.isOpen():
break
line = ser.readline()
if line:
self.queue.put(datetime.datetime.now(), line)
finally:
ser.close()
print "Thread stopped"
def stop(self):
print "Thread stopping..."
self.cancel.set()
def main():
conn = MySerialConnection()
conn.start()
last_timestamp = datetime.datetime(1900, 1, 1)
while True:
try:
time.sleep(0.5)
try:
(timestamp, line) = conn.queue.get_nowait()
if timestamp < (last_timestamp + MIN_PAUSE):
print "Teil 2:", line.rstrip()
print "---"
else:
print "Teil 1:", line.rstrip()
last_timestamp = timestamp
except Queue.Empty:
pass
except KeyboardInterrupt:
print "KeyboardInterrupt"
break
conn.stop()
conn.join()
if __name__ == "__main__":
main()
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hallo Gerold,
vielen Dank für dein ausführliches Codebeispiel!
Wie erwähnt benutze ich schon die Timoutfunktion von serial.readline() - ein Leseversuch in der Pause gibt keine Zeichen zurück, d.h. sobal zwei aufeinanderfolgende Lesevorgänge gleich sind, kann ich sicher sein, das Paket erfasst und geprüft zu haben.
Aber wenn man kein eingebautes Timeout hat, ist dein Ansatz sicherlich hilfreich. Zeigt auch schön Threading...
vielen Dank für dein ausführliches Codebeispiel!
Wie erwähnt benutze ich schon die Timoutfunktion von serial.readline() - ein Leseversuch in der Pause gibt keine Zeichen zurück, d.h. sobal zwei aufeinanderfolgende Lesevorgänge gleich sind, kann ich sicher sein, das Paket erfasst und geprüft zu haben.
Aber wenn man kein eingebautes Timeout hat, ist dein Ansatz sicherlich hilfreich. Zeigt auch schön Threading...