
Zitat von
fredyxx
Zitat von HaWe
in meinen eigenen Programmen jage ich sämtliche Inputwerte (analog + digital) aber auch fast immer durch Filter (Lowpass oder gleitender Median von 3), um auch weitere (!) Störeffekte im laufenden Betrieb durch Prellen von Kontakten oder schwankende ADC Werte zu ent-rauschen und zu glätten
Trotzdem würde mich interessieren, wie das konkret aussieht.
am einfachsten geht es mit dem Lowpassfilter; der merkt sich eine Art gleitenden Durchschnitt:
du fragst in einer schnellen Schleife (z.B. alle 1-10ms) den Wert eines Ausgangs ab, z.B.
Code:
void loop() {
float oldvar, fvar;
int pinvar, pinNr;
oldvar = fvar;
pinvar = digitalRead (pinNr);
fvar = 0.4*pinvar + 0.6*oldvar;
pinvar = round(fvar);
delay(5);
//...
}
wenn z.B. bisher "0" anlag (also oldvar=0) und jetzt 1x "1" gemessen wurde, ergibt sich
0.4*1 + 0 = 0.4
round(0.4) = 0
bleibt es ein einmaliger Ausreißer, wird der Wert also verschluckt, es bleibt bei 0.
Kommt jetzt in der nächsten Abfragerunde aber nochmal eine "1" dazu, ergibt sich
0.4*1 + 0.6*0.4 = 0.4 +0.24 = 0.64
round(0.64) = 1
wenn also erneut eine "1" anliegt, also quasi nach 2 Durchläufen "dauerhaft", dann kommt jetzt eine 1 heraus.
Die Summe aus beiden Faktoren soll immer 1 betragen, also
0.4 & 0.6
oder 0.2 & 0.8
oder 0.3 & 0.7
oder 0.5 & 0.5 (entspricht arithmetischem Mittel)
oder für analoge Werte auch z.B. 0.9 & 0.1 oder 0.1 & 0.9
allgemein:
Durchschnitt = a*aktuell + (1-a)*Durchschnitt, 0<a<1
durch "Spielen" mit den Koeffizienten und testen kannst du den Filter für deine Anwendung darauf optimieren und Störungs-empfindlicher und schneller reagierend (größere a) oder Störungs-unempfindlicher und träger machen (kleinere a).
Da du sowieso in den loops ein paar ms delays brauchst, fällt das bisschen float-Arithmetik auch absolut nicht ins Gewicht. Falls doch: per Integer mit 100 multiplizieren und das Ergebnis später wieder durch 100 teilen, ist aber nicht nötig bei dem bisschen Rechnerei.
Lesezeichen