Lab 05 - Projektowanie filtrow IIR
Projektowanie filtrów IIR
Wstęp
Filtry IIR (Infinite Impulse Response)
Jest to klasa filtrów rekursywnych, czyli posiadających sprzężeń zwrotnych. Oznacza to że odpowiedź filtru wyznaczana jest jako kombinacja liniowa pewnej ilości próbek sygnału wejściowego i wyjściowego. Transmitancja ma postać: \[ H(z)=\frac{a_{0}+a_{1} z^{-1}+\ldots+a_{p} z^{-p}}{1+\left(b_{1} z^{-1}+\ldots+b_{q} z^{-q}\right)} \] a zapis równania różnicowego: \[ y(n) = a_{0} x(n)+a_{1} x(n-1)+\ldots+a_{p} x(n-p) - b_{1} y(n-1)+\ldots+b_{p} y(n-p) \] gdzie \(x(n)\) jest sygnałem wejściowym, \(y(n)\) sygnałem wyjściowym.
Typy filtrów
Zazwyczaj do projektowania filtrów IIR używa się tzw. prototypów określających strukturę filtra determinującą jego parametry w paśmie przepustowym i zaporowym, a następnie prototyp dostosowuje się do wymagań projektowych (tłumienia, zafalowań w paśmie przepustowym, stomości pasma przejściowego, typu filtra (DP, Gp, PP, PZ) Najczęściej używanymi prototypami są prototyp Butterwortha, Czebyszewa I i II rodzaju oraz filtr eliptyczny, Bessela. Prototypy te mają różne właściwości, więcej na ich temat możesz znaleźć w materiałach z wykładu. Poniżej zebrano tylko najważniejsze cechy:
paśmo przepustowe | pasmo zaporowe | stromość | nieliniowość charakterystyki | |
---|---|---|---|---|
Butterowth | ch. monotoniczna | ch. monotoniczna | N*6dB/oct | najbardziej liniowa spośród filtrów IIR |
Chebyszew I | ch. niemonotoniczna | ch. monotoniczna | lepsza niż Butterwortha | silniejsza niż Czebyszewa II |
Czebyszew II | ch. monotoniczna | ch. niemonotoniczna | lepsza niż Butterwortha | silniejsza niż Butterwortha |
Eliptyczny | ch. niemonotoniczna | ch. niemonotoniczna | lepsza niż Czebyszewa | Dużo silniejsza niż Czebyszewa II |
Metody projektowania filtrów
Poniżej przedstawiono procedurę projektowania filtrów: 1. Przeanalizowanie wymagań częstotliwościowych stawianych filtrowi i wybór odpowiedniego rodzaju filtra prototypowego i wybór odpowiedniego filtra prototypowego (Butterowtha, Czebyszewa typu I, czebyszewa typu II, eliptycznego) 2. Przeliczenie wymagań projektowych, stawianych filtrowi na rząd filtra 3. Zaprojektowanie transmitancji filtra 4. Sprawdzenie właściwości zaprojektowanego układu.
W Pythonie do oszacowaniu rzędu filtra i zaprojektowania transmitancji można wykorzystać następujące funkcje:
parametry projektowe | wyznaczenie rzędu | wyznaczenie transmitancji | |
---|---|---|---|
Butterowth | N, fn | N, fn = signal.buttord(fp, fz, Rp, Rs, fs=fs) | b, a = signal.butter(N, fn, btype=‘low’, fs=fs) |
Chebyszew I | N, Rp, fn | N, fn = signal.cheb1ord(fp, fz, Rp, Rs, fs=fs) | b, a = signal.cheby1(N, Rp, fn, btype=‘low’, fs=fs) |
Czebyszew II | N, Rp, fn | N, fn = signal.cheb2ord(fp, fz, Rp, Rs, fs=fs) | b, a = signal.cheby2(N, Rp, fn, btype=‘low’, fs=fs) |
Eliptyczny | N, Rp,Rs, fn - rząd filtra | N,fn = signal.ellipord(fp, fz, Rp, Rs, fs=fs) | b, a = signal.ellip(N, Rp,Rs, fn, btype=‘low’, fs=fs) |
Parametry projektowe: - fp - częstotliwość graniczna pasam przepustowego - fz - częstotliwość graniczna pasam zaporowego - Rp - minimalne wzmocnienie w paśmie zaporowym w [dB] - wyrażone jako 20log(1-max(rp)) - Rs - tłumienie w paśmie przepustowym i zaporowym - fs - częstotliwość próbkowania - N - rząd filtra - btype={‘lowpass’, ‘highpass’, ‘bandpass’, ‘bandstop’} - fn - czestotliwość tłumienia -3dB
import numpy as np
import scipy.signal as signal
import matplotlib
import matplotlib.pyplot as plt
= 3000
fc = 4500
fz = 1
rp = 60
rs = 8
N def plot_response(w, hf, hfb=None, label=''):
= plt.subplots(tight_layout=True)
fig, ax 3000, lw=1, ls=(0, (10, 5)), c='k')
ax.axvline(if hfb is not None:
='#c0c0c0', label='Butterworth')
ax.plot(w, hfb, c=label)
ax.plot(w, hf, label
ax.grid()
ax.legend()0, 12000)
ax.set_xlim(-120, 5)
ax.set_ylim('Częstotliwość [Hz]')
ax.set_xlabel('Wzmocnienie [dB]')
ax.set_ylabel(# ax.set_title('Charakterystyka częstotliwościowa filtru IIR')
return ax
# filtr Butterwortha
= 3000 # fpass [Hz]
fp = 4500 # fstop [Hz]
fz = 1 # -1dB w paśmie przepustowym
Rp = 60 # -60db w paśmie zaporowym
Rs = 48000 # częstotliwość próbkowania
fs
= signal.buttord(fp, fz, Rp, Rs, fs=fs)
N, fn = signal.butter(N, fn, 'low', fs=fs)
bb, ab = signal.freqz(bb, ab, 2048, fs=fs)
wb, hb = 20 * np.log10(np.abs(hb))
hbd
# filtr Czebyszewa I
= signal.cheb1ord(fp, fz, Rp, Rs, fs=fs)
N, fn = signal.cheby1(N, Rp, fn, 'low', fs=fs)
bc1, ac1 = signal.freqz(bc1, ac1, 2048, fs=fs)
wc1, hc1 = 20 * np.log10(np.abs(hc1))
hc1d
# filtr Czebyszewa II
= signal.cheb2ord(fp, fz, Rp, Rs, fs=fs)
N, fn = signal.cheby2(N, Rs, fn, 'low', fs=fs)
bc2, ac2 = signal.freqz(bc2, ac2, 2048, fs=fs)
wc2, hc2 = 20 * np.log10(np.abs(hc2))
hc2d
# filtr Eliptyczny
= signal.ellipord(fp, fz, Rp, Rs, fs=fs)
N, fn = signal.ellip(N, Rp,Rs, fn, 'low', fs=fs)
be, ae = signal.freqz(be, ae, 2048, fs=fs)
we, he = 20 * np.log10(np.abs(he))
hed
# wszystko razem
= plot_response(wb, hbd, None, 'Butterworth')
ax ='Czebyszew I')
ax.plot(wc1, hc1d, label='Czebyszew II')
ax.plot(wc2, hc2d, label='Eliptyczny')
ax.plot(we, hed, label ax.legend()
Opóźnienie grupowe
Każdy filtr wprowadza opóźnienie sygnału - mierzone jako przysunięcie fazowe, lub opóźnienie grupowe, które jest zależne m.in od rzędu oraz typu filtra
# charakterystyka fazowa
= plt.subplots(2, 2, tight_layout=True, figsize=(8, 6))
fig, ax for a in ax.ravel():
3000, lw=1, ls=(0, (10, 5)), c='k')
a.axvline(
a.grid()0, 8000)
a.set_xlim(-180, 180)
a.set_ylim(0][0].plot(wb, np.degrees(np.angle(hb)))
ax[0][0].set_title('Butterworth')
ax[0][1].plot(wc1, np.degrees(np.angle(hc1)))
ax[0][1].set_title('Czebyszew I')
ax[1][0].plot(wc2, np.degrees(np.angle(hc2)))
ax[1][0].set_title('Czebyszew II')
ax[1][1].plot(we, np.degrees(np.angle(he)))
ax[1][1].set_title('Eliptyczny')
ax[for a in ax[1]:
'Częstotliwość [Hz]')
a.set_xlabel(for a in (ax[0][0], ax[1][0]):
'Faza [°]')
a.set_ylabel(
# opóźnienie grupowe
= plt.subplots(2, 2, tight_layout=True, figsize=(8, 6))
fig, ax for a in ax.ravel():
3000, lw=1, ls=(0, (10, 5)), c='k')
a.axvline(
a.grid()0, 8000)
a.set_xlim(0][0].plot(*signal.group_delay((bb, ab), 2048, fs=fs))
ax[0][0].set_title('Butterworth')
ax[0][1].plot(*signal.group_delay((bc1, ac1), 2048, fs=fs))
ax[0][1].set_title('Czebyszew I')
ax[1][0].plot(*signal.group_delay((bc2, ac2), 2048, fs=fs))
ax[1][0].set_title('Czebyszew II')
ax[1][1].plot(*signal.group_delay((be, ae), 2048, fs=fs))
ax[1][1].set_title('Eliptyczny')
ax[for a in ax[1]:
'Częstotliwość [Hz]')
a.set_xlabel(for a in (ax[0][0], ax[1][0]):
'Opóźnienie [próbki]')
a.set_ylabel(
plt.show()
Filtracja i filtracja zerofazowa
Opóźnienie grupowe może być obserwowane w sygnale po filtracji:
### filtracja sygnału
= np.arange(500)
t = np.sin(2 * np.pi * t * 500 / fs)
x1 = np.sin(2 * np.pi * t * 2500 / fs) * 0.5
x2 = x1 + x2
x # sygnały po filtracji
= signal.lfilter(be, ae, x1)
y1 = signal.lfilter(be, ae, x2)
y2 = signal.lfilter(be, ae, x)
y
= plt.subplots(2, figsize=(8, 6), tight_layout=True)
fig, ax 0].plot(x1)
ax[0].plot(y1)
ax[1].plot(x2)
ax[1].plot(y2)
ax[for aa in ax:
aa.grid()'Amplituda')
aa.set_ylabel(1].set_xlabel('Nr próbki')
ax[0].set_title('Sygnał 500Hz przed i po filtracji')
ax[1].set_title('Sygnał 2500Hz przed i po filtracji') ax[
jeśli sygnał zostanie przefiltrowany dwukrotnie (od początku i od końca), wtedy opóźnienie grupowe (przesunięcie fazowe) jest równe zero.
# filtracja zerofazowa
= signal.filtfilt(be, ae, x)
y2
= plt.subplots(2, figsize=(8, 6), tight_layout=True)
fig, ax 0].plot(x)
ax[0].plot(y)
ax[1].plot(x)
ax[1].plot(y2)
ax[for aa in ax:
aa.grid()'Amplituda')
aa.set_ylabel(1].set_xlabel('Nr próbki')
ax[0].set_title('Sygnał przed i po filtracji')
ax[1].set_title('Sygnał przed i po filtracji zerofazowej') ax[
Stabilność filtrów IIR
W przypadku stosowania filtrów wyższych rzędów, filtry IIR mogą być niestabilne z uwagi kumulowanie się błędów numerycznych, w wyniku których realne wartości biegunów będą leżały poza okręgiem jednostkowym. W związku z tym należy je reprezentować jako kaskade filtrów rzędu 2 (SOS).
= 48000
fs
= np.zeros(200, dtype=np.float64)
x 0] = 1
x[
# filtr DP 3 kHz eliptyczny, rzędu 20
= signal.ellip(20, 1, 60, 3000, btype='low', fs=fs)
b, a
= signal.lfilter(b, a, x)
y1 = plt.subplots(2, tight_layout=True, figsize=(8, 6))
fig, ax 0].plot(y1)
ax[
= signal.tf2zpk(b, a)
z, p, k print(np.max(np.abs(p)))
# filtr SOS
= signal.ellip(20, 1, 60, 3000, btype='low', fs=fs, output='sos')
sos = signal.sosfilt(sos, x)
y2
= ax[1].plot(y2)
stem plt.show()
Zadania
Dla sygnału fs=48kHz, zaprojektuj 4 filtry Czebyszewa 1 rzędu 4: górno przepustowy (fp=3kHz), dolno-przepustowy (fp=3kHz), pasmowo przepustowy (1-3kHz), pasmowo zaporowy (1-3kHz), gdzie tłumienie w paśmie przepustowym nie jest większe niż 1dB. Wyświetl charakterystyki fazowe oraz odpowiedzi impulsowe.
Zakładając, że \(f_s\)=500Hz, a okres obseracji wynosi T=20s przygotować wektor sygnału testowego o postaci:
\[ x(t)=sin(3\cdot 2\pi\cdot t)+cos(10\cdot 2\pi\cdot t)+cos(25\cdot 2\pi\cdot t)+sin(35\cdot 2\pi\cdot t)+sin(50\cdot 2\pi\cdot t)+sin(100\cdot 2\pi\cdot t) \]
Zaprojektować filtr dolnoprzepustowy rekursywny Czebyszewa II, który umożliwi stłumienie składowych 50 i 100Hz. Przyjąć, że tłumienie w paśmie zaporowym nie powinno być mniejsze niż 55dB, zaś oscylacje w paśmie przepustowym nie powinny przekraczać 0.1%. Szerokość pasma przejściowego ustalić na 5Hz. Po zaprojektowaniu przefiltruj sygnał i wyznacz opóźnienie filtra dla składowych w paśmie przepustowym.
Zaprojektuj filtr Eliptyczny pasmowo-zaporowy dla składowej 25Hz, załóż, że pasmo zaporowe ma szerokość 1Hz, a pasmo przejściowe szerokośc taką jak w pkt 3. Określ jakie jest efektywne tłumienie składowej 25Hz sygnału oraz czas ustalania odpowiedzi (pamiętaj, żeby sygnał miał długość min 20s).
Dokonaj porównania zachowania filtra z zadania 4 z filtrem pasmowo-zaporowym z FIR z zadania 6 z lab nr 3?
- Czy czas ustalania się odpowiedzi tego filtra jest dłuższy niż filtra IIR?
- Czy czas pojawienia się odpowiedzi tego filtra jest dłuższy niż filtra IIR? (jako czas pojawienia się odpowiedzi dla filtra FIR przyjmij moment pojawienia się sygnału na wyjściu)
- Dla ktorego z filtrów opóźnienie fazowe składowej 25Hz jest większe?
Określ jaka jest minimalna szerokość pasma przejściowego filtra 25Hz z zad 4 w wersji ze współczynnikami wielomianu transmitancji (nie w wersji SOS), która spowoduje, że przy wymuszeniu składową 25Hz odpowiedź będzie dążyła do nieskończoności, obserwacje prowadż w czasie 100s
Autorzy: Piotr Kaczmarek