Definiciones iniciales
p = cos ɸ
q = sin ɸ
ck = cos(k · ɸ)
sk = sin(k · ɸ)
r = coeficiente de filtrado
fo = frecuencia de corte
fs = frecuencia de muestreo
Filtro pasa banda
ck+1 = r · (p · ck - q · sk) + ul
sk+1 = r · (q · ck + p · sk)
Estas ecuaciones describen un filtro pasa banda recursivo. Los términos ck y sk representan las componentes coseno y seno de la señal filtrada, respectivamente. El coeficiente r controla el ancho de banda del filtro.
float p, q, ck, sk, r;
float ul;
void setup() {
p = cos(0.5);
q = sin(0.5);
ck = 0.0;
sk = 0.0;
r = 0.9;
ul = 0.0;
}
void loop() {
float ck_nuevo = r * (p * ck - q * sk) + ul;
float sk_nuevo = r * (q * ck + p * sk);
ck = ck_nuevo;
sk = sk_nuevo;
}
b1=-r^2 b2=2·r·cos(2·π·fo/fs)
#include <Arduino.h>
float r = 0.9;
float fo = 1000.0;
float fs = 10000.0;
float b1, b2;
void setup() {
float pi = 3.14159265358979323846;
float omega = 2.0 * pi * fo / fs;
b1 = -r * r;
b2 = 2.0 * r * cos(omega);
}
void loop() {
float muestraEntrada = analogRead(A0) * 5.0 / 1023.0;
float muestraFiltrada = b1 * muestraEntrada + b2 * muestraEntrada;
}
Filtro pasa banda senoidal cosenoidal
ck2 = b1 · ck1 + b2 · ck + uk
Donde:
b1 = -r^2
b2 = 2 · r · cos(2 · π · fo / fs)
Esta es una implementación específica de un filtro pasa banda, donde fo es la frecuencia central del filtro y fs es la frecuencia de muestreo. El término uk representa la entrada del filtro.
#include <Arduino.h>
float b1, b2;
float ck1, ck, uk;
void setup() {
b1 = -0.81;
b2 = 0.9;
ck1 = 0.0;
ck = 0.0;
uk = 0.0;
}
void loop() {
float ck2 = b1 * ck1 + b2 * ck + uk;
ck1 = ck;
ck = ck2;
}
Eco simple
yk = sk + a · skm
Donde sk es el sonido original y skm es la señal retardada atenuada por el factor a. Esta ecuación simula un eco simple.#include <Arduino.h>
float a = 0.5;
float skm = 0.0;
void setup() {
}
void loop() {
float sk = analogRead(A0) * 5.0 / 1023.0;
float yk = sk + a * skm;
skm = yk;
}
Eco múltiple
yk = sk + a · skL + b · skm
Esta es una extensión del eco simple, añadiendo un segundo término de eco con diferente retardo (L) y atenuación (b).#include <Arduino.h>
float a = 0.5;
float b = 0.3;
float kL = 0.0;
float skm = 0.0;
void setup() {
}
void loop() {
float sk = analogRead(A0) * 5.0 / 1023.0;
float yk = sk + a * kL + b * skm;
kL = yk;
skm = sk;
}
Filtro FIR (Respuesta Impulsiva Finita)
yk = a0 · xk + a1 · xk-1 + a2 · xk-2 + ...
O en notación de suma:
y(n) = Σ a(k) · x(n - k)
Estas ecuaciones describen un filtro FIR, donde la salida y(n) es una combinación lineal de las entradas actuales y pasadas x(n-k), ponderadas por los coeficientes a(k).#include <Arduino.h>
float a0, a1, a2;
float xk1, xk2;
void setup() {
}
void loop() {
float xk = analogRead(A0) * 5.0 / 1023.0;
float yk = a0 * xk + a1 * xk1 + a2 * xk2;
xk2 = xk1;
xk1 = xk;
}
#include <Arduino.h>
const int LEN = 10;
float a[LEN] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
float x[LEN];
float y = 0.0;
void setup() {
for (int i = 0; i < LEN; i++) {
x[i] = analogRead(A0) * 5.0 / 1023.0;
}
}
void loop() {
y = 0.0;
for (int i = 0; i < LEN; i++) {
y += a[i] * x[i];
}
for (int i = LEN - 1; i > 0; i--) {
x[i] = x[i - 1];
}
x[0] = analogRead(A0) * 5.0 / 1023.0;
}
Filtro IIR (Respuesta Impulsiva Infinita)
y(n) = Σ a(k) · x(n - k) + Σ b(k) · y(n - k)
Esta ecuación describe un filtro IIR, que incluye tanto las entradas pasadas x(n-k) como las salidas pasadas y(n-k) en el cálculo de la salida actual. Los coeficientes a(k) y b(k) determinan las características del filtro.
Estas fórmulas representan diferentes tipos de filtros y efectos comúnmente utilizados en DSP. Cada una tiene sus propias características y aplicaciones específicas en el procesamiento de señales de audio y otros tipos de señales digitales.#include <Arduino.h>
const int LEN = 10;
float a[LEN] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
float b[LEN] = {0.5, 0.4, 0.3, 0.2, 0.1, 0.0, -0.1, -0.2, -0.3, -0.4};
float y[LEN];
void setup() {
for (int i = 0; i < LEN; i++) {
y[i] = 0.0;
}
void loop() {
float x = analogRead(A0) * 5.0 / 1023.0;
float yn = 0.0;
for (int k = 0; k < LEN; k++) {
yn += a[k] * x * pow(0.5, k) + b[k] * y[k];
}
for (int i = LEN - 1; i > 0; i--) {
y[i] = y[i - 1];
}
y[0] = yn;
}
Filtro FIR en Procesamiento Digital de Señales
El filtro FIR (Finite Impulse Response) es un tipo de filtro digital que responde únicamente a una cantidad finita de muestras. Su implementación en sistemas embebidos, como Arduino, permite la eliminación de ruido y el suavizado de señales.
Este método se basa en una combinación ponderada de valores pasados de la señal de entrada para calcular la salida filtrada.
Fundamento Matemático del Filtro FIR
La ecuación del filtro FIR para una señal discreta se expresa como:
Fórmula de cálculo:
Filtrado2 = (FactorFIR · w.Previous) + (((w.Previous2 + w.Previous3) / 2) · (1 - FactorFIR))
|
FactorFIR = Coeficiente de ponderación
w.Previous = Muestra anterior
w.Previous2, w.Previous3 = Muestras previas adicionales
Filtrado2 = Salida filtrada
|
// Implementación de un filtro FIR en Arduino
double FactorFIR = 0.8; // Coeficiente FIR
double Filtrado2;
double wPrevious = 0;
double wPrevious2 = 0;
double wPrevious3 = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
double nuevaEntrada = analogRead(A0); // Leer señal de entrada
Filtrado2 = (FactorFIR * wPrevious) + (((wPrevious2 + wPrevious3) / 2) * (1 - FactorFIR));
// Almacenar valores anteriores
wPrevious3 = wPrevious2;
wPrevious2 = wPrevious;
wPrevious = nuevaEntrada;
Serial.println(Filtrado2); // Enviar resultado filtrado
delay(100); // Intervalo de muestreo
}
Conclusión
Este filtro FIR permite suavizar la señal de entrada reduciendo el ruido sin necesidad de una transformada recursiva.
Gracias a su implementación en sistemas embebidos, se puede aplicar en procesamiento de señales analógicas, telecomunicaciones y sensores industriales.
Filtro FIR con Ventana Bartlett (Triangular)
La ventana Bartlett es una técnica de suavizado aplicada a filtros FIR para reducir los efectos de truncamiento. Su forma triangular atenúa gradualmente los coeficientes, mejorando la respuesta en frecuencia y reduciendo el rizado en la banda de paso.
Fundamento Matemático
La ventana Bartlett se define como:
Fórmula de cálculo:
w(n) = 1 - |(2n / (N - 1)) - 1|
Fórmula aplicada en el filtro FIR:
Filtrado = Σ [w(n) · x(n)]
|
w(n) = Coeficiente de ventana Bartlett (valor entre 0 y 1)
N = Número total de coeficientes del filtro
x(n) = Muestra de entrada
Filtrado = Señal filtrada
|
// Implementación de filtro FIR con ventana Bartlett en Arduino
const int N = 5; // Número de coeficientes
double ventanaBartlett[N] = {0.2, 0.4, 0.6, 0.4, 0.2}; // Coeficientes Bartlett
double muestras[N] = {0, 0, 0, 0, 0}; // Historial de muestras
void setup() {
Serial.begin(9600);
}
void loop() {
double nuevaEntrada = analogRead(A0); // Leer señal de entrada
double filtrado = 0;
// Desplazamiento de muestras
for (int i = N - 1; i > 0; i--) {
muestras[i] = muestras[i - 1];
}
muestras[0] = nuevaEntrada;
// Aplicación de filtro FIR con ventana Bartlett
for (int i = 0; i < N; i++) {
filtrado += ventanaBartlett[i] * muestras[i];
}
Serial.println(filtrado); // Mostrar salida filtrada
delay(100);
}
Conclusión
El uso de la ventana Bartlett en filtros FIR permite una mejor atenuación del rizado sin comprometer la respuesta en frecuencia. Es útil en aplicaciones de procesamiento de señales donde se requiere una transición suave en la banda de paso.
Filtro FIR con Ventanas Hann y Hamming
Las ventanas Hann y Hamming son funciones de ponderación utilizadas en filtros FIR para mejorar la respuesta en frecuencia y reducir el rizado en la banda de paso. Ambas suavizan los coeficientes del filtro, pero la ventana Hamming ofrece mejor atenuación en la banda de rechazo.
Fundamento Matemático
Las funciones de ventana se definen como:
Fórmula de la ventana Hann:
w(n) = 0.5 · (1 - cos(2 · π · n / (N - 1)))
Fórmula de la ventana Hamming:
w(n) = 0.54 - 0.46 · cos(2 · π · n / (N - 1))
|
w(n) = Coeficiente de ventana
N = Número total de coeficientes
n = Índice de la muestra
π = Constante matemática
|
// Implementación de filtro FIR con ventanas Hann y Hamming en Arduino
const int N = 5; // Número de coeficientes
double ventanaHann[N] = {0.5, 0.75, 1.0, 0.75, 0.5}; // Coeficientes Hann
double ventanaHamming[N] = {0.54, 0.74, 1.0, 0.74, 0.54}; // Coeficientes Hamming
double muestras[N] = {0, 0, 0, 0, 0}; // Historial de muestras
void setup() {
Serial.begin(9600);
}
void loop() {
double nuevaEntrada = analogRead(A0); // Leer señal de entrada
double filtradoHann = 0;
double filtradoHamming = 0;
// Desplazamiento de muestras
for (int i = N - 1; i > 0; i--) {
muestras[i] = muestras[i - 1];
}
muestras[0] = nuevaEntrada;
// Aplicación de filtro FIR con ventana Hann
for (int i = 0; i < N; i++) {
filtradoHann += ventanaHann[i] * muestras[i];
filtradoHamming += ventanaHamming[i] * muestras[i];
}
Serial.print("Hann: ");
Serial.print(filtradoHann);
Serial.print(" | Hamming: ");
Serial.println(filtradoHamming); // Mostrar salida filtrada
delay(100);
}
Conclusión
Las ventanas Hann y Hamming suavizan la transición de los coeficientes en filtros FIR, reduciendo el rizado y mejorando la atenuación en la banda de rechazo. Son ampliamente utilizadas en procesamiento de señales digitales y telecomunicaciones.
Filtro FIR con Ventana Blackman
La ventana Blackman es una función de ponderación utilizada en filtros FIR para lograr una alta atenuación en la banda de rechazo y reducir el rizado en la banda de paso. Se caracteriza por una transición suave y una reducción drástica de lóbulos secundarios en la respuesta en frecuencia.
Fundamento Matemático
La ventana Blackman se define como:
Fórmula de la ventana Blackman:
w(n) = 0.42 - 0.5 · cos(2 · π · n / (N - 1)) + 0.08 · cos(4 · π · n / (N - 1))
|
w(n) = Coeficiente de ventana Blackman
N = Número total de coeficientes del filtro
n = Índice de la muestra
π = Constante matemática
|
// Implementación de filtro FIR con ventana Blackman en Arduino
const int N = 5; // Número de coeficientes
double ventanaBlackman[N] = {0.42, 0.58, 1.0, 0.58, 0.42}; // Coeficientes Blackman
double muestras[N] = {0, 0, 0, 0, 0}; // Historial de muestras
void setup() {
Serial.begin(9600);
}
void loop() {
double nuevaEntrada = analogRead(A0); // Leer señal de entrada
double filtradoBlackman = 0;
// Desplazamiento de muestras
for (int i = N - 1; i > 0; i--) {
muestras[i] = muestras[i - 1];
}
muestras[0] = nuevaEntrada;
// Aplicación de filtro FIR con ventana Blackman
for (int i = 0; i < N; i++) {
filtradoBlackman += ventanaBlackman[i] * muestras[i];
}
Serial.println(filtradoBlackman); // Mostrar salida filtrada
delay(100);
}
Conclusión
La ventana Blackman es ideal cuando se requiere una alta atenuación en la banda de rechazo, reduciendo interferencias y mejorando la precisión en el filtrado de señales. Es ampliamente usada en procesamiento digital de señales y aplicaciones de telecomunicaciones.
Filtro FIR con Ventana Kaiser
La ventana Kaiser es una de las más flexibles en el diseño de filtros FIR, ya que permite ajustar la relación entre atenuación en la banda de rechazo y la transición en la banda de paso mediante el parámetro β. Esto la hace útil en aplicaciones donde se requiere un control preciso del filtrado.
Fundamento Matemático
La ventana Kaiser se define mediante la función de Bessel de primera especie:
Fórmula de la ventana Kaiser:
w(n) = I0(β · sqrt(1 - (2n / (N - 1))²)) / I0(β)
|
w(n) = Coeficiente de la ventana Kaiser
I0(β) = Función de Bessel modificada de primera especie
N = Número total de coeficientes del filtro
n = Índice de la muestra
β = Parámetro de control de la ventana
|
Ejemplo de Implementación en Arduino:
// Implementación de filtro FIR con ventana Kaiser en Arduino
#include
const int N = 5; // Número de coeficientes
double beta = 4.0; // Parámetro de ajuste de la ventana Kaiser
double ventanaKaiser[N]; // Coeficientes Kaiser
double muestras[N] = {0, 0, 0, 0, 0}; // Historial de muestras
// Función para calcular la ventana Kaiser
double I0(double x) {
double sum = 1;
double fact = 1;
double power = 1;
for (int k = 1; k < 10; k++) { // Aproximación de la función Bessel
fact *= k;
power *= (x / 2) * (x / 2);
sum += power / (fact * fact);
}
return sum;
}
void setup() {
Serial.begin(9600);
// Calcular los coeficientes de la ventana Kaiser
for (int n = 0; n < N; n++) {
ventanaKaiser[n] = I0(beta * sqrt(1 - pow((2.0 * n / (N - 1)) - 1, 2))) / I0(beta);
}
}
void loop() {
double nuevaEntrada = analogRead(A0); // Leer señal de entrada
double filtradoKaiser = 0;
// Desplazamiento de muestras
for (int i = N - 1; i > 0; i--) {
muestras[i] = muestras[i - 1];
}
muestras[0] = nuevaEntrada;
// Aplicación de filtro FIR con ventana Kaiser
for (int i = 0; i < N; i++) {
filtradoKaiser += ventanaKaiser[i] * muestras[i];
}
Serial.println(filtradoKaiser); // Mostrar salida filtrada
delay(100);
}
Conclusión
La ventana Kaiser ofrece un control ajustable sobre el filtrado al modificar el parámetro β, permitiendo un compromiso entre la anchura de la banda de transición y la atenuación en la banda de rechazo. Es especialmente útil en sistemas digitales donde se requiere optimización de los coeficientes del filtro FIR.