Wie macht man digital eine Dämpfung von Messwerten?

Gast #1920378
Lesenswert?
• ▲
▼
Hallo alle miteinander!

Ich habe mal eine Frage bezüglich der Dämpfung eines Messsignals in der 
Industrie.

Wenn ich zum Beispiel so einen Drucktransmitter vor mir habe, dann kann 
ich da eine Dämpfung von z.B. 10sek eingben und dann erreicht das 
Ausgangssignal erst nach 10sek den eigentlich Wert, der zum Messwert 
gehörte.

Wie wird so etwas praktisch realisiert?

Ich könnte ja z.b. ab einem neuen Messwert einen Timer starten, welcher 
10sek runterzählt und den neuen Ausgangswert (meist ja ein eingeprägter 
Strom) in 10 gleiche Teile einteilt und diesen immer weiter ändert.

Aber: So ein Messwert ändert sich ja quasi kontinuierlich (einen ruhigen 
ADC gibt es ja nicht). Daher würde bei jedem neuen Messwert der Timer 
neu gestartet und das Ergebnis quasi nie erreicht.

Wird das so gemacht, oder wie ist die praktische Lösung?


Danke, Mr. Wurst guck in die Luft
Gast #1920401
Lesenswert?
• ▲
▼
Naja eigentlich ist es ganz einfach.
Ein einfacher FIR Filter ist der gleitende Mittelwert. Du misst z.B. 
einmal pro Sekunde und merkst Dir jeweils die letzten 10 Messwerte. Du 
addierst diese und teilst das Ergebnis durch 10, das ist dann die 
Ausgabe des Filters. In der nächsten Sekunde misst Du wieder, der 
älteste gespeicherte Wert fliegt raus und Deine Ausgabe ist wieder die 
Summe der gespeicherten Werte durch 10 usw.

Gruss,
Thorsten
Gast #1920411
Lesenswert?
• ▲
▼
Thorsten schrieb:
> Ein einfacher FIR Filter ist der gleitende Mittelwert

Das hört sich schon wieder einfacher an.
Nur wie wird das dann gemacht, wenn man beispielsweise Dämpfungen von 
2min hat. Muss mann dan 2min jede Sekunde messen und damit rechnen?

Das würde ja Speicher ohne Ende fressen...
Gast #1920425
Lesenswert?
• ▲
▼
Tims Beispiel ist ein sog. exponential averaging Filter. Der frisst 
weniger Speicher, Du musst aber gut aufpassen, dass Du Dir nicht durch 
Rundungsfehler Deine Auflösung reduzierst (besonders wenn Du mit 
Ganzzahlen arbeitest).
Stärkere Filterung kannst Du auch über einen rekursiven Filter 
realisieren (Stichwort IIR). Hier merkst Du Dir nicht die letzten zehn 
Messwerte, sondern z.B. die letzten zehn Ausgaben des Filters.
Wenn Du beim einfachen gleitenden Mittelwert bleiben willst, kannst Du 
den Speicherbedarf auch dadurch reduzieren, dass Du nicht alle Sekunde 
misst, sondern z.B. alle 10 Sekunden. Dann erhältst Du allerdings auch 
nur alle 10 Sekunden einen neuen gefilterten Wert.
Gruss,
Thorsten
Gast #1920426
Lesenswert?
• ▲
▼
Tim schrieb:
> Messwert = Messwert_alt * 0.95 + Messwert * 0.05

Und wie würde ich so auf eine eingestellte Zeit kommen?

holger schrieb:
> Nö, du kannst auch alle 12s messen. Oder alle 30s...

Auc hier die selbe Frage. Sorry - ich würde das gerne verstehen, habe 
aber gerade noch so meine Probleme damit - also wie meine Berechnung auf 
eine voreingestellte Zeit hinausläuft.
#1920428
Lesenswert?
• ▲
▼
Mal ein anderer Ansatz mit infiniter Impulsantwort:
1
#define ANZAHL_MITTELUNG 10 //nur ein Beispiel mit 10
2
int32_t mittelung(int16_t neuer_messwert)
3
{
4
   static int32_t speicher;
5

6
   speicher /= ANZAHL_MITTELUNG;
7
   speicher = (ANZAHL_MITTELUNG - 1) + neuer_messwert;
8

9
   return(speicher);
10
}
bitte um Diskussion, mfg mf
#1920438
Lesenswert?
• ▲
▼
Hast Recht. War ein Schnellschuss.
1
#define ANZAHL_MITTELUNG 10 //nur ein Beispiel mit 10
2
int32_t mittelung(int16_t neuer_messwert)
3
{
4
   static int32_t speicher;
5

6
   speicher /= ANZAHL_MITTELUNG;
7
   speicher = ((ANZAHL_MITTELUNG - 1) * speicher) + neuer_messwert;
8

9
   return(speicher);
10
}
Gast #1920441
Lesenswert?
• ▲
▼
>Auc hier die selbe Frage. Sorry - ich würde das gerne verstehen,

(0 + 0 + 0 + 0) / 4 = 0
(0 + 0 + 0 + 4) / 4 = 1
(0 + 0 + 4 + 4) / 4 = 2
(0 + 4 + 4 + 4) / 4 = 3
(4 + 4 + 4 + 4) / 4 = 4
(4 + 4 + 4 + 0) / 4 = 3
(4 + 4 + 0 + 0) / 4 = 2
(4 + 0 + 0 + 20) / 4 = 6
(0 + 0 + 20 + 20) / 4 = 10
(0 + 20 + 20 + 20) / 4 = 15
(20 + 20 + 20 + 20) / 4 = 20

Besser?
Gast #1920443
Lesenswert?
• ▲
▼
Jo,
Dieser Ansatz hat genau das erwähnte Problem mit der Auflösung.

Annahme:
speicher sei 100
neuer_messwert sei 11
Du kannst beliebig lange 11 in den Filter geben - es wird immer 10 
rauskommen. Das gilt auch für 19 noch (109/10=10). Die Ganzzahldivision 
schneidet Dir immer was ab. Deshalb ist der Filter in dieser Form 
ungeeignet.

Gruss,
Thorsten
#1920477
Lesenswert?
• ▲
▼
Naja also, wenn ich mit Festkommaarithmetik in Richtung "genau" gehen 
will, muss ich einen großen Datentyp nehmen und in ebendiesen auch genug 
große Zahlen rein schieben. Da hilft es, die eingehenden Messwerte um 
ein paar Bits nach links zu schieben(damit man sozusagen binäre 
Nachkommastellen erhält), und mit diesen zu großen Zahlen zu arbeiten.

Deswegen hab ich jetzt auch immer den "speicher" als Rückgabewert. Der 
ist natürlich um den Faktor ANZAHL_MITTELUNG zu groß.

Ich habe mal ein billiges Testprogramm für die Funktion angehängt.
Dazu, was ich in einem Beispiel bei m.E. guter Nutzung des 
Wertebereiches herausbekomme.
Und du siehst, dass - Ich gebe zu, dass es an der Quantisierung liegt - 
mein Kondensator in Software auch niemals voll wird.
mfg mf
Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #1920711
Lesenswert?
• ▲
▼
Hier geht Genauigkeit flöten:
1
   speicher /= ANZAHL_MITTELUNG;
2
   speicher = ((ANZAHL_MITTELUNG - 1) * speicher) + neuer_messwert;
3
   return(speicher/ANZAHL_MITTELUNG);
Mal angenommen, der speicher hätte den Wert 99 und neuer_messwert 
den Wert 10. Dann kommt heraus:
1
   speicher /= ANZAHL_MITTELUNG;                                    // 99/10 = 9
2
   speicher = ((ANZAHL_MITTELUNG - 1) * speicher) + neuer_messwert; // 9*9 + 10 = 91 
3
   return(speicher/ANZAHL_MITTELUNG);                               // 9
neuer_wert kann beliebig lang 10 sein, es kommen immer nur 9 als 
Ergebnis heraus...

> Und du siehst, dass - Ich gebe zu, dass es an der Quantisierung liegt -
> mein Kondensator in Software auch niemals voll wird.
Besser ist es, wenn die Summe (= "Kondensatorspannung") nicht 
heruntergeteilt wird, sondern in ganzer Genauigkeit bleibt:
1
   speicher -= speicher/ANZAHL_MITTELUNG;                           // 99 - (99/10) = 90
2
   speicher = speicher + neuer_messwert;                            // 90 + 10 = 100
3
   return(speicher/ANZAHL_MITTELUNG);                               // 10

Siehe: http://www.lothar-miller.de/s9y/categories/21-Filter

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.