Forum: Mikrocontroller und Digitale Elektronik Messwerte "glätten"


von Michael R. (Firma: Brainit GmbH) (fisa)


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

von eProfi (Gast)


Lesenswert?

PT1-Filter:

#define filterStaerke 6
int32_t tmpSum;
tmpSum += (tmpSum >> filterStaerke) + tmpInput;

tmpSum steigt dann auf das 2**filterStaerke-fache von tmpInput an, 
deshalb auch 32bit.

von Ingo (Gast)


Lesenswert?

Gleitender mittelwert über n Werte. Warum wir die Raumtemperatur auf 3 
Nachkommastellen ausgegeben? Genauer als 0,3 Grad dürfte die eh nicht 
sein...


Ingo

von Michael R. (Firma: Brainit GmbH) (fisa)


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?

von Anja (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Was hält ihr davon?

Ich würde zusätzlich noch die Bedingung setzen daß der neue Wert für 
eine Mindestanzahl Meßwerte stabil ist bzw. der Abstand zu einem 
parallel geführten PT1-Filter unter einer Schwelle liegt.

Gruß Anja

von fonsana (Gast)


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

von Bronco (Gast)


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.

von Hannes L. (hannes)


Lesenswert?

Ganz praktisch ohne die ganze hochtrabende Theorie:

Mit PT1-Filter glätten (Ausreißer beseitigen),
dann per Hysterese auf "grobe" (0,2K?) Änderungen prüfen,
danach die nichtssagenden Hundertstel und Tausendstel wegwerfen.

...

von Udo S. (urschmitt)


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°.

von Udo S. (urschmitt)


Lesenswert?

Michael Reinelt schrieb:
> und ein speicherplatz-sparendes Logging

Genau deswegen: schmeiss die letzten 2 Stellen weg!

von Rene (Gast)


Lesenswert?

Ein Tiefpass benutzt genau eine Speicherzelle der jeweiligen Wortbreite. 
siehe
http://www.ibrtses.com/embedded/exponential.html

von Peter D. (peda)


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


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...

von Peter D. (peda)


Lesenswert?

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

Nö, das ist die ehrliche Methode.
Das andere ist dem Anwender etwas vorlügen.

von Harald W. (wilhelms)


Lesenswert?

Peter Dannegger schrieb:
> Michael Reinelt schrieb:
>> Einfach "die letzten zwei Stellen
>> streichen" ist da eher die Holzhammer-Methode...
>
> Nö, das ist die ehrliche Methode.
> Das andere ist dem Anwender etwas vorlügen.

Ich würde die Stellen nicht streichen, sondern sinnvoll runden.
Gruss
Harald

von Udo S. (urschmitt)


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.

von Udo S. (urschmitt)


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 :-)

von Harald W. (wilhelms)


Lesenswert?

Udo Schmitt schrieb:

> Aber nimm ruhig weiter die Schieblehre um die Brotdicke beim Frühstück
> zu kontrollieren.

Bei meinem AG habe ich ein Interferrometer, das eine solche Dicke
auf einige Zehntel Nanometer genau messen kann. Das wäre für diesen
Zweck doch sicher noch besser geeignet. :-)
Gruss
Harald

von Udo S. (urschmitt)


Lesenswert?

:-)
Danke Harald, du hebst meine Laune bei dem tristen Wetter.

von Michael R. (Firma: Brainit GmbH) (fisa)


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.

von Stiefelwutz (Gast)


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.

von Stiefelwutz (Gast)


Lesenswert?

Oder schau Dir mal das an:

        http://de.wikipedia.org/wiki/RRDtool

von Harald W. (wilhelms)


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

von Fabian O. (xfr)


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.

von Bronco (Gast)


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.

von Fabian O. (xfr)


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
}

von Anja (Gast)


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

von Praktiker (Gast)


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?

von Wolfgang (Gast)


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?

von Laura Meische (Gast)


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.

von Prototyp (Gast)


Angehängte Dateien:

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.

von Abdul K. (ehydra) Benutzerseite


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"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.