Messwerte "glätten"

(Firma: Brainit GmbH) #3028808
Lesenswert?

Hi zusammen,

folgende Sitiation: ich bekomme von meiner heizung jede Sekunde Daten 
auf den PC angeliefert, und diese "rauschen"

z.B.
04.02.2013 04:09:18  X_T_AUL  -792
04.02.2013 04:09:27  X_T_AUL  -904
04.02.2013 04:10:02  X_T_AUL  -792
04.02.2013 04:10:11  X_T_AUL  -904
04.02.2013 04:10:37  X_T_AUL  -792

(T_AUL steht für Temperatur Außenluft)

oder

03.02.2013 22:31:42  X_T_RAUM  22251
03.02.2013 22:33:28  X_T_RAUM  22225
03.02.2013 22:35:03  X_T_RAUM  22251
03.02.2013 22:36:49  X_T_RAUM  22225

(Raumtemperatur)

die Werte sind integers, skaliert mit 1000, d.h. 22251 steht für 
22.251°C

wie man sieht ist die Differenz bei Außenluft immer 112, bei 
Raumtemperatur immer 26, ich vermute also dass das niederwertigste Bit 
genau diese Wertigkeit hat. Dass diese Wertigkeit unterschiedlich ist, 
macht die Sache nicht einfacher

Die Daten werden momentan geloggt, und eh schon nur bei Änderungen 
(deshalb gibts auch nicht jede Sekunde einen Wert)

ich möchte diese Daten nun "glätten" im Sinne von Rauschen eliminieren 
und Anzahl der Log-Einträge reduzieren.

Erste Idee: simples Runden: schlechte Idee, weil 22251 wäre 22.3, 22225 
wäre 22.2, also nicht wirklich was gewonnen

zweite Idee: Mittelwert-Bildung, dann runden. Schon besser, aber: wohin 
runden? Auf wieviele Stellen? idealerweise sollte das System 
"selbstlernend" sein, da wie oben zu sehen die "Genauigkeit" je nach 
Parameter unterschiedlich ist (und ich hab doch einige Parameter, wo ich 
nicht jeden getrennt behandeln will)

dritte Idee: digitales Filter: Bessel oder Butterworth? welche ordnung?

vierte idee: Dithering http://www.mikrocontroller.net/articles/Dithering 
Da blick ich aber nicht wirklich durch...

Gibts da sowas wie "best practices"?

Danke, Michi
(Firma: Brainit GmbH) #3028829
Lesenswert?

PT1-Glied klingt schon mal sehr gut... die Art der "Mittelwert-Bildung" 
kannte ich zwar, aber der Name PT1 ist mir neu. Man lernt ja jeden tag 
was neues...

Aber: Diese Art der Glättung wird mein eigentliches problem, nämlich die 
Anzahl der Log-Einträge, eher verschlimmern: Ich krieg viele 
Zwischenwerte, wo sich jeder vom vorherigen unterscheidet, und damit 
noch mehr Einträge...

@ingo: die Daten werden per Modbus abgefragt, alle Daten als 
32-bit-Integer codiert, und bei Temperaturen wird einfach mit 1000 
multipliziert. Das ist vom Gerät her so vorgegeben. Die vielen 
Kommastellen dürften von der Umrechnung Widerstand=>Temperatur herrühren 
(PT100 und so...)


Vielleicht denk ich aber auch zu kompliziert: mein Problem ist, dass ich 
bei jeder Änderung einen neuen Datensatz speichere. Und hier löst reines 
Runden mein Problem nicht: springt ein Wert zwischen 20.24 und 20.25, 
und ich runde, dann springt er halt zwischen 20.2 und 20.3,also nix 
gewonnen...

Ich könnte ja aber nicht stur auf Änderung prüfen, sondern auf Delta: 
Erst wenn die Abweichung zum zuletzt gespeicherten Wert größer als ein 
Schwellwert ist, wird gespeichert! Damit ließe sich die Glättung per PT1 
und ein speicherplatz-sparendes Logging ideal kombinieren...

Was hält ihr davon?
Gast #3028848
Lesenswert?

Michael Reinelt schrieb:
> wie man sieht ist die Differenz bei Außenluft immer 112, bei
> Raumtemperatur immer 26, ich vermute also dass das niederwertigste Bit
> genau diese Wertigkeit hat. Dass diese Wertigkeit unterschiedlich ist,
> macht die Sache nicht einfacher

Dann maskiere das letzte oder die beiden letzten Bits aus und teste was 
passiert.
Und, nein dabei verschenkst Du keine Genauigkeit, die Bits sind sowieso 
nur geraten.

fonsana
Gast #3028862
Lesenswert?

Ich sehe ein Probem darin, daß Deine Werte eine Genauigkeit suggerieren, 
die gar nicht vorhanden ist.

Angenommen, Deine Vermutung ist richtig und der Unterschied von -0.904°C 
zu -0.792°C wäre genau ein LSB.
Dann entspricht Deine Auflösung an dieser Stelle der Temperaturkurve ca. 
0.1K
Du gibst aber 3 Nachkommastellen an.

Mein Tip: Begrenze die Genauigkeit der Werte auf einen sinnvollen 
Bereich , z.B. 0.2K.

Noch ein Tip:
http://www.dspguide.com/ch15.htm
beschreibt sehr schön, wie und warum man Rauschen per 
MovingAverage-Filter wegbekommt.
#3028947
Lesenswert?

Eine -zugegeben etwas provokante- Frage:
Streichst du dein Nutellabrot morgens mit dem Mikrometer?

In etwa so sinnvoll ist der Versuch die Messwerte zu glätten, die sich 
um max. 1/10° unterscheiden, nur weil hinten noch 2 Zufallszahlen 
dranhängen, die aus der Binär zu Dezimal Konvertierung stammen.
Schmeiss die hinteren 2 Stellen ZUERST weg, und runde:
Bei Aussentemperatur auf höchstens 1°, selbst das braucht für die 
Heizungssteuerung keine Sau, und für die Innentemp. von mir aus auf 
0,2°.
Die Sensoren haben wahrscheinlich sowiso eine Genauigleit von +- 1 oder 
gar 2°.
(Firma: Brainit GmbH) #3029201
Lesenswert?

Peter Dannegger schrieb:
> Das ist kein Rauschen, sondern 1LSB des AD-Wandlers. Das kriegst Du
> nicht genauer gemacht.
> Daß es bei verschiedenen Werten unterschiedlich ist, liegt wohl daran,
> daß der Sensor nichtlinear ist und eine Korrekturrechnung erfolgt.

Danke, Peter! Du hast es erfasst... Genauer will ich's eh nicht kriegen, 
nur das "Zittern" des LSB eliminieren. Einfach "die letzten zwei Stellen 
streichen" ist da eher die Holzhammer-Methode...


bei der gelegenheit gleich noch eine Frage zum PT1-Filter: ich hab 
gelesen das PT1 entspricht einem Teifpass 1. ordnung, also ein RC-Glied. 
Dort ist die grenzfrequenz 1/(2*Pi*R*C).

Gibts was "vergleichbares" für das PT1-Glied? Hängt dort natürlich von 
der Abtast-Frequenz ab...
#3029220
Lesenswert?

Michael Reinelt schrieb:
> Einfach "die letzten zwei Stellen
> streichen" ist da eher die Holzhammer-Methode...

Die LSB ist bei den ersten Werten in der 3! Stelle, die beiden letzten 
Ziffern ergeben sich nur weil sich binäre Zahlen nicht glatt in dezimale 
umrechnen können.

Ein Zappeln des LSB kann man nie ganz verhindern, höchstens seine 
Frequenz heruntersetzen.

Dein Holzhammer hat gerade mal 50g und du willst damit einen 180 Nagel 
in den Balken schlagen.

Aber nimm ruhig weiter die Schieblehre um die Brotdicke beim Frühstück 
zu kontrollieren.
#3029224
Lesenswert?

Harald Wilhelms schrieb:
> Ich würde die Stellen nicht streichen, sondern sinnvoll runden.

Richtig, hatte mich hier schlecht ausgedrückt.
Obwohl auch ein Streichen nur ein Fehler von max 0,05° wären, was mehr 
als eine ganze Größenordnung besser als der wahrscheinliche Fehler der 
Messung wäre.

Wahrscheinlich sitzt jetzt der Aussentemperatursensor so, daß die Sonne 
draufscheinen kann :-)
(Firma: Brainit GmbH) #3029236
Lesenswert?

Ich esse kein Nutellabrot!

Die letzten Stellen kommen meiner Meinung nach nicht von der 
binär->dezimal-umrechnung, sondern vom Umrechenfaktor Widerstand=> 
Temperatur (die berühmten 0.00385), schlimmstenfalls wird sogar 
nichtlinear umgerechnet.

trotzdem bin ich bei euch: sinnvoll runden. nur - wo ist sinnvoll?

Wie ich schon geschrieben habe - springt ein Wert zwischen 20.241 und 
20.253,
und ich runde, dann springt er halt zwischen 20.2 und 20.3, also nix
gewonnen...

Und bevor ihr euch am Begriff "Temperatur" aufhängt - ich krieg auch 
noch andere Werte (Drehzahlen, CO2-Gehalt, ...) die zwar dasselbe 
grundlegende Problem haben (schwanken des LSB) aber in ganz anderen 
Wertebereichen. ich müsste irgendwie auf "signifikante bits" runden, 
bzw. eben genau das LSB wegwerfen (und vielleicht gleich noch eins dazu) 
nur müsst ich das erstmal finden....

außerdem behindert eine zu starke Rundung noch eine andere Auswertung: 
Das Erkennen von Tendenzen. Auch wenn der absolute Fehler bei der 
Raumtemperatur bei +/- 2K läge, so lassen sich doch auch leichte 
temperaturänderungen gut erkennen.
Gast #3029281
Lesenswert?

Also, Du hast ein Logging-Problem, es sind Dir zu viele Daten?

Einfache Lösung: Nur alle 5 Sekunden oder alle 10 Sekunden oder nur jede 
Minute speichern.

Andere Lösung, Du willst entscheidenden, wann sich eine signifikante 
Änderung eines Wertes ergeben hat, die es sich lohnt zu speichern.

Dazu musst Du erstmal entscheiden, wann eine solche signifikante 
Änderung vorliegt. Momentan ist jede Änderung signifikant.

Ein möglicher Ansatz wäre z.B., immer die letzten 5 Messwerte anzusehen: 
Wenn drei der letzten fünf Messwerte (egal welche) gleich dem letzten 
gespeichertem sind, dann wird kein neuer Messwert gespeichert.

Solche Verfahren kannst Du beliebig "intelligent" machen. Z.B. könnte es 
eine Schwelle für ein Fehlerquadratsumme geben. Wenn diese überschritten 
ist, wird ein neuer Messwert gespeichert.
#3029309
Lesenswert?

Michael Reinelt schrieb:

> Wie ich schon geschrieben habe - springt ein Wert zwischen 20.241 und
> 20.253,
> und ich runde, dann springt er halt zwischen 20.2 und 20.3, also nix
> gewonnen...

Das Rauschen des letzten Bits kannst Du bei digitaler Verarbeitung
nun mal nicht verhindern. Bei Temperaturen macht es aber nur selten
Sinn, eine höhere Genauigkeit als 0,1 Grad anzuzeigen. Ob man eine
solche Genauigkeit überhaupt erreicht, ist dann noch eine andere
Frage.
Gruss
Harald
#3029323
Lesenswert?

Michael Reinelt schrieb:
> Danke, Peter! Du hast es erfasst... Genauer will ich's eh nicht kriegen,
> nur das "Zittern" des LSB eliminieren. Einfach "die letzten zwei Stellen
> streichen" ist da eher die Holzhammer-Methode...

Wie wärs mit einer Hysterese?
1
#define ABS(x) (((x)<0)?-(x):(x))
2
#define RESOLUTION 250
3

4
void temp_log_task(void)
5
{
6
  static int logged = 0;
7
  int now  = get_temp();
8
  int diff = ABS(now - logged);
9
  if (diff >= RESOLUTION / 2) {
10
    // Wert runden (optional)
11
    logged = ((now + RESOLUTION / 2) / RESOLUTION) * RESOLUTION;
12
    log_temp(logged);
13
  }
14
}

Statt den Wert zu runden, könnte man ihn auch in der Bitbreite 
reduzieren, falls der Speicherplatz in der Logdatei relevant ist.
Gast #3029357
Lesenswert?

Mein Senf dazu:

1. Ich setze mal voraus, daß sowohl bei 0°C als auch bei 20°C das 
Rauschen im ADC-Rohwert gleich ist (1 bis 2 LSBs).
Dann macht es Sinn, den ADC-Rohwert zu tiefpaßfiltern, mit PT1 oder 
MovingAverage, um das statistische Rauschen zu entfernen.
PT1 z.B. so:
1
gefiltert = gefiltert * (1.0 - faktor) + rohwert * (faktor);
mit faktor = 0.0 bis 1.0
Die Filterfrequenz ergibt sich aus dem "faktor" und dem Zeitraster, wie 
oft Du den Filter rechnest.

2. Lege beim Loggen eine Hysterese fest, also der aktuelle Werte muß 
sich um x zum Vorgänger verändert haben, damit Du ihn loggst.
Wenn Du die Hysterese relativ zum Meßwert nimmst (als Prozentwert), 
löst sich auch Dein Problem, daß Du über den Meßbereich unterschiedliche 
Stabilität der Stellen hast.
Z.B. so:
1
if ( (aktuell > (alt * 1.05)) || (aktuell < (alt * 0.95)) )
ergibt 5% "Hysterese".

PS:
Ich hab zur Verständlichkeit einfach mal Fließkomma hingeschrieben, aber 
das ganze läßt sich natürlich auch einfach als Fixkomma implementieren.
#3029675
Lesenswert?

Mir ist gerade aufgefallen, dass mein Code oben gar keine Hysterese ist, 
sondern im Prinzip nur rundet. Negative Zahlen sogar falsch ...

Richtig wäre es so:
1
#define RESOLUTION 250
2

3
void temp_log_task(void)
4
{
5
  static int logged = 0;
6
  int now  = get_temp();
7
  int diff = now - logged;
8
  if (diff >= RESOLUTION || diff <= -RESOLUTION) {
9
    logged = now;
10
    // Wert runden (optional)
11
    int offset = RESOLUTION / 2;
12
    offset = (logged < 0) ? -offset : offset;
13
    logged = ((logged + offset) / RESOLUTION) * RESOLUTION;
14
    // Wert speichern
15
    log_temp(logged);
16
  }
17
}
Gast #3030109
Lesenswert?

Michael Reinelt schrieb:
> Dort ist die grenzfrequenz 1/(2*Pi*R*C).
>
> Gibts was "vergleichbares" für das PT1-Glied? Hängt dort natürlich von
> der Abtast-Frequenz ab...

Klar gibt es das:
Im einfachsten Fall ist die Abtastfrequenz viel größer als die 
Zeitkonstante R*C.
Beim PT1-Glied ist die Anfangssteigung gleich der Zeitkonstante.
-> Beim digitalen Regler ist der Anteil neu zu alt gleich dem Verhältnis 
Abtastzeit zu Zeitkonstante.

Beispiel:
Die Zeitkonstante R*C = 160 ms die Abtastrate = 10 ms.
PT1,neu = PT1,alt + 10ms/160ms*(Messwert,neu - PT1,alt)

Wobei sich der Wert 1/16 einfach durch 4*Rechtsshift ergibt.
Die Grenzfrequenz wird genauso wie beim analogen Beispiel aus der 
Zeitkonstante berechnet.

Gruß Anja
Gast #3030133
Lesenswert?

Bronco schrieb:
> Wenn Du die Hysterese relativ zum Meßwert nimmst (als Prozentwert),
> löst sich auch Dein Problem, daß Du über den Meßbereich unterschiedliche
> Stabilität der Stellen hast.

Wenn du das bei der Temperatur machst, erübrigt sich die relative 
Hystere von selbst, weil der Messwert allermeist im Bereich 250 .. 300 K 
liegt, d.h. sich nur über einen überschaubaren Bereich von knapp 20% 
ändert.
Oder welcher Temperaturbezugspunkt schwebte dir vor? Und wieso gerade 
der?
Gast #3030168
Lesenswert?

Michael Reinelt schrieb:
> 04.02.2013 04:09:18  X_T_AUL  -792
> 04.02.2013 04:09:27  X_T_AUL  -904
> 04.02.2013 04:10:02  X_T_AUL  -792
> 04.02.2013 04:10:11  X_T_AUL  -904
> 04.02.2013 04:10:37  X_T_AUL  -792

Das sieht mir doch sehr periodisch aus, als ob da irgendetwas mit der 
Datenerfassung nicht stimmt. So gleichmäßig schwankt die Sonne selten. 
Ist das auch über längere Zeiträume so?
Gast #3032698
Lesenswert?

Wie wär's mit einem Median-Filter. Dann bleiben alle Stellen erhalten 
aber das Zittern verschwindet (vielleicht bei geeignetert Länge). Obwohl 
der Median eigentlich besser gegen Außreißer geeignet ist.
Gast #3236366
Lesenswert?

genau Laura!
hier endet die Diskussion, wo sie gerade anfängt interessant zu werden.
(Deshalb mein Kommentar auch ein halbes Jahr später)
Selbst wenn man davon ausgeht, daß in jeder Schwingung (gezappel) Info 
steckt, sollte man nach meiner langjährigen Erfahrung grundsätzlich 
einen Mittenwertfilter einsetzen bevor man die Ergebnisse mit o.g. 
Verfahren weiterverarbeitet. Über eine Eliminierung der Störeinflüsse 
reden wir hier nat. nicht. Ungewollte, unperiodische Spitzen lassen sich 
nicht immer vermeiden.
Ich benutze gerne einen 1 aus 3 Spike(?)-Filter. Mit den Begriffen kenne 
ich mich nicht so gut aus, aber am besten ich hänge mal eine C-Funktion 
zum Verständnis an.
Ich würde gerne lesen, daß jemand das effektiver schreiben kann. Von der 
Funktion bin ich allerdings mehrfach überzeugt worden.
Gerade, wenn man auf fast jedes Sampeln angewiesen ist, kenne ich gar 
keine andere vernünftige Filterung als Alternative.
Aber auch mit mehr Verarbeitungszeit zur Verfügung und nur einen 
Durchlauf (i=1)der Funktion kann man das Ergebnis rekursiv wieder zur 
"Vorqualifizierung" benutzen. Wie gesagt, was hier Standardbegriffe 
angeht, bin ich ungebildet. Deshalb nenne ich es mal einen rukursiven 
Mittenwertfilter:
Man "füttert" die Funktion "Mitte" dann nur noch mit Werten, die dem 
vorherigen Ergebnis angenähert wurden.
einfaches Bsp.:

Messergebnis = Mitte(Messplatz_1, ((Messergebnis+ADC_Wert)/2), 1);

schön schnell, wenn auch nicht gerade Data Memory-sparend, selbst wenn 
man int32_t entsprechend anpasst.
Und dann kann das eigentliche Filtern losgehen.

Viel Spaß und nicht ärgern lassen

P.
Angehängte Dateien:
Persönliche Seite #3239729
Lesenswert?

Wolfgang schrieb:
> Michael Reinelt schrieb:
>> 04.02.2013 04:09:18  X_T_AUL  -792
>> 04.02.2013 04:09:27  X_T_AUL  -904
>> 04.02.2013 04:10:02  X_T_AUL  -792
>> 04.02.2013 04:10:11  X_T_AUL  -904
>> 04.02.2013 04:10:37  X_T_AUL  -792
>
> Das sieht mir doch sehr periodisch aus, als ob da irgendetwas mit der
> Datenerfassung nicht stimmt. So gleichmäßig schwankt die Sonne selten.
> Ist das auch über längere Zeiträume so?

Es kann auch schlicht durch die Umrechnung kommen:
X_T_AUL=k1*T+k2 wobei T der physikalische Meßwert ist.
Wenn man die Koeffizienten ausrechnet (X_T_AUL einfacherhalber positiv 
benutzt), ergibt sich ja:
k1=112 k2=8 und T dann in Einzelschritten

Wenn du die Daten reduzieren willst, speichere also den Wert T und nicht 
X_T_AUL !

Hm. Stoff der 7.Klasse "Lineare Gleichung"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren