mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP FIR Low-, High-, Bandpass und Bandstop Filtern


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Vili V. (villamosvili)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,


kann mir jemand erleuchten, was der Unterschied auf 
Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass, 
Bandpass und Bandstop Filtern ist?

Ich habe mir paar Beispielimplementierungen bezüglich FIR Filter 
gesucht, leider die Beispiele, die ich gefunden habe, waren für FIR 
low-pass Filter.

Der Unterschied ist mir zwischen den einzelnen Filtertypen klar. Auf 
Implementierungsebene blicke ich aber noch nicht.

Autor: Carl (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
>kann mir jemand erleuchten, was der Unterschied auf
>Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass,
>Bandpass und Bandstop Filtern ist?

Die Filterkoeffizienten sind unterschiedlich, die Implementierung 
gleich.

Autor: Vili V. (villamosvili)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carl schrieb:
>>kann mir jemand erleuchten, was der Unterschied auf
>>Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass,
>>Bandpass und Bandstop Filtern ist?
>
> Die Filterkoeffizienten sind unterschiedlich, die Implementierung
> gleich.

Heißt es, dass die unterschiedlichen Filtertypen mit der unteren 
Funktion realisierbar sind? Beim Aufruf der Funktion muss man ja aber 
auf die richtige Parametrisierung achten, sprich Filterkoeffizienten und 
Delay Elementen.
void fir(input_buffer, *output_buffer, coeff, delay)
{
  y[n] = x[n] * h[n]
}

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vili V. schrieb:
> Heißt es, dass die unterschiedlichen Filtertypen mit der unteren
> Funktion realisierbar sind?

Mit genau dieser Funktion nicht. Denn die multipliziert nur ein Element 
von Array x mit einem Element von Array h und speichert das Ergebnis in 
Element y. Dein "coeff" wird dabei z.B. ignoriert.

Der Name der Funktion lautet zwar fir, aber sie implementiert keinen 
FIR-Filter. Hättest du eine funktionierende FIR-Funktion, dann würde 
gelten, was Carl geschrieben hat.

Autor: Dergute W. (derguteweka)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Moin,

Es ist, wie schon die Vorschreiber schruben, eine reine Frage der 
Koeffizienten; die Berechnung selbst bleibt immer gleich.
Man kann z.B. ein Hoch/Tiefpasspaeaerchen basteln, das sich nur in einem 
einzigen Koeffizienten unterscheidet. Das spart Rechnerei, wenn man 
beide Filterergebnisse braucht. "s" ist ein Zwischenergebnis, das ist 
fuer Hochpass und Tiefpass gleich; der Unterschied entsteht erst durch 
Addition bzw. Subtraktion des gewichteten buf[7]:
s = (f->buf[ 0]+f->buf[14])*(-3) +
    (f->buf[ 2]+f->buf[12])*  9  -
    (f->buf[ 4]+f->buf[10])* 22  +
    (f->buf[ 6]+f->buf[ 8])* 80;

    lp=(s+f->buf[7]*128)/256;

    hp=(s-f->buf[7]*128)/256;

Das ganze Ding gibts hier:
Beitrag ""LED-Spectrumanalyzer"software ohne Fouriertransformation"

Gruss
WK

Autor: Robert K. (Firma: Medizintechnik) (robident)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carl schrieb:
> Die Filterkoeffizienten sind unterschiedlich, die Implementierung
> gleich.

Aber nicht, was C und C++ angeht. Stichwort Koeffizientenidentität und 
Koheränz. Man kann in C++ Filter mit optimierten Koeffizienten geschickt 
und auch sehr ungeschickt auf mehrere threads verteilen.

Autor: Robert K. (Firma: Medizintechnik) (robident)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> eine reine Frage der
> Koeffizienten;

Warum verwendest du nur jeden zweiten Wert? Sind die Koeffs dazwischen 
Null?

Autor: Dergute W. (derguteweka)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

Robert K. schrieb:
> Sind die Koeffs dazwischen
> Null?

Jepp. Multiplikationen mit Null wirken angenehm performancesteigernd.

Gruss
WK

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vili V. schrieb:
> kann mir jemand erleuchten, was der Unterschied auf
> Implementierungsebene in C/C++ zwischen FIR Low-Pass, High-Pass,
> Bandpass und Bandstop Filtern ist?

Was hat ein FIR Filter mit C/C++ zu tun? Ich verstehe deinen Begriff 
"Implementierungsebene" nicht.

Also, was ein FIR-Filter ist, weißt du hoffentlich: es ist ein Filter, 
das nur die letzten n Samples berücksichtigt und keinerlei Rückführung 
eines Ergebnisses enthält. Filter, die letzteres tun, heißen IIR.

Was ein Lowpaß oder Highpaß oder Bandpass oder Bandsperre ist, weißt du 
hoffentlich auch.

Bleiben also nur noch die zwei Fragen:
a. Wie konstruiert man eines der genannten Filter?
b. Wie schreibt man das in der Programmiersprache deiner Wahl?

Vili V. schrieb:
> leider die Beispiele, die ich gefunden habe, waren für FIR
> low-pass Filter.

Das ist doch OK so. Damit hast du eigentlich alles, was du brauchst, 
denn:

1. einen Lowpaß kannst du damit schon mal selber berechnen. Vergiß aber 
das Normieren nicht, also alle Koeffizienten so skalieren, daß die 
Verstärkung des Filters = 1 ist.

2. aus dem Wissen, daß die Differenz des Eingangssignales zum 
Ausgangssignal des Lowpasses gleich ein Highpass ist, weißt du nun 
schon, wie man einen Highpass macht: für alle Koeffizienten Vorzeichen 
umdrehen, zum in der Mitte befindlichen Koeffizienten 1 addieren.

Hinweis dazu: So ein Filter macht man am besten mit einer ungeraden 
Anzahl von Taps, damit man genau ein Sample exakt in der Mitte hat. 
Das ist für das Filter (so es denn symmetrisch ist) das aktuelle Sample. 
Jaja, du speist neue Samples bei n/2 in der Zukunft ein, dann wandern 
sie durch das Filter, kommen am Zeitpunkt 0 vorbei und verschwinden bei 
-n/2 auf Nimmerwiedersehen in der Vergangenheit.

3. Durchlaßbereiche, die sich nicht überlappen, kann man zusammenfassen, 
also einen Tiefpaß für 100 Hz kann man zu einem Hochpaß für 3 kHz 
addieren, heraus kommt eine Bandsperre von 100 Hz bis 3 kHz.

Damit weißt du jetzt auch, wie man eine Bandsperre schreibt. Und wenn du 
Punkt 2 erinnerst, dann weißt du auch, wie man daraus einen Bandpaß 
macht.

Und was du für eine Fensterfunktion benutzt, ist deine Entscheidung. 
Kaiser ist - wenn man's recht betrachtet - auch nicht wesentlich 
aufwendiger als Blackman.

Also, wo ist dein Problem?

W.S.

Autor: Jürgen S. (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> Jepp. Multiplikationen mit Null wirken angenehm performancesteigernd.

... führen aber auch zu einer pauschalen Unterdrückung von Frequenzen im 
Signal und damit Verwurf von Information. Bei bestimmten Anwendungen wie 
der Mustererkennung führt dies zu einer schlechteren Trennung von 
gewollten und ungewollten Signalanteilen und verringerten 
Unterscheidbarkeit.

Auch das hier:

W.S. schrieb:
> 2. aus dem Wissen, daß die Differenz des Eingangssignales zum
> Ausgangssignal des Lowpasses gleich ein Highpass ist, weißt du nun
> schon, wie man einen Highpass macht:

klappt dann nicht so gut.

Autor: Bernd (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> s = (f->buf[ 0]+f->buf[14])*(-3) +
>     (f->buf[ 2]+f->buf[12])*  9  -
>     (f->buf[ 4]+f->buf[10])* 22  +
>     (f->buf[ 6]+f->buf[ 8])* 80;
>
>     lp=(s+f->buf[7]*128)/256;
>
>     hp=(s-f->buf[7]*128)/256;
Sehr schön!

Wie kommt man auf diese Koeffizienten?
So hier?: https://www.dsprelated.com/showarticle/1113.php

Autor: Dergute W. (derguteweka)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

Jürgen S. schrieb:
> Bei bestimmten Anwendungen wie
> der Mustererkennung führt dies zu einer schlechteren Trennung von
> gewollten und ungewollten Signalanteilen und verringerten
> Unterscheidbarkeit.

Jepp. Und bei bestimmen Anwendungen wie frequenzabhaengigem LED-Geblinke 
fuehrt dies dazu, dass man die gesamte digitale Signalverarbeitung 
locker in Echtzeit auf einem Atmega hinkriegt - mit einer 
Filtersteilheit, die den Anhaengern von analogen Bandfiltern in 
Kleinserie das Pipi in die Augen treibt.
Also Augen auf bei der Filterauswahl :-)

Bernd schrieb:
> Wie kommt man auf diese Koeffizienten?

Jepp, z.B. so wie in deinem Link oder z.B. so:
round(-256*firls(14,[0 0.38 0.62 1],[1 1 0 0]))
mit ein bisschen Rumprobieren an den Filtergrenzen, so dass das 
resultierende Filter trotz Rundungsfehlern auf 8 bit Koeffizienten nicht 
zu gruselig wird.

Gruss
WK

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.