Referencia: McClellan 5 p167
Se introduce el análisis para un sistema discreto en tiempo con respuesta de impulso finita, FIR (Finite Impulse Response), también conocido como filtros FIR.
Un filtro es un sistema con valores de salida resultantes de la suma ponderada de un número finito de valores de una secuencia de entrada. Se define como una operación también conocida como ecuación de diferencias.
1. El filtro de Medias Móviles
Una señal discreta se modifica por medio de un filtro que se determina como un promedio de un intervalo que se desplaza en el tiempo. Para un sistema tipo causal, se tiene:
y[n] = \sum_{k=n-M}^{n} b_{n-k} x[k] = b_{(M)} x[n-M ] + b_{(M-1)} x[n-M+1] + \text{...} + b_{(0)} x[n]cuando los coeficientes de bk no son iguales, se dice que el promedio o media móvil es ponderado.
2. Ejercicio. Señal rectangular
Referencia: McClellan ejemplo 5.1 p174
Considere un sistema con media móvil para 3 puntos que se expresa como una ventana que desplaza.
y[n] = \sum_{k=n-2}^{n} \frac{1}{3} x[k]con entrada rectangular entre [0,10]

Ref: Señales Escalón unitario μ(t) e Impulso unitario δ(t). blog de Señales y Sistemas
La señal se define como un escalón que se compone de dos señales escalón:
x[n]= \mu [n] -\mu [n-11]Para el algoritmo se define a partir de μ[n] que en Sympy es Heaviside. Se indican la cantidad de muestras a observar.
# INGRESO
u = sym.Heaviside(n)
# señal como suma de las partes
muestrasN = 10 + 1 # # intervalo [0,10]
xn = u - u.subs(n,n-muestrasN)
# FIR media móvil
ventana = 2 + 1 # intervalo [0,2]
bk = np.ones(ventana, dtype=float)/ventana
causal = True # causal o no causal
En la media móvil se requiere M=2, si el sistema es causal y el vector bk que son los valores de ponderación. Se obtienen los siguientes resultados:
muestreo: 11 ; tamaño ki: 17
x[n]: Heaviside(n) - Heaviside(n - 11)
bk: [0.33333333 0.33333333 0.33333333]
3. Ejercicio con señal de dos componentes
Considere la señal con un componente exponencial y otro componente senoidal que se considera ruido o interferencia que degrada la señal a observar. Se pretende minimizar o remover el efecto del componente senoidal
x[n]= \begin{cases} (1-02)^n + \frac{1}{2}\cos(2 \pi n /8 + \pi/4), & 0 \le n \le 40 \\0 , & n<0\end{cases}Realice el ejercicio con media móvil que tiene una ventana de 7 puntos o M=6.
Usando el algoritmo se tiene el siguiente resultado:

muestreo: 41 ; tamaño ki: 55
x[n]: (1.02**n + 0.5*cos(pi*n/4 + pi/4))*(Heaviside(n) - Heaviside(n - 40))
bk: [0.14285714 0.14285714 0.14285714 0.14285714
0.14285714 0.14285714 0.14285714]
El bloque de ingreso para el algoritmo es:
# INGRESO
u = sym.Heaviside(n)
# señal como suma de las partes
muestrasN = 40 + 1 # # intervalo [0,40]
x0 = u - u.subs(n,n-muestrasN)
x1 = 1.02**n +0.5*sym.cos(2*pi*n/8 + pi/4)
xn = x1*x0
# FIR media móvil
ventana = 6 + 1 # intervalo [0,6]
bk = np.ones(ventana, dtype=float)/ventana
causal=True # causal o no causal
4. Algoritmo en Python
El modelo de algoritmo para los ejercicios se presenta para la señal rectangular. Para otros ejercicios se actualiza la señal en el bloque de ingreso.
La variable causal=True establece el signo de la ventana deslizante, si el sistema es causal, el signo es negativo.
Algoritmos y funciones: telg1034.py
# ejemplo 5.1 p174 FIR - Media Móvil general
# telg1034 DSP fiec-espol edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
import telg1034 as dsp
# variables continuas
from telg1034 import t,A,w,f,p,pi,DosPi,I,equivalentes
# variables discretas
from telg1034 import n
# INGRESO
u = sym.Heaviside(n)
# señal como suma de las partes
muestrasN = 10 + 1 # # intervalo [0,10]
xn = u - u.subs(n,n-muestrasN)
# FIR media móvil
ventana = 2 + 1 # intervalo [0,2]
bk = np.ones(ventana, dtype=float)/ventana
causal = True # causal o no causal
# PROCEDIMIENTO ----------------
# muestreo x[n]
ki = np.arange(-ventana,muestrasN + ventana,1,dtype=int)
xni = sym.lambdify(n,xn, modules=equivalentes)
xki = xni(ki)
# FIR Media Móvil
causal_sign = +1 # sistema causal
if not(causal): # sistema no causal
causal_sign = -1
# ajuste de intervalo con ventana
yki = np.zeros(muestrasN + 2*ventana,dtype=float)
for i in range(-ventana,muestrasN + 2*ventana,1):
unaventana = 0
for k in range(0,ventana,1):
if (i-causal_sign*k)>=0 and (i-causal_sign*k)<=(muestrasN+ventana):
unaventana = unaventana + xki[i-causal_sign*k]*bk[k]
yki[i] = unaventana
# SALIDA
print('muestreo:',muestrasN,' ; tamaño ki:',len(ki))
print('x[n]:',xn)
print('bk:',bk)
# GRAFICA FIR
plt.subplot(211) # x[n]
plt.stem(ki,xki,linefmt = 'C0:',
label='x[n]')
plt.xlabel('n')
plt.ylabel('x[n]')
plt.title('FIR Media Móvil')
plt.legend()
plt.subplot(212) # y[n]
plt.stem(ki,yki,linefmt = 'C2:',label='y[n]')
plt.xlabel('n')
plt.ylabel('y[n]')
plt.legend()
plt.show()