Timing Problem bei einem Sensor

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Daito
User
Beiträge: 2
Registriert: Freitag 21. April 2017, 08:14

Hallo Leute,

ich hab ein kleines Timing Problem mit meinem Sensor, welcher periodisch Daten einliest.

Mein Skript sieht bisher folgendermaßen aus

Code: Alles auswählen

#!/usr/bin/python -u

import serial
import sys
import os
import time

port= '/dev/ttyUSB0'
f = file ('/home/mint/Desktop/Werte.txt','w')

def main():
	ser = serial.Serial(port, 4800)
	if not ser.isOpen():
		print "Unable to open serial port %s" % port
		sys.exit(1)
		
	while True:
		line = ser.read(118)
		line = line.strip()
		f.write(line)
		#print line
		
main()			
Der Sensor, der per USB angeschlossen ist, liest also periodisch die Daten ein und schreibt sie mir anschließend in eine Datei.
Das Problem: Der Sensor misst nur, wenn die Lampe blinkt. Und diese blinkt in Sekundenabstand.
Wenn ich also das Skript starte, kann es passieren, dass Were vom letzten Messvorgang und Werte vom darauffolgenden Messvorgang sich vermischen. Ich muss quasi das Skript genau im richtigen Moment starten.

Ein kompletter Messvorgang sieht so aus:

@
I01010100B00725030178
V0107AD46
I02020100B0072530148
V020EE349
I035300B5
V03FE3190
Io4550065
V04
014193
$

Manchmal finde ich das @ jedoch mitten drin, wenn quasi 2 Messvorgänge sich vermischen. Das @ signalisiert aber den Start. Ich habe schon versucht das Skript erst dann schreiben zu lassen, wenn er das @ sieht, aber dann kamen die Daten zum Teil unvollständig an.. Mal hat ne Zeile gefehlt, mal haben 10 Zeilen gefehlt.

Bin bisschen mit meinem Latein am Ende .. Wie sorg ich dafür, dass das Skript einen kompletten Messvorgang in die Datei schreibt, die idealerweise mit dem @ beginnt? Ich muss die Werte nämlich noch parsen, aber wenn die Werte bei jedem Start anders beginnen, hab ich ein Problem.

Liebe Grüße
Daito
Zuletzt geändert von Anonymous am Freitag 21. April 2017, 12:16, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Daito: die Daten kommen bei Dir in Blöcken von 118 Bytes an. Diese könntest Du in einen Buffer schreiben und alles, was vor einem @ kommt verwerfen. Anschließend könntest Du testen, ob ein kompletter Messdatensatz vorliegt. Falls das der Fall ist, diesen entnehmen und auswerten. Ansonsten warten, bis die nächsten Sensordaten dem Buffer hinzugefügt werden.

Du kannst nicht davon ausgehen, dass das Ergebnis eines read-calls mit den Messdaten stets synchron und vollständig ist. Auch dann nicht, wenn die im read-call angegebene Bytezahl mit der Datenmenge des Messvorgangs übereinstimmt, da sich ja bereits Daten im Sensorbuffer befinden können (was, wie Du schreibst, ja auch der Fall zu sein scheint). Auch ist die Frage, ob jeder Messvorgang jedesmal genau die gleiche Menge an Daten liefert.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Daito: wenn Du schon weißt, dass @ das Trennzeichen ist, mußt Du einfach so lange lesen, bis ein @-Zeichen kommt, und dann bis zum nächsten @. Und wie kbr schon geschrieben hat, kann der erste Block unvollständig sein. Das Öffnen der Datei außerhalb von main ist unschön. Die Prüfung auf isOpen ist unsinnig, da falls das Öffnen fehlschlägt, die Zeile davor schon mit einer Exception abbricht.
Daito
User
Beiträge: 2
Registriert: Freitag 21. April 2017, 08:14

Also schreibe ich in das Skript, dass solange gelesen werden soll, bis ein @ auftaucht und anschließend solange geschrieben wird, bis das nächste @ auftaucht. Dann dürfte die Datei dem Format entsprechen, das ich für den Parser benötige..
Ergibt Sinn!

Nur wie wird das realisiert?

Ich begeb mich mal ein bisschen auf die Suche, falls jemand die Lösung schnell und unkompliziert parat hat, wäre das cool :-)
BlackJack

@Daito: Du vermischst hier lesen und schreiben zu stark. Lies solange bis Du sicher mindestens eine Nachricht/Messung komplett hast und liefer das Ergebnis als *eine* Zeichenkette. Puffere falls nötig zusätzliche Daten von der nächsten Nachricht. Oder lies tatsächlich zeilenweise wenn die Daten tatsächlich so in Zeilen kommen wie Du das gezeigt hast, und teile dann den Strom von Zeilen in Blöcke die mit der @-Zeile beginnen und mit der $-Zeile enden, falls das die Weiterverarbeitung vereinfacht.

Schau Dir am besten mal Generatorfunktionen an, damit man das lesen und den Zustand/Puffer den man sich da merken muss leicht in einer Funktion kapseln kann und diese Logik von der restlichen Verarbeitung trennen kann.
Antworten