FIR Filter Koeffizienten

Gast #3807285
Lesenswert?

Hallo Zusammen

Ich habe in mein Programm ein FIR Filter aus einem Buch implementiert um 
Sensor signale von einem Accelometer zu filtern.

Ich will recht langsame Bewgungen messen bis max 1 Hz ...

jetzt getz es darum den Filter anzupassen kennt jemand ein gutes Tool..
Samplingrate 200HZ

11 Koeffizienten
LP Freuquenz 0-1 Herz Verstärken
1-100 Hz -40dB

Gruß

RL
#3808336
Lesenswert?

>>>>
11 Koeffizienten
LP Freuquenz 0-1 Herz Verstärken
1-100 Hz -40dB

Man braucht bei einem Filter ne spec für den Übergangsbereich: bei 1Hz 
kann nicht gleichzeitig 'verstärkt' werden und -40dB Verstärkung sein.

Mit der spec:
0dB bei 0Hz
0dB bei 1Hz
11.Ordnung

bist Du bei ungefähr 30Hz bei -40dB, bei 20. Ordnung/17Hz/-40dB.

Cheers
Detlef

clear
fb=firls(11,[0 1/100 0.3 1],[1 1 0 0]);
H=freqz(fb,1,1024);
f=100*linspace(0,1,length(H));
clf
plot(f,20*log10(abs(H)/max(abs(H))));
grid
return
Gast #3808396
Lesenswert?

Hallo Zusammen ich habe mal ein Analyser Tool in Processing gerschreiben 
mit den Werten for dem Filter und nach dem Filter.

Ich verwende jetzt ein FIR Filter mit 11 Koefizienten...

es filtert... aber eher mehr quantisiert als Filtern.... brauche ich 
mehr Koeffizienten ?
Angehängte Dateien:
Gast #3809862
Lesenswert?

Danke Jürgen..

Ich verwende jetzt 40 Koefizienten ...und hab die Grenzfrequenz an 2-3 
Hz gesetzt, allerdings kommt es es aus dem Filter nichts mehr raus...

ich hoffe mein Filter Algorythmus stimmt hier mein Code

float filter_MM (int filter_input)
{
//Bild 7: C-Code für FIR-Filter mit Circular Buffer und Integer-Zahlen
for(i = 0; i < nc; i++)
 circular_buffer[i] = 0;
// Der folgende Code wird jedes Mal ausgeführt, wenn ein
// neuer Eingangswert (new_sample) zur Verfügung steht
// Schreibe neuen Eingangswert in Buffer
// Eingangswerte werden um 6 bit nach rechts verschoben
// (entspricht Multiplikation mit 1/64)
circular_buffer[zeiger] = filter_input >> 6;
// Inkrementiere Zeiger modulo nc
zeiger = (zeiger + 1) % nc;
// Berechne neuen Ausgangswert
y = 0;
for(i = 0; i < nc; i++)
 y += (b[i] * circular_buffer[(zeiger + i) % nc]);

print(y);

return y;
}
Persönliche Seite #3809941
Lesenswert?

Raph schrieb:
> zum Spaß auch ein Filter mit gleitenden Mittelwert gebildet
Gleitende Mittelwerte sind faktisch eine Faltung mit einem Rechteck und 
dies führt zu einem entsprechendem Filterverhalten, d.h. Oberwellen 
werden durchgelassen. Das ist wenig sinnvoll.

Poste doch mal bitte Deine Koeffizienten. Ich würde soviele nehmen, wie 
der Controller zeitlich packt und sie so skalieren, dass man durch einen 
Binärwert dividieren kann.
Gast #3810610
Lesenswert?

1
float filter_MM (int filter_input)
2
{
3

4
for(i = 0; i < nc; i++)
5
 circular_buffer[i] = 0;   // <<<----------??????
6

7

8
circular_buffer[zeiger] = filter_input >> 6;
9
zeiger = (zeiger + 1) % nc;
10

11
y = 0;
12
for(i = 0; i < nc; i++)
13
 y += (b[i] * circular_buffer[(zeiger + i) % nc]);
14

15
return y;
16
}

Raph, du initialisiert bei jedem Filterdurchlauf den Ringpuffer mit 0 ? 
Das kann aber nicht funktionieren...
Gast #3811765
Lesenswert?

ja ich merks... es macht das signal schön  aber die Ausreiser gehen 
durch...

danke für das finden des Code Fehlers....

hier meine Filter Koeffizienten

a[0]=-0.000701250661962441;
a[1]= 0.000046089023855544;
a[2]= 0.001154985352103564;
a[3]= 0.002673409852606819;
a[4]= 0.004636976278026471;
a[5]= 0.007064989147159639;
a[6]= 0.009957083185894836;
a[7]= 0.013290744695288856;
a[8]= 0.017019963943888782;
a[9]= 0.021075203702531312;
a[10]= 0.025364786937348383;
a[11]= 0.029777712068029465;
a[12]= 0.034187803982450180;
a[13]= 0.038459010813441816;
a[14]= 0.042451568083819148;
a[15]= 0.046028680431598711;
a[16]= 0.049063322801486786;
a[17]= 0.051444742100100568;
a[18]= 0.053084249133936882;
a[19]= 0.053919929128394668;
a[20]= 0.053919929128394668;
a[21]= 0.053084249133936882;
a[22]= 0.051444742100100568;
a[23]= 0.049063322801486786;
a[24]= 0.046028680431598711;
a[25]= 0.042451568083819148;
a[26]= 0.038459010813441816;
a[27]= 0.034187803982450180;
a[28]= 0.029777712068029465;
a[29]= 0.025364786937348383;
a[30]= 0.021075203702531312;
a[31]= 0.017019963943888782;
a[32]= 0.013290744695288856;
a[33]= 0.009957083185894836;
a[34]= 0.007064989147159639;
a[35]= 0.004636976278026471;
a[36]= 0.002673409852606819;
a[37]= 0.001154985352103564;
a[38]= 0.000046089023855544;
a[39]=-0.000701250661962441;
Persönliche Seite #3811987
Lesenswert?

Nee, nee, da stimmt was net :-)

So wie mir das aussieht, hast Du entweder eine falsche Grenzfrequenz 
benutzt oder ein Fenster drin. Dieses bewirkt aber, dass in Deinem Fall, 
wenn Du erheblich weniger Koeffizienten, als Abtastpunkte hast (200:40), 
dass es die Kurve dominiert. D.h. das Fenster bestimmt die Koeffizienten 
und wird selber zum Filter. Praktisch entspricht Deine Kurve einer 
Grenzfrequenz von geschätzt 5-10Hz.

Selbst in dem gewählten Beispiel 1, mit einer Grenzfrequnz von 2Hz ist 
das Fenster komplett dominant. Die grüne Kurve wäre nämlich die für 
2Hz@40TAPs@200Hz passenden Koeffizienten.

Du musst die Abtastrate senken oder das Fenster abflachen, bzw komplett 
weglassen. Dies erklärt nämlich auch, warum Dein Rechteck / gleitender 
Mittelwert so gut funktioniert hat.

Am Besten wäre IMHO ein Konfiguration nach Bild 2, also MEHR TAPs, als 
Abtastfrequenz, sodass die Koeffizienten mehr, als eine Perdiode 
umspannen. Dann macht auch das Glätten durch ein Fenster Sinn.

Die Koeffizienten lägen dann bei:

-0,001014149
-0,003192120
-0,005718685
-0,008763348
-0,012467575
-0,016925590
-0,022166331
-0,028137703
-0,034694168
-0,041588619
-0,048469259
-0,054882055
-0,060279001
-0,064032194
-0,065453429
-0,063818709
-0,058396819
-0,048480863
-0,033421489
-0,012660347
0,014237694
0,047555104
0,087396463
0,133668768
0,186068400
0,244075609
0,306957108
0,373776998
0,443415918
0,514597948
0,585924468
0,655913825
0,723045439
0,785806728
0,842741087
0,892495108
0,933863193
0,965827823
0,987593889
0,998615718

und wären spiegelsymmetrisch zu nutzen, damit es 80 werden, wobei Du 
auch nur die positive Hälfte benutzen kannst und bei 40 TAPs bleibst.
Persönliche Seite #3812039
Lesenswert?

Naja, das ist das kleinste Problem, da die am Ende ohnehin gerundet 
werden. Jedenfalls macht man so an der Stelle schon mal keinen Fehler. 
Die Genauigkeit der Koeffizienten ist aber teilweise durchaus ein 
Problem, weil sich auch kleine Fehler zu digitalem Rauschen addieren. 
Sicherheitshalber sollten sie daher eine Dezimal-Stelle genauer sein, 
als der höchste denkbare Fehler, als Dynamik x Filtertapzahl. Hier also 
z.B. (6+2+1) = 9-stellig bei 16 Bit und vollausgesteuerten Koeffizienten 
mit 100 TAPs.

In seinem Fall mit 200 TAPS und Aussteuerung 0,05 täten 11-12 Stellen 
reichen.
Gast #3817119
Lesenswert?

Ein FIR-Filter mit float-Koeffizienten??? Das wird extrem langsam und 
ist auch noch ungeschickt.
Mach' lieber intelligente Festpunktarithmetik.
z.B. 16 Bit Daten, Koeffizienten mit 12..14 Bit (in einer 16-Bit-Zahl).
Multiplikation ergibt dann 32 Bit. Aufaddieren in 32 Bit. zum Schluss 
skalierst du das Ergebnis mit 2e-Potenz - shift right (oder du benutzt 
nur die obersten 16 Bit)...

PS:
Wenn du auch negative Koeffizienten verwendest, bekommt der Frequenzgang 
einen schärferen Knick, aber bei einem abrupten Eingangssprung bekommst 
du ca. 8% Überschwinger...
Gast #3820939
Lesenswert?

Alex schrieb:
> Wenn du auch negative Koeffizienten verwendest, bekommt der Frequenzgang
> einen schärferen Knick, aber bei einem abrupten Eingangssprung bekommst
> du ca. 8% Überschwinger...
Ob das 8% sind oder mehr, hängt aber von dem Filter ab. So pauschal ist 
das nicht stimmig.
Gast #3858161
Lesenswert?

Ich habe jetzt 100 Koefizienten, den "WindowW rausgemacht
soweit auf dem richtigen Weg. Allerdings scheint der Filter instabil zu 
sein
was die Folge hat das die Werte mit der Zeit immer höher werden, Wie 
kann ich das verhindern ?...Anbei noch ein Screenshot zu den 
Einstellungen
mein Code:
float filter_MM_2 (int filter_input)
{
//Bild 7: C-Code für FIR-Filter mit Circular Buffer und Integer-Zahlen
 for(i = 0; i < nc; i++)
 {
 circular_buffer[i] = 0;
 }
// Der folgende Code wird jedes Mal ausgeführt, wenn ein
// neuer Eingangswert (new_sample) zur Verfügung steht
// Schreibe neuen Eingangswert in Buffer
// Eingangswerte werden um 6 bit nach rechts verschoben
// (entspricht Multiplikation mit 1/64)
circular_buffer_2[zeiger_2] = filter_input >>7;
// Inkrementiere Zeiger modulo nc
zeiger_2 = (zeiger_2 + 1) % ncc;
// Berechne neuen Ausgangswert

for(ii = 0; ii < ncc; ii++)
{ y += (a[ii] * circular_buffer_2[(zeiger_2 + ii) % ncc]);
}


return y;
}
Angehängte Dateien:
#3858472
Lesenswert?

Darf ich mal wieder auf meinen Text verweisen:
http://www.mikrocontroller.net/articles/Digitalfilter_mit_ATmega
da verwende ich Scilab zur Berechnung der Filterkoefizienten.

Die Literatur dazu :
http://elm.eeng.dcu.ie/~ee317/Matlab_Clones/signal.pdf
mit den Programmtexten 
http://www.mikrocontroller.net/wikifiles/8/82/SignalFiles.pdf
Ab Seite 83 ist der "remez"-Befehl zur Berechnung von 
FIR-Filter-Koeffizienten beschrieben.
Gast #3860836
Lesenswert?

Brauchst Du eigentlich FIR (z.B. konstante Gruppenlaufzeit), ansonsten 
wäre für so eine Anwendung vermutlich ein IIR Filter die schnellere und 
effizientere Alternative.

Mit Octave (Mathlab) geht das schnell zu berechnen. Wenns Quick&Dirty 
reicht und Du kleine Windows Tools magst, dann evtl. auch WinFilter.exe 
;-)
Gast #3875179
Lesenswert?

Christoph Kessler (db1uq) schrieb:
> Ab Seite 83 ist der "remez"-Befehl zur...

genau DAS ist so eine Quelle, wie ich sie hasse: Dutzende Beispiele 
hingeklatscht, ohne jegliche Erläuterung, ohne verstehbare Namen - eben 
ohne jegliches Verständnis für Didaktik.

Ich habe den schlimmen Eindruck, daß genau dieses ein typisches Zeichen 
der heutigen Zeit ist: Leute, die eigentlich lehren sollten, tun es 
nicht und andere Leute, die zwar das Wissen und Können haben, aber es 
wirklich nicht rüberbringen können, versuchen das Lehren ersatzeshalber 
dennoch. Das ist im Prinzip zwar löblich, aber trotzdem ein fruchtloses 
Tun.

Dieses Land braucht nicht noch mehr Studienfächer, sondern bessere 
Professoren!

W.S.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren