Hallo,
ich hab folgendes Problem:
Ich möchte gern die Werte die mein Atmega/Xmega über den ADC bekommt
filtern.
Da gibt es ja mehrere Varianten und Möglichkeiten.
Zur Zeit habe ich diese Variante:
X[n] = (k-1)/k * X[n-1] + adc/k
Meine Samplefrequenz beträgt 10kHz
Wie errechne ich jetzt die Dämpfung und die Grenzfrequenz?
Bitte um Hilfe
Danke
Nochmal zum Verständnis, dass oben genannte Filter ist ein IIR-Fiter!?
Wenn ich ein FIR Filter haben möchte muss ich doch eigentlich im
einfachsten Fall einen gleitenden Mittelwert über n Werte bilden oder?
> Nochmal zum Verständnis, dass oben genannte Filter ist ein IIR-Fiter!?
Ja.
> Wenn ich ein FIR Filter haben möchte muss ich doch eigentlich im> einfachsten Fall einen gleitenden Mittelwert über n Werte bilden oder?
Ja.
> X[n] = (k-1)/k * X[n-1] + adc/k> Meine Samplefrequenz beträgt 10kHz> Wie errechne ich jetzt die Dämpfung und die Grenzfrequenz?
Grenzfrequenz ist f_g = (10 kHz/k) / (2*Pi)
Dämpfung ist 20 dB/Dekade, da Filter 1. Ordnung
Hallo Johannes,
Johannes schrieb:> Grenzfrequenz ist f_g = (10 kHz/k) / (2*Pi)
Was sollen die 2*Pi da? Du rechnest mit der Frequenz und willst als
Ergebnis die Frequenz. Bei dir müssten die 10kHz als Kreisfrequenz
gegeben sein.
Oder bin ich gerade irgend wie falsch?
MfG
Tec
> Johannes schrieb:>> Grenzfrequenz ist f_g = (10 kHz/k) / (2*Pi)> Was sollen die 2*Pi da? Du rechnest mit der Frequenz und willst als> Ergebnis die Frequenz. Bei dir müssten die 10kHz als Kreisfrequenz> gegeben sein.
Die Formel ist erst mal nur eine Näherung für f_g << f_Sample. Hatte ich
vergessen dazuzuschreiben.
Für die Zeitkonstante gilt:
tau = k / f_Sample
Das kann man sich damit herleiten, dass am Anfang, wenn X[n-1] = 0 ist
und ein Eingangssignal adc != 0 reinkommt, dann ist nach dem ersten
Sample X[n] = adc/k.
Wenn das Signal mit der gleichen Steigung weiter ansteigen würde, dann
würde es k Zyklen dauern, bis X[n] = adc ist. Also die die Zeitkonstante
k Zyklen, also k/f_Sample.
Die Grenzfrequenz ist definiert als 1/(2*Pi*tau), damit erhält man die
Formel von oben.
PS: Etwas eleganter kann man statt
X[n] = (k-1)/k * X[n-1] + adc/k
die Formel ausmultiplizieren nach
X[n] = X[n-1] + (adc - X[n-1])/k
Wenn man dann noch k1 = 1/k ersetzt erhält man
X[n] = X[n-1] + (adc - X[n-1])*k1
Damit erspart man sich die beiden Divisionen.
Besselworth schrieb:> Hallo,>> ich hab folgendes Problem:> Ich möchte gern die Werte die mein Atmega/Xmega über den ADC bekommt> filtern.
Du meinst, mit einem passenden Programm?
Es ist Dir aber klar, das Du auch vor dem Eingang analog filtern
musst, um den Aliasing-Effekt zu vermeiden?
Gruss
Harald
Harald Wilhelms schrieb:> Es ist Dir aber klar, das Du auch vor dem Eingang analog filtern> musst, um den Aliasing-Effekt zu vermeiden?
Ja sicher, das ist klar. Mir geht es hier auch weniger um ein
tatsächliches Problem sondern nur ums Begreifen.
Nach langem Nachrechnen mit Excel bin ich zu dem Ergebnis gekommen, das
wenn ich ein Gleichspannungssignal habe, dass im Idealfall nicht raucht
und auch keine Spannungssprünge drinnen hat, am besten die Formel oben
zu nehmen ist IIR-Filter mit k>= 16. Hier werden Ausreißer sauber weg
gebügelt.
Zusammenfassend:
HIER IIR-Filter 1.Ordnung mit fg = fs/(k*2*pi) und
X[n] = X[n-1] + (adc - X[n-1])*k1
Möchte ich jedoch Größen messen, die sich auch mal schnell ändern
(Ströme z.B.) sollte ich lieber mit gleitendem Mittelwert über n Werte
rechnen (FIR Filter n-ter Ordung?) um eine gewisse Dynamik zu behalten.
Oder was meint ihr?
Wie sieht das hier mit Grenzfrequenz und Dämpfung aus?
Vielen Dank schonmal
Besselworth schrieb:> Nach langem Nachrechnen mit Excel bin ich zu dem Ergebnis gekommen, das> wenn ich ein Gleichspannungssignal habe, dass im Idealfall nicht raucht> und auch keine Spannungssprünge drinnen hat, am besten die Formel oben> zu nehmen ist IIR-Filter mit k>= 16. Hier werden Ausreißer sauber weg> gebügelt.>> Zusammenfassend:> HIER IIR-Filter 1.Ordnung mit fg = fs/(k*2*pi) und> X[n] = X[n-1] + (adc - X[n-1])*k1>>> Möchte ich jedoch Größen messen, die sich auch mal schnell ändern> (Ströme z.B.) sollte ich lieber mit gleitendem Mittelwert über n Werte> rechnen (FIR Filter n-ter Ordung?) um eine gewisse Dynamik zu behalten.> Oder was meint ihr?>> Wie sieht das hier mit Grenzfrequenz und Dämpfung aus?
Nun, es sollte Dir klar sein, das ein Filter immer irgendwie
"etwas wegschneidet". Es ist daher schwer zu sagen, wieviel
"wegschneiden" Du noch tolerierst und wiviel Du wirklich
brauchst. Ich habe mich zwar lange mit Digitalen Filtern
beschäftigt, die Filterkurven waren aber zum Glück vorgegeben.
Welches Filter man für einen bestimmten Zweck benutzt, ist
auch viel Gefühlssache. Wenn man sich intensiver mit dieser
Thematik beschäftigt, muss man auch ziemlich bald tief in
die höhere Mathematik eintauchen (Z-Transformation usw.).
Ein Thema, welches mir auch nicht so besonders liegt.
Inwieweit hier auch Mathematiker mitlesen, weiss ich nicht.
Gruss
Harald
> Möchte ich jedoch Größen messen, die sich auch mal schnell ändern> (Ströme z.B.) sollte ich lieber mit gleitendem Mittelwert über n Werte> rechnen (FIR Filter n-ter Ordung?) um eine gewisse Dynamik zu behalten.> Oder was meint ihr?
Wenn du schnellere Änderungen mitbekommen möchtest, muss das k eben
kleiner werden anstatt 16.
Ein FIR-Filter hat den Nachteil, dass man meistens ein Filter höherer
Ordnung und damit mehr Rechenleistung braucht; vor allem, wenn die
Grenzfrequenz << Abtastrate ist.
Der Vorteil bei einem FIR-Filter ist, dass man damit linearphasige
Filter machen kann und dass man die Nulltellen der Übertragunsfunktion
so legen kann, dass bestimmte Frequenzen komlett herausgefiltert werden.
Das ist z.B. praktisch, wenn man bei einer PWM den Strom messen möchte.
Da kann man einen gleitenden Mittelwert über genau eine PWM-Periode
berechnen und filtert damit die PWM und alle Oberwellen raus.
Danke Harald,
mein Ziel ist es ohne großen mathematischen Aufwand ein Filter zu
programmieren, dass weder den µC auslastet, noch mich an der Rand des
Wahnsinns treibt. Eigentlich sollen die hardware-vorgefilterten Werte
nur nochmal "rund" gemacht werden. Leider lassen sich Spikes meist nie
ganz vermeiden, sodass man diese dann per Software rauskicken muss um
den Regler nicht nervös zu machen. Wenn ich z.B. eine Batteriespannung
von 120V messen und auf nem LCD darstelle möchte, ist auch klar das der
Wert nicht sonderlich stark bzw. garnicht schwanken sollte. Hier währe
dann ein IIR mit sehr hoher Dämpfung gefragt. Für andere Dinge, wie du
schon sagst, nach Gefühl einen FIR-Filter über n-Werte.
Hat mich auf jedenfalls schonmal weiter gebracht.
Für weitere Ratschläge bin ich jederzeit dankbar.
Johannes schrieb:> Ein FIR-Filter hat den Nachteil, dass man meistens ein Filter höherer> Ordnung und damit mehr Rechenleistung braucht; vor allem, wenn die> Grenzfrequenz << Abtastrate ist.
Ich habe mich mit Wertigkeiten einzelner Messwert noch nicht
auseinandergesetzt, aber wenn alle Werte im Fenster die gleiche
Wertigkeit haben, so ist der Aufwand doch "nur" eine Addition aller
Werte und ein Teilen bzw. Shift durch die Anzahl an Werten, die im
Idealfall auf der Basis 2 aufbauen, oder irre ich mich?
Besselworth schrieb:> Ich habe mich mit Wertigkeiten einzelner Messwert noch nicht> auseinandergesetzt, aber wenn alle Werte im Fenster die gleiche> Wertigkeit haben, so ist der Aufwand doch "nur" eine Addition aller> Werte und ein Teilen bzw. Shift durch die Anzahl an Werten, die im> Idealfall auf der Basis 2 aufbauen, oder irre ich mich?
Also ein Filter mit rechteckiger Kurve im Zeitbereich. Wenn Du das
mittels Transformation in den Frequenzbereich umrechnest, sieht die
Frequenzkurve ziemlich "wild" aus. Die einzige (Filter-)Funktion,
die sowohl im Frequenzbereich als auch im Zeitbereich gleich aussieht,
ist die Gaussfunktion. Deshalb werden z.B. bei der Rauheitsmessung
auch sog. Gaussfilter verwendet.
Habe gerade mal mit WinFilter gespielt. Wenn ich über 30 Werte mittle
und die vorgeschlagenen Koeffizieten benutze, erreiche genau was mir so
vorschwebt. Ich denke mal:
1
#define Ntap 30
2
3
#define DCgain 65536
4
5
__int16fir(__int16NewSample){
6
__int16FIRCoef[Ntap]={
7
35,
8
72,
9
78,
10
142,
11
170,
12
290,
13
367,
14
610,
15
808,
16
1343,
17
1847,
18
3226,
19
4640,
20
10622,
21
16987,
22
10622,
23
4640,
24
3226,
25
1847,
26
1343,
27
808,
28
610,
29
367,
30
290,
31
170,
32
142,
33
78,
34
72,
35
35,
36
38
37
};
38
39
static__int16x[Ntap];//input samples
40
__int32y=0;//output sample
41
intn;
42
43
//shift the old samples
44
for(n=Ntap-1;n>0;n--)
45
x[n]=x[n-1];
46
47
//Calculate the new output
48
x[0]=NewSample;
49
for(n=0;n<Ntap;n++)
50
y+=FIRCoef[n]*x[n];
51
52
returny/DCgain;
53
}
sollte auch kein allzugroßen Rechenaufwand bedeuten, wenn ich meinem
Gefühl trauen kann. Nettes Programm
Nochmal ne rein formelle Frage, wenn ich ein solches Filter benutzen
möchte, macht man dann eine Source-Datei wo der Filteralgorithmus so oft
wie benötigt drinnen steht (8x ADC-Kanäle = 8 x Code für jeweils 1x
ADC-Kanal) oder eher je Kanal einen Sourcecode? Ich denke letzteres ist
übersichtlicher wenn man unterschiedliche Koeffizienten hat.
Danke
> Habe gerade mal mit WinFilter gespielt. Wenn ich über 30 Werte mittle> und die vorgeschlagenen Koeffizieten benutze, erreiche genau was mir so> vorschwebt.> ...> sollte auch kein allzugroßen Rechenaufwand bedeuten, wenn ich meinem> Gefühl trauen kann. Nettes Programm
Das sind halt 30 Multiplikationen und 30 Additionen, die man in jedem
Update-Takt durchrechnen muss. Außerdem muss man immer die letzten 30
Messwerte im Speicher halten (Ringpuffer oder Schieberegister) und
braucht auch noch 30 Speicherstellen für die Koeffizienten.
Beim IIR-Filter 1. Ordnung hat man eine Multiplikation und 3 Additionen
pro Update-Zyklus und braucht wesentlich weniger Speicher.
Es ist also schon ein geweisser Unterschied. Es kommt aber auf die
Anwendung an, was besser geeignet ist. Manche Aufgagen lassen sich
einfach nur mit ein FIR-Filter lösen, da muss man also den höheren
Aufwand in kauf nehmen.