Sabemos que, en general, la función de transferencia de un filtro viene dada por:
H(z)=∑Mk=0bkz−k∑Nk=0akz−k
Ahora sustituya para evaluar la función de transferencia en el círculo unitario:z=ejω
H(ejω)=∑Mk=0bke−jωk∑Nk=0ake−jω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 .e−jω
ze
- Use la
polyval
funció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
:
Y la salida de mi script:
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'})
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:
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) enfreqz
. ¿Están los dos filtros adentrohfilt
? O uno adentron
?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.
considere esta identidad trigonométrica:
que tiene una respuesta de frecuencia compleja
que tiene magnitud al cuadrado:
usando la identidad trigonométrica anterior, obtienes una magnitud al cuadrado:
whereϕ≜sin2(ω2)
if your gear is intending to plot this as dB, it comes out as
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.
fuente