En el mundo de la electrónica, los sensores suelen enfrentarse a dos grandes enemigos: el ruido eléctrico de alta frecuencia (que hace que las lecturas oscilen sin control) y el desplazamiento de la línea base o DC offset (cambios lentos o niveles fijos que dificultan detectar variaciones rápidas).
Tradicionalmente, estos problemas se resolvían soldando resistencias y condensadores para crear filtros analógicos. Sin embargo, gracias al Procesamiento Digital de Señales (DSP), podemos replicar este comportamiento directamente en el sketch (programa/código) de nuestro Arduino.
En este tutorial, aprenderás a sustituir componentes físicos por ecuaciones de diferencias. Veremos cómo implementar desde cero:
A_Introduccion:
Para implementar filtros pasabajos y pasaaltos por software en Arduino, se sustituyen los componentes físicos (resistencias, capacitores y amplificadores operacionales) por ecuaciones de diferencias que procesan la señal muestreada digitalmente.
A continuación, se presentan las implementaciones para filtros de primer orden:
1. Filtro Pasabajos (Low-Pass Filter)
Este filtro permite el paso de frecuencias bajas y atenúa el ruido de alta frecuencia. Es ideal para suavizar lecturas de sensores ruidosos.
Ecuación:
Donde:
Ejemplo:
2. Filtro Pasaaltos (High-Pass Filter)
Este filtro permite el paso de frecuencias altas y bloquea componentes continuos (DC) o cambios lentos.
Ecuación:
Ejemplo:
A tener en cuenta:
-Tiempo de muestreo: A diferencia de los circuitos analógicos con operacionales, la frecuencia de corte en software depende de la velocidad a la que ejecutas el loop. Para resultados precisos, usa micros() para asegurar intervalos constantes.
-Cálculo de 𝛼 : Si conoces la frecuencia de corte deseada (𝑓𝑐) y el tiempo de muestreo (𝑑𝑡),puedes calcular 𝛼 para el pasabajos como: 𝛼=𝑑𝑡𝑅𝐶+𝑑𝑡 , donde 𝑅𝐶=12𝜋𝑓𝑐
-Librerías: Si necesitas filtros más complejos (como Butterworth de segundo orden), existen librerías como Arduino-Filters que facilitan la implementación sin manejar manualmente las ecuaciones…
B_ De la teoría a la practica…
A continuación, un sketch práctico que toma una lectura analógica y aplica simultáneamente un Filtro Pasabajos (LPF) para suavizar ruido y un Filtro Pasaaltos (HPF) para detectar cambios rápidos o eliminar la componente continua (offset).
Ejemplo:
Para implementar ambos filtros sobre una misma señal, el enfoque más eficiente es procesarlos en serie o en paralelo dentro del mismo ciclo de muestreo.
-Ajuste de 𝛼: En el Pasabajos, un 𝛼 pequeño (ej. 0.05) elimina mucho ruido pero introduce retardo (lag).
-En el Pasaaltos, si el valor filtrado tiende a quedarse en 0 aunque la señal se mueva lento, el filtro está cumpliendo su función de eliminar la componente continua.
-Consistencia Temporal: Para aplicaciones profesionales (como audio o ECG), el uso de delay() no es preciso. Se recomienda usar temporizadores o librerías especializadas como Arduino-Filters que gestionan el tiempo de muestreo internamente para garantizar una respuesta en frecuencia exacta.
C_Usos prácticos?
-Acelerómetros: El Pasabajos filtra las vibraciones del motor en un dron para que el acelerómetro solo detecte la inclinación real.
-Audio Simple: El Pasabajos puede actuar como un control de "Tono" (treble cut) si procesas una señal de audio digital.
-Sensores de Flexión: En guantes robóticos, el Pasabajos evita que los dedos mecánicos tiemblen por pequeñas variaciones eléctricas en los sensores de flexión.
-Monitoreo de Ritmo Cardíaco (PPG) mediante un sensor de pulso infrarrojo: En este escenario, la señal que entrega el sensor es extremadamente ruidosa y "sucia" para procesarla directamente.
Si aplicamos en este caso Filtro Pasabajos (LPF): Se usaria para eliminar el "ruido blanco" y las interferencias de alta frecuencia (como el parpadeo de luces fluorescentes o ruido eléctrico). Esto suaviza la señal para que el pulso se vea como una onda curva y no como una línea "astillada".
Si sumamos el Filtro Pasaaltos (HPF): Lograriamos eliminar el Offset DC (la línea base). Cuando mueves un poco el dedo en el sensor, la señal sube o baja de nivel bruscamente. El pasaaltos "centra" la señal en cero, permitiendo que solo detectes los cambios rápidos (los latidos), sin importar si el sensor está recibiendo más o menos luz ambiental en ese momento.
Veamos un ejemplo de código combinado para este sensor:
Este sketch procesa la señal de un sensor de pulso en el pin A0 y entrega una señal limpia lista para contar latidos
Para poder hacer un sistema de monitoreo cardíaco, necesitamos añadir una lógica de detección de umbral (threshold) y un cálculo de tiempo entre latidos.
La señal que sale del filtro pasaaltos (filteredHPF) está centrada en cero. Un latido se detecta cuando la señal sube por encima de un umbral positivo y luego baja. Usamos millis() para calcular los latidos por minuto (BPM).
Fuente: (e-book) ProyectosARDUINOdesdeCERO Autor: ETI Patagonia
Tradicionalmente, estos problemas se resolvían soldando resistencias y condensadores para crear filtros analógicos. Sin embargo, gracias al Procesamiento Digital de Señales (DSP), podemos replicar este comportamiento directamente en el sketch (programa/código) de nuestro Arduino.
En este tutorial, aprenderás a sustituir componentes físicos por ecuaciones de diferencias. Veremos cómo implementar desde cero:
- Filtros Pasabajos (Low-Pass): Para suavizar señales y eliminar el "ruido" de sensores ruidosos.
- Filtros Pasaaltos (High-Pass): Para eliminar componentes continuas y centrar la señal en los cambios significativos.
A_Introduccion:
Para implementar filtros pasabajos y pasaaltos por software en Arduino, se sustituyen los componentes físicos (resistencias, capacitores y amplificadores operacionales) por ecuaciones de diferencias que procesan la señal muestreada digitalmente.
A continuación, se presentan las implementaciones para filtros de primer orden:
1. Filtro Pasabajos (Low-Pass Filter)
Este filtro permite el paso de frecuencias bajas y atenúa el ruido de alta frecuencia. Es ideal para suavizar lecturas de sensores ruidosos.
Ecuación:
Donde:
Ejemplo:
CSS:
float alpha = 0.1; // Factor de filtrado (0.1 = filtrado fuerte, 0.9 = suave)
float filteredValue = 0;
void loop()
{
int rawValue = analogRead(A0);
// Implementación del filtro pasabajos
filteredValue = (alpha * rawValue) + ((1.0 - alpha) * filteredValue);
Serial.println(filteredValue);
delay(10); // Importante mantener un tiempo de muestreo constante
}
2. Filtro Pasaaltos (High-Pass Filter)
Este filtro permite el paso de frecuencias altas y bloquea componentes continuos (DC) o cambios lentos.
Ecuación:
Ejemplo:
CSS:
float alpha = 0.8;
float prevX = 0;
float filteredY = 0;
void loop()
{
int currentX = analogRead(A0);
// Implementación del filtro pasaaltos
filteredY = alpha * (filteredY + currentX - prevX);
prevX = currentX; // Guardar para el siguiente ciclo
Serial.println(filteredY);
delay(10);
}
A tener en cuenta:
-Tiempo de muestreo: A diferencia de los circuitos analógicos con operacionales, la frecuencia de corte en software depende de la velocidad a la que ejecutas el loop. Para resultados precisos, usa micros() para asegurar intervalos constantes.
-Cálculo de 𝛼 : Si conoces la frecuencia de corte deseada (𝑓𝑐) y el tiempo de muestreo (𝑑𝑡),puedes calcular 𝛼 para el pasabajos como: 𝛼=𝑑𝑡𝑅𝐶+𝑑𝑡 , donde 𝑅𝐶=12𝜋𝑓𝑐
-Librerías: Si necesitas filtros más complejos (como Butterworth de segundo orden), existen librerías como Arduino-Filters que facilitan la implementación sin manejar manualmente las ecuaciones…
B_ De la teoría a la practica…
A continuación, un sketch práctico que toma una lectura analógica y aplica simultáneamente un Filtro Pasabajos (LPF) para suavizar ruido y un Filtro Pasaaltos (HPF) para detectar cambios rápidos o eliminar la componente continua (offset).
Ejemplo:
CSS:
// Variables para el Filtro Pasabajos (LPF)
float alphaLPF = 0.15; // Suavizado: valores bajos = más filtrado
float filteredLPF = 0;
// Variables para el Filtro Pasaaltos (HPF)
float alphaHPF = 0.85; // Estabilidad: cercano a 1 para dejar pasar solo picos rápidos
float prevRawValue = 0;
float filteredHPF = 0;
const int sensorPin = A0;
void setup()
{
Serial.begin(115200);
// Inicialización para evitar saltos bruscos al arranque
filteredLPF = analogRead(sensorPin);
prevRawValue = filteredLPF;
}
void loop()
{
int rawValue = analogRead(sensorPin);
// 1. FILTRO PASABAJOS (Suaviza la señal)
// Ecuación: y[n] = α*x[n] + (1-α)*y[n-1]
filteredLPF = (alphaLPF * rawValue) + ((1.0 - alphaLPF) * filteredLPF);
// 2. FILTRO PASAALTOS (Detecta cambios rápidos/quita el DC)
// Ecuación: y[n] = α*(y[n-1] + x[n] - x[n-1])
filteredHPF = alphaHPF * (filteredHPF + rawValue - prevRawValue);
// Guardar valor actual para el siguiente cálculo del HPF
prevRawValue = rawValue;
// Visualización en el Serial Plotter
Serial.print("Original:"); Serial.print(rawValue);
Serial.print(",");
Serial.print("PasaBajos:"); Serial.print(filteredLPF);
Serial.print(",");
Serial.print("PasaAltos:"); Serial.println(filteredHPF);
delay(10); // Frecuencia de muestreo de ~100Hz
}
Para implementar ambos filtros sobre una misma señal, el enfoque más eficiente es procesarlos en serie o en paralelo dentro del mismo ciclo de muestreo.
-Ajuste de 𝛼: En el Pasabajos, un 𝛼 pequeño (ej. 0.05) elimina mucho ruido pero introduce retardo (lag).
-En el Pasaaltos, si el valor filtrado tiende a quedarse en 0 aunque la señal se mueva lento, el filtro está cumpliendo su función de eliminar la componente continua.
-Consistencia Temporal: Para aplicaciones profesionales (como audio o ECG), el uso de delay() no es preciso. Se recomienda usar temporizadores o librerías especializadas como Arduino-Filters que gestionan el tiempo de muestreo internamente para garantizar una respuesta en frecuencia exacta.
C_Usos prácticos?
-Acelerómetros: El Pasabajos filtra las vibraciones del motor en un dron para que el acelerómetro solo detecte la inclinación real.
-Audio Simple: El Pasabajos puede actuar como un control de "Tono" (treble cut) si procesas una señal de audio digital.
-Sensores de Flexión: En guantes robóticos, el Pasabajos evita que los dedos mecánicos tiemblen por pequeñas variaciones eléctricas en los sensores de flexión.
-Monitoreo de Ritmo Cardíaco (PPG) mediante un sensor de pulso infrarrojo: En este escenario, la señal que entrega el sensor es extremadamente ruidosa y "sucia" para procesarla directamente.
Si aplicamos en este caso Filtro Pasabajos (LPF): Se usaria para eliminar el "ruido blanco" y las interferencias de alta frecuencia (como el parpadeo de luces fluorescentes o ruido eléctrico). Esto suaviza la señal para que el pulso se vea como una onda curva y no como una línea "astillada".
Si sumamos el Filtro Pasaaltos (HPF): Lograriamos eliminar el Offset DC (la línea base). Cuando mueves un poco el dedo en el sensor, la señal sube o baja de nivel bruscamente. El pasaaltos "centra" la señal en cero, permitiendo que solo detectes los cambios rápidos (los latidos), sin importar si el sensor está recibiendo más o menos luz ambiental en ese momento.
Veamos un ejemplo de código combinado para este sensor:
Este sketch procesa la señal de un sensor de pulso en el pin A0 y entrega una señal limpia lista para contar latidos
CSS:
// Parámetros de filtrado
float alphaLPF = 0.2;
float alphaHPF = 0.95;
float filteredLPF = 0;
float filteredHPF = 0;
float prevLPF = 0;
// Variables para el conteo de pulsos
const float threshold = 20.0; // Umbral de detección (ajustar según sensor)
bool pulseDetected = false;
unsigned long lastBeatTime = 0;
float bpm = 0;
void setup()
{
Serial.begin(115200);
}
void loop()
{
int rawValue = analogRead(A0);
// 1. FILTRADO (Pasabajos + Pasaaltos en cascada)
filteredLPF = (alphaLPF * rawValue) + ((1.0 - alphaLPF) * filteredLPF);
filteredHPF = alphaHPF * (filteredHPF + filteredLPF - prevLPF);
prevLPF = filteredLPF;
// 2. DETECCIÓN DE LATIDO (Lógica de umbral)
// Si la señal supera el umbral y no habíamos detectado un pulso aún...
if (filteredHPF > threshold && !pulseDetected)
{
pulseDetected = true;
unsigned long currentTime = millis();
unsigned long duration = currentTime - lastBeatTime;
// Validar que el latido sea realista (evitar rebotes menores a 300ms / 200 BPM)
if (duration > 300)
{
bpm = 60000.0 / duration; // 60,000 ms en un minuto
lastBeatTime = currentTime;
}
}
// Resetear la detección cuando la señal baja del umbral (con un poco de histéresis)
if (filteredHPF < (threshold * 0.8))
{
pulseDetected = false;
}
// 3. SALIDA DE DATOS
Serial.print("Señal_Limpia:"); Serial.print(filteredHPF);
Serial.print(",");
Serial.print("Umbral:"); Serial.print(threshold);
Serial.print(",");
Serial.print("BPM:"); Serial.println(bpm);
delay(10); // Muestreo de 100Hz
}
Para poder hacer un sistema de monitoreo cardíaco, necesitamos añadir una lógica de detección de umbral (threshold) y un cálculo de tiempo entre latidos.
La señal que sale del filtro pasaaltos (filteredHPF) está centrada en cero. Un latido se detecta cuando la señal sube por encima de un umbral positivo y luego baja. Usamos millis() para calcular los latidos por minuto (BPM).
Si notamos que el BPM salta mucho, se puede aplicar un tercer filtro pasabajos exclusivamente a la variable bpm para suavizar la lectura final que se muestra al usuario.
Fuente: (e-book) ProyectosARDUINOdesdeCERO Autor: ETI Patagonia