Forum: Digitale Signalverarbeitung / DSP / Machine Learning digitales Filter so schwer?


von Besselworth (Gast)


Lesenswert?

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

von Marko (Gast)


Lesenswert?

Dämpfung und Grenzfrequenz kannst du mit dem Befehl filt2xd2x berechnen 
!

von Besselworth (Gast)


Lesenswert?

Sorry, Programmiersprache ist C, hatte ich vergessen...

von Besselworth (Gast)


Lesenswert?

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?

von Johannes (Gast)


Lesenswert?

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

von Besselworth (Gast)


Lesenswert?

Danke!

von Johannes (Gast)


Lesenswert?

> 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

von Tecnologic (Gast)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

Die Zeitkonstante des Filters ist k/Abtastfrequenz, die Grenzfrequenz
ist 1/(2·pi·Zeitkonstante). Daher kommen die 2·pi.

von Johannes (Gast)


Lesenswert?

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

von Harald Wilhelms (Gast)


Lesenswert?

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

von Besselworth (Gast)


Lesenswert?

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

von Harald Wilhelms (Gast)


Lesenswert?

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

von Johannes (Gast)


Lesenswert?

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

von Besselworth (Gast)


Lesenswert?

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.

von Besselworth (Gast)


Lesenswert?

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?

von Harald Wilhelms (Gast)


Lesenswert?

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.

von Besselworth (Gast)


Lesenswert?

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
__int16 fir(__int16 NewSample) {
6
    __int16 FIRCoef[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 __int16 x[Ntap]; //input samples
40
    __int32 y=0;            //output sample
41
    int n;
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
    return y / DCgain;
53
}

sollte auch kein allzugroßen Rechenaufwand bedeuten, wenn ich meinem 
Gefühl trauen kann. Nettes Programm

von Besselworth (Gast)


Lesenswert?

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

von Johannes (Gast)


Lesenswert?

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

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.