4.4 (Diskrete) Faltung - FIR-Filter

4.4.1 Motivation

In der digitalen Signalverarbeitung werden diskrete Signalen verarbeitet. Die in diesem Kapitel behandelte Faltung ist also die digitale (diskrete) Faltung, bei der die Signale aus einzelnen Abtastwerten bestehen.

Als Motivation betrachten wir folgendes Beispiel: Von einem Sensor wird ein Signal aufgenommen, welches stark verrauscht ist. Die Messwerte schwanken, obwohl sich die eigentliche Größe nur langsam ändert.

Verrauschtes Signal

Wie kann man das Rauschen reduzieren und das Signal verbessern?

4.4.2 Grundidee der Faltung

Jedes lineare, zeitinvariante System (LTI-System) lässt sich vollständig durch seine Impulsantwort h[n] beschreiben. Die Impulsantwort ist die Antwort des Systems auf einen einzelnen Impuls (Delta-Funktion), also ein Signal, das an einer Stelle den Wert 1 hat und sonst 0 ist.

Die Faltung ist die Rechenvorschrift, mit der man bestimmt, wie das Eingangssignal x[n] durch die Impulsantwort in das Ausgangssignal y[n] umgewandelt wird.

Anschaulich bedeutet das:

  • Man „schiebt“ die Impulsantwort über das Eingangssignal,
  • multipliziert die überlappenden Werte,
  • und summiert sie auf.

So entsteht Schritt für Schritt das Ausgangssignal.

Alltagsbeispiele (inkl. Demo)

  • Echo: Signal + eine verzögerte Kopie → Impulsantwort hat zwei Peaks (Beispiel: α = 0.6 → Signal plus ein Echo 4 Samples später, etwas leiser)

$$ h = [1, \; 0, \; 0, \; 0, \; \alpha] $$

  • Hall/Reverb: Summe vieler Echos mit abnehmender Stärke → Impulsantwort mit vielen Peaks.

  • Gleitender Mittelwert: Signal wird geglättet → Impulsantwort besteht nur aus gleich großen Werten (siehe Abschnitt 4.4.5).

Damit wird klar: Die Impulsantwort h[n] bestimmt den Charakter des Filters oder Systems.

In der Signalverarbeitung nutzt man Faltung, um Filter zu bauen. Der Filter wird durch die Koeffizienten h bestimmt. Sie ist unabhängig von der Abtastrate und der Zeit sondern eine reine mathematische Operation auf diskreten Werten.

4.4.3 Anwendung der Faltung (Beispiel)

Ein einfaches Beispiel:

  • Eingangssignal (diskret): x = [7, 3, 5, 8, 4]
  • Filterkoeffizienten: h = [1, 3]

Zuerst kann man die Anzahl der Ausgangswerte berechnen:

\[ \text{Anzahl Ausgangswerte} = \text{Anzahl Eingangswerte} + \text{Anzahl Filterkoeffizienten} -1 \]

In unserem Beispiel also: 5 + 2 - 1 = 6 Ausgangswerte.

Im nächsten Schritt wird die Faltung durchgeführt:

n x[n] h[0] h[1] y[n] = x[n]h[0] + x[n-1]h[1]
0 7 1 7 * 1 = 7
1 3 1 3 3 * 1 + 7 * 3 = 24
2 5 1 3 5 * 1 + 3 * 3 = 14
3 8 1 3 8 * 1 + 5 * 3 = 23
4 4 1 3 4 * 1 + 8 * 3 = 28
5 3 4 * 3 = 12

Ergebnis: y = [7, 24, 14, 23, 28, 12]

Mit der Matlab Funktion conv(x, h) kann die Faltung einfach durchgeführt werden.

x = [7,3,5,8,4]; % Eingangssignal
h = [1,3]; % Filterkoeffizienten

out = conv(x,h);
out =    7    24    14    23    28    12

4.4.4 Mathematische Definition

Die diskrete Faltung wird so beschrieben:

\[ y[n] = \sum_{k=0}^{L_h-1} h[k] \cdot x[n-k] \]
  • x[n]: Eingangssignal (Samples)
  • h[k]: Filterkoeffizienten (Impulsantwort)
  • y[n]: Ausgangssignal
  • L_h: Anzahl der Filterkoeffizienten (Länge von h)

Die Koeffizienten h bestimmen also, wie stark die aktuellen und vorherigen Werte ins Ergebnis eingehen.

4.4.5 Beispiel: Gleitender Mittelwert

Ein einfaches Beispiel um Faltung zu zeigen ist ein gleitender Mittelwert-Filter. Er berechnet den Durchschnitt der letzten 'M'-Samples und glättet somit das Signal.

Allgemein gilt:

\[ h=\left[\tfrac{1}{M},\,\tfrac{1}{M},\,\ldots,\,\tfrac{1}{M}\right] \quad \text{(M-mal)} \]

M ist die Anzahl der Filterkoeffizienten (Größe des Fensters). Durch Anpassen von M kann die Glättung verstärkt oder abgeschwächt werden.

Es handelt sich um einen Tiefpass-Filter, der hochfrequente Anteile (Rauschen) reduziert. Die Größe von M wird durch den gewünschten Kompromiss zwischen Glättung und Reaktionszeit bestimmt und hängt vom jeweiligen Anwendungsfall ab.

Beispiel für einen Filter mit drei Filterkoeffizienten (M=3):

\[ h = \left[\tfrac{1}{3},\,\tfrac{1}{3},\,\tfrac{1}{3}\right] \]

Ergebnis:
$$ y[n] = \frac{x[n] + x[n-1] + x[n-2]}{3} $$

Wenn man diesen Filter auf das verrauschte Signal anwendet, erhält man ein geglättetes Signal:

Geglättetes Signal

Das Prinzip der Faltung lässt sich natürlich nicht nur zum Glätten, sondern auch für viele andere Filtertypen anwenden.

4.4.6 Weitere Filter-Beispiele

  • Differenzfilter
    Hebt Änderungen hervor (Kanten-Detektor).
\[ h = [1,\,-1] \]
  • Geglätteter Filter
    Stärkerer Mittelwert, „weicheres“ Glätten (h ist eine Gaußsche Verteilung).
\[ h = [0.25,\,0.5,\,0.25] \]
  • Identität (kein Filter)
    Ausgang = Eingang.
\[ h = [1] \]

Verrauschtes Signal

4.4.7 Unterstützung durch die Hardware/Bibliotheken

Viele Mikrocontroller bieten Hardware-Unterstützung für Faltung-Rechenoperationen an (z.B. DSP-Befehle). Alternativ können Software-Bibliotheken wie CMSIS-DSP genutzt werden, die optimierte Funktionen für Faltung bereitstellen.

DSP (Digital Signal Processing) Prozessoren haben oft spezielle Befehle, die Faltung effizient ausführen können. Diese sind besonders nützlich für Echtzeitanwendungen, bei denen die Rechenleistung begrenzt ist.

In der nächsten Übung wird ein einfachen FIR-Filter (Moving Average) direkt auf dem STM32 implementiert, um die Wirkung zu beobachten.

4.4.8 Umsetzung in der Praxis

Bei diesem Beispiel implementieren wir einen gleitenden Mittelwert-Filter in C auf einem Mikrocontroller.

Der Pseudocode für die Faltung mit einem gleitenden Mittelwert-Filter könnte so aussehen:

#define M 8 // Anzahl der Filterkoeffizienten
uint16_t buffer[M] = {0}; // Ringpuffer für die letzten M Werte
uint32_t sum = 0; // Summe der letzten M Werte
uint8_t idx = 0;  // Index im Ringpuffer

uint16_t moving_average(uint16_t new_val) {
    sum -= buffer[idx];       // Ältesten Wert entfernen
    buffer[idx] = new_val;    // Neuen Wert einfügen
    sum += new_val;           // Neuesten Wert zur Summe hinzufügen
    idx = (idx + 1) % M;      // Index im Ringpuffer aktualisieren
    return sum / M;           // Durchschnitt berechnen
}

// In main loop / ADC callback:
raw = read_adc();
filtered = moving_average(raw);

4.4.9 Verbindung zu FIR-Filtern

Ein Signal kann durch Faltung mit einer Reihe von Koeffizienten \( h[k] \) verändert werden.

Wenn diese Koeffizienten fest vorgegeben sind und die Impulsantwort nach endlich vielen Werten endet, spricht man von einem FIR-Filter (Finite Impulse Response).

Dabei können die Anzahl der Koeffizienten und deren Werte frei gewählt werden, um den gewünschten Filtereffekt zu erzielen.

Ein FIR-Filter berechnet das Ausgangssignal also mit der oben genannten Faltungsformel.

Eigenschaften eines FIR-Filters

  • FIR = „Finite Impulse Response“ → die Impulsantwort (h) hat eine endliche Länge \(L_h\).
  • Der Filter arbeitet nur mit aktuellen und vergangenen Eingangswerten, d.h. keine Rückkopplung.
  • FIR-Filter sind immer stabil, weil die Impulsantwort nach einer endlichen Zeit zu Null wird.
  • Je nach Wahl der Koeffizienten \(h[k]\) kann der Filter sehr unterschiedlich wirken:
Filtertyp Beschreibung Beispiel
Tiefpass Glättet schnelle Änderungen,
reduziert Rauschen
Moving Average

z.B. \(h = [ \tfrac{1}{3}, \tfrac{1}{3}, \tfrac{1}{3} ]\)
Hochpass Hebt schnelle Änderungen hervor,
reagiert stark auf Sprünge
Differenzfilter

z.B. \(h = [ 1, -1 ]\)
Bandpass Lässt nur einen bestimmten
Frequenzbereich durch
Kombination aus Tief- und Hochpass

z.B. \(h = [ 1, 0, -1 ]\)
Identität Gibt das Signal unverändert weiter \(h = [1]\)