PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Daten auf Plausibilität überprüfen...



Willa
04.07.2009, 19:16
Hallo!
Ich werte mit nem mega32 einen RC-Empfänger aus. Bei einigen Stickkombinationen und wildem Rumgerühre springt einer der ausgelesenen Werte manchmal. Ich denke, dass ich an der Auswertung selber nichts verbessern kann, deswegen würde ich gerne die ausgelesenen Werte auf ihre Richtigkeit hin überprüfen und falsche Werte rausschmeissen.
Das Ganze sollte natürlich möglichst wenig Rechenzeit in Anspruch nehmen. Einfach einen starken Tiefpass einprogrammieren kann ich auch nicht, dann wird die Reaktion auf die Knüppel zu langsam.

Bisher mache ich es so:
sempf(i) ist das Signal aus dem Empfänger für die 4 Kanäle, das Signal geht von -37 bis +37



'wenn neues signal mehr als 50 vom alten signal abweicht, dann altes signal halten.
For I = 1 To 4
If Sempf(i) > Aempfh(i) Or Sempf(i) < Aempfl(i) Then 'wenn ausserhalb der Grenzen
Sempf(i) = Aempf(i) 'neuer Wert = alter wert
End If
Aempf(i) = Sempf(i) 'alter wert = neuer Wert
Aempfh(i) = Sempf(i) + 50 'obere Grenze
Aempfl(i) = Sempf(i) - 50 'untere Grenze
Next

Mit dem Code wird also überprüft, ob der neue Wert sich um mehr als "50" vom alten Wert unterscheidet. Falls das so ist wird der alte Wert weiterverwendet.
Dadurch ergeben sich einige Probleme. Wenn ich die Sticks ganz schnell bewege, dann werden die neuen Werte nicht mehr akzeptiert. Und zwar werden die so lange nicht akzeptiert, bis ich den Stick wieder da hin bewegt habe wo die schnelle Bewegung gestartet wurde.
Gibt es elegantere Methoden um "Ausreisser" zu detektieren und auszusortieren? Zur Not muss ich doch einen Tiefpass nehmen.......
Vielen Dank für eure Tipps!

vohopri
04.07.2009, 20:51
Hallo William,

wenn du immer mit dem letzten plausiblen Wert vergleichst, must du bei einem zu heftigen beabsichtigten Sprung wieder zurück.

Ich würde aber nicht mit dem letzten plausiblen Wert vergleichen, sondern mit einem gleitenden Mittelwert. In die Berechnung des gleitenden Mittelwerts gehen plausible wie unplausible Werte ein. Je nach Dimensionierung der Parameter, können dann 1, 2, oder 3 Ausreisser ignoriert werden, aber danach, eben beim 2, 3, oder 4 Wert wird der extreme Wert akzeptiert.

Braucht wenig Rechenzeit und Speicher. Starke Sprünge werden mit Verzögerung angenommen, aber das ist der Preis fürs Aussortieren der Ausreisser. Mässige Veränderungen werdne ohne Verzögerung durchgereicht.

hoffe, das nützt bei deiner Fragestellung und grüsse,
Hannes

Willa
04.07.2009, 21:00
Hi Hannes,
also so eine Art stdev-test: Wenn neuer Wert größer als alter Wert + 3*stdev der letzten 10 Werte, dann nicht akzeptieren. Könnte ganz gut klappen. Allerdings werde ich wohl kaum die Standardabweichung schnell genug berechnen können, vielleicht nehme ich den Median oder das arithmetische Mittel +- x wie von dir vorgeschlagen. Das werde ich mal testen :-D
Gute idee!

vohopri
04.07.2009, 21:34
Hi,

ja Standardabweichung kostet natürlich.

Gleitender Mittelwert geht ja annähernd auch so (k.A. wie das Verfahren heisst, du kennst es wahrscheinlich ohnehin):

Neuer-MW = (Alter-MW * (N - 1) + Aktueller-Messwert) / N

N ist konstant, je grösser es gewählt wird, umso träger folgt der gleitende Mittelwert. Das Schöne ist, man braucht keinen Messwert speichern.

Analog könnte man aber auch eine gleitende Standardabweichung näherungsweise berechnen, denn in der Rechenformel habe ich nur den Mittelwert und das Mittel der quadrierten Werte drin. Da braucht es nach obigem Schema auch keine gespeicherten Werte.

Das Wurzelziehen wird man sich klarerweise auch sparen und stattdessen den quadriertem Messwert mit der Varianz vergleichen. Quadrierte Werte fallen ohnehin an.

grüsse,
Hannes

Besserwessi
04.07.2009, 21:38
Die Standardabweichung braucht man auch nicht jedesmal neu berechenen. Das ist eine konstante Schranke ab der man die Werte als schlecht ansieht. In Echtzeit muß man nur den Mittelwert der letzten 2-4 Werte berechenen. Bei zu vielen Werten hat man das Problem, das man auch relativ alte Werte nutzt und dann Probleme hat wenn man den Stick schnell bewegt.

Die erste Verbesserung wäre es den Vergleich nicht mit dem letzten akzeptierten Wert, sondern mit dem letzten empfangenen Wert zu machen. Das führt dann allerdings dazu, das nach einem Ausreißer noch ein Wert verworfen wird. So schlimm sollte das aber nicht sein, denn man würde ohnehin nichts wesentlich anders akzeptieren.

Dafür werden 2 annähernd gleiche Werte immer akzeptiert.

Willa
05.07.2009, 14:13
Danke euch beiden :-D !
Es funktioniert sehr schön, ich kann richtig beobachten wie fehlerhafte Werte aussortiert werden und sich nicht auf den Rest des Programms auswirken.


For I = 1 To 5
Mittelwertempf(i) = Mittelwertempf(i) * 3
Mittelwertempf(i) = Mittelwertempf(i) + Empf(i)
Shift Mittelwertempf(i) , Right , 2
Aempfh(i) = Mittelwertempf(i) + 12
Aempfl(i) = Mittelwertempf(i) - 12
If Empf(i) > Aempfh(i) Or Empf(i) < Aempfl(i) Then
Empf(i) = Mittelwertempf(i)
'Print "kaputt: " ; i
End If
Next


Ich nehme nur den mittelwert der letzten vier Messungen, das reicht anscheinend, denn die Fehler scheinen einzeln zu kommen. Mein Programm verlangsamt sich dadurch von 431Hz auf 410Hz. Das ist durchaus akzeptabel.

p.s.: Bei bascom gibt es nichts wie
if wert1 > (wert2 + 10) then...
oder?

Besserwessi
05.07.2009, 14:57
Soweit ich weiss geht das bei BASCOM nicht mehr als eine Rechenoperation zu machen one das Ergebnis wieder in einer Variablen zu speichern.

Diese Einschränkung war für mich Grund genug auf C zu wechseln.