Sinais No Matlab
Sinais No Matlab
Sinais No Matlab
15 de Junho de 2015
Conteúdo
I Comandos Básicos 2
1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2 Command Window e Workspace . . . . . . . . . . . . . . . . . . 2
3 Editor - Utilizando Scripts . . . . . . . . . . . . . . . . . . . . . . 3
4 Vetores e Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
5 Plotagem de Gráficos . . . . . . . . . . . . . . . . . . . . . . . . . . 8
II Sinais e Sistemas 17
6 Geração de Sinais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7 Energia e potência de sinais . . . . . . . . . . . . . . . . . . . . . 30
8 Convolução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
9 Transformada Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
10 Transformada de Laplace . . . . . . . . . . . . . . . . . . . . . . . 42
11 Série de Fourier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
12 Transformada de Fourier . . . . . . . . . . . . . . . . . . . . . . . 48
x = 2
x =
x = 3;
y = 2;
c = x - y
c =
clc
clear all
clc limpa a Command Window e clear all limpa todas as variáveis para
evitar erros em programas longos e/ou repetitivos. Um programa bem escrito
não requer uma limpeza de variáveis no meio dele, porém existem casos especiais.
x = 3;
y = 2;
c = x - y
%
c =
Agora tente mudar o valor de x de 3 para 4. Como pode ter percebido não
há como editar uma linha já executada na Command Window. Para poder ter
mais liberdade de edição temos que criar um script, que é como se fosse um
programa a ser executado e que podemos modificar a vontade.
clc
clear all
close all
4 Vetores e Matrizes
O MAT em MATLAB não é de Math, e sim de Matrix. O grande poder do
MATLAB está em toda a liberdade que trabalhar com sistemas multidimensi-
onais oferece. É interessante procurar no help do MATLAB métodos de como
declarar vetores e matrizes, pois existem diversos e cada um é otimizado para
um certo tipo de tarefa, os que serão demostrar são os mais fáceis de entender
porém não necessariamente os mais rápidos computacionalmente.
x = [1 2 3 4 5]
x =
1 2 3 4 5
x = [0 x 6]
x =
0 1 2 3 4 5 6
y = [x 7]
y =
0 1 2 3 4 5 6 7
A = [1 2 3 ; 4 5 6]
1 2 3
4 5 6
A-1
ans =
0 1 2
3 4 5
A*2
ans =
2 4 6
8 10 12
A.^2
ans =
1 4 9
16 25 36
clear all
A = [1 2 1 ; 1 1 0; 1 1 1]
A =
1 2 1
1 1 0
1 1 1
B = [1 2 3]
B =
1 2 3
A = A^3
A =
11 15 6
6 8 3
9 12 5
B’
1
2
3
C = A * B’
C =
59
31
48
C + B’*(-5)
ans =
54
21
33
A^-1
ans =
Acessar elementos dos vetores é feito por meio de parêntesis, na forma (li-
nha,coluna)
A(1,1)
11
A(3,2)
ans =
12
x = a:b:c
x = 0:0.1:10;
Gera um vetor começando em 0, incrementando de 0.1 em 0.1 e terminando
em 10. Este vetor irá possuir 101 elementos ( (10*10)+1 ) por causa do zero.
Podemos conferir verificando o comprimento:
length(x)
ans =
101
Vetores declarados desta forma são úteis para fazer gráficos com muitos pontos,
como veremos a seguir.
5 Plotagem de Gráficos
MATLAB fornece uma gama enorme de métodos de plotagem de dados, neste
documento será mostrado apenas o básico, porém é fortemente recomendado
que procure na documentação do MATLAB os diferentes métodos de plotagem
que podem ser úteis dependendo do seu propósito.
x = -pi:pi/100:pi;
y = sin(x);
Nesta associação acima, y automaticamente vira um vetor, avaliando x elemento
a elemento. Como x vai de −π a −π , temos um perı́odo completo do seno
armazenado em y, agora podemos plotar.
Sempre que vamos plotar um gráfico é necessário abrir uma nova janela com o
comando figure, seguido de plot(X,Y), onde X são os dados do eixo X e Y os
do eixo Y. É importante que tenham as mesmas dimensões:
figure
plot(x,y);
1
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
figure
plot(x,y,’color’,’red’);
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
O estilo da linha também pode ser modificado, sempre logo após os dados:
figure
plot(x,y,’--’,’color’,’red’);
1
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
Plotar vários gráficos na mesma janela é simples caso tenham o mesmo tamanho,
e podemos associar estilos diferentes a cada um simplesmente colocando os dados
x e y ordenados corretamente:
x = -pi:pi/100:pi;
y1 = sin(x);
y2 = sin(x-0.25);
y3 = sin(x-0.5);
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
figure
hold on
.
.
.
hold off
figure
hold on
plot(x,y1,’--’,’LineWidth’,3,’color’,’blue’);
plot(x,y2,’:’,’color’,’cyan’);
plot(x,y3,’color’,’green’);
hold off
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
figure
plot(x,y)
title(’Gráfico do seno centrado em zero’)
xlabel(’x’)
ylabel(’sin(x)’)
Gráfico do seno centrado em zero
1
0.8
0.6
0.4
0.2
sin(x)
-0.2
-0.4
-0.6
-0.8
-1
-4 -3 -2 -1 0 1 2 3 4
x
figure
plot(x,y)
grid on %este comando adiciona um quadriculado ao gráfico
title(’Gráfico normal’)
xlabel(’x’)
ylabel(’exp(x)’)
Gráfico normal
8
5
exp(x)
0
-1 -0.5 0 0.5 1 1.5 2
x
figure
plot(-x,y)
grid on
title(’Gráfico revertido no tempo (plot(-x,y))’)
xlabel(’x’)
ylabel(’exp(x)’)
5
exp(x)
4
0
-2 -1.5 -1 -0.5 0 0.5 1
x
figure
plot(x,-y)
grid on
title(’Gráfico invertido em relaç~
ao ao eixo x (plot(x,-y))’)
xlabel(’x’)
ylabel(’exp(x)’)
Gráfico invertido em relação ao eixo x (plot(x,-y))
0
-1
-2
-3
exp(x)
-4
-5
-6
-7
-8
-1 -0.5 0 0.5 1 1.5 2
x
Todos os gráficos acima foram feitos para tempo contı́nuo, porém quando va-
mos plotar sinais discretos é interessante utilizar o comando stem(X,Y) em
vez do plot. Na sequência abaixo também está sendo introduzido o comando
linspace, que pode substituir o outro método de geração de vetores (observe a
transposição):
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 1 2 3 4 5 6 7
figure
X1 = linspace(0,2*pi,50)’;
X2 = linspace(-2*pi,0,50)’;
Y1 = cos(X1);
Y2 = sin(X2);
hold on
stem(X1,Y1,’filled’,’green’)
stem(X2,Y2,’:diamondr’)
title(’Gráfico com opç~
oes’)
hold off
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
-8 -6 -4 -2 0 2 4 6 8
figure
hold on
grid minor
stem(X1,Y1,’filled’,’green’,’DisplayName’,’Gráfico 1’)
stem(X2,Y2,’filled’,’:diamondr’,’DisplayName’,’Gráfico 2’)
title(’Gráfico com muitas opç~
oes’)
xlabel(’Amostras’)
ylabel(’Valores’)
legend(’-DynamicLegend’)
hold off
Gráfico com muitas opções
1
Gráfico 1
0.8 Gráfico 2
0.6
0.4
0.2
Valores
-0.2
-0.4
-0.6
-0.8
-1
-8 -6 -4 -2 0 2 4 6 8
Amostras
X = linspace(-2,2,50)’;
Y = X.^2;
figure
subplot(2,1,1)
plot(X,Y,’b’)
title(’Gráfico de Cima’)
subplot(2,1,2)
stem(X1,Y2,’r’)
title(’Gráfico de Baixo’)
Gráfico de Cima
4
0
-2 -1.5 -1 -0.5 0 0.5 1 1.5 2
Gráfico de Baixo
1
0.5
-0.5
-1
0 1 2 3 4 5 6 7
tempoinicial = -5;
tempofinal = 10;
amostras = tempofinal - tempoinicial;
t = linspace(tempoinicial,tempofinal,amostras+1); %geramos nosso vetor tempo
for i = 1:length(t)
if(t(i)>=0)
u(i) = 1;
else
u(i) = 0;
end
end
Podemos plotar o resultado:
figure
stem(t,u)
grid on
title(’Degrau Unitário’),axis([tempoinicial tempofinal 0 1.5])
Degrau Unitário
1.5
0.5
0
-5 0 5 10
clear all
tempoinicial = -1;
tempofinal = 10;
amostras = tempofinal - tempoinicial;
t = linspace(tempoinicial,tempofinal,amostras+1); %geramos nosso vetor tempo
alpha = 1; %inclinaç~
ao da rampa
u = alpha*t;
for i = 1:length(u)
if(u(i)<=0)
u(i) = 0;
end
end
Plotando:
figure
stem(t,u)
grid on
title(’Rampa Unitária’);
Rampa Unitária
10
0
-2 0 2 4 6 8 10
alpha = 1; %inclinaç~
ao da rampa
u = alpha*t;
No loop abaixo percorremos o vetor da rampa procurando valores negativos
(tempo negativo) e os retirando. Essa condição pode ser ajustada para o sinal
que se quer gerar.
for i = 1:length(u)
if(u(i)<=0)
u(i) = 0;
end
end
Plotando:
figure
plot(t,u)
grid on
title(’Rampa Unitária’);
Rampa Unitária
10
0
-2 0 2 4 6 8 10
alpha = 1; %inclinaç~
ao da rampa
u = alpha*t;
for i = 1:length(u)
if(u(i)<=0)
u(i) = 0;
end
end
figure
plot(tinv,u)
title(’Rampa Unitária Invertida no Tempo’);
0
-10 -8 -6 -4 -2 0 2 4 6 8 10
figure
plot(-t,u)
title(’Rampa Unitária Invertida no Tempo’);
0
-10 -8 -6 -4 -2 0 2 4 6 8 10
ud = alpha*(t-2);
u = alpha*t;
for i = 1:length(ud)
if(ud(i)<=0)
ud(i) = 0;
end
if (u(i)<=0)
u(i) = 0;
end
end
figure
hold on
grid on
plot(t,ud,’b’,’DisplayName’,’Rampa Deslocada de 2’)
plot(t,u,’black’,’DisplayName’,’Rampa Original’)
title(’Rampa Unitária deslocada’);
legend(’-DynamicLegend’);
hold off
0
-10 -8 -6 -4 -2 0 2 4 6 8 10
amp = 1;
t = 0:0.01:10;
u = zeros(1,length(t));
u(t>4 & t<5) = amp;
figure
plot(t,u)
title(’Pulso de 4 a 5 com amplitude 1’);
Pulso de 4 a 5 com amplitude 1
1
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
0 1 2 3 4 5 6 7 8 9 10
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
-5 0 5 10
Expansão no tempo de sinais contı́nuos e discretos pode ser feita apenas mul-
tiplicando as variáveis por constantes, no entanto para gerar sinais expandidos
com perda de informação podemos usar a função upsample(x,n) que expande
as amostras por um fator inteiro n:
amp = 1;
ups = 2;
t = 0:1:10;
u = zeros(1,length(t));
u(t>=1 & t<=4) = amp;
us = upsample(u,ups);
ts = 0:(length(us)-1);
figure
subplot(2,1,1)
stem(t,u),grid on,axis([0 10 0 1])
title(’Pulso’);
subplot(2,1,2)
stem(ts,us),grid on,axis([0 10 0 1])
title(’Pulso expandido com perda’);
0.5
0
0 1 2 3 4 5 6 7 8 9 10
0.5
0
0 1 2 3 4 5 6 7 8 9 10
Manipulações com loops de for podem gerar qualquer sinal, basta criatividade
e paciência. Felizmente o MATLAB fornece ferramentas prontas para geração
dos sinais mais comuns que podem ser necessários.
close all
clear all
sigfreq = 10;
tau = 1/sigfreq;
sampfreq = 1000;
Ts = 1/sampfreq;
Tf = 1;
Chama-se a gensig e plotamos o gráfico:
[u,t] = gensig(’sin’,tau,Tf,Ts);
Em 1 segundo amostrando a 1 kHz esperamos 1000 amostras, contando com o
zero espera-se um vetor de 1001 posições:
ans =
1001
length(t)
ans =
1001
Esta ferramenta é útil pois não precisamos nos preocupar com a geração de ve-
tores nas dimensões certas, ele faz tudo automaticamente. Tendo isto podemos
plotar o resultado:
figure
plot(t,u,’b’)
tt = sprintf([’Senóide de frequ^
encia %dHz, duraç~
ao de %ds’...
’ e amostrada a %dkHz’],sigfreq,Tf,sampfreq/1000);
title(tt)
Senóide de frequência 10Hz, duração de 1s e amostrada a 1kHz
1
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
figure
subplot(2,1,1)
plot(t,u1)
tt = sprintf([’Onda quadrada de frequ^encia %dHz, duraç~
ao de %ds’...
’ e amostrada a %dkHz’],sigfreq,Tf,sampfreq/1000);
title(tt)
subplot(2,1,2)
plot(t,u2)
tt = sprintf([’Pulso periódico de frequ^
encia %dHz, duraç~
ao de %ds’...
’ e amostrada a %dkHz’],sigfreq,Tf,sampfreq/1000);
title(tt)
Onda quadrada de frequência 10Hz, duração de 1s e amostrada a 1kHz
1
0.5
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.5
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Onda dente de serra (10 Hz com 1 kHz de amostragem) pode ser feita com:
Tf = 5;
T = Tf*(1/sigfreq);
dt = 1/sampfreq;
t = 0:dt:T-dt;
x = sawtooth(2*pi*sigfreq*t);
figure
plot(t,x)
tt = sprintf([’Onda dente de serra de frequ^
encia %dHz, duraç~
ao de %ds’...
’ e amostrada a %dkHz’],sigfreq,Tf,sampfreq/1000);
title(tt)
grid on
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5
x2 = sawtooth(2*pi*sigfreq*t,0.5);
figure
hold on
plot(t,x,’color’,’blue’,’DisplayName’,’Dente de serra’)
plot(t,x2,’color’,’red’,’DisplayName’,’Triangular’)
tt = sprintf(’Ondas dente de serra e triangular’);
title(tt)
legend(’-DynamicLegend’)
hold off
grid on
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5
sampfreq = 12;
Tf = 5;
T = Tf*(1/sigfreq);
dt = 1/sampfreq;
t = 0:dt:T-dt;
x = sawtooth(2*pi*sigfreq*t);
figure
plot(t,x)
tt = sprintf([’Onda dente de serra de frequ^
encia %dHz, duraç~
ao de %ds’...
’ e amostrada a %dHz’],sigfreq,Tf,sampfreq);
title(tt)
grid on
grid minor
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45
Como podemos ver a função claramente não representa uma dente de serra,
embora tenha sido amostrada do mesmo sinal.
∞ N
X 2 1 X 2
Ex = |xn | Px = lim |xn |
N →∞ 2N + 1
n=−∞ n=−N
Fazer a energia pela definição é direto, vamos criar um sinal discreto e calcular:
t=0:1:20;
y = zeros(length(t),1)’;y(4:16)=1;
x = y.*(sin(2*pi*t/15)+1);
figure
stem(t,x),grid on,title(’Sinal’)
xlabel(’Amostras’),ylabel(’Valores’)
energia = sum(abs(x).^2)
energia =
17.4825
1.8
1.6
1.4
1.2
Valores
1
0.8
0.6
0.4
0.2
0
0 2 4 6 8 10 12 14 16 18 20
Amostras
N −1
1 X 2
Px = |xn |
N n=0
t = 0:20;
x = sin((pi*t)/10);
figure
stem(t,x),grid on,title(’Sinal’)
xlabel(’Amostras’),ylabel(’Valores’)
potencia = sum(abs(x).^2)/length(x)
potencia =
0.4762
0.8
0.6
0.4
0.2
Valores
0
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12 14 16 18 20
Amostras
O motivo pela qual o valor não é 0.5 exatamente é devido a pequenos erros
numéricos. Se aumentarmos o número de amostras vemos que o erro diminui:
t = 0:0.001:20;
x = sin((pi*t)/10);
potencia = sum(abs(x).^2)/length(x)
potencia =
0.5000
Para sinais contı́nuos fica ainda mais fácil, pois podemos aplicas as formulas
diretamente:
Z ∞ Z ∞
2 1 2
Ex = |x(t)| dt Px = lim |x(t)| dt
−∞ 2T T →∞ −∞
tic
syms t T
y = sin(t);
energia=int(y,t,-inf,inf)
potencia=limit((1/T)*int(y^2,-T/2,T/2),T,inf)
temposym = toc
NaN
potencia =
1/2
temposym =
3.6608
tic
Tf = 10000;
t = 0:0.01:Tf;
y = sin(t);
energia = sum(abs(y).^2)
potencia = sum(abs(y).^2)/length(y)
tempofloat = toc
energia =
4.9999e+05
potencia =
0.5000
tempofloat =
0.0292
8 Convolução
A convolução, como já deve saber, é de extrema importância em processamento
de sinais, por esse motivo o MATLAB já tem uma implementação da operação
com o comando conv(X,Y), onde X e Y são seus sinais de entrada, começamos
pela geração dos sinais:
amp = 1;
t = 0:1:20;
u = zeros(1,length(t));
u(t>=4 & t<=16) = amp;
a = 2;
u2 = a*t - 2;
for i = 1:length(u2)
if(u2(i)<=0)
u2(i) = 0;
end
if(t(i)>=14) u2(i) = 0;
end
end
c = conv(u,u2);
tc = 0:(length(c)-1);
figure
subplot(3,1,1)
stem(t,u,’blue’),title(’Sinal 1’),grid minor
subplot(3,1,2)
stem(t,u2,’black’),title(’Sinal 2’),grid minor
subplot(3,1,3)
stem(tc,c,’red’),title(’Convoluç~
ao de 1 e 2’),grid minor
0.5
0
0 2 4 6 8 10 12 14 16 18 20
Sinal 2
40
20
0
0 2 4 6 8 10 12 14 16 18 20
Convolução de 1 e 2
200
100
0
0 5 10 15 20 25 30 35 40
Também, caso seja necessário, podemos fazer a convolução por meio de um loop
lógico, conforme abaixo:
L1 = length(u);
L2 = length(u2);
X=[u,zeros(1,L2)];
H=[u2,zeros(1,L1)];
for i=1:L2+L1-1
C(i)=0;
for j=1:L1
if(i-j+1>0)
C(i)=C(i)+X(j)*H(i-j+1);
else
end
end
end
Plotando vemos que o resultado é idêntico:
tC = 0:(length(C)-1);
figure
subplot(2,1,1)
stem(tC,C,’b’),title(’Convoluç~
ao por loop’),grid minor
subplot(2,1,2)
stem(tc,c,’r’),title(’Convoluç~
ao por conv’),grid minor
150
100
50
0
0 5 10 15 20 25 30 35 40
150
100
50
0
0 5 10 15 20 25 30 35 40
9 Transformada Z
Transformada Z é muito fácil de ser calculada no MATLAB. A forma mais fácil
envolve utilizar variáveis simbólicas, no caso se quisermos a Transformada Z de
a+exp (n), fazemos a, n e z simbólicos e utilizamos o comando zatrans(a,b,c),
onde a é a expressão, b a variável no tempo e c a variável z.
clear all
close all
syms n z a
Y = ztrans(a+exp(n),n,z) %levar a+exp(n) de n para z
Y =
ans =
num = [ 1 0 1 ];
den = [ 1 -1.85 0.9 ];
TS = 1;
H = tf(num,den,TS)
H =
z^2 + 1
------------------
z^2 - 1.85 z + 0.9
Ou alternadamente:
z = tf(’z’,1);
H = (z^2 + 1) / (z^2 - 1.85*z + 0.9)
H =
z^2 + 1
------------------
z^2 - 1.85 z + 0.9
4
Amplitude
-2
-4
0 20 40 60 80 100 120 140
Time (seconds)
figure
step(H)
title(’Resposta ao Degrau Unitário’)
Resposta ao Degrau Unitário
60
50
40
Amplitude
30
20
10
0
0 20 40 60 80 100 120
Time (seconds)
Como o sistema é linear, caso queiramos um degrau não unitário basta multipli-
car a saı́da por uma constante, uma vez que step pode ser tratado como figura
mas também retorna os valores da simulação:
y = amplitude*step(H);
figure
stairs(y)
tt = sprintf(’Resposta ao Degrau de Amplitude %0.2f’,amplitude);
title(tt)
Resposta ao Degrau de Amplitude 0.30
18
16
14
12
10
0
0 20 40 60 80 100 120
Como podemos ver em relação ao anterior, o valor final foi menor, como espe-
rado.
z = tf(’z’,1);
H = (0.05*(z - 1)) / (z^2 - 1.85*z + 0.9);
Em seguida declaramos o tempo de simulação
[y,t]=lsim(H,rampa,t);
figure
stem(t,y)
2.5
1.5
0.5
0
0 20 40 60 80 100 120
lsim pode simular qualquer tipo de entrada, por exemplo uma onda quadrada
de perı́odo de 20 amostras, durando 100 amostras e de amplitude 5:
[u,t] = gensig(’square’,20,120,1);
[y,t] = lsim(H,5*u,t);
figure
hold on
stem(t,y,’b’,’DisplayName’,’saida’)
stem(t,u,’r’,’DisplayName’,’entrada’)
hold off
1.5
0.5
-0.5
-1
-1.5
0 20 40 60 80 100 120
0.5
-0.5
-1
-1.5
0 20 40 60 80 100 120
[p,z] = pzmap(H)
p =
0.9250 + 0.2107i
0.9250 - 0.2107i
z =
figure
pzmap(H)
daspect([1 1 1]) %deixa os eixos iguais
0.8
0.6
0.4
-0.2
-0.4
-0.6
-0.8
-1
-1 -0.5 0 0.5 1
Real Axis
ltiview(’step’,H,t);
10 Transformada de Laplace
A Transformada de Laplace em MATLAB é completamente análoga a Trans-
formada Z, com a diferença que não precisamos passar a taxa de amostragem,
já que estamos no tempo contı́nuo:
close all
clear all
syms a t s
F = laplace(sin(a*t),t,s)
F =
a/(a^2 + s^2)
ans =
sin(a*t)
Fazer Laplace inversa é mais seguro do que a Z inversa, porém ainda assim é
boa prática utilizar apenas para conferir resultados.
num = [ 1/5 ];
den = [ 1 1/5 1/5 ];
H = tf(num,den)
H =
0.2
-----------------
s^2 + 0.2 s + 0.2
Ou alternadamente:
syms s
s = tf(’s’);
H = 1/5 / (s^2 + s/5 + 1/5)
H =
1
-------------
5 s^2 + s + 1
0.2
-0.2
0 10 20 30 40 50 60 70
Time (seconds)
Step Response
1.5
Amplitude
0.5
0
0 10 20 30 40 50 60
Time (seconds)
[p,z] = pzmap(H)
p =
-0.1000 + 0.4359i
-0.1000 - 0.4359i
z =
No caso acima não temos zeros. Para passar de continuo para discreto e vice-
versa pode-se usar o comando c2d(TF,Ts,método) para ir de continuo para
discreto, onde TF é a função de transferência, Ts o perı́odo de amostragem e
o método (normalmente utilizamos a Zero-order hold com a opção ’zoh’ ) ou
d2c(TF,método) para ir de discreto para contı́nuo.
Hd =
0.09212 z + 0.08615
---------------------
z^2 - 1.64 z + 0.8187
Hc =
0.2
-----------------
s^2 + 0.2 s + 0.2
Estes resultados são confiáveis e podem ser usados com segurança. Recomenda-
se pesquisar sobre transformações bilineares em MATLAB para melhor enten-
dimento do processo.
11 Série de Fourier
A série de fourier é uma aplicação direta de fórmulas e somatórios, serão apre-
sentados dois loops exemplos sobre como fazer estas séries em código, porém em
MATLAB é mais interessante ver as aplicações decorrentes do teorema em vez
de puramente recriar sinais.
close all
Exemplo 1: onda dente de serra. Caso deseje rode este script para diferentes
valores de N e descomente a linha pause(0.1), verá uma animação da série se
formando.
figure;
for i = 1:5
N = i; %Ordem da série
Fs = 8192; %Freq de amostragem
t = linspace(0,1-1/8192,Fs);
0.5 0.5
0 0
0 0.5 1 0 0.5 1
Ordem 3 Ordem 4
1 1
0.5 0.5
0 0
0 0.5 1 0 0.5 1
Ordem 5 Ordem 500
1 1
0.5 0.5
0 0
0 0.5 1 0 0.5 1
for N = 1:7
x = [0:100]/100;
f = ones(1,101)*1/2;
for i = 1:2:N
a = 2/pi/i;
f = f+ a*sin(2*pi*i*x);
end
subplot(2,4,N)
plot(x,f)
tt = sprintf(’Ordem %d’,N);
title(tt),axis([0 1 -0.2 1.2])
end
N = 500;
x = [0:100]/100;
f = ones(1,101)*1/2;
for i = 1:2:N
a = 2/pi/i;
f = f+ a*sin(2*pi*i*x);
end
subplot(2,4,8)
plot(x,f)
tt = sprintf(’Ordem %d’,N);
title(tt),axis([0 1 -0.2 1.2])
Ordem 1 Ordem 2 Ordem 3 Ordem 4
1 1 1 1
0 0 0 0
1 1 1 1
0 0 0 0
Neste exemplo vimos como apenas as harmônicas ı́mpares são coletadas. Nos
exemplos de aplicação vamos ver como podemos usar a série de fourier para
aproximar sinais e fazer análises.
close all
f=10;
overSampRate=30;
fs=overSampRate*f;
nCyl = 5;
t=0:1/fs:nCyl*1/f;
x=sin(2*pi*f*t);
figure
plot(t,x);
title([’Seno f=’, num2str(f), ’Hz’]);
xlabel(’Tempo(s)’);
ylabel(’Amplitude’);
Seno f=10Hz
1
0.8
0.6
0.4
0.2
Amplitude
-0.2
-0.4
-0.6
-0.8
-1
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5
Tempo(s)
70
60
Valores da Transformada
50
40
30
20
10
0
0 200 400 600 800 1000 1200
Amostra (N)
Precisamos usar abs(x) para tomar a magnitude do sinal apenas, uma vez que
temos parte real e imaginária. Você consegue entender o gráfico acima? Tudo
que ele está nos dizendo são os valores da magnitude do sinal em cada amostra
feita no espectro de frequência. É importante entender bem a parte teórica da
matéria para utilizar a FFT corretamente.
O gráfico anterior não nos serve de muita coisa para análise, pois o que nos
interessa são as componentes espectrais do sinal, para isso precisamos ”trans-
formar”o eixo x em valores de frequência, podemos começar normalizando o
vetor de amostras:
nVals = nVals/NFFT;
figure
plot(nVals,abs(X));
title(’Saı́da padr~
ao da FFT - Espectro Espelhado’);
xlabel(’Frequ^encia Normalizada’)
ylabel(’Valores da Transformada’);
70
60
Valores da Transformada
50
40
30
20
10
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Frequência Normalizada
fVals = fs*(-NFFT/2:NFFT/2-1)/NFFT;
X = fftshift(fft(x,NFFT));
figure
plot(fVals,abs(X));
set(gca,’xtick’,[-150:20:150]) %melhora precis~
ao de leitura
title(’Espectro Espelhado shiftado’);
xlabel(’Frequ^
encia (Hz)’)
ylabel(’Valores da Transformada’);
grid minor
Espectro Espelhado shiftado
80
70
60
Valores da Transformada
50
40
30
20
10
0
-150 -130 -110 -90 -70 -50 -30 -10 10 30 50 70 90 110 130 150
Frequência (Hz)
close all
figure
plot(t,y)
title(’Senóide com ruı́do gaussiano’)
-1
-2
-3
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5
Nossa senóide agora está com muito ruı́do e praticamente irreconhecı́vel, o que
espera-se no espectro? Podemos refazer a FFT e verificar:
fVals = fs*(-NFFT/2:NFFT/2-1)/NFFT;
Y = fftshift(fft(y,NFFT));
figure
plot(fVals,abs(Y));
set(gca,’xtick’,[-150:20:150])
title(’FFT da senóide ruidosa’);
xlabel(’Frequ^
encia (Hz)’)
ylabel(’Valores da Transformada’);
grid on
grid minor
70
60
Valores da Transformada
50
40
30
20
10
0
-150 -130 -110 -90 -70 -50 -30 -10 10 30 50 70 90 110 130 150
Frequência (Hz)
Vemos que agora o resto do espectro ganhou magnitude, porém ainda assim
a frequência dominante é a do sinal original, podemos conferir sobrepondo os
gráficos e diminuindo a janela, como é usual não considerar frequências negativa
esta parte é excluı́da do gráfico.
figure
hold on
plot(fVals,abs(X),’b’,’DisplayName’,’sem ruido’),axis([0 50 0 90])
plot(fVals,abs(Y),’r’,’DisplayName’,’com ruido’),axis([0 50 0 90])
title(’Senoides com e sem ruido’);
xlabel(’Freq^
encia (Hz)’)
ylabel(’Valores da Transformada’);
legend(’-DynamicLegend’)
grid on
grid minor
hold off
70
Valores da Transformada
60
50
40
30
20
10
0
0 5 10 15 20 25 30 35 40 45 50
Freqência (Hz)
Vamos ver agora como mudar a quantidade de amostras utilizadas na FFT pode
alterar o gráfico resultante.
n = [0:29];
x = cos(2*pi*n/10);
N1 = 32;
N2 = 64;
N3 = 256;
X1 = abs(fft(x,N1));
X2 = abs(fft(x,N2));
X3 = abs(fft(x,N3));
F1 = [0 : N1 - 1]/N1;
F2 = [0 : N2 - 1]/N2;
F3 = [0 : N3 - 1]/N3;
figure
subplot(3,1,1)
plot(F1,X1),title(’N = 32’),axis([0 1 0 20])
subplot(3,1,2)
plot(F2,X2),title(’N = 64’),axis([0 1 0 20])
subplot(3,1,3)
plot(F3,X3),title(’N = 256’),axis([0 1 0 20])
10
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
N = 64
20
10
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
N = 256
20
10
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
n = [0:29];
x1 = cos(2*pi*n/10);
x2 = [x1 x1];
x3 = [x1 x1 x1];
N = 2048;
X1 = abs(fft(x1,N));
X2 = abs(fft(x2,N));
X3 = abs(fft(x3,N));
F = [0:N-1]/N;
figure
subplot(3,1,1)
plot(F,X1),title(’3 periodos’),axis([0 1 0 50])
subplot(3,1,2)
plot(F,X2),title(’6 periodos’),axis([0 1 0 50])
subplot(3,1,3)
plot(F,X3),title(’9 periodos’),axis([0 1 0 50])
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
6 periodos
50
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
9 periodos
50
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Pesquise por Spectral Leakage e leia sobre o teoria, pode ser muito útil aqui-
sitando e tratando sinais discretos. Um método simples e rápido, porém com
menos opções, é usar a função pwelch(x) para achar a magnitude doe sinais
no espectro da frequência. Pesquise no manual do MATLAB como usar devi-
damente esta função, abaixo temos um exemplo simples:
T=10;
Ts=0.0005;
Fs=1/Ts;
t=[0:Ts:T];
x=cos(2*pi*150*t)+cos(2*pi*250*t)+sin(2*pi*500*t);
[pxx,f] = pwelch(x,5000,[],5000,Fs);
figure
plot(f,pow2db(pxx),’black’),grid minor
xlabel(’Frequ^
encia (Hz)’)
ylabel(’Magnitude (dB)’)
-20
-40
-60
Magnitude (dB)
-80
-100
-120
-140
-160
-180
-200
0 100 200 300 400 500 600 700 800 900 1000
Frequência (Hz)
Este tipo de gráfico não pode ser considerado uma Transformada de Fourier dire-
tamente, porém para identificar onde encontram-se as frequências fundamentais
do sinal é útil.
Parte III
Assuntos Avançados
13 Diagrama de Bode
Diagrama de Bode é um tipo de gráfico muito utilizado e muito simples de
se entender. Caso não saiba como interpretar um, leia sobre antes de tentar
entender os códigos desta seção. Como diagramas de Bode sempre são de um
sistema o primeiro passo é escrevê-lo por sua função de transferência:
s = tf(’s’);
H = (12345/(s+54321))
H =
12345
---------
s + 54321
figure
bodeplot(H)
grid on
Bode Diagram
Magnitude (dB) -10
-20
-30
-40
0
Phase (deg)
-45
-90
10 3 10 4 10 5 10 6
Frequency (rad/s)
figure
h = bodeplot(H);
setoptions(h,’FreqUnits’,’Hz’,’PhaseVisible’,’off’);
title(’Diagrama de Bode’)
ylabel(’Magnitude’)
xlabel(’Frequ^
encia’)
grid on
Diagrama de Bode
-10
-15
-20
Magnitude (dB)
-25
-30
-35
-40
-45
-50
10 2 10 3 10 4 10 5 10 6
Frequência (Hz)
numTF=[0 12345];
denomTF=[1 54321];
w=0:10:10e6;
figure
subplot(2,1,1)
semilogx(w,20*log10(y1))
grid on
ylabel(’Magnitude (dB)’)
title(’Diagrama de Bode’)
subplot(2,1,2)
semilogx(w,y2*(180/pi))
grid on
ylabel(’Fase (^angulo))’)
xlabel(’Frequ^
encia (Rad/s)’)
Diagrama de Bode
0
Magnitude (dB)
-20
-40
-60
10 1 10 2 10 3 10 4 10 5 10 6 10 7
0
Fase (ângulo))
-50
-100
10 1 10 2 10 3 10 4 10 5 10 6 10 7
Frequência (Rad/s)
Fazer manualmente é útil para melhor customizar as opções e escalas, mas deve
ser feito com cuidado.
14 Filtros
Como será visto na matéria de Circuitos Elétricos e Eletrônicos, filtros são uma
parte importantı́ssima do tratamento de sinais. Antes de começar a estudar os
clear all
close all
x = sin(2*pi*300*t)+0.2*sin(2*pi*8000*t);
xlow = sin(2*pi*300*t);
figure
subplot(2,1,1)
plot(t,x)
title(’Sinal de Entrada’);
xlabel(’Tempo (s)’);
ylabel(’Valor’);
NFFT = length(t)*2;
fVals = fs*(-NFFT/2:NFFT/2-1)/NFFT;
X = fftshift(fft(x,NFFT));
subplot(2,1,2)
1
Valor
-1
-2
0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1
Tempo (s)
Espectro do Sinal
6000
Magnitude
4000
2000
0
0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000
Frequência (Hz)
nf = 2*pi*1000/fs
nf =
0.0628
xm = abs(fft(x,fs*2));
tam = length(xm);
figure
hold on
plot(0:1/(tam/2 -1):1, xm(1:tam/2)/6000)
0.9
0.8
0.7
0.6
Magnitude
0.5
0.4
0.3
0.2
0.1
0
0 0.02 0.04 0.06 0.08 0.1 0.12 0.14 0.16 0.18 0.2
Frequencia Normalizada (π rads/amostra)
ff = [0:1/(tam/2 -1):1];
[b,a] = butter(5,nf,’low’);
A função freqz(b,a) plota um diagrama de bode para análise de filtros discre-
tos, pesquise pela freqs(b,a) para filtros contı́nuos.
h = freqz(b,a,floor(tam/2));
h = abs(h);
hold on
plot(ff,h,’r’)
legend(’Espectro do Sinal’,’Resposta do Filtro’);
0.8
0.7
0.6
Magnitude 0.5
0.4
0.3
0.2
0.1
0
0 0.02 0.04 0.06 0.08 0.1 0.12 0.14 0.16 0.18 0.2
Frequencia Normalizada (π rads/amostra)
Como podemos ver o ganho do filtro passa a ser -3db na frequencia de corte
especificada. Agora podemos filtrar:
xf = filter(b,a,x);
figure
subplot(2,1,1)
plot(t,x),title(’Sinal Original’),axis([0 0.01 -1.2 1.2]);
xlabel(’Tempo (s)’);
ylabel(’Valor’);
subplot(2,1,2)
plot(t,xf,’r’),title(’Sinal Filtrado’),axis([0 0.01 -1.2 1.2]);
xlabel(’Tempo (s)’);
ylabel(’Valor’);
Sinal Original
1
0.5
Valor
-0.5
-1
0 0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009 0.01
Tempo (s)
Sinal Filtrado
1
0.5
Valor
-0.5
-1
0 0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009 0.01
Tempo (s)
figure
hold on
plot(t,xlow),axis([0 0.01 -1.2 1.2]);
xlabel(’Tempo (s)’);
ylabel(’Valor’);
plot(t,xf,’r’),axis([0 0.01 -1.2 1.2]);
legend(’Sinal Original’,’Sinal Filtrado’);
hold off
1 Sinal Original
Sinal Filtrado
0.5
Valor
-0.5
-1
0 0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009 0.01
Tempo (s)
Observe que a maior parte das manipulações matemáticas foi para plotar gráficos
didaticamente compreensı́veis, se o objetivo é simplesmente filtrar, podemos
usar menos comandos. No exemplo abaixo vamos trocar para um passa-altas, e
ver a diferença:
[b,a] = butter(5,nf,’high’);
xfh = filter(b,a,x);
Nos comandos acima o sinal já foi filtrado, plotar o resultado é simples, observe
a escala dos eixos:
figure
subplot(2,1,1)
plot(t,x),title(’Sinal Original’),axis([0 0.004 -1.2 1.2]);
xlabel(’Tempo (s)’);
0.5
Valor
-0.5
-1
0 0.5 1 1.5 2 2.5 3 3.5 4
Tempo (s) ×10 -3
Sinal Filtrado
0.2
Valor
-0.2
Filtros contı́nuos são feitos com a opção s, abaixo temos o exemplo do MA-
TLAB, utilizando Fc = 2 GHz e ordem 5, todos passa-baixas. Na sequência de
chamada [zb,pb,kb] = butter(n,2*pi*f,’s’); , o filtro é gerado na forma
de zeros/polos/ganhos, e como é contı́nuo passamos a freqência em radianos.
A função [bb,ab] = zp2tf(zb,pb,kb); transforma os zeros/polos/ganhos em
uma função de transferência, e freqs(b,a,N); gera a resposta em frequência
para b e a com N amostras.
n = 5;
f = 2e9;
[zb,pb,kb] = butter(n,2*pi*f,’s’);
[bb,ab] = zp2tf(zb,pb,kb);
[hb,wb] = freqs(bb,ab,4096);
[z1,p1,k1] = cheby1(n,3,2*pi*f,’s’);
[b1,a1] = zp2tf(z1,p1,k1);
[h1,w1] = freqs(b1,a1,4096);
[z2,p2,k2] = cheby2(n,30,2*pi*f,’s’);
[b2,a2] = zp2tf(z2,p2,k2);
[h2,w2] = freqs(b2,a2,4096);
[ze,pe,ke] = ellip(n,3,30,2*pi*f,’s’);
figure
plot(wb/(2e9*pi),mag2db(abs(hb)))
hold on
plot(w1/(2e9*pi),mag2db(abs(h1)))
plot(w2/(2e9*pi),mag2db(abs(h2)))
plot(we/(2e9*pi),mag2db(abs(he)))
axis([0 4 -40 5])
grid
title(’Comparaç~
ao dos tipos de Filtros’)
xlabel(’Frequ^
encia (GHz)’)
ylabel(’Atenuaç~
ao (dB)’)
legend(’butter’,’cheby1’,’cheby2’,’ellip’)
Comparação dos tipos de Filtros
5
butter
0 cheby1
cheby2
-5 ellip
-10
Atenuação (dB)
-15
-20
-25
-30
-35
-40
0 0.5 1 1.5 2 2.5 3 3.5 4
Frequência (GHz)
Z
ẋ x
u B + C + y
Felizmente para nós o MATLAB contém diversas ferramentas para lidar com
esse tipo de representação. A sequência de comandos abaixo cria um sistema
neste formato:
A = [1 1 ; -5 -2];
B = [1 ; 3];
C = [-1.2 -1.6];
D = 0;
sys = ss(A,B,C,D)
sys =
a =
x1 x2
x1 1 1
x2 -5 -2
b =
u1
x1 1
x2 3
c =
d =
u1
y1 0
figure
step(sys)
Step Response
4
2
Amplitude
-1
-2
0 2 4 6 8 10 12
Time (seconds)
[A,B,C,D] = tf2ss(num,den);
sys = ss(A,B,C,D)
systf =
-6 s + 6.8
-----------
s^2 + s + 3
sys =
a =
x1 x2
x1 -1 -3
x2 1 0
b =
u1
x1 1
x2 0
c =
x1 x2
y1 -6 6.8
d =
u1
y1 0
A = [0 1;-5 -2];
B = [0;3];
C = [0 1];
D = 0;
sys = ss(A,B,C,D,0.25)
sys =
a =
x1 x2
x1 0 1
x2 -5 -2
b =
u1
c =
x1 x2
y1 0 1
d =
u1
y1 0
clear all
close all
m = 1;
k = 1;
b = 0.2;
Montamos as matrizes de estado e em seguida o sistema:
A = [0 1; -k/m -b/m];
B = [0 1/m]’;
C = [1 0];
D = [0];
sys(1) = ss(A,B,C,D)
sys =
a =
x1 x2
x1 0 1
x2 -1 -0.2
b =
u1
x1 0
c =
x1 x2
y1 1 0
d =
u1
y1 0
figure
impulse(sys(1))
title(’Resposta impulsional do sistema’)
Resposta impulsional do sistema
1
0.8
0.6
0.4
Amplitude
0.2
-0.2
-0.4
-0.6
-0.8
0 10 20 30 40 50 60
Time (seconds)
figure
subplot(3,1,1)
hold on
for b = 0.1:0.2:0.5
A = [0 1; -k/m -b/m];
B = [0 1/m]’;
sys(2) = ss(A,B,C,D);
0.5 k = 1.0
0 k = 6.0
k = 11.0
-0.5
0 20 40 60 80 100 120
Resposta impulsional mudando m
0.5 m = 1.0
0 m = 6.0
m = 11.0
-0.5
0 20 40 60 80 100 120
G = tf(2,[1 3 0])
H = zpk([],-5,5)
G =
2
---------
s^2 + 3 s
H =
5
-----
(s+5)
u G H y
serie = series(G,H)
serie =
10
-------------
s (s+5) (s+3)
G
u + y
H
paralelo = parallel(G,H)
paralelo =
5 (s+0.7566) (s+2.643)
----------------------
s (s+3) (s+5)
u + G y
realimentacao = feedback(G,H)
realimentacao =
2 (s+5)
--------------------------------
(s+5.663) (s^2 + 2.337s + 1.766)
realimentacao2 = feedback(G,H,+1)
realimentacao2 =
2 (s+5)
---------------------------------
(s-0.5157) (s^2 + 8.516s + 19.39)
sistema = parallel(feedback(G,H),series(feedback(H,G),G))
17 Controle PID
Um dos tipos de controle mais famosos é o PID ( Proportional-Integral-
Derivative ). Vamos ver como fazer um controlador PID em MATLAB e ver as
vantagens que ele fornece. Começamos declarando a função de transferência da
planta:
close all
num = [1];
den = [1 3 1];
Gp = tf(num,den)
Gu = feedback(Gp,1)
figure
grid minor
step(Gu)
Gp =
1
-------------
s^2 + 3 s + 1
Gu =
1
-------------
s^2 + 3 s + 2
0.45
0.4
0.35
0.3
Amplitude
0.25
0.2
0.15
0.1
0.05
0
0 1 2 3 4 5 6 7
Time (seconds)
Como podemos ver o sistema demora bastante para responder e para em apro-
ximadamente 0.5 em vez do nosso setpoint, que no caso é 1 já que o degrau de
entrada é unitário. Vamos agora montar o controlador PID apenas com o ganho
proporcional e ver o que acontece:
Kp = 1;
Kd = 0;
Ki = 0;
Gc = pid(Kp,Ki,Kd);
Gm = feedback(series(Gc,Gp),1);
t = (0:0.01:7)’;
figure
grid on
step(Gu,Gm,t)
0.45
0.4
0.35
0.3
Amplitude
0.25
0.2
0.15
0.1
0.05
0
0 1 2 3 4 5 6 7
Time (seconds)
figure
hold on
grid on
for Kp = [1 2 5 10 15 20 26]
Gc = pid(Kp,Ki,Kd);
Gm = feedback(series(Gc,Gp),1);
dn = sprintf(’Kp = %d’,Kp);
data = step(Gm,t);
plot(t,data,’DisplayName’,dn)
h = legend(’-DynamicLegend’);
h.Location = ’best’;
end
title(’Resposta da Planta com diferentes valores de Kp’)
ylabel(’Amplitude’)
xlabel(’Tempo(s)’)
1.2
Amplitude 0.8
0.6
Kp = 1
Kp = 2
0.4 Kp = 5
Kp = 10
Kp = 15
0.2 Kp = 20
Kp = 26
0
0 1 2 3 4 5 6 7
Tempo(s)
Como podemos ver o sistema teve uma subida muito mais rápida, porém agora
ganhamos um comportamento oscilatório. Podemos confirmar isto vendo os
polos dos dois sitemas:
sem_controle = pole(Gu)
com_controle = pole(Gm)
sem_controle =
-2
-1
com_controle =
-1.5000 + 4.9749i
-1.5000 - 4.9749i
figure
hold on
grid on
for Kd = [0 1 3 6 9]
Gc = pid(Kp,Ki,Kd);
Gm = feedback(series(Gc,Gp),1);
1.2
1
Amplitude
0.8
0.6
0.4
Kd = 0
Kd = 1
Kd = 3
0.2
Kd = 6
Kd = 9
0
0 1 2 3 4 5 6 7
Tempo(s)
Repare que os polos voltaram a ser somente reais, porém agora estão muito mais
rápidos, ou seja, o sistema chega em regime permanente muito mais rápido e
sem oscilações, podemos verificar vendo os polo novamente:
com_controle = pole(Gm)
com_controle =
-9
-3
Vemos que o sistema agora está muito mais comportado, isto é devido ao fato
de que o ganho derivativo tenta fazer com que a derivada do setpoint e da saı́da
seja a mesma, portanto quanto maior mais comportado fica. Não podemos, no
entanto, aumentar demais este parâmetro uma vez que ele ”luta”contra o ganho
proporcional e deixa o sistema mais lento. Olhando para este gráfico podemos
achar que o sistema está ótimo já, mas repare que estamos fora do valor alvo em
regime permanente que no nosso caso é 1. Isso é corrigido com ganho integral,
figure
hold on
grid on
for Ki = [0 1 2 4 6 8]
Gc = pid(Kp,Ki,Kd);
Gm = feedback(series(Gc,Gp),1);
dn = sprintf(’Ki = %d’,Ki);
data = step(Gm,t);
plot(t,data,’DisplayName’,dn),axis([0 7 0.9 1.05])
h = legend(’-DynamicLegend’);
h.Location = ’best’;
end
title(’Resposta da Planta com diferentes valores de Ki’)
ylabel(’Amplitude’)
xlabel(’Tempo(s)’)
pole(Gm)
ans =
-9.1425
-2.5087
-0.3488
1
Amplitude
Ki = 0
0.95 Ki = 1
Ki = 2
Ki = 4
Ki = 6
Ki = 8
0.9
0 1 2 3 4 5 6 7
Tempo(s)
0.9
0.6
Amplitude
0.5
0.4
0.3
0.2
0.1
0
0 1 2 3 4 5 6 7
Tempo(s)
1
ZR = R, ZC = e ZL = jωL
jωC
O que essas impedâncias nos dizem são que R não tem sua resistência aparente
ao sistema alterada com a frequência, enquanto que a de L aumenta e a de C
diminui com o aumento da frequência. Vamos modelar o circuito RC abaixo,
tomando como saı́da a tensão VL (t) através do capacitor C :
+
+
U (t) − VC (t) C
−
Para fazer a análise no domı́nio da frequência basta trocar R e C por suas res-
pectivas impedâncias e tomar como saı́da a tensão Vc (jω) através do capacitor:
ZR
+
+
U (jω) − VC (jω) ZC
O problema agora passou a ser um simples divisor de tensão já que podemos
tratar todos os elementos como resistências e a solução para a função de trans-
ferência H(jω) vira:
1
VC (jω) jωC 1
H(jω) = = 1 =
U (jω) jωC +R 1 + jωRC
1 1
H(s) = fc = [Hz]
1 + sRC 2πRC
s = tf(’s’);
R = 1*10^3;
C = 3*10^-6;
H =
1
-----------
0.003 s + 1
figure
grid minor
h = bodeplot(H);
setoptions(h,’FreqUnits’,’Hz’,’PhaseVisible’,’off’);
Bode Diagram
0
-5
-10
Magnitude (dB)
-15
-20
-25
-30
10 0 10 1 10 2 10 3
Frequency (Hz)
fc = 1/(2*pi*R*C)
fc =
53.0516
5
Tensão(V)
1 Entrada
Saída
Nivel DC
0
0 0.002 0.004 0.006 0.008 0.01 0.012 0.014 0.016 0.018 0.02
Tempo
De fato vemos que o embora com algum ripple o filtro tirou grande parte das
altas frequências. Podemos usar a mesma estratégia para extrair o Duty-Cycle
de um sinal do tipo PWM ( Pulse Width Modulation ):
4.5
3.5
3
Tensão(V)
Entrada
2.5 Saída
Duty Cycle Esperado
2
1.5
0.5
0
0 0.002 0.004 0.006 0.008 0.01 0.012 0.014 0.016 0.018 0.02
Tempo
ZR
+
+
U (jω) − VL (jω) ZL
s = tf(’s’);
R = 2*10^2;
L = 3*10^-2;
H = (L*s)/(R+L*s)
fc = R/(2*pi*L)
H =
0.03 s
------------
0.03 s + 200
fc =
1.0610e+03
figure
grid minor
h = bodeplot(H);
setoptions(h,’FreqUnits’,’Hz’,’PhaseVisible’,’off’);
-5
-10
-15
Magnitude (dB)
-20
-25
-30
-35
-40
-45
-50
10 1 10 2 10 3 10 4 10 5
Frequency (Hz)
Tensão(V) 2
1
Entrada
0 Saída
Nivel DC
-1
-2
-3
0 0.002 0.004 0.006 0.008 0.01 0.012 0.014 0.016 0.018 0.02
Tempo
mean(y(ceil(length(y)/2):length(y)))
ans =
0.0010
Outra forma de inverter o tipo de filtro é trocar a ordem dos elementos. Para fil-
tros de segunda ordem são necessários mais elementos armazenadores de energia,
sejam estes mais dos mesmos ou um circuito RLC. A forma de achar a função
de transferência e simular é sempre a mesma. Tente colocar um capacitor em
paralelo com um indutor no lugar do único elemento armazenador de energia e
verifique que agora o filtro é do tipo passa-banda. Experimente também cha-
mar a interface interativa sobre circuitos RLC executando o comando rlc gui
na Command Window.
v = [2 1 2 1];
c1 = conv(1,v)
c2 = conv(0.5,v)
c3 = conv(-1,v)
figure
hold on
stem(c1);stem(c2);stem(c3);
h=legend(’Impulso Unitário’,’Impulso de 0.5’,’Impulso Unitário negativo’);
h.Location = ’best’;
c1 =
2 1 2 1
c2 =
c3 =
-2 -1 -2 -1
2
Impulso Unitário
Impulso de 0.5
1.5
Impulso Unitário negativo
0.5
-0.5
-1
-1.5
-2
1 1.5 2 2.5 3 3.5 4
Convoluir um sinal por um escalar faz uma escala do vetor, daı́ o nome. Você
pode conferir melhor checando os resultados numéricos em vez do plot. Esta
propriedade é muito útil para operações com vetores. Vamos tentar algo mais
complexo:
1 1
0 0
0 5 10 0 5 10
Atraso de 2 Atraso de 3
2 2
1 1
0 0
0 5 10 0 5 10
Atraso de 4 Atraso de 5
2 2
1 1
0 0
0 5 10 0 5 10
figure
hold on
subplot(2,1,1)
stem(conv(v,[1 0 0 0 0 0]),’r’),grid on,axis([1 9 0 3])
title(’Sinal Original’)
subplot(2,1,2)
stem(conv(v,[0 0 1.5 0 0 0]),’black’)
title(’Atraso de 2 e multiplicaç~
ao por 1.5’), grid on
0
1 2 3 4 5 6 7 8 9
0
1 2 3 4 5 6 7 8 9
Isso tudo cai no fato de que podemos utilizar a convolução para filtrar sinais.
Basta pensar que colocando o vetor certo para convoluir com o sinal, podemos
alterar como quisermos o mesmo. Vamos fazer algumas operações para tentar
entender como esse processo se realiza:
a=[1 0 0 0 0 1];
figure
stem(conv(v,a))
2
1.8
1.6
1.4
1.2
0.8
0.6
0.4
0.2
0
1 2 3 4 5 6 7 8 9
1.5
2
1
1
0.5
0 0
0 2 4 6 8 0 2 4 6 8
Vetor: [ 1 0 1 0 0] Vetor: [ 1 1 0 0 0]
4 3
3
2
2
1
1
0 0
0 2 4 6 8 0 2 4 6 8
O que a operação acima fez foi mostrar que podemos também fazer produtos
de sinais, e desta forma construir filtros. Vamos fazer um filtro de média móvel
utilizando este conceito. Sabendo como a convolução faz o somatório podemos
fazer um filtro de média móvel de duas amostras simplesmente com:
f=conv(v,[0.5 0.5]);
figure
stem(f)
0.5
0
1 1.5 2 2.5 3 3.5 4 4.5 5
A principio pode não parecer muita coisa, mas repare que o sinal ficou muito
mais estável, perdeu oscilações. A visualização fica mais fácil com um sinal mais
completo:
close all
s=sin(pi/10:pi/20:10*pi)*3;
figure
plot(s,’LineWidth’,1.4)
legend(’Sinal Limpo’);
3
Sinal Limpo
-1
-2
-3
0 20 40 60 80 100 120 140 160 180 200
Vamos contaminar com ruı́do e ver se conseguimos filtrar com o mesmo filtro
anterior:
n=randn(size(s));
-2
-4
-6
0 20 40 60 80 100 120 140 160 180
Vemos que o filtro de média móvel de duas amostras não se mostrou muito
eficaz. Podemos aumentar para um de 5 fazendo:
N = 5;
d(1:N)=1/N;
plot(conv(sn,d),’black’,’LineWidth’,1.4),axis([0 length(sn) -6 6])
legend([{’Limpo’},{’Ruidoso’},{’Filtrado’},{’Fortemente Filtrado’}]);
6
Limpo
Ruidoso
4 Filtrado
Fortemente Filtrado
-2
-4
-6
0 20 40 60 80 100 120 140 160 180
figure
hold on
plot(s)
plot(filtfilt(d,1,sn))
legend({’Sinal Original’,’Sinal Ruidoso pós Filtros’})
4
Sinal Original
3 Sinal Ruidoso pós Filtros
-1
-2
-3
-4
0 20 40 60 80 100 120 140 160 180 200
O sinal filtrado agora não possui atraso, porém o filtro começou a diminuir a
amplitude da senóide também. Estude filtros de média móvel para entender
como funcionam e logo entenderá o motivo desta atenuação. Se inserir um filtro
sem fortes flutuações faz o filtro impedir as fortes flutuações de passar, o que um
filtro com fortes flutuações irá fazer? Vamos usar a mesma estratégia, porém
fazendo o vetor do filtro flutuar:
a = [1 -1 1 -1]/4;
figure
hold on;
plot(sn,’r’)
plot(filtfilt(a,1,sn), ’g’)
legend([{’Sinal Ruidoso’},{’Sinal com Passa-Altas aplicado’}]);
hold off
-2
-4
-6
0 20 40 60 80 100 120 140 160 180 200
Um filtro de oscila o quão rápido a taxa de amostragem permite irá fazer com
que todas as frequências altas passem. O que estamos fazendo aqui é criando
uma resposta impulsional arbitrária e convoluindo-a com um sinal. A idéia é
que podemos filtrar qualquer sinal com a convolução de um filtro cuja função
de transferência gera uma resposta impulsional adequada, e isto é válido para
qualquer filtro FIR ( Finite Impulse Response ).
clear all
Tf = 12
Ts = 0.001;
Fs = 1/Ts;
t = 0:0.001:Tf;
y = sin(2*pi*t+pi/2);
figure
hold on
plot(t,y);
Tf =
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12
Fs = 10;
tsamp = 0:1/Fs:Tf;
ysamp = sin(2*pi*tsamp+pi/2);
plot(tsamp,ysamp,’o’)
1
0.8
0.6
0.4
0.2
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12
figure
f = fit(tsamp’,ysamp’,’fourier1’)
plot(f,tsamp,ysamp,’o’)
f =
1
data
0.8 fitted curve
0.6
0.4
0.2
0
y
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12
x
figure
f = fit(tsamp’,ysamp’,’fourier4’)
plot(f,tsamp,ysamp,’o’),axis([0 12 -1 1])
f =
1
data
0.8 fitted curve
0.6
0.4
0.2
0
y
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12
x
figure
subplot(2,1,1)
hold on
plot(t,y),title(’Sinal Amostrado’),axis([0 12 -1.1 1.1])
tsamp = 0:1/2:Tf;
ysamp = sin(2*pi*tsamp+pi/2);
plot(tsamp,ysamp,’o’)
legend(’Sinal Original’,’Sinal Amostrado’)
f = fit(tsamp’,ysamp’,’fourier4’)
subplot(2,1,2)
plot(f,tsamp,ysamp,’o’),axis([0 12 -1.1 1.1])
title(’Aproximaç~
ao por Fourier’)
Sinal Amostrado
1
Sinal Original
0.5 Sinal Amostrado
-0.5
-1
0 2 4 6 8 10 12
0
y
-0.5
-1
0 2 4 6 8 10 12
x
figure
hold on
plot(t,y)
tsamp = 0:0.75:Tf;
ysamp = sin(2*pi*tsamp+pi/2);
f =
1
data
0.8 fitted curve
0.6
0.4
0.2
0
y
-0.2
-0.4
-0.6
-0.8
-1
0 2 4 6 8 10 12
x
Claramente o sinal não pode ser reconstruı́do, por isso a série de fourier retorna
uma senóide de frequência diferente. Não importa o grau da aproximação esta
situação vai se manter.
21 Estimativas de Comportamento
Vamos ver agora como lidar com sistemas MIMO e como estimar modelos com
load SteamEng
vapor = iddata([GenVolt,Speed],[Pressure,MagVolt],0.05);
vapor.InputName = {’Press~ ao’;’Tens~
ao de Magnetizaç~
ao’};
vapor.OutputName = {’Tens~
ao Gerada’;’Rotaç~
ao’};
respimp = impulseest(vapor,50);
Podemos plotar os resultados, vemos que o MATLAB automaticamente coloca
janelas relacionando entradas e saı́das. No exemplo abaixo foi pedido ao MA-
TLAB para mostrar também as regiões de confiança com grau 3, já que é um
modelo probabilı́stico:
figure
showConfidence(stepplot(respimp),2)
Step Response
From: Pressão From: Tensão de Magnetização
0.6
To: Tensão Gerada
0.4
0.2
0
Amplitude
-0.2
0.8
0.6
To: Rotação
0.4
0.2
-0.2
0 0.5 1 1.5 2 2.5 0 0.5 1 1.5 2 2.5
Time (seconds)
espest = ssest(vapor)
A =
x1 x2 x3
x1 -39.81 3.896 -0.4863
x2 1.66 0.3261 6.661
x3 -3.357 -3.675 -8.094
B =
Press~
ao Tens~
ao de Ma
x1 -0.009856 1.116
x2 -0.07379 -0.04638
x3 0.5102 0.06856
C =
x1 x2 x3
Tens~
ao Gerad 16.01 2.205 0.4865
Rotaç~
ao 0.129 4.042 0.1007
D =
Press~
ao Tens~
ao de Ma
Tens~
ao Gerad 0 0
Rotaç~
ao 0 0
K =
Tens~
ao Gerad Rotaç~
ao
x1 0.1744 0.1011
x2 1.581 3.112
x3 -1.235 -0.6663
Parameterization:
FREE form (all coefficients in A, B, C free).
Feedthrough: none
Disturbance component: estimate
Number of free coefficients: 27
Use "idssdata", "getpvec", "getcov" for parameters and their uncertainties.
Status:
Estimated using SSEST on time domain data "vapor".
Fit to estimation data: [93.92;78.93]% (prediction focus)
FPE: 3.795e-06, MSE: 0.004155
figure
showConfidence(stepplot(respimp,’b’,espest,’r’,2))
legend(’resp. Imp.’,’Estado’)
Step Response
From: Pressão From: Tensão de Magnetização
0.6
To: Tensão Gerada
0.4
0.2
0
Amplitude
-0.2
0.6
resp. Imp.
0.4 Estado
To: Rotação
0.2
-0.2
0 0.5 1 1.5 2 0 0.5 1 1.5 2
Time (seconds)
espest2 = ssest(vapor(1:250))
espest2 =
Continuous-time identified state-space model:
dx/dt = A x(t) + B u(t) + K e(t)
y(t) = C x(t) + D u(t) + e(t)
A =
x1 x2 x3 x4
x1 -29.43 -4.561 0.5994 -5.199
x2 0.4848 -0.8662 -4.101 -2.336
x3 2.839 5.084 -8.566 -3.855
x4 -12.13 0.9224 1.818 -34.29
B =
Press~
ao Tens~
ao de Ma
x1 0.1033 -1.617
C =
x1 x2 x3 x4
Tens~
ao Gerad -16.39 0.3767 -0.7566 2.808
Rotaç~
ao -5.623 2.246 -0.5356 3.423
D =
Press~
ao Tens~
ao de Ma
Tens~
ao Gerad 0 0
Rotaç~
ao 0 0
K =
Tens~
ao Gerad Rotaç~
ao
x1 -0.3555 0.08531
x2 -0.02308 5.195
x3 1.526 2.132
x4 1.787 0.03216
Parameterization:
FREE form (all coefficients in A, B, C free).
Feedthrough: none
Disturbance component: estimate
Number of free coefficients: 40
Use "idssdata", "getpvec", "getcov" for parameters and their uncertainties.
Status:
Estimated using SSEST on time domain data.
Fit to estimation data: [86.9;74.84]% (prediction focus)
FPE: 4.242e-05, MSE: 0.01414
figure
showConfidence(stepplot(espest,’b’,espest2,’r’,2))
legend(’Completo’,’Parcial’)
0.2
0
Amplitude
-0.2
0.6
Completo
0.4 Parcial
To: Rotação
0.2
-0.2
espectro = spa(vapor);
figure
bode(espectro,’b’,espest2,’r’)
h = legend(’Real’,’Estimado’);
h.Location = ’best’;
Bode Diagram
To: Tensão Gerada
-50
To: Tensão Gerada
Magnitude (dB) ; Phase (deg)
-100
1440
-1440
0
To: Rotação To: Rotação
-50
-100
720
0 Real
Estimado
-720
10 0 10 2 10 0 10 2
Frequency (rad/s)
22 Simulação de um Motor DC
Vamos analisar rapidamente o comportamento de um motor DC. Não vamos
entrar na parte de modelagem, existem inúmeras fontes explicando o processo.
s = tf(’s’);
J=0.01;
b=0.1;
K=0.01;
R=1;
L=0.5;
Gv =
0.01
---------------------------
0.005 s^2 + 0.06 s + 0.1001
Ga =
0.01
-------------------------------
0.005 s^3 + 0.06 s^2 + 0.1001 s
Gv.InputName = ’Tens~
ao’;
Gv.OutputName = ’Velocidade’;
Ga.InputName = ’Tens~
ao’;
Ga.OutputName = ’^
Angulo’;
polos_velocidade = pole(Gv)
polos_angulo = pole(Ga)
polos_velocidade =
-9.9975
-2.0025
polos_angulo =
0
-9.9975
-2.0025
figure
subplot(2,1,1)
step(Gv)
subplot(2,1,2)
step(Ga)
Step Response
From: Tensão To: Velocidade
0.1
Amplitude
0.05
0
0 0.5 1 1.5 2 2.5 3 3.5
Time (seconds)
Step Response
From: Tensão To: Ângulo
20
15
Amplitude
10
0
0 20 40 60 80 100 120 140 160 180 200
Time (seconds)
Vemos que quando o tempo vai a infinito, o output também vai, logo o sistema
não é BIBO-estável. Para facilitar vamos tornar dois sistemas SISO em um
SIMO ( Single Input Multiple Outputs ):
figure
subplot(1,2,1)
step(G);
subplot(1,2,2)
impulse(G);
figure
bode(G);
Step Response Impulse Response
From: Tensão From: Tensão
0.1 0.15
0.08
To: Velocidade
To: Velocidade
0.1
0.06
0.04
0.05
0.02
Amplitude
Amplitude
0 0
4 0.1
0.08
3
To: Ângulo
To: Ângulo
0.06
2
0.04
1
0.02
0 0
0 10 20 30 40 0 1 2 3 4
Time (seconds) Time (seconds)
Bode Diagram
From: Tensão
To: Ângulo To: VelocidadeTo: Velocidade
-100
Magnitude (dB) ; Phase (deg)
-200
0
-90
-180
0
-100
-200
0
To: Ângulo
-180
-360
10 -1 10 0 10 1 10 2 10 3
Frequency (rad/s)
0.5
-0.5
-1
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5
Saidas
0.04
0.02
-0.02 Velocidade
Ângulo
-0.04
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5
Kp = 100;
Gc = feedback(Ga*Kp,1);
Gc.InputName = ’Velocidade Desejada’;
figure
step(Gc,0:0.01:20);
1.8
1.6
1.4
Amplitude 1.2
0.8
0.6
0.4
0.2
0
0 2 4 6 8 10 12 14 16 18 20
Time (seconds)
Claramente o sistema irá se estabilizar pelo único motivo que o motor possui
atritos internos modelados pela constante b.
Vamos utilizar alguns métodos de critério de estabilidade para ver como o sis-
tema se comporta para o controle de posição:
figure
rlocus(Ga),axis([-20 5 -10 10]);
Root Locus
10
6
Imaginary Axis (seconds -1)
-2
-4
-6
-8
-10
-20 -15 -10 -5 0 5
Real Axis (seconds -1)
Podemos ver que mesmo com amortecimento, um ganho muito alto irá deses-
tabilizar o sistema. Execute o comando acima e use o cursor para descobrir
este ganho, substitua no controle proporcional e veja que de fato desestabiliza
o sistema. O diagrama de Nyquist é facilmente plotável para ajudar nestas
conclusões:
1.5
1
Imaginary Axis
0.5
-0.5
-1
-1.5
-2
-2.5
-1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0
Real Axis
V =
0 99.9500 4.0100
0 -9.9975 -2.0025
1.0000 1.0000 1.0000
Jo =
0 0 0
0 -9.9975 0
0 0 -2.0025
Ob =
0 0 2
0 2 0
Co =
inob = length(a)-rank(Ob)
inco = length(a)-rank(Co)
inob =
inco =
b = 0;
figure
step(Gc2,0:0.01:20);
Ga2 =
0.01
-------------------------------
Step Response
×10 19 From: Velocidade Desejada To: Out(1)
3
0
Amplitude
-1
-2
-3
-4
-5
-6
0 2 4 6 8 10 12 14 16 18 20
Time (seconds)
Vemos que o sistema, de fato, se torna instável. Mesmo que seja estável com
atrito o controle proporcional não é viável devido ao longo tempo de assenta-
mento, alto overshoot, muitas oscilações e eventual instabilidade. Vamos imple-
mentar um controle PID para atenuar estes efeitos:
Kp = 180;
Kd = 110;
Ki = 10;
Gc = pid(Kp,Ki,Kd);
Gm = feedback(series(Gc,Ga),1);
t = (0:0.01:7)’;
figure
step(Gm,t)
1.2
Amplitude
0.8
0.6
0.4
0.2
0
0 1 2 3 4 5 6 7
Time (seconds)
KL = 3629365359589.16;
ZL = [-4099.1739050971;-9.99749803456527;-2.00250672035499;...
-0.000239385686210815;-0.000244138720373711;-4094.41313804988+...
2.75004872395928i;-4094.41313804988-2.75004872395928i];
PL = [-4099.17391633088;0;-5462.9811678135;-0.000244139915105965;...
-4094.41313243444+2.75005916623674i;-4094.41313243444-...
2.75005916623674i;-3510.25431148115+1435.21774068424i;...
-3510.25431148115-1435.21774068424i];
KG = 14339905.5815134;
ZG = [-0.988430249319106;-8.4895499071315+3.02061433321695i;...
-8.4895499071315-3.02061433321695i];
PG = [-138.516201360636;0;-63.3666467558354+116.433332601832i;...
-63.3666467558354-116.433332601832i];
CLS = zpk(ZL,PL,KL);
CLQG = zpk(ZG,PG,KG);
1
Amplitude
0.8
0.6
0.4
0.2
0
0 0.2 0.4 0.6 0.8 1 1.2 1.4
Time (seconds)