con las condiciones iniciales y[-1]=11/16, y[-2]=37/36,
ante una entrada x[n]=(-2)-nμ[n]
Respuesta total
=
respuesta a entrada cero
+
respuesta a estado cero
En el ejemplo se encuentra que la solución total de la ecuación de diferencias se puede separar en dos componentes. El primero es generado por las condiciones iniciales y el segundo por la entrada x[n]
respuesta total = (respuesta a entrada cero) + (respuesta estado cero)
continuando luego con el proceso de fracciones parciales y cambio al dominio de tiempo discreto. (realizado en desarrollo analítico), aqui se usa la transformada_z inversa con Sympy:
La transformada z convierte las ecuaciones de diferencias en expresiones algebraicas que permiten encontrar soluciones en el dominio z. A partir de las soluciones en el dominio z, se aplica la transformada inversa z que lleva a la solución en el dominio del tiempo
Ejercicio1
Referencia: Lathi Ejemplo 5.5 p510
Resolver
y[n+2] – 5 y[n+1] + 6 y[n] = 3 x[n+1] + 5 x[n]
con las condiciones iniciales y[-1]=11/16, y[-2]=37/36,
ante una entrada x[n]=(2)-nμ[n]
Desarrollo analítico
Usando la propiedad de desplazamiento de 2 unidades a la derecha.
y[n] – 5 y[n-1] +6 y[n-2] = 3 x[n-1] + 5 x[n-2]
se aplica la transformada z, teniendo en cuenta que y[n-k] significa y[n-k]μ[n], pues consideramos solamente la situación de n≥0, y[n] esta presente incluso antes de n=0.
En el lado derecho se muestran términos generados por una respuesta natural y una respuesta forzada. Dicho de otra forma, se muestran términos generados por las condiciones iniciales y por la señal x[n].
reagrupando el lado derecho en forma de numerador y denominador
(1−5z1+6z21)Y[z]=z(z−0.5)3z2−9.5z+10.5
se puede reescribir, multiplicando cada lado por z2
Muchas de las transformadas X(z) de interés en la práctica son funciones racionales, que pueden ser expresadas como la suma de fracciones parciales, cuyas transformadas inversas pueden ser encontradas rápidamente en la tabla de transformadas.
Se busca evitar realizar el integral en el plano complejo requerido para encontrar la transformada inversa de z.
El método de las fracciones parciales es práctico porque cada x[n] transformable se define para n≥0, existe su correspondiente X[z] definida para |z|>r0 y viceversa. (r0 es constante)
Para desarrollar y probar el algoritmo con Sympy-Python, se usará el desarrollo de los tres ejercicios siguientes, con polos únicos, repetidos y complejos. El algoritmo final del literal c integra las soluciones anteriores.
Que tiene una entrada con términos multiplicadas por μ[n-1], que es un inconveniente y no deseable. Se prefieren las transformadas respecto a μ[n].
Observando la tabla de transformadas z entre los ítems 6a y 7, se tiene que si la señal X[n] es multiplicada por u[n], el numerador tiene un factor z. Esto se consigue expandiendo en fracciones parciales X[z]/z que son fracciones parciales modificadas cuando se tiene un factor z en el numerador y luego se restauran multiplicando el todo el resultado por z.
que es el resultado esperado y con respuesta equivalente al resolver con algoritmo iterativo para n=0,1,2,3,…
Por este motivo, es recomendable siempre expandir en fracciones parciales X[z]/z en lugar de solo X[z], pues tiene un factor z en el numerador.
Algoritmo en Python
Para realizar el ejercicio, debemos considerar usar Sympy. Las operaciones se realizan al dividir X[x]/z y simplificar la nueva expresión Xzz, luego una expansión Xzp. El resultado se multiplica término a término por z y de añaden a la expresión total Xzfp.
El bloque de ingreso que se modifica para cada caso es:
Para encontrar las constantes, se evalúa la expresión de la izquierda con los valores de cada raíz del denominador, en cada caso se obvia el término de la raíz en el denominador,
reemplazando en la transformada, se encuentra x[n].
x[n]=[2+3.2(5)ncos(0.927n−2.246)]μ[n]
pasamos a probar el algoritmo, donde se encuentra que para el denominador hay raíces complejas. Otra forma de observar es que las funciones parciales aún entregan resultados con términos que tienen el denominador con grado 2. Donde hay que usar expresiones de la tabla de transformadas.
El algoritmo inicia de la misma forma que en la sección anterior. Ahora hay que revisar el grado del denominador en cada término. Si es de grado 2, se calculan los valores de r, β y θ para armar las transformada a partir de la tabla.
# Transformada z- Fracciones parciales# Polos únicos, repetidos y complejos# Lathi Ejercicio 5.3a pdf495# blog.espol.edu.ec/telg1001import numpy as np
import sympy as sym
# INGRESO
z = sym.Symbol('z')
Pz = 2*z*(3*z+17)
Qz = (z-1)*(z**2-6*z+25)
#Pz = z*(2*z**2-11*z+12)#Qz = (z-1)*(z-2)**3##Pz = 8*z-19##Qz = (z-2)*(z-3)
Xz = Pz/Qz
# PROCEDIMIENTOdefapart_z(Fz):
''' fracciones parciales en dominio z
modifica con factor 1/z
'''
Fz = sym.simplify(Fz)
# fracciones parciales modificadas con 1/z
Fzz = (Fz)/z
Fzm = sym.apart(Fzz,z)
# restaura z
term_suma = sym.Add.make_args(Fzm)
Fzp = 0*z
for term_k in term_suma:
Fzp = Fzp + term_k*z
return(Fzp)
defQ_cuad_z_parametros(Fz):
''' parametros cuadraticos en dominio z
'''defQ_cuad_z_term(untermino):
''' parametros cuadraticos en dominio z
de un termino de fraccin parcial
'''
unparametro ={}
# revisa denominador cuadratico
[numerador,denominador] = (untermino).as_numer_denom()
gradoD = 0
coeficientesD = denominador
gradoN = 0
coeficientesN = numerador
ifnot(denominador.is_constant()):
denominador = denominador.as_poly()
gradoD = denominador.degree()
coeficientesD = denominador.coeffs()
ifnot(numerador.is_constant()):
numerador = numerador.as_poly()
gradoN = numerador.degree()
coeficientesN = numerador.coeffs()
if gradoD == 2 and gradoN==2:
a = float(coeficientesD[1])/2
gamma2 = float(coeficientesD[2])
gamma = np.sqrt(gamma2)
A = float(coeficientesN[0])
B = float(coeficientesN[1])
rN = (A**2)*gamma2 + B**2 - 2*A*a*B
rD = gamma2 - a**2
r = np.sqrt(rN/rD)
beta = np.arccos(-a/gamma)
thetaN = A*a-B
thetaD = A*np.sqrt(gamma2-a**2)
theta = np.arctan(thetaN/thetaD)
unparametro = {'r':r,
'gamma':gamma,
'beta':beta,
'theta':theta}
return(unparametro)
Fz = apart_z(Fz)
# parametros denominador cuadratico
Qs2 = {}
term_suma = sym.Add.make_args(Fz)
for term_k in term_suma:
Qs2_k = Q_cuad_z_term(term_k)
iflen(Qs2_k)>0:
Qs2[term_k] = Qs2_k
return(Qs2)
Fz = apart_z(Xz)
Qs2 = Q_cuad_z_parametros(Fz)
# SALIDAprint('\n Xz:')
sym.pprint(Xz)
print('\n Xz en fracciones parciales')
sym.pprint(Fz)
iflen(Qs2)>0:
print('parametros cuadraticos: ')
for Qs2_k in Qs2:
print(Qs2_k,':')
for cadauno in Qs2[Qs2_k].keys():
print(cadauno,'\t',Qs2[Qs2_k][cadauno])
Dada la similitud entre sistemas LTIC y LTID, las convenciones para diagramas de bloques y las reglas de interconexión son idénticas a los sistemas contínuos. Los diagramas mostrados se realizan con el programa Xcos de SciLab.
Una función de transferencia general se expresa como:
La función de transferencia es de primer orden (N=1), por lo que solo se usará un retraso para el diagrama. Los coeficientes de retroalimentación de retraso y adelanto son:
a1= 5 y b0 = 0, b1=2
La imagen presenta dos formas de realizar los diagramas
Ejemplo 2. H(z)
Referencia: Lathi 5.8b p522
H(z)=z+14z+28
la función de transferencia también es de primer orden (N=1), los coeficientes de retraso y adelanto son:
a1= 1 y b0 = 4, b1=28
La imagen presenta dos formas de realizar el diagrama de bloques
Ejemplo 3. H(z)
Referencia: Lathi 5.8c p522
H(z)=z+7z
la función de transferencia también es de primer orden (N=1), los coeficientes de retraso y adelanto son:
a1= 7 y b0 = 1, b1=0
Ejemplo 4. H(z)
Referencia: Lathi 5.8d p522
H(z)=z2+6z+54z+28
la función de transferencia también es de segundo orden (N=2), los coeficientes de retraso y adelanto son:
a1= 6, a2= 5 y b0 = 0, b1=4, b2=28
Ejemplo 5. Sistema LTI D
Referencia: Ejemplo Openheim 10.28 p784
Considere el sistema LTI causal descrito mediante:
y[n]−41y[n−1]=x[n]
con función del sistema:
H(z)=1−41z−11
Aqui z-1 es la función del sistema con retraso unitario. El diagrama de bloques en la figura contiene un lazo de retroalimentación.
y[n]−41z−1y[n]=x[n]y[n]=x[n]+41z−1y[n]
Ejemplo 6. Función H(z)
Referencia: Ejemplo Openheim 10.29 p785
Considere un sistema LTI causal con función del sistema:
H(z)=1−41z−11−2z−1
La función se puede separar en bloque de denominador y numerador, semejante a los polinomios Q(E) y P(E).
=[1−41z−11][1−2z−1]
Se observa en el diagrama (a) que z-1 se encuentra duplicado pues ambos bloques toman la misma señal para aplicarle un atraso, cada uno le da a una ganancia diferente. Por lo que un solo bloque z-1 puede realizar la misma operación.
En el mundo de los circuito digitales y componentes, la situación se interpreta como un componente duplicado, lo que tiene implicaciones de costos de implementación, recuerde el tema cuando construye un circuito digital usando puertas lógicas y registros.
La Transformada z inversa, usa la Tabla de Paresf[n] y F[z] y los algoritmos para buscar una expresión semejante F.match() en conjunto con la tabla de propiedades y los algoritmos desarrollados en la sección anterior. El resultado se integra desde telg1001.py y se muestra en los siguientes ejemplos:
Ejemplo 1. Transformada z inversa de una fracción X[1/z]
Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:
X[z]=1−az−11 , ∣z∣>∣a∣X[z]=z−az , ∣∣∣z∣>∣a∣
siendo la expresión de ingreso al algoritmo:
F = z/(z - 2)
el resultado es:
f[n] : (2**n*Heaviside(n), Abs(z) > 2, True)
>>>
Ejemplo 1a. Instrucciones Python
# transformada z propiedades con Sympy# aplicar luego de buscar en tabla de paresimport sympy as sym
import telg1001 as fcnm
# INGRESO
n = sym.Symbol('n', real=True)
z = sym.Symbol('z')
u = sym.Heaviside(n)
# (a**n)*f[n] <--> F(z/a)
F = z/(z - 2) #f = (2**n)*u# PROCEDIMIENTO
fn = fcnm.inverse_z_transform(F,z,n)
# SALIDAprint('f[n] :',fn)
El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.
Ejemplo 2. Transformada z inversa usando expansión en fracciones parciales
Referencia: Lathi 5.3 a
Encuentre la transformada z inversa para:
F[z]=(z−2)(z−3)8z−19
el ingreso para el algoritmo del ejercicio anterior es:
activando la variable sym.SYMPY_DEBUG=True, se observa el proceso de fracción parcial modificada, la búsqueda en la tabla, y aplicación de una propiedad de la transformada z.
Muchas de las transformadas X[z] de interés práctico son fracciones de polinomios en z, que pueden ser expresadas como una suma de fracciones parciales cuya inversa puede ser revisada en una tabla de transformadas z.
El método de fracciones parciales funciona dado que para cada x[n] transformable con n≥0 le corresponde una X[z] única definida para |z|>a y viceversa. Para lo mostrado, se supone que se usa la fracción parcial mas simple.
Ejemplo 1a. Transformada z inversa de una fracción X[1/z]
Continuando con el ejercicio presentado para convertir x[n] a X[z], se tiene que:
X[z]=1−az−11 , ∣z∣>∣a∣
la expresión se puede expandir en series se potencias y obtener los primeros términos de la secuencia de x[n]. Los términos son útiles si se se requieren los m primeros términos de la secuencia, es decir n se encuentra en [0,m-1]
X[z]:
z
------
-a + z
F[z]:
2 3 4 5 6
a a a a a a /1 \
1 + - + -- + -- + -- + -- + -- + O|--; z -> oo|
z 2 3 4 5 6 | 7 |
z z z z z \z /
Términos x[n] entre[0,7]
[1, a, a**2, a**3, a**4, a**5, a**6]
x[n] con a= 1/2
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625]
Al final de la serie F[z] se muestra un término con el orden del error.
De los términos mostrados, se observa que X[n] = an
Usando por ejemplo a=1/2, se obtiene como resultado de x[n],
>>> xi
[1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625]
Ejemplo 1a. Instrucciones Python
# transformada z inversa de X[z]import sympy as sym
# INGRESO
z = sym.symbols('z',)
n = sym.symbols('n', nonnegative=True)
a = sym.symbols('a')
u = sym.Heaviside(n)
Xz = 1/(1-a*z**(-1))
# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)
m = 7 # Términos a graficar# PROCEDIMIENTO# Series de potencia z**(-1)
Fz = sym.series(Xz,z**(-1), n=m)
# Terminos de X[n]
xn = []
termino = Fz.args
for i inrange(0,m,1):
xn.append(termino[i]*(z**i))
# SALIDAprint('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('\n Términos x[n] entre [0,'+str(m)+']')
print(xn)
# GRAFICA valores ---------------import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i inrange(0,m,1):
valor = xn[i].subs({z:1,a:a_k})
xi.append(float(valor))
ki.append(i)
print('\n x[n] con a=',a_k)
print(xi)
# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()
plt.show()
Ejemplo 1b. Transformada z inversa de una fracción dada con X[z]
Si la expresión se usa de la forma simplificada, que es la más común para tratar las expresiones con Sympy, el algoritmo anterior para las series no realiza la misma respuesta.
X[z]=z−az , ∣∣∣z∣>∣a∣X[z]=1−az−11 , ∣∣∣z∣>∣a∣
Para este caso se multiplica el numerador y denominador por 1/z, obteniendo la expresión del ejemplo anterior. Para generar la serie se realiza el, cambio de variable Z=1/z para generar la serie sobre Z. Luego se restablece en la expresión antes de mostrar los términos, y se obtiene el mismo resultado.
De los términos mostrados, se observa que X[n] = an
Ejemplo 1b. Instrucciones en Python
# transformada z inversa de X[z]# supone que la expresión son fracciones parcialesimport sympy as sym
# INGRESO
z = sym.symbols('z')
n = sym.symbols('n', integer=True, positive=True)
a = sym.symbols('a')
Xz = z/(z-a)
# valor a como racional en dominio 'ZZ' enteros
a_k = sym.Rational(1/2).limit_denominator(100)
m = 7 # Términos a graficar# PROCEDIMIENTO# expresión Xz con z para aplicar serie# separa numerador y denominador
[Pz,Qz] = Xz.as_numer_denom()
Pz = (Pz*(1/z)).expand(1/z)
Qz = (Qz*(1/z)).expand(1/z)
# cambia Z por 1/z
Z = sym.symbols('Z')
PZ = Pz.subs(1/z,Z)
QZ = Qz.subs(1/z,Z)
XZ = PZ/QZ
# Series de potencia de Z
FZ = sym.series(XZ,Z, n=m)
Fz = FZ.subs(Z,1/z) # restituye 1/z# Terminos de X[n]
xn = []
termino = Fz.args
for i inrange(0,m,1):
xn.append(termino[i]*(z**i))
# SALIDAprint('X[z]: ')
sym.pprint(Xz)
print('\n F[z]:')
sym.pprint(Fz)
print('Términos x[n] entre[0,'+str(m)+']')
print(xn)
# GRAFICA valores ---------------import numpy as np
import matplotlib.pyplot as plt
# Terminos de X[n]
xi = [] ; ki=[]
for i inrange(0,m,1):
valor = xn[i].subs({z:1,a:a_k})
xi.append(float(valor))
ki.append(i)
print('\n x[n] con a=',a_k)
print(xi)
# grafica entrada x[n]
plt.axvline(0,color='grey')
plt.stem(ki,xi,label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title(r'x[n]= $'+str(sym.latex(xn))+'$')
plt.grid()
plt.show()
El algoritmo presentado puede ser tomado como punto de partida para los siguientes ejercicios. Realizado para explicación conceptual.