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
>Wird das so gemacht, oder wie ist die praktische Lösung?
Nur alle 10s messen.
Wahlweise ein digitaler Filter. Google mal FIR oder IIR Filter. Gruss, Thorsten
holger schrieb: > Nur alle 10s messen. Nee, so kann das nicht sein, die verhalten sich anders - der Strom steigt dann trotzdeman, aber halt sehr langsam bis zum Endwert. Würde ich nur alle 10s messen, dann würde der Messwert schlagartig springen.
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
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...
Ohne Speicher zu fressen: Messwert = Messwert_alt * 0.95 + Messwert * 0.05
>Muss mann dan 2min jede Sekunde messen und damit rechnen?
Nö, du kannst auch alle 12s messen. Oder alle 30s...
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
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.
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
Jo K. schrieb: > ANZAHL_MITTELUNG - 1 Dann würdest du doch immer die Konstante 9 zum Messwert dazu addieren?!
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 | } |
>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?
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
Thorsten schrieb: > Dieser Ansatz hat genau das erwähnte Problem mit der Auflösung. Das weiß ich auch, deswegen hab ich ja schon möglichst "dicke" Datentypen gewählt. Das ist im elektrischen Sinne aber genau dasselbe wie das hier:
1 | ____ |
2 | o---|____|---+----o |
3 | | R | | |
4 | U_in| = C |U_out |
5 | V | V |
6 | o------------+----o |
Die e-Funktion beschert uns das gleiche. mf
Jo, die dicken Datentypen helfen Dir in dem Fall aber nicht. Den Vergleich mit dem "elektrischen Sinne" hab ich nicht kapiert - hier findet ja keine Ganzzahldivision statt... Gruss, Thorsten
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.