Forum: Digitale Signalverarbeitung / DSP / Machine Learning Wie kann man einen IIR Filter stabilisieren


von Anh L. (leanh2)


Lesenswert?

Hallo

Ich habe gerade Problem mit meinem IIR Filter, und zwar er ist nicht 
stabil

Er hat einige Pole, die außerhalb der Einheitskreis und damit, instabil

Ganz allgemeine Fragen: welche Möglichkeiten hat man, um diesen 
instabilen Filter zu stabilisieren ?

Viele Grüße

von Detlef _. (detlef_a)


Lesenswert?

Was meinst Du?
Du kannst das instabile Filter so in einen Regelkreis einbauen, dass der 
insgesamt stabil wird. Ansonsten müssen die Pole schon im Einheitskreis 
bleiben, ansonsten wird das Filter instabil.

Cheers
Detlef

von Anh L. (leanh2)


Lesenswert?

Detlef _a schrieb:
> Was meinst Du?
> Du kannst das instabile Filter so in einen Regelkreis einbauen, dass der
> insgesamt stabil wird. Ansonsten müssen die Pole schon im Einheitskreis
> bleiben, ansonsten wird das Filter instabil.
>
> Cheers
> Detlef

Kann man z.B die Übertragungsfunktion von diesem instabilen Filter 
zerlegen, in einer minimalphasigen System und ein Allpass. Dann ist der 
Filter stabil oder
Gruß

von Detlef _. (detlef_a)


Lesenswert?

Man kann ein nicht-Minimalphasensystem in ein Minimalphasensystem und 
einen Allpass zerlegen. Dabei geht es aber um Nullstellen ausserhalb des 
Einheitskreises, Du hast aber Polstellen ausserhalb.

Cheers
Detlef

von BoDe (Gast)


Lesenswert?

Anh Le schrieb:
> Ganz allgemeine Fragen: welche Möglichkeiten hat man, um diesen
> instabilen Filter zu stabilisieren ?

Filterkoeffizienten ändern ;-)

von Anh L. (leanh2)


Lesenswert?

Detlef _a schrieb:
> Man kann ein nicht-Minimalphasensystem in ein Minimalphasensystem und
> einen Allpass zerlegen. Dabei geht es aber um Nullstellen ausserhalb des
> Einheitskreises, Du hast aber Polstellen ausserhalb.
>
> Cheers
> Detlef

Danke für deine Antwort
Konkret ist so folgendes
Ich habe einen FIR Filter mit der Übertrafungsfunktion H(z) und dies 
soll ich invertieren als H'(z) = 1/ H(z) und ich soll jetzt H'(z) 
stabilisieren.
H'(z) hat einige Pole, die außerhalb des Einheitskreises liegen.

Kann ich meine obige Ansatz verwenden. Wäre sehr nett, wenn du kurz 
erklärst, warum kann ich oder warum kann ich nicht
Viele Grüße

von Detlef _. (detlef_a)


Lesenswert?

Die Nullen von H(z) werden ja zu Polen von H'(z) und zwar mit Kehrwert 
des Betrags der ursprünglichen Null. Vllt. trifft es ja die Dir 
vorgegebene spec. wenn du die Nullen von H(z), die innerhalb des 
Einheitskreises liegen, am Kreis spiegeltst, also Winkel beibehalten und 
Kehrwert des Betrags nehmen. Dann sind alle Nullen ausserhalb und fallen 
nach Transformation zu H'(z) in den Einheitskreis, das Ding wird also 
stabil.

Cheers
Detlef

von Anh L. (leanh2)


Lesenswert?

Moin
Und noch eine Frage:

Kann man jedes zeitdiskrete System zerlegen oder nur stabiles nicht 
minimalphasiges System
Danke
Viele Gruesse

von Eg (Gast)


Lesenswert?

Hallo

ich habe dasselbe Problem wie oben schon beschrieben. Ich versuche 
derzeit einen IIR-Filter höherer Ordnung auf FPGA-Ebene zu 
implementieren. Die Eckdaten des Filters wie  Abtastfrequenz 
Grenzfrequenz, Sperr-und Durchlassdämpfung sind bekannt. Die 
dazugehörigen Filterkoeffizienten wurden mittels Matlab ermittelt. Die 
einzelnen Komponenten wie der Addierer, Multiplizierer und Verzögerer 
habe ich schon in VHDL entworfen. Allerdings ist es bekannt, das 
IIR-Filter dazu neigen instabil zu werden, sofern Rundungsfehler der 
Berechnungen oder der Koeffizienten vorhanden sind. Ich habe jetzt schon 
meine Koeffizienten auf VHDL-Eben 30 Bit groß gemacht und frage mich ob 
dies immer noch nicht genau genug ist. Ich versuche derzeit Lösungen zu 
finden wie ich meinen Filter stabilisieren kann. Würde mich auf ein paar 
Ideen freuen

Gruß

von Helmut S. (helmuts)


Lesenswert?

> Ich habe einen FIR Filter mit der Übertrafungsfunktion H(z) und dies
soll ich invertieren als H'(z) = 1/ H(z) und ich soll jetzt H'(z)
stabilisieren.
H'(z) hat einige Pole, die außerhalb des Einheitskreises liegen.


Ist das nicht schon vom Ansatz her falsch?
Du machst ein Filter das bei bestimmten Frequenzen unendliche 
Verstärkung hat. Wie soll das in der Anwendung jemals funktionieren ohne 
zu schwingen?

von Detlef _. (detlef_a)


Lesenswert?

>>> einen IIR-Filter höherer Ordnung auf FPGA-Ebene zu implementieren.

Höhere Ordnung ist schwierig. Du zerlegst das Filter in 
hintereinandergeschaltete Teilfilter 2.Ordnung, das ist stabiler, besser 
zu übersehen und unempfindlicher gegen nichtlineare Effekte, z.B. 
Grenzzyklen. Zur Paarung der Pole mit den Nullstellen gibt es auch 
einiges zu sagen, da muss Du mal kucken.

Cheers
Detlef

von Eg (Gast)


Lesenswert?

Hallo Detlef,

Danke für deine Antwort. Das was du angesprochen hast habe ich 
berücksichtigt. Ich habe den Filter in Direktform2, SOS implementiert. 
Sprich in Kaskaden Form (Mehrere Sektionen 2.Ordnung). Ich weiß auch 
dass wenn alle Sektionen für sich stabil sind, dass das gesamte System 
stabil ist. Ich schaffe es aber nicht einen einfachen Bandpass 4.Ordnung 
mit folgenden Eckdaten zu stabilisieren (Implementierung auf 
FPGA-Ebene).

Eckdaten:
Fs=4882.8125Hz
Fc1=500Hz
Fc2=800Hz

Entwurfs mittels FDATool Matlab mit Einstellung Elliptic,Equiripple. 
Zusätzlich weiß ich nicht wie sich die Auswirkung der Instabilität auf 
der Hardware bemerkbar macht. Ich sehe am Oszilloskop ein Ausgangssignal 
obwohl ich am Eingang des AD-Wandlers nichts Einspeise. Ich gehe davon 
aus das dies das instabile Verhalten des Filters ist. Vielleicht 
könntest du auch mal genauer die Sache mit der Pol-und Nullstellen 
Paarung genauer erläutern. Vielen Dank im Voraus

Gruß

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Quantisiere doch erst mal die Koeffizienten, und kontrolliere ob das 
Filter mit den quantisierten Koeffizienten stabil ist bzw. überhaupt 
noch den gewünschten Frequenzgang hat. Gerade elliptische Filter 
reagieren sehr empfindlich auf Quantisierung. Erst wenn das alles passt 
kannst du dir Gedanken um "Online"-Quantisierungseffekte machen 
(Quantisierungsrauschen, Grenzzyklen). Sicherlich ist ein Oszilloskop 
aber nicht das geeignete Debugging-Instrument für ein FPGA. Eine 
bitexakte Nachbildung des Filters in MATLAB oder ein VHDL-Simulator 
wären da sinnvoller.

von Eg (Gast)


Lesenswert?

Diesen Vorgang habe ich schon durchgeführt. Folgendes Habe ich gemacht:

-Filterkoeffizienten per Matlab bestimmt.
-Koeffizienten von Dezimal in Dual Festkommazahl (Vektor 30 Bit) 
umgerechnet
-Dual Festkommazahl wieder in Dezimal Kommazahl umgerechnet (abgerundete 
Filterkoeffizienten)

Die abgerundeten Filterkoeffizienten habe ich in Matlab eingegeben und 
geprüft ob der Filter stabil ist. Matlab liefert mir als Ergebnis das 
der Filter Stabil ist. Trotzdem Funktioniert das leider nicht.

von Detlef _. (detlef_a)


Lesenswert?

>> Matlab liefert mir als Ergebnis das der Filter Stabil ist.

Wie macht es das, indem es die Pole mit den gerundeten Koeffizienten 
berechnet? Du musst, wie schon gesagt, das Filter bitgenau simulieren. 
Das geht in Matlab, indem Du die integer-Rechnung des FPGAs 
nachvollziehst, mit allen Rundungen der Zwischenergebnisse.

Ausgangssignal ohne Eingangssignal kann Grenzzyklus sein, 
wahrscheinlicher ist aber ein Implementierungsfehler ;-) .

Mit der richtigen Paarung der Pole und Nullen kannst Du die benötigte 
Dynamik (Bitbreite) runterdrücken, auch gut zu simulieren.

mail mal die Filter.

Cheers
Detlef

von Eg (Gast)


Lesenswert?

die abgerundeten Filterkoeffizienten berechne ich selber. Ich habe mir 
dazu ein C-Programm geschrieben das mir die originalen 
Filterkoeffizienten aus einer Datei einliest, die Berechnung der 
gerundeten Filterkoeffizienten durchführt und die gerundeten 
Filterkoeffizienten wieder in eine Datei ausliest. Somit kann ich die 
gerundeten Filterkoeffizienten schneller implementieren ohne das per 
Hand durchzuführen. Habe auch verifiziert ob die gerundeten Werte von 
dem Programm übereinstimmen. Um die Stabilität hier zu prüfen nutze  ich 
wieder das FDATool. Der Unterschied ist nur das ich einen Filter 
importiere. Ich gebe dem FDATool die SOS und G Matrix vor mit den 
gerundeten Koeffizienten  und lasse mir das Pol und Nullstellendiagramm 
anzeigen. Das mit der nach Implementierung in Matlab ist eine gute Idee. 
Ich werde mal versuchen den Filter in Simulink bis in Bitebene 
aufzubauen und zu Simulieren. So hattest du es bestimmt gemeint oder…? 
Was würdest du gerne von den Filtern sehen? Etwa den Entwurf von dem 
FDATool?
Gruß

von Detlef _. (detlef_a)


Lesenswert?

>>Was würdest du gerne von den Filtern sehen?

Zwei SOS sind 2*5 Zahlen, zehn integer Werte mit ihrer Skalierung, die 
hast Du doch implementiert (oder kann FDATool VHDL exportieren?). SOS 
Repräsentierung des FDATools kenne ich nicht, G-Matrix (gain?) auch 
nicht, vermutlich liegt die Lösung in einer korrekten Bedienung des 
tools.

Du hast C drauf, darin kann man integer Filter auch gut simulieren.

Cheers
Detlef

von Eg (Gast)


Lesenswert?

Hallo Detlef,

ich erhalte für den oben genannten Filter von Matlab folgende 
Koeffizienten:

G-Matrix (Gain Faktoren)
G1=0,170467974908347
G2=0,170467974908347
G3=1

SOS-Matrix

Filterkoeffizienten Sektion1
Zähler:      Nenner:
B1=1      A1=1
B2=0      A2=-1,38131865455268
B3=-1                   A3=0,788859239856839

Filterkoeffizienten Sektion2
Zähler      Nenner:
B4=1      A4=1
B5=0      A5=-0,983403466910449
B6=-1        A6=0,734577208191707

Die Nenner Koeffizienten werden alle noch mit -1 multipliziert. Das 
bedeutet dass sich ihr Vorzeichen ändert. Das mit der Skalierung habe 
ich noch nicht ganz verstanden. Soweit ich verstanden habe darf die 
Gesamtverstärkung nicht größer als 1 werden. Falls ja wie kann das 
realisiert werden.

Gruß

von Detlef _. (detlef_a)


Angehängte Dateien:

Lesenswert?

Das Ding ist ein absolut gutmütiger Bandpass, Beträge der Pole sind 
0.888 bzw. 0.857. Wenn die Beträge 0.99 wären könnte das schwierig 
werden, aber die Pole sind Lichtjahre vom Einheitskreis weg.

Frequenzgang.jpg zeigt den Frequenzgang des Filters. Dann habe ich mal 
grob auf 13Bit quantisiert, siehe angehängtes script, freqdiff ist die 
Differenz des quantisierten zum nicht-quantisierten, -60dB Unterschied. 
impulsdiff.jpg ist der Unterschied in den Impulsantworten, alles gut.

Das Ding kannst Du gut in integer rechnen, da oszilliert nix, bei Dir 
steckt noch ein Fehler in der Implementierung.

>>Die Nenner Koeffizienten werden alle noch mit -1 multipliziert.
Nein, A(1) sowieso nicht und wenn die A(2) A(3) das Vorzeichen wechseln 
wirds instabil.

Vllt. liegen Deine Probleme daran?

Cheers
Detlef


clear

%G-Matrix (Gain Faktoren)
G1=0.170467974908347;
G2=0.170467974908347;
G3=1;

fb1=[1 0 -1];
fa1=[1 -1.38131865455268 0.788859239856839];
fb2=[1 0 -1];
fa2=[1 -0.983403466910449 0.734577208191707];
H1=freqz(fb1,fa1);
H2=freqz(fb2,fa2);
H=G1*G2*H1.*H2;
plot(20*log10(abs(H)));

fff=8192;
fb1r=round(fb1*fff)/fff;
fa1r=round(fa1*fff)/fff;
fb2r=round(fb2*fff)/fff;
fa2r=round(fa2*fff)/fff;
H1r=freqz(fb1r,fa1r);
H2r=freqz(fb2r,fa2r);
Hr=G1*G2*H1r.*H2r;
figure(1);
plot(1:length(H),20*log10(abs(H)),'b.-',1:length(Hr),20*log10(abs(Hr)),' 
r.-');
figure(2);
plot(20*log10(abs(H-Hr)))

n=200;
irep=filter(fb1,fa1,[1 zeros(1,n)]);
irep=filter(fb2,fa2,irep);
irepr=filter(fb1r,fa1r,[1 zeros(1,n)]);
irepr=filter(fb2r,fa2r,irepr);
figure(3);
plot(1:length(irep),irep,'b.-',1:length(irepr),irepr,'r.-')
plot(1:length(irep),irep-irepr)

von Eg (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Detlef,

danke für deine Schnelle Antwort. Ich denke auch dass es ein 
Implementierungsfehler sein müsste. Ich habe mich falsch ausgedrückt 
bezüglich des Vorzeichenwechsels. A0 ist in dieser Form immer 1. Im 
Anhang findest du die dazugehörige Filterstruktur einer Sektion. Wie du 
sehen kannst, findet bei  A1 und A2 noch ein Vorzeichenwechsel statt. 
Vielleicht liegt da ja mein Verständnisproblem. Bin gerade dabei mich im 
Bereich der Skalierung der Koeffizienten und Eingangsdaten einzulesen. 
Weiß aber noch nicht genau wie das funktionieren soll. Soweit ich jetzt 
weiß verhindert die Skalierung einen unerwünschten Overflow. Allerdings 
müssen hier gescheite Skalierungsfaktoren gewählt werden. Da ich noch 
ein Anfänger in diesem Bereich bin komm ich nur schleppend voran. 
Deshalb freue ich mich für jeden kleinen Denkansatz.

Gruß

von Detlef _. (detlef_a)


Lesenswert?

>>Vielleicht liegt da ja mein Verständnisproblem.
Ja, für diese Struktur nimmst Du die Koeffs. wie sie sind, nix 
Vorzeichenwechsel. Ist der Klassiker für digitale Filter.

>>Soweit ich jetzt weiß verhindert die Skalierung einen unerwünschten Overflow.
Ja genau. Hängt davon was Dein FPGA nativ kann, vllt. 18x18Bit=36Bit? 
Das würde dicke reichen, das funzt schon für 13Bit Koeffizienten: Du 
skalierst 1=8192, multiplizierst und shiftest dann 13Bit runter. Wenn 
Deine Eingangsweite z.B. 16Bit breit sind benötigst Du 13+16=29 Bit 
Rechendynamik, passt in 36 Bit Rechnung rein (ähm, grob gerechnet, ein 
Bit kommt für Vorzeichen hinzu, ein Koeff. ist  größer 1, nochmal ein 
Bit dazu, aber immer noch genug Dynamik übrig).
Das Filter selber ist unkritisch, das muss gehen.

Cheers
Detlef

von Eg (Gast)


Lesenswert?

>> Hängt davon was Dein FPGA nativ kann, vllt. 18x18Bit=36Bit?

So wie ich weiß besitzt das Board zwölf 18-Bit Multiplizierer. Ich 
verwende einen 12 Bit AD-und DA-Wandler. Somit ist mein 
Eingangswertebereich 2047 bis -2048 (Zweier Komplement). Heißt das, dass 
ich 1 Bit für das Vorzeichen, 11 Bit vor dem Komma und 13 Bit nach dem 
Komma brauche (für alle Koeffizienten und Eingangsvektoren)? Könntest du 
vielleicht die Quantisierung für einen Koeffizienten durchführen dann 
würde ich das besser verstehen.

Gruß

von Detlef _. (detlef_a)


Lesenswert?

>>. Heißt das, dass ich 1 Bit für das Vorzeichen, 11 Bit vor dem Komma
Ja, 12 Bit Wandler, 1 Bit Vorzeichen und 11 Bit Rest, das ist das x(n) 
entsprechend Deinem Strukturbild.

Jetzt rechnest Du für ein SOS zwei Formeln entsprechend Deinem 
Strukturbild:
(I)  d(n)=x(n)-a1*d(n-1)-a2*d(n-2)
(II) y(n)=d(n)-d(n-2) (b0=1,b1=0,b2= -1)

Jetzt zur Dynamik. Bei Quantisierung der Koeffs auf 13 Bit (geht auch 
mehr Bits, nur ein Beispiel):

A2=-1,38131865455268
A2*8192 ~ -11316=a1 (hat 15Bit)
A3=0,788859239856839
A3*8192 ~ 6462=a2 (hat 13 Bit)
G1=0.170467974908347  ~ 1396/8192

Also (in C notation)
(I) d(n)=x(n)-(11316*d(n-1)+6462*d(n-2)) >>13;
(II)y(n)=(1396*(d(n)-d(n-2)))>>13;

Das wäre mal nen erster hack. Das geht vllt. noch bißchen besser, weil 
man in Formel (I) zuviele Bits für 18*18 Bit Multiplizierer wegwirft, 
aber das sollte so erstmal funzen, allerdings ist es schon spät, 
möglichweise ist nen bug drin.

Aber mal probieren, das geht ja in C einfach: integer Rechnung 
implementieren, passband signal reinstecken, das muß rauskommen, 
stopband Siganl muss unterdrückt werden.

Cheers
Detlef

von Eg (Gast)


Lesenswert?

Würde es aber nach dieser Berechnungsmethode nicht zu sehr starken 
Fehlern kommen? Oder habe ich das falsch verstanden? Ich führe mal ein 
einfaches Rechenbeispiel durch. Angenommen meine Eingangsweite wäre 
4-Bit. Das würde heißen, dass der Wertebereich von 7 bis –8 beträgt. Ich 
skaliere auf 1=16
Angenommen ich habe einen Koeffizient der hat den Wert 1.75 und muss nun 
einen Multiplikation mit dem Eingangswert von 2 durchführen.

Binärdarstellung:

1.75=1.1100
+2= 0010

Multiplikation:

0010x1.1100= 0011.1000

Rechtschifft um vier ergibt 0011 und Dezimal 3. Eigentlich ergibt der 
Wert 3.5. Da dieser Wert  bei jeder Rückkopplung in die Berechnung 
eingeht, machen wir doch einen Fehler.

Gruß

von Detlef _. (detlef_a)


Lesenswert?

Yo, so ist das, die Rechnung stimmt. Du zeigst auch lediglich den 
Rundungsfehler: 2*1.75 ~ 3. Der Quantisierungsfehler für die 
Koeffizienten ist bei Deinem Beispiel nicht drin, weil 1.75*16 eine 
ganze Zahl ist, aber z.B. 0.788859239856839*8192 ist keine. Aber keine 
Sorge, das funktioniert schon, das ist keine Hexerei, die Fehler und 
flaws kriegst Du durch genügend Bitbreite kontrolliert.

Cheers
Detlef

von Detlef _. (detlef_a)


Angehängte Dateien:

Lesenswert?

Ich brauchte Spass und habe das erste Teilsystem

G1=0.170467974908347;
fb1=[1 0 -1];
fa1=[1 -1.38131865455268 0.788859239856839];

mal in integer gerechnet, C-Code angehängt.

freq1 und freq2 zeigen Amplitudengang und Phasengang des Systems, mit 
Matlab berechnet. Die Eingangs/Ausgangssignale habe ich mit C berechnet 
und mit Matlab angezeigt.

Bei der Resonanzfrequenz 112/512 ( 1 entspricht Nyquist Frequenz) 
erwarte ich +4dB ~ Faktor 1.6 und 0 Grad Phasenverschiebung, passt, 
siehe Bild freq3

Bei Nyquist/2 erwarte ich ca. -11dB ~ 0.28 und Phasenverschiebung von 
fast -pi, passt, siehe Bild freq4.

Das funzt gut so, mach das so mal aufm FPGA!

Cheers
Detlef

#include <conio.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>


/*******************************************/
int biquad(int i)
/*******************************************/
{
static int32_t q2=0,q1=0;
int32_t r,rr;

#define A1  ((int32_t)((-1.38131865455268*8192)))
#define A2  ((int32_t)((0.788859239856839*8192)))
#define GG  ((int32_t)((0.170467974908347*8192)))

r=i-((A1*q1+A2*q2)>>13);
rr=q2;
q2=q1;
q1=r;
return((GG*(q1-rr))>>13);
}


/****************************************************************/
int main() {
int k=0,m=0,i;
FILE *fo,*fod,*foc;

if((foc=fopen("e:\\interim\\rein.txt","r"))==NULL){
    printf("geht nicht auf \n");return(0);}
if((fod=fopen("e:\\interim\\raus.txt","w"))==NULL){
    printf("geht nicht auf \n");return(0);}
do{
k=fscanf(foc,"%d \n",&i);
if(k==EOF) break;
m++;
//sscanf(c,"%e\n",&t1);
printf("%d %d \n",m,i);
fprintf(fod,"%d\n",biquad(i));
} while(1);

return(1);

}

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.