Você está na página 1de 17

Universidade de São Paulo

Escola Politécnica

Experiencia 3: Projeto de filtros


IIR de Butterworth
PSI-3431 – Processamento Estatístico de Sinais

Ellen Laureto Barbosa


9378933

São Paulo
2020
Sumário
1. Função analogButter ______________________________ 3
2. Utilização da função analogButter ___________________ 3
3. Filtragem do sinal ________________________________ 5
4. Verificação do resultado com funções já prontas ______ 7
5. Filtragem pelo critério min-max _____________________ 9
6. Código em Julia 1.4.0 ____________________________ 11
7. Conclusão _____________________________________ 17

2
1. Função analogButter
Como pedido na primeira parte foi criada uma função analogButter em
Julia 1.4.0, a função tem como entrada 𝛿𝑟 , 𝛿𝑝 , Ὢ𝑟 𝑒 Ὢ𝑝 .

A primeira coisa que a função faz é normalizar as frequências de corte e


passagem Ὢ𝑟 𝑒 Ὢ𝑝 onde , Ὢ𝑝𝑛 = 1 e , Ὢ𝑟𝑛 = Ὢ𝑟 ⁄ Ὢ𝑝

Sendo assim se calcula os deltas de atenuação:


√2 ∗ 𝛿𝑝 − 𝛿𝑝 2 √1 − 𝛿𝑟 2
∆1 = 𝑒 ∆2 =
1 − 𝛿𝑝 𝛿𝑟
Tendo os deltas se calcula o N e C.

∆2
𝑙𝑛(∆1) ∆1 ∆2
𝑁≥ 𝑒 ≤C≤
𝑙𝑛(Ὢ𝑟𝑛 ) Ὢ𝑝𝑛 𝑁 Ὢ𝑟𝑛 𝑁
Sendo assim, N foi escolhido como sendo o menor valor inteiro dentro
deste intervalo e C a média do limite inferior e superior do intervalo
dado.
Com N e C calculados pode-se calcular os polos, zeros e ganhos. Os
zeros num filtro Butterworth só existem no infinito então aproximamos
para um vetor com 0 elementos. Todos os polos 𝑠𝑘 não são adequados
para se utilizar no filtro, já que possuem parte real positiva, logo
seleciona só os N elementos com parte real negativa

1 𝜋 𝜋 𝜋
𝑝𝑘 = 𝑁 𝑒 𝑗∗( 2 +2𝑁+𝑁𝑘) 0 ≤ 𝑘 ≤ 𝑁
√𝐶
E 𝑘𝑛 𝑠𝑒 𝑑𝑎 𝑝𝑜𝑟 𝑘𝑛 =1/C.

Após se obter o resultado volta-se para a forma não-normalizada e


retorna o valor de zc , k c e 𝑝c
zc = zn (já que não há zeros na aproximação)

Ὢ𝑝 N
𝑝c = Ὢ𝑝 *𝑝𝑘 e kc =
C
2. Utilização da função analogButter
No enunciado da experiência recebeu a seguintes especificações para o
projeto:
• Faixa de passagem: 0 ≤ ω ≤ ωp = 0,05π rad/amostra
• Faixa de rejeição: 0,5π rad/amostra = ωr ≤ ω ≤ π rad/amostra
• Atenuação mínima na faixa de rejeição: 40 dB
• Queda máxima na faixa de passagem δp = 0,05.

3
Como a função não funciona adequadamente com valores nesse
formato, precisou alterar para a entrada aceitada. A atenuação na faixa
de rejeição precisa estar em módulo, logo:
40 = -20 log (δr)
Chega-se no resultado de δr=0,01.

As frequências passaram por uma transformação bilinear:


Ὢ𝑟 = 𝑡𝑎𝑛(ωr/2) Ὢ𝑝 = 𝑡𝑎𝑛(ωp/2)

Com isso concluído se chamou a função analogButter e com os zn, pn e


kn se chamou ZeroPoleGain para se obter um filtro com formatos polos
zeros e ganho.

Assim como pedido no enunciado se utiliza o comando


convert(PolynomialRatio, filtrozpk) para converter um filtro no formato de
ZeroPoleGain para um de coeficientes.

Gráfico 1 – Resposta do filtro Butterworth Passa-Baixa analógico

4
Gráfico 2 – Representação somente dos polos com parte real negativa do filtro
proposto.

Após isso precisa voltar o filtro para digital utilizando uma transformação
bilinear novamente onde:
𝑧−1 1+𝑠
𝑠= ↔ 𝑧=
𝑧+1 1−𝑠
Após transformar os polos e obter-se os zeros, se obtém o k:
∏𝑖(−𝑝𝑧𝑖 )
𝑘 =
∏𝑗(−𝑧𝑧𝑗 )

Em seguida se converte pz, zz e k para ZeroPoleGain assim tendo H(z)


com os seguintes coeficientes e ganho

3. Filtragem do sinal
O sinal de entrada se dar por:
𝜋
𝑠[𝑛] = 𝑠𝑒𝑛( 𝑛) + 𝑣[𝑛]
20
Aonde v[n] é um ruído branco Gaussiano com média nula e variância
0,04 e n = 0 ... 1000
Utilizou a função randn* 𝜎 (desvio padrão) para se obter um ruído com
essa variância desejada pelo enunciado, isso pode se ver pelo resultado
da própria definição da variância

5
∑𝑛𝑖=1(𝑥𝑖 − 𝑥̅ )²
𝜎² =
𝑛−1

Gráfico 3 – Sinal de entrada s[n]


Para filtrar foi feita a função filtragem onde ela recebe H(z) e uma função
de entrada x[n], uma implementação direta de filtro recursivo, dada pela
figura abaixo.

Figura 1 – Implementação direta de um filtro recursivo

Ou seja, dada pela função recursiva:

y[i] = -a1*y[i-1] -a2*y[i-2] -a3*y[i-3] +b0*x[i]+b1*x[i-1] +b2*x[i-2] +b3*x[i-3]


i ∈ [0;n]

6
Gráfico 4 – Comparação do sinal limpo, sinal com ruído e sinal filtrado.

Olhando gráfico 4, percebe-se que ainda há uma pequena variação em


relação com o sinal limpo, porém o sinal está muito mais limpo.

4. Verificação do resultado com funções já prontas


Para verificar o resultado utilizando o filtro de Butterworth se utilizou a
biblioteca Scipy do Python.
Utilizou a função buttord que recebe as frequências de passagem,
rejeição, a atenuação máxima de passagem e mínima na banda de
rejeição.
Logo após chamou a função butter e colocou nas entradas dessa: a
saída da função buttord, a especificação que era um filtro passa baixa e
o indicador que queria receber os coeficientes, recebendo assim, os
coeficientes a e b do filtro.
O processo foi feito outra vez para conseguir os zeros, polos e ganho e
assim plotar o gráfico do filtro e dos polos e zeros.

7
Gráfico 5 – Resposta do Filtro Butterworth Passa-Baixa analógico utilizando a
biblioteca Scipy do Python

Gráfico 6 – Polos e zeros do Filtro Butterworth Passa-Baixa analógico utilizando a


biblioteca Scipy do Python

Assim com o filtro feito, utilizou a função filt de Julia para filtrar o sinal

8
Gráfico 7 – Comparação do Sinal de saída utilizando a biblioteca Scipy (ynovo[n]) e
filtro projetado (y[n])

Comparando ambos os gráficos se verificam que há uma diferença


muito próxima de zero entre os resultados, ou seja, os sinais ynovo[n] e
y[n] são praticamente os mesmos, podemos assim considerar o projeto
de filtro desenvolvido nessa experiencia válido.

5. Filtragem pelo critério min-max


O critério min-max, se deseja minimizar o máximo do módulo da
diferença do filtro obtido e o filtro desejado utilizando os coeficientes
h[n], ou seja:
min max
W(𝜔) | H(ej𝜔 )-Hd (ej𝜔 )|
h[0], . . . , h[N-1] 𝜔 ∈ F
Onde F é faixa onde o ganho precisa ser bem controlado, ou seja F =
[0;𝜔p ]U[𝜔r ;π], já fora de F não é considerado para o cálculo, pois entre a
banda de passagem e a banda de rejeição haverá sempre uma
diferença muito grande entre o filtro desejado e o obtido, já que em todo
filtro real a queda é feita de maneira continua.

Para se fazer o projeto utilizando o algoritmo de Parks-McClellan

Se calcula os coeficientes, dados por:

-10 log (𝛿𝑝 ∗ 𝛿𝑟)-13


N ≈ +1
2,324∆𝜔
Se utiliza a função remez, que utiliza o algoritmo de Remez, entrando
com o comprimento N e a descrição da banda passante, ganho e peso
desejado e a descrição da banda de rejeição, ganho e peso desejado.

9
No caso da banda passante o ganho e o peso desejado é 1 para ambos,
já na banda de rejeição, o ganho desejado é 0 e o peso é dado por
δp/δr.

Gráfico 8 – Resposta ao impulso do filtro h[n] pelo critério de min-max.

Gráfico 9 – Resposta em frequência do filtro h[n] obtido pelo critério de min-max

Como se observa no gráfico 9, o filtro obedece aos critérios da banda de


rejeição e passagem e não precisa ter um incremento de N, logo
podendo ser utilizado.

Utilizando a função filt de Julia filtrou o s[n] e esse foi o seguinte


resultado.

10
Gráfico 10 – Comparação do Sinal de saída entre o sinal filtrado por Butterworth (sf[n])
e o sinal filtrado pelo critério de min-max (yminmax[n])

Observa-se que com o filtro de Butterworth o N necessário para atingir as


condições é 3, já no Filtro Min-Max com algoritmo de Parks-McClellan é
muito maior, N=8.
Os filtros IIR são bons para caso estejamos lidando com um filtro deseja
com a faixa de transição muito pequena, ∆𝜔 muito pequeno, com o menor
número de coeficientes possível como se pode ver pelos resultados,
apesar que não é possível obter uma fase linear.
Ao verificar visualmente a saída do filtro min-max e do filtro de Butterworth
é possível notar uma diferença também, onde a saída filtro de Butterworth
se mostra muito melhor e muito mais próxima do resultado desejado
𝜋
y[n] = 𝑠𝑒𝑛(20 𝑛)

6. Código em Julia 1.4.0

using DSP;
using PyPlot;
using Statistics;
using Polynomials;
using PyCall;

function analogButter(δp,δr,Ωp,Ωr)

###Frequencias normalizadas
Ωpn = 1.0
Ωrn = Ωr / Ωp

∆1=sqrt(2*δp-δp^2)/(1-δp);

∆2= sqrt(1-δr^2)/(δr);

N=ceil(Int, log(∆2/∆1)/log(Ωrn/Ωpn));

11
C=0.5*((∆1/(Ωpn^N)) + (∆2/(Ωrn^N)))

pn=(1/C^(1/N))*exp.(im*((pi/2 + pi/(2N)).+ (0:N-1)*pi/N))

kn = 1/C

zn= Array{Float64,1}();

#voltando

pc= Ωp*pn
kc = Ωp^N / C

return zn,pc,kc
end

ωp = 0.05π
ωr= 0.5π
δp = 0.05
δr = 0.01 ###−40 = 20 log10 (δr)
Ωp=tan(ωp/2)
Ωr=tan(ωr/2)

(zc,pc,kc)=analogButter(δp,δr,Ωp,Ωr)

filtrozpk = ZeroPoleGain(zc, pc, kc)

coefa(filtrozpk)

coefb(filtrozpk)

filtro=convert(PolynomialRatio, filtrozpk)

plot(real.(pc),imag.(pc),"xr")
plot([0;0],1.1*[minimum(imag.(pc));maximum(imag.(pc))])
axis("square")
grid();
title("Polos do filtro analógico")
xlabel("Re{z}")
ylabel("Imag{z}")

Hs = ZeroPoleGain(zc, pc,kc)
hsfiltro=convert(PolynomialRatio, Hs)
Ω = range(0,1,length=200)
Hf = freqs(Hs,Ω)
f=plt.figure()
plot(Ω, amp2db.(abs.(Hf)))
grid()
title("Resposta em frequência do filtro analógico")
plot([0;ωp/pi],amp2db(1-δp)*[1;1],"r")
plot([0.64;1], amp2db(δr)*[1;1],"r")
xlabel(L"$\hat{\Omega}$");
ylabel(L"$|H{j\Omega})|$");
f.add_subplot(223,position=[0.6,0.4,0.25,0.25])
plot(Ω, amp2db.(abs.(Hf)))
plot([0;ωp/pi],amp2db(1-δp)*[1;1],"r")
axis([0,1.2*Ωp,amp2db(1-δp)-0.05,0.05])
grid()
title("Banda passante")

12
xlabel(L"$\hat{\Omega}$");

function z2s(z)
if abs(z) == Inf
return 1
else
return (z-1)/(z+1)
end
end

function s2z(s)
if s == Inf
return -1.0
elseif s == -Inf
return 1.0
else
return (1+s)/(1-s)
end
end

pz = s2z.(pc)

Ωpn = 1.0

Ωrn = Ωr / Ωp

∆1=sqrt(2*δp-δp^2)/(1-δp);

∆2= sqrt(1-δr^2)/(δr);

N=ceil(Int, log(∆2/∆1)/log(Ωrn/Ωpn));

zz = s2z.(Inf * ones(N))

k = real(prod(1 .- pz)/prod(1 .- zz))

print("k = ",k)

H = ZeroPoleGain(zz, pz,k)

a=coefa(H)

for i=1:4
print("a[",i,"] =",a[i],"\n")
end

b=coefb(H)

for i=1:4
print("b[",i,"] =",b[i],"\n")
end

n=0:1000;
sf=sin.((pi/20).*n);
v=0.2.*randn(Float64, 1001);

var(v) #variancia de v

s=sf+v;

plot(n,s);

13
title("Sinal de Entrada")
xlabel("n")
ylabel("s[n]")
grid();

function filtragem(H,x)

y=zeros(1001);

a=coefa(H);

b=coefb(H);

y[1]=b[1]*x[1]
y[2]=b[1]*x[2]+b[2]*x[1]-a[2]*y[1]
y[3]=b[1]*x[3]+b[2]*x[2]+b[3]*x[1]-a[2]*y[2]-a[3]*y[1]

for i=4:1001
y[i] = -a[2]*y[i-1] -a[3]*y[i-2] -a[4]*y[i-3] + b[1]*x[i] +
b[2]*x[i-1]+b[3]*x[i-2]+ b[4]*x[i-3]

end
return y
end

y=filtragem(H,s)

subplot(311)
plot(n,sf);
ylabel("s[n] limpo")
grid()
subplot(312)
plot(n,s)
grid()
ylabel("s[n]")
subplot(313)
plot(n,y)
ylabel("sf[n]")
xlabel("n")
grid()

var(y)

sig = pyimport("scipy.signal");

N,Wn = sig.buttord(ωp/π, ωr/π, -20*log10(1-δp), -20*log10(δr))

(b, a) = sig.butter(N, Wn, btype="lowpass", output="ba")

ω = range(0, π, length=500)
coefbutt = PolynomialRatio(b,a)
Hbcoef = freqz(coefbutt, ω)
f=plt.figure()
plot(ω/π, amp2db.(abs.(Hbcoef)))
plot([0;ωp/π],amp2db(1-δp)*[1;1],"r")
plot([ωr/π;1],amp2db(δr)*[1;1],"r")
xlabel(L"$\omega/\pi$")
ylabel(L"$|H_{b}(e^{j\omega})|$")
axis([0, 1, -50, 1])

14
grid();
f.add_subplot(222)
plot(ω/π, amp2db.(abs.(Hbcoef)))
plot([0;ωp/π],amp2db(1-δp)*[1;1],"r")
xlabel(L"$\omega/\pi$")
ylabel(L"$|H_{b}(e^{j\omega})|$")
axis([0, 1.1ωp/π, 2*amp2db(1-δp), amp2db(1+δp)])
title("Zoom da banda passante")
grid();

[b a]

z,p,k = sig.butter(N, Wn, btype="lowpass", output="zpk")


print("ganho= ",k)
plot(real.(z),imag.(z),"o",label="zeros")
plot(real.(p),imag.(p),"x",label="pólos")
grid()
xlabel("Re{z}")
ylabel("Imag{z}")
legend();

zpkbutt=ZeroPoleGain(z,p,k)
Hbzpk = freqz(zpkbutt, ω)
f=plt.figure()
plot(ω/π, amp2db.(abs.(Hbzpk)))
plot([0;ωp/π],amp2db(1-δp)*[1;1],"r")
plot([ωr/π;1],amp2db(δr)*[1;1],"r")
xlabel(L"$\omega/\pi$")
ylabel(L"$|H_{b}(e^{j\omega})|$")
title("Filtro de Butterworth")
axis([0, 1, -50, 1])
grid();
f.add_subplot(222,position=[0.5,0.5,0.33,0.33])
plot(ω/π, amp2db.(abs.(Hbzpk)))
plot([0;ωp/π],amp2db(1-δp)*[1;1],"r")
xlabel(L"$\omega/\pi$")
ylabel(L"$|H_{b}(e^{j\omega})|$")
axis([0, 1.1ωp/π, 2*amp2db(1-δp), amp2db(1+δp)])
title("Zoom da banda passante")
grid();

zpkbutt = digitalfilter(Lowpass(Wn), Butterworth(N))


print("ganho= ",zpkbutt.k)
plot(real.(zpkbutt.z),imag.(zpkbutt.z),"o",label="zeros")
plot(real.(zpkbutt.p),imag.(zpkbutt.p),"x",label="pólos")
grid()
axis([-1,1,-1,1])
xlabel("Re{z}")
ylabel("Imag{z}")
legend();

coefbutt = convert(PolynomialRatio, zpkbutt)

[coefb(zpkbutt) coefa(zpkbutt)]

ynovo=filt(zpkbutt,s)

subplot(211)
grid()
plot(n,ynovo)
ylabel("ynovo[n]");

15
subplot(212)
plot(n,y)
ylabel("y[n]");
xlabel("n");
grid()

Δω = ωr - ωp

ωc = (ωp+ωr)/2

A=-20*log10(min(δp, δr))

N = ceil(Int,(-10*log10(δp*δr)-13)/(2.324*Δω))+1

h = remez(N, [(0, ωp/2π) => (1, 1), (ωr/2π, 0.5) => (0,
δp/δr)]);
M = N-1
L = M/2

n=0:M
stem(n,h)
xlabel(L"$n$")
title("Resposta ao impulso, min-max")
ylabel(L"$h[n]$");

hf = PolynomialRatio(h,[1])
H = freqz(hf,ω)
subplot(211)
plot(ω/π,20*log10.(abs.(H)))
plot([0;ωp/π],20*log10.([1-δp;1-δp]),"r")
plot([0;ωp/π],20*log10.([1+δp;1+δp]),"r")
#plot([ωp;ωp]/π,[-65;5])
axis([0,ωc/π,-0.5,0.5])
grid()
ylabel(L"$|H(e^{j\omega})|$")
xlabel(L"$\omega/\pi$");
ylabel("Banda passante")
subplot(212)
plot(ω/π,20*log10.(abs.(H)))
plot([ωr;π]/π,20*log10.([δr;δr]),"r")
plot([ωr;ωr]/π,[-A-15,5],"r")
axis([ωc/π,1,-A-15,-A+5])
ylabel("Banda de rejeição")
#plot(ω/π,angle.(H)*180/π)
grid()
xlabel(L"$\omega/\pi$");

yminmax=filt(h,s)

x=0:1000;
subplot(211)
plot(x,yminmax)
ylabel("yminmax[n]");
grid()
subplot(212)
plot(x,y)
ylabel("y[n]");
xlabel("n");
grid()

16
7. Conclusão
Nessa experiência permitiu aprender a projetar um filtro Butterworth
desde o início e como também projetar uma função de filtragem utilizando
métodos recursivos. Foi possível verificar o resultado usando funções de
bibliotecas da própria linguagem utilizada para o projeto, sendo assim
permitirá utiliza-las em vez de fazer novamente o filtro, porem o
conhecimento obtido de como funciona o algoritmo e para que serve se
torna de suma importância para o entendimento da área de
processamento de sinais.
Além disso a comparação de resultados com um filtro FIR pelo critério de
min-max e um filtro IIR de Butterworth, conseguimos aprender a diferença
entre um filtro FIR e um filtro IIR em número de coeficientes e resultado,
quando precisamos de um filtro com frequência de passagem e de
rejeição muito próximas entre si. Já que o filtro IIR de Butterworth nesse
caso se mostrou muito mais eficiente que o filtro FIR com algoritmo de
Parks-McClellan.

17

Você também pode gostar