¿Cómo graficar manualmente la respuesta de frecuencia de un filtro Butterworth de paso de banda en MATLAB sin la función freqz?

15

Tengo el siguiente código que aplica un filtro de paso de banda a una señal. Soy un novato en DSP y quiero entender lo que está sucediendo detrás de escena antes de continuar.

Para hacer esto, quiero saber cómo trazar la respuesta de frecuencia del filtro sin usar freqz.

[b, a] = butter(order, [flo fhi]);
filtered_signal = filter(b, a, unfiltered_signal)

Dados los resultados, [b, a]¿cómo haría esto? Parece que sería una tarea simple, pero me cuesta encontrar lo que necesito en la documentación o en línea.

También me gustaría entender cómo hacer esto lo más rápido posible, por ejemplo, usando un fftu otro algoritmo rápido.

William
fuente

Respuestas:

25

Sabemos que, en general, la función de transferencia de un filtro viene dada por:

H(z)=k=0Mbkzkk=0Nakzk

Ahora sustituya para evaluar la función de transferencia en el círculo unitario:z=ejω

H(ejω)=k=0Mbkejωkk=0Nakejωk

Por lo tanto, esto se convierte solo en un problema de evaluación polinómica en un determinado . Aquí están los pasos:ω

  • Cree un vector de frecuencias angulares para la primera mitad del espectro (no es necesario subir a ) y guárdelo .ω=[0,,π]2πw
  • Pre-calcular el exponente en todos ellos y almacenarlo en variable .ejωze
  • Use la polyvalfunción para calcular los valores de numerador y denominador llamando: polyval(b, ze)dividirlos y almacenarlos H. Como estamos interesados ​​en la amplitud, tomemos el valor absoluto del resultado.
  • Convierta a escala dB utilizando: - en este caso es el valor de referencia.HdB=20log10H1

Poniendo todo eso en el código:

%% Filter definition
a = [1 -0.5 -0.25]; % Some filter with lot's of static gain
b = [1 3 2];

%% My freqz calculation
N = 1024; % Number of points to evaluate at
upp = pi; % Evaluate only up to fs/2
% Create the vector of angular frequencies at one more point.
% After that remove the last element (Nyquist frequency)
w = linspace(0, pi, N+1); 
w(end) = [];
ze = exp(-1j*w); % Pre-compute exponent
H = polyval(b, ze)./polyval(a, ze); % Evaluate transfer function and take the amplitude
Ha = abs(H);
Hdb  = 20*log10(Ha); % Convert to dB scale
wn   = w/pi;
% Plot and set axis limits
xlim = ([0 1]);
plot(wn, Hdb)
grid on

%% MATLAB freqz
figure
freqz(b,a)

Salida original de freqz:

ingrese la descripción de la imagen aquí

Y la salida de mi script:

ingrese la descripción de la imagen aquí

Y una comparación rápida en escala lineal: ¡se ve genial!

[h_f, w_f] = freqz(b,a);
figure
xlim = ([0 1]);
plot(w, Ha) % mine
grid on
hold on
plot(w_f, abs(h_f), '--r') % MATLAB
legend({'my freqz','MATLAB freqz'})

ingrese la descripción de la imagen aquí

Ahora puede reescribirlo en alguna función y agregar algunas condiciones para que sea más útil.


Otra forma (propuesta anteriormente es más confiable) sería usar la propiedad fundamental, que la respuesta de frecuencia de un filtro es una Transformada de Fourier de su respuesta de impulso:

H(ω)=F{h(t)}

Por lo tanto, debe alimentar la señal δ(t) su sistema , calcular la respuesta de su filtro y tomar la FFT de la misma:

d = [zeros(1,length(w_f)) 1 zeros(1,length(w_f)-1)];
h = filter(b, a, d);
HH = abs(fft(h));
HH = HH(1:length(w_f));

En comparación, esto producirá lo siguiente:

enter image description here

jojek
fuente
1
Explicación detallada
partida
Estoy pensando en esta línea a = [1 -0.5 -0.25]; % Some filter with lot's of static gain. ¿Puede explicarme la selección de estos parámetros aquí, por favor? Estoy leyendo el manual de mi Matlab y dice [h,w] = freqz(hfilt,n)en una parte de la sinapsis. Estás dando dos filtros (a, b) en freqz. ¿Están los dos filtros adentro hfilt? O uno adentro n?
Léo Léopold Hertz 준영
Solo para aclarar a los demás: "No es necesario subir hasta 2 pi" es cuando los coeficientes son reales. Hay aplicaciones para filtros con coeficientes complejos y en ese caso el espectro ya no será simétrico y en ese caso querría extender la frecuencia a 2 pi.
Dan Boschen
14

esto es solo un apéndice a la respuesta de jojek que es más general y perfectamente bueno cuando se usa matemática de doble precisión. cuando hay menos precisión, hay un "problema de coseno" que surge cuando la frecuencia en la respuesta de frecuencia es muy baja (mucho más baja que Nyquist) y también cuando las frecuencias resonantes del filtro son muy bajas.

|H(ejω)|2|H(ejω)|=|H(ejω)|

considere esta identidad trigonométrica:

cos(ω) = 12sin2(ω2)

sin2(ω2)ω0

sin2(ω2)

H(z)=b0+b1z1+b2z2a0+a1z1+a2z2

que tiene una respuesta de frecuencia compleja

H(ejω)=b0+b1ejω+b2ej2ωa0+a1ejω+a2ej2ω

que tiene magnitud al cuadrado:

|H(ejω)|2=|b0+b1ejω+b2ej2ω|2|a0+a1ejω+a2ej2ω|2=(b0+b1cos(ω)+b2cos(2ω))2+(b1sin(ω)+b2sin(2ω))2(a0+a1cos(ω)+a2cos(2ω))2+(a1sin(ω)+a2sin(2ω))2=b02+b12+b22+2b1(b0+b2)cos(ω)+2b0b2cos(2ω)a02+a12+a22+2a1(a0+a2)cos(ω)+2a0a2cos(2ω)

|H(ejω)|cos(ω)cos(2ω)ω11

usando la identidad trigonométrica anterior, obtienes una magnitud al cuadrado:

|H(ejω)|2=b02+b12+b22+2b1(b0+b2)cos(ω)+2b0b2cos(2ω)a02+a12+a22+2a1(a0+a2)cos(ω)+2a0a2cos(2ω)=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(12sin2(ω))a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(12sin2(ω))=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(2cos2(ω)1)a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(2cos2(ω)1)=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(2(12sin2(ω2))21)a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(2(12sin2(ω2))21)=b02+b12+b22+2b1(b0+b2)(12ϕ)+2b0b2(2(12ϕ)21)a02+a12+a22+2a1(a0+a2)(12ϕ)+2a0a2(2(12ϕ)21)=b02+b12+b22+2b1(b0+b2)(12ϕ)+2b0b2(18ϕ+8ϕ2)a02+a12+a22+2a1(a0+a2)(12ϕ)+2a0a2(18ϕ+8ϕ2)=b02+b12+b22+2b1b0+2b1b24(b1b0+b1b2)ϕ+2b0b216b0b2ϕ+16b0b2ϕ2a02+a12+a22+2a1a0+2a1a24(a1a0+a1a2)ϕ+2a0a216a0a2ϕ+16a0a2ϕ2=(b02+b12+b22+2b1b0+2b1b2+2b0b2)4(b1b0+b1b24b0b2)ϕ+16b0b2ϕ2(a02+a12+a22+2a1a0+2a1a2+2a0a2)4(a1a0+a1a24a0a2)ϕ+16a0a2ϕ2=14(b02+b12+b22+2b1b0+2b1b2+2b0b2)(b1b0+b1b24b0b2)ϕ+4b0b2ϕ214(a02+a12+a22+2a1a0+2a1a2+2a0a2)(a1a0+a1a24a0a2)ϕ+4a0a2ϕ2=(b0+b1+b22)2ϕ(4b0b2(1ϕ)+b1(b0+b2))(a0+a1+a22)2ϕ(4a0a2(1ϕ)+a1(a0+a2))

where ϕsin2(ω2)

if your gear is intending to plot this as dB, it comes out as

20log10|H(ejω)| = 10log10((b0+b1+b22)2ϕ(4b0b2(1ϕ)+b1(b0+b2)))10log10((a0+a1+a22)2ϕ(4a0a2(1ϕ)+a1(a0+a2)))

so your division turns into subtraction, but you have to be able to compute logarithms to some base or another. numerically, you will have much less trouble with this for low frequencies than doing it the apparent way.

robert bristow-johnson
fuente
2
That's really cool, thank you Robert! +1
jojek
@Robert I "believe" similar to my comment for Jojek above that this only applies as well when the coefficients are real (and therefore the spectrum is symmetric and thus the magnitude converts to cosines as you show)... Am I correct?
Dan Boschen
yes. that commitment is made when you go from the first line of |H(ejω)|2=... to the second line. no going back after that.
robert bristow-johnson