Hallo Leute,
ich will mir mit meinem ATMega128 drei digitale Filter basteln.
Einen Notch-Filter(50Hz), einen Tiefpass(ca.150Hz) und einen
Hochpass(ca. 1Hz).
Den Notch-Filter habe ich bereits implementiert und er funktioniert.
Die Koeffizienten habe ich in MATLAB berechnet. Das Eingangssignal hat
eine Samplerate von 500Hz und ist ein signed long 32-Bit Wert.
Folgende Filterform habe ich verwendet:
Die Gleichungen für ein IIR-Filter Direct-Form II, SOS
w[n] = Gin*x[n] + a1*w[n-1] + a2*w[n-2]
y[n] = Gout*(b0*w[n] + b1*w[n-1] + b2*w[n-2])
Filterkoeffizienten:
//Zähler
b[0] = 1
b[1] = -1.6180339887498947
b[2] = 0.99999999999999989
//Nenner
a[0] = 1.6077528939666013
a[1] = -0.98729186796473045
Um mit Festkommazahlen rechnen zu können müssen die Koeffizienten ja
skaliert werden.
Da die Koeffizienten nicht im Bereich -1...+1 liegen habe ich sie
zunächst durch 2 geteilt und dann mit 2^(31) multipliziert um sie im Q31
Format abzuspeichern.
Das ist der C-Code meines Filters.
1 | signed long iir_notch(signed long new_sample, signed long *w)
|
2 | {
|
3 | signed long b[3], a[2], y;
|
4 |
|
5 | signed long mult_q31(signed long factor1, signed long factor2)
|
6 | {
|
7 | return (signed long) (((signed long long)factor1 * (signed long long)factor2) >> 31);
|
8 | }
|
9 | //Scaled Coefficients(x/2 * 2^(31)) --> Q31
|
10 | b[0] = 1073741824;
|
11 | b[1] = -1737350766;
|
12 | b[2] = 1073741824;
|
13 | a[0] = 1726311525;
|
14 | a[1] = -1060096571;
|
15 |
|
16 | w[0] = (new_sample + mult_q31(a[0],w[1]) + mult_q31(a[1],w[2]));
|
17 |
|
18 | y = (mult_q31(b[0],w[0]) + mult_q31(b[1],w[1]) + mult_q31(b[2],w[2]));
|
19 |
|
20 | w[2] = w[1];
|
21 | w[1] = w[0];
|
22 |
|
23 | return y;
|
24 | }
|
Hat jemand noch eine Idee wie man die Koeffizienten vielleicht noch
besser skalieren könnte um das Ergebnis möglicherweise noch zu
verbessern??