Sappiamo che in generale la funzione di trasferimento di un filtro è data da:
H(z)=∑Mk=0bkz−k∑Nk=0akz−k
Ora sostituisci z=ejω per valutare la funzione di trasferimento sul cerchio unitario:
H(ejω)=∑Mk=0bke−jωk∑Nk=0ake−jωk
Quindi questo diventa solo un problema di valutazione polinomiale in un dato ω . Ecco i passaggi:
- Crea un vettore di frequenze angolari ω=[0,…,π] per la prima metà dello spettro (non è necessario salire fino a 2π ) e salvalo in
w
.
- Esponente pre-calcolo e−jω in tutti e memorizzarlo in variabile
ze
.
- Utilizzare la
polyval
funzione per calcolare i valori di numeratore e denominatore chiamando polyval(b, ze)
:, dividerli e archiviarli H
. Poiché siamo interessati all'ampiezza, prendiamo il valore assoluto del risultato.
- Converti in scala dB usando: HdB=20log10H - in questo caso 1 è il valore di riferimento.
Inserendo tutto ciò nel codice:
%% 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)
Uscita originale di freqz
:
E l'output del mio script:
E un rapido confronto in scala lineare: sembra fantastico!
[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'})
Ora puoi riscriverlo in qualche funzione e aggiungere alcune condizioni per renderlo più utile.
Un altro modo (precedentemente proposto è più affidabile) sarebbe usare la proprietà fondamentale, che la risposta in frequenza di un filtro è una trasformata di Fourier della sua risposta all'impulso:
H(ω)=F{h(t)}
Pertanto è necessario immettere il segnale del tuo sistema δ(t) , calcolare la risposta del filtro e prenderne il FFT:
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));
In confronto ciò produrrà quanto segue: