Go Down

Topic: Meßwerte filtern ? (Read 4669 times) previous topic - next topic

rudirabbit

Hallo,
Ich habe zeichne hier den Luftdruckverlauf über 24 Stunden auf.
Die Werte werden immer 10 Minuten gemessen und in ein EEprom geschrieben.
Der Sensor ist ein BMP085, ab und zu kommt es zu "Ausreißern", warum auch immer.

Code: [Select]

#include <BMP085.h>
BMP085 dps = BMP085();

dps.init(MODE_ULTRA_HIGHRES, 41500, true);



Der Sensor wird so initalisiert. Evtl. kann man dieses Problem an der Wurzel packen ?

Ich versuche den Meßwert derzeit so zu filtern:
Code: [Select]


float druckschnitt_gleit=0;

...
druckschnitt_gleit=((druckschnitt_gleit*0.1)+((float)Pressure) *0.9);




Dies läuft immer 10 Minuten lang, und wird dann mit einem Zeitstempel in ein EEprom geschrieben.
Viel bringt dies aber nicht, wenn man sich die Grafik anschaut.   
An dem Faktor derezit 0.1 habe ich noch nichts gedreht.
Arduino UNO,MEGA,DUE 
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

Scherheinz

Hey!
Und wenn du den Schnitt ganz weglässt und jeden Wert direkt speicherst? Vll sind die Fehlmessungen so unrealistisch das du sie einfach rausfiltern kannst. Ich hatte das gleiche Problem mit einem Temperatur/Feuchtefühler der auch immer abends manchmal Werte von manchmal  260°C und  143% angezeigt hat. Aber das kann man über Grenzwerte gut rausfiltern.

Versorgst du über Batterie oder Netzteil?
Da es bei mir auch immer abends vor kam, hatte ich Impulse aus dem Netz im Verdacht. (Nachtspeicherheizungen etc....)

Gruß
Hier könnte ihre Werbung stehen

rudirabbit

Versorge das Ding via Netzteil läuft ja 24/7.
Hängt aber derzeit am USB eines PC's, der auch ausgeschaltet hier 5V liefert.
 

Mit deinem Verdacht liegst du wohl schon richtig, ich logge noch andere Werte (Windspeed,Richtung) und nicht selten haben die zur gleichen Zeit diese Ausreißer.


Jetzt stellt sich die Frage wie ein Netzteil auszusehen hat, welches solche Störungen filtert.
Einn Trafo Gleichrichter Elkos und einen 780X wird wohl nicht ausreichen. 
Arduino UNO,MEGA,DUE 
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

UliH

Hallo

Gerade der Luftdruck ändert sich ja nur sehr langsam. Mehr als 1hPa in 10 Minuten kann normalerweise nicht sein. Ich würde einfach den gemessenen Wert mit dem vorherigen Meßwert vergleichen. Wenn die Abweichung > 1hPa ist, die Messung mehrfach wiederholen und den Durchschnitt der Wiederholungsmessungen nehmen.

Gruß Ulrich

Scherheinz

Kannst du das ganze nicht mal über eine Batterie laufen lassen?
Und ein leicht abgeschirmtes Gehäuse ist auch nie ein Fehler....
Der Ansatz von Ulrich finde ich auch sehr gut.

Gruß
Hier könnte ihre Werbung stehen

guntherb

Der beste Ansatz ist natürlich, falsche Wert erst gar nicht entstehen  zu lassen.

Manchmal geht das aber nicht. Dann ist der zweitbeste Ansatz, Werte die nicht stimmen können zu ignoriren.

UliH hat da schon einen Ansatz skizziert. Wenn sich der Messwert um mehr als tbd vom letzten (gefilterten) Wert unterscheidet, dann einfach wegwerfen und nochmal messen.

Deine Filterformel ist so eleganter:
Code: [Select]
int FilterFaktor = 9;
druckschnitt_gleit=((druckschnitt_gleit*FilterFaktor)+(float)Pressure) / (FilterFaktor+1);

Dadurch bildest du einen Tiefpassfilter mit Tau = FilterFaktor / Aufruffrequenz
Grüße
Gunther

rudirabbit

Beide Vorschläge (Ulrich und Gunther)  gerade eingebaut. Mal sehen wie es jetzt ausschaut.


Code: [Select]
druckschnitt_gleit=((druckschnitt_gleit*0.1)+((float)Pressure) *0.9);

Dann war meine Formel abgesehen vom falschen Faktor 0.1  grundsätzlich falsch.
Bei 0.1 hätte es wohl so aussehen müssen
Code: [Select]
druckschnitt_gleit=((druckschnitt_gleit*0.1)+((float)Pressure) *1.1);
Arduino UNO,MEGA,DUE 
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

guntherb

Nicht unbedingt falsch.

Deine Formel hat schon korrekt gefiltert: Bei jedem Messen 10% des alten Wertes + 90% des Neuen.

Ist halt ein sehr schwacher Filter.

besser wäre gewesen:
Code: [Select]
druckschnitt_gleit=((druckschnitt_gleit*0.9)+((float)Pressure) *0.1);
Das wären dann bei jedem Messen 90% des alten Wertes + 10% des Neuen.

Das wäre ein Filter mit dem Ausreißer nur noch zu 10% eingehen. Wenn aber der Ausreisser deutlich größer ist, dann kann dir das auch noch den Wert versauen.

Meine Formel hat nur den Vorteil, dass du nur einen FilterFaktor hast, mit dem du die Filterfrequenz verstellen kannst.
Grüße
Gunther

Scherheinz

Dann bin ich mal auf das Ergebnis gespannt, der einstellbare Faktor ist schon mal eine gute Idee.
Wenn es nicht wie bei mir Fehler von Faktor ü20 sind wird das auf jeden fall funktionieren. Falls du immernoch Abweichungen hast kannst du die Uhrzeiten mal mit den Daten von gestern vergleichen, würde mich mal interessieren.

Hier könnte ihre Werbung stehen

udoklein

#9
Jan 04, 2015, 02:03 pm Last Edit: Jan 04, 2015, 02:32 pm by Udo Klein
Anstatt alle 10 Minuten zu messen würde ich alle 10s messen und nach 10 Minuten den Median (und nicht den Durchschnitt) der letzten 60 Messungen als Meßwert nehmen. Dann sollten sich Ausreiser sehr in Grenzen halten.
Check out my experiments http://blog.blinkenlight.net

rudirabbit

Bis jetzt schaut es gut aus  :)
 
Zitat von Gunther:
Quote
Dadurch bildest du einen Tiefpassfilter mit Tau = FilterFaktor / Aufruffrequenz
Mir fehlt es bei den Filtern an Grund Wissen, habe das nie gelernt.
Und so richtig verstehe ich die Zusammenhänge mit der Zeitkonstante nicht wirklich.
 
Also wann nehme ich welchen Filterfaktor und warum ?


@Udo Klein: Das klingt logisch, im Moment scheint der Tiefpass aber Lösung zu sein.
Das ganze läuft gerade noch, ich teste erstmal dies. 
Arduino UNO,MEGA,DUE 
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

Doc_Arduino

#11
Jan 04, 2015, 10:44 pm Last Edit: Jan 04, 2015, 10:47 pm by Doc_Arduino
Hallo,

welchen Filterfaktor man nimmt hängt von der Reaktionsschnelligkeit ab auf sich ändernde Werte und auch wie stabilisiert die Meßwerte sein soll. Hängt voneinander ab.

Je kleiner der Filterfaktor um größeren Einfuss hat der eine neue aktuelle Meßwert auf den Gesamtdurchschnitt. Je größer der Filterfaktor ist umso gemütlicher und träger wird die Reaktion auf neue Meßwerte im Gesamtdurchschnittswert.

Bei Udo's Methode erhält man in seinem Bsp. aller 10min einen gefilterten Meßwert.

Bei Gunthers Methode erhält man nach anfänglicher Wartezeit, bis sich sich der Endwert am Meßwert angenähert hat, am laufenden Band aktuelle Durchschnittswerte die nur in der Trägheit abhängig vom Filterfaktor sind.

Gunther hatte das mal genauer erklärt, hier im Beitrag #21 mit Exceltabelle zur Veranschaulichung.
http://forum.arduino.cc/index.php?topic=210945.new;topicseen#new

In meinem aktuellen Projekt bin ich runter auf einen Filterfaktor 2 und habe nach ca. 15 Messungen zu 99% den aktuellen Eingangswert als Durchschnittsmeßwert. Von 0 auf die zu messende Spannung. 15 benötigte Messungen sind träge genug um Schwankungen auszugleichen. In Gunthers Tabelle gibts dafür zur Anschauung die Sprungantworttabelle. Sieht wie eine e Funktion aus oder verhält sich wohl auch wie eine solche.

Wenn Du ohne Pause messen kannst, kannste den Filterfaktor auch sachte erhöhen. Kommt drauf an wie oft Du messen möchtest welche Methode günstiger wäre für Deinen Fall.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

jurs

Der Sensor ist ein BMP085, ab und zu kommt es zu "Ausreißern", warum auch immer.
Grundsätzlich wäre es am besten, die Ursache für die Ausreißer zu finden und zu beseitigen.

Wenn andere Sensoren zur selben Zeit "spinnen" wie der Luftdrucksensor, besteht die Vermutung, dass Du ein grundsätzliches Problem mit der Schaltung hast. Stromversorgung, Wackelkontakt, EMV-Störungen durch elektrische Geräte in der Nähe.

Wenn nur der Luftdrucksensor betroffen ist, kommen spezifische Gründe für die Ausreißer in Frage. Zum Beispiel zeitweilige Erschütterungen. Oder wenn Du relativ gut schließende Zimmertüren hast, kannst Du sogar ein schnelles Öffnen/Schließen der Zimmertür zu Luftdruckschwankungen führen. Wenn es in der Küche eine starke Dunstabzugshaube gibt, kann der Unterdruck beim Einschalten der Dunstabzugshaube ggf. auch in verbundenen Nachbarräumen noch festgestellt werden. Oder jemand zündet direkt vor Deinem Wohnzimmerfenster einen Polenböller, dessen Druckwelle sich bis in Dein Haus ausbreitet.

In dem Fall, dass in einer längeren Abfolge von Messungen immer nur einzelne Werte stark abweichen, gibt es eine ganz einfache Methode, die Ausreißer zu eliminieren: Und zwar wenn Du nicht den "arithmetischen Mittelwert" oder den "gefilterten Mittelwert" sondern den "medianen Mittelwert" aus einer Vielzahl von Messungen nimmst.

Der mediane Mittelwert ist der Wert, bei dem genau so viele Werte höher wie niedriger sind. Am besten aus einer ungeraden Anzahl von Messwerten zu ermitteln.

Beispiel: Du ermittelst eine Minute lang von Sekunde 0 bis zu Sekunde 60 je einen Luftdruckwert, insgesamt 61 Messwerte. Diese Messreihe sortierst Du. Dann nimmst Du den Wert in der Mitte, also aus der sortierten Folge den 31. Wert und das ist dann Dein Luftdruck-Mittelwert für diese Minute.

Da können dann selbst Ausreißer bei sein, die zehnmal, hundertmal oder tausendmal so hoch sind wie der "wahre" Wert, und dennoch bekommst Du am Ende einen extrem guten Mittelwert, der von den Ausreißern praktisch überhaupt nicht verzerrt wird.

Das Verfahren versagt erst dann, wenn mehr als die Hälfte Deiner Messwerte Ausreißer sind.






Scherheinz

Gibts schon neue Erkenntnisse? ;D
Hier könnte ihre Werbung stehen

rudirabbit

#14
Jan 07, 2015, 10:01 am Last Edit: Jan 07, 2015, 10:26 am by rudirabbit
Die Vorschläge von Udo mit dem Median erfordern ein extra Timeimg.
Mein Serverprojekt ist schon sehr umpfangreich, deshalb muss ich mir schon genau überlegen wie ich das einbaue.
Da ich die Zeit dafür gerade nicht habe, funktioniert dies als workaround ganz gut.  
Code: [Select]


void updatelogdata()
{
static long altpressure;
dps.getPressure(&Pressure);


if ((Pressure <=altpressure+100 && Pressure >=altpressure-100) || altpressure==0)
                                          {
            int FilterFaktor = 9;
            druckschnitt_gleit=((druckschnitt_gleit*FilterFaktor)+(float)Pressure) / (FilterFaktor+1);
                                        altpressure=Pressure;
                                            }



  

Wobei jurs schon recht hat, der mechanische Aufbau des Ganzen bietet schon Fehlerquellen.
Ist ein Arduino 2560 mit Ram ext, darüber ein Ethernet Shield aus China das ab und an Probleme macht.
Denke die ISP Pins sind das Problem.
Darüber ist ein ProtoShield mit Steckbrett, hier befinden sich zwei I2C EEproms der BMP Sensor und ein 433mhz Empfänger Modul.
Das ganze ist also mit Drahtbrücken auf dem Steckbrett verdrahtet und schaut alles andere als vertrauenswürdig aus.

Wenn ich mal viel Zeit habe, mache ich mir ein eigenes PCB Shield mit einen W5100 Modul das ich schon habe, eben alles zum Draufstecken (433mhz Empfänger,W5100 Modul ,433mhz Empfänger)


Arduino UNO,MEGA,DUE 
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

Go Up