Capítulo 9 Projeto usando equivalentes discretos

Objetivo: digitalizar (isto é, obter a equação de diferenças) de um controlador contínuo que já está projetado.

O resultado é obtido em duas partes:

1 - Obtem-se uma função de transferência discreta a partir de uma contínua 2 - Converte-se a função discreta em uma equação de diferenças

A equação de diferenças pode ser implementada no microcontrolador sem grandes dificuldades.

A seguir vemos 2 métodos para fazer a parte (1).

9.1 Método de Tustin

Idéia central: tratar a aproximação discreta como integração numérica

\[\begin{align} u[k] = u[k-1] + \frac{T}{2}\left(e[k]+e[k-1]\right) \end{align}\]

Transformando:
\[\begin{align} \frac{U(z)}{E(z)} = \frac{T}{2}\,\frac{1+z^{-1}}{1-z^{-1}} \end{align}\]

Equação de mapeamento \(s\) para \(z\) \[\begin{align} s \longmapsto \frac{2}{T}\,\frac{1-z^{-1}}{1+z^{-1}} = \frac{2}{T}\,\frac{z-1}{z+1} \end{align}\]

Outra forma de deduzir

Série de Taylor: \(e^{x} \approx 1 + x\)

Então \[\begin{align} z = e^{sT} = \frac{e^{sT/2}}{e^{-sT/2}} \approx \frac{1+sT/2}{1-sT/2} \end{align}\]

Resolvendo \(s\) em função de \(z\) resulta na mesma equação.

Exemplo 8.1:

\[\begin{align} D(s) = 10\,\frac{s/2+1}{s/10+1} \end{align}\]

\(\omega_s = 25\cdot \omega_{BW} =250\) rad/s.

\(f_s \approx 40\) Hz. \(T =1/40 = 0.025\) seg.

O pacote “control” possui funções especializadas que resolvem facilmente estas contas. No entanto, parece haver algumas diferenças de implementação que produzem resultados ligeiramente diferentes.

import control as ct

T = 0.025
Ds = 10*ct.tf([1/2,1],[1/10,1])
Dz = ct.c2d(Ds,T,method='bilinear')
print('Discreto: ', Dz)
## Discreto:  
## 45.56 z - 43.33
## ---------------
##   z - 0.7778
## 
## dt = 0.025

Solução com pacote simbólico

import sympy as sp

T = 0.025
s,z = sp.symbols(['s', 'z'])
Ds = 10*(s/2+1)/(s/10+1)
Dz =  Ds.subs(s,(2/T)*(z-1)/(z+1))
Dz = Dz.simplify()

str = sp.latex(Dz)

\[ D(z) = \frac{10 \cdot \left(410.0 z - 390.0\right)}{90.0 z - 70.0} \]

Sempre é bom fazer uma simulação e ver se os resultados são coerentes. Tente melhorar os resultados com o período de amostragem.

T = 0.1
Ds = 10*ct.tf([1/2,1],[1/10,1])
Dz = ct.c2d(Ds,T,method='bilinear')
td,yd = ct.step_response(Dz,0.5)
t,y = ct.step_response(Ds,0.5)

from matplotlib import pyplot as plt

plt.plot(t,y,label='continuo');
plt.step(td,yd,label='Tustin');
plt.grid();
plt.legend();
plt.show();

9.2 Mapeamento de pólos e zeros

  • Calcule um pólo/zero discreto para cada pólo/zero contínuo usando \(z=e^{sT}\).
  • Iguale o número de zeros ao de pólos adicionando termos \((z+1)\) ao numerador (opcional)
  • Multiplique a função de transferência por um ganho de modo que o ganho DC discreto seja igual ao contínuo.

Exemplo 8.2:

O controlador encontrado é \(D(s) = 0.81\,\displaystyle\frac{s+0.2}{s+2}\). O período de amostragem estabelecido é 1 segundo. O controlador possui um pólo em \(s=-2\) e um zero \(s=-0.2\).

Como o controlador tem o mesmo número de pólos e zeros, então o controlador digital deverá ser da forma:

\[\begin{align} \hat{D}(z) &= K \frac{z-a}{z-b} \end{align}\]

Cálculo do pólo: \(b = \exp(-2\cdot 1)\) (resultado será visto em Python)
Cálculo do zero: \(a = \exp(-0.2\cdot 1)\)

O ganho digital \(K\) é calculado igualando os ganhos DC da FT contínua e discreta, \(D(0)=\hat{D}(1)\).

Resolução simbólica

import numpy as np
import sympy as sp

Período de amostragem. Mapeamento dos pólos discretos a partir dos contínuos.

T = 1
a = np.exp(-0.2*T).round(4)
b = np.exp(-2*T).round(4)

Construção das funções contínua e discreta.

Ds = 0.81*(s+0.2)/(s+2)
K = sp.symbols('K')
Dz = K*(z-a)/(z-b)

Iguala os ganhos DC e estabelece equação final

equacao = sp.Eq(Ds.subs(s,0), Dz.subs(z,1))

str = sp.latex(equacao)

\[ 0.081 = 0.209668092980224 K \] Resolução da equação com o próprio “sympy”.

sol = sp.solve(equacao)

str = 'K = ' + sp.latex(sol[0])

Solução do ganho: \[ K = 0.386324875896305 \]

Retorna à função original para encontrar forma final:

Dz = Dz.subs(K,sol[0].round(4))

\[\begin{align} D(z) &= \frac{0.3863 \left(z - 0.8187\right)}{z - 0.1353}\\D(z) &= \frac{0.3863 z - 0.3163}{z - 0.1353} \end{align}\]

Fazer com o módulo “control” é um pouco mais direto. Acompanhe:

Ds = 0.81*ct.tf([1,0.2],[1,2])         
T = 0.020                            
a = np.exp(T*Ds.zeros())               
b = np.exp(T*Ds.poles())               
num = np.poly(a)                      
den = np.poly(b)                      
Dz = ct.tf(num,den,T)                  
Dz = Dz*Ds.dcgain()/Dz.dcgain()        
print(Dz)
## 
## 0.081 z - 0.08068
## ------------------
## 0.1018 z - 0.09782
## 
## dt = 0.02

Vamos fazer uma simulação para conferir:

t,y = ct.step_response(Ds,1.5)
k,yd = ct.step_response(Dz,1.5)
plt.plot(t,y,label='Contínuo')
## [<matplotlib.lines.Line2D object at 0x000002B053DA1E20>]
plt.step(k,yd,label='Mapeamento')
## [<matplotlib.lines.Line2D object at 0x000002B053DA3A70>]
plt.grid()
plt.xlabel('Tempo (seg)')
## Text(0.5, 0, 'Tempo (seg)')
plt.legend()
## <matplotlib.legend.Legend object at 0x000002B054AA90A0>
plt.show()

Exemplo um pouco mais complexo:

Ache o equivalente por mapeamento da função: \[ \begin{align} G(s) &= \frac{s^2-1}{s(s^2+16)} \end{align} \]

Utilize \(T=0.01\).

from numpy import exp, round
T = 0.05
polos = [0,4j,-4j]
zeros = [-1,1]

A = [exp(s*T) for s in polos]
B = [exp(s*T) for s in zeros]
K1 = sp.symbols('K_1')
G1 = K1 * sp.prod([z-b for b in B]) / sp.prod([z-a for a in A])
DC1 = sp.simplify(G1*(z-1)).subs(z,1)
DC = -1/16
k1 = sp.solve(sp.Eq(DC1,DC))[0]
G1 = G1.subs(K1,k1)

\[ G(z) = \frac{0.9965 \left(z - 1.051\right) \left(z - 0.9512\right)}{\left(z - 1.0\right) \left(z - 0.9801 - 0.1987 i\right) \left(z - 0.9801 + 0.1987 i\right)} \]

K2 = sp.symbols('K_2')
G2 = K2 * sp.prod([z-b for b in B]) *(z+1) / sp.prod([z-a for a in A])
DC2 = sp.simplify(G2*(z-1)).subs(z,1)
DC = -1/16
k2 = sp.solve(sp.Eq(DC2,DC))[0]
G2 = G2.subs(K2,k2)

\[ G(z) = \frac{0.4982 \left(z - 1.051\right) \left(z - 0.9512\right) \left(z + 1.0\right)}{\left(z - 1.0\right) \left(z - 0.9801 - 0.1987 i\right) \left(z - 0.9801 + 0.1987 i\right)} \]

9.3 Converter para equação de diferenças.

Para converter a função do controlador para uma equação de diferenças, introduzimos os sinais de entrada e saída do controlador, distribuimos os coeficientes da equação depois aplicamos a transformada inversa.

Normalmente a equação de diferenças é escrita em termos de atrasos (valores passados), então pode ser conveniente converter a função discreta para potências negativas antes de fazer a transformação.

Voltando ao exemplo 8.2:

Como o sistema é de ordem (grau do denominador) 1, multiplicamos numerador e denominador por \(z^{-1}\).

\[\begin{align} D(z) &= \frac{0.3863𝑧−0.3162}{𝑧−0.1353}\,\cdot \frac{z^{-1}}{z^{-1}}\\ &= \frac{0.3863−0.3162z^{-1}}{1−0.1353z^{-1}} \end{align}\]

Introduzimos os sinais de entrada \(E(z)\) (erro) e saída \(U(z)\) (ação de controle) na equação e distribuimos.

\[\begin{align} \frac{U(z)}{E(z)}&= \frac{0.3863−0.3162z^{-1}}{1−0.1353z^{-1}}\\ (1−0.1353z^{-1})\,U(z) &= (0.3863−0.3162z^{-1}) E(z)\\ U(z) &= 0.1353z^{-1}U(z) + 0.3863E(z)−0.3162z^{-1}E(z) \end{align}\]

Aplicando a transformada inversa e a propriedade do atraso temos a equação que implementa o controlador:

\[\begin{align} u[k] &= 0.1353u[k-1] + 0.3863e[k]−0.3162e[k-1] \end{align}\]