Ayuda con mi codigo y filtros paso-bajo

jejeje es verdad... como ayer empece a buscar y estaba cerrada la wiki en ingles jajaja, pero bueno vere que sucede con mi código..... a lo mejor en dos dias me tiene diciendo no me funciona ayuda jejeje

EDITO:
en c debería quedar algo así no??

double filtropasobajo (double *x, double *y,
int M, double xm1)
{
int n;
y[0] = x[0] + xm1;
for (n=1; n < M ; n++) {
y[n] = x[n] + x[n-1];
}
return x[M-1];
}

pues la verdad me he hecho lios con este filtro no se como agregarlo jejeje cada vez que trato me sale mal(obvio no se lo que hago)

¿qué no entiendes del filtro paso bajo? Me refiero a conceptos, nada de código. Seguro que si lo entiendes no tienes problemas de hacerlo con la cantidad de información que hay en internet.

Por cierto, para rpm se suele usar "moving average filter", es decir, tomar ciertas medidas y hacer la media (mejor usar la variable del contador, en vez con el float para mejor rendimiento del código).

I don't really speak Spanish, but this might be useful: filter library - Science and Measurement - Arduino Forum

Hello doggenj.

First sorry for my bad english. I took a look for your library. I think it's a good idea to do a library for a lot filters. I see you did it only 5 days ago. I hope you continue the development of this library. I think it's very important you do an explanation of your library. Characteristics of Bessel and Chebyshev filters, what is filter order.I don't see any explanation for your library for the functions and parameters ("b" is Bessel filter, "c" is...). Either any explanation in the examples.

For last, in your library I don't see the parameter for the frequency corner. I see it's very important, isn't? And value and filtered are declared as int. Could it be poor for any applications? Could it be better to declare as long or float?

I talk you for you can improve your library because I think it's a great idea.

doggenj:
I don't really speak Spanish, but this might be useful: http://arduino.cc/forum/index.php/topic,52681.msg376017.html#msg376017

Muy interesante, y hay un generador de filtros automáticos por software y todo. El tema de los filtros es muy complicado, yo los conceptos los entiendo pero no consigo que se me ocurra ninguna utilidad salvo la de filtrar frecuencias de audio. ¿A alguien se le ocurre algún ejercicio sencillo donde se pueda implementar los filtros con arduino? Gracias por el link

Con cualquier sensor para elminar el ruido ambiente, por ejemplo un sensor de distancias de infrarrojos de estos que se ven tanto, sharp creo que son. Es normal implementar un filtro fir paso bajos para eliminar los picos que puedas tener debido al ruido ambiente y promediar la medida.

Por ejemplo si tienes un programa que hace algo cuando el sensor lee x distancia, se puede disparar debido al ruido, implementando un filtro pasobajos previenes que pase ésto, ya que te comes los picos y promedias las medidas.

Por otro lado meter un filtro de este tipo también te supone meter un retardo en la señal que has de consideras en ciertos sistemas.

(español, con traductor Google)

Es una buena idea añadir más información a los ejemplos.
He añadido una página wiki, con un poco información básica.
http://code.google.com/p/arduino-signal-filtering-library/wiki/SignalFilteringBasics

"Int" es de 16 bits en el código de Arduino, ya que el ADC es de 10 bits, esto debería ser suficiente (para algunos de los cálculos es necesaria una mayor precisión)

@ionhs: Realmente no se entiende la pregunta, pero un estándar de Arduino no es lo suficientemente rápido para procesar la señal de audio en tiempo real.
@JMN: Mi uso principal del filtro de un sensor de distancia :slight_smile: (Sharp GP2Y0A21YK IR Distance sensor) (Google Code Archive - Long-term storage for Google Code Project Hosting. )

Como JMN, yo creo que el ejemplo más fácil de imaginar es el de medir luz (cualquiera la aplicación que sea, por ejemplo los sensores de distancia, los ldr,etc).
A tu alrededor, tienes una gran fuente de ruido.... los 50 Hz de la red eléctrica. Por ejemplo, tus fluorescentes estarán apagandose/encendiendose a dicha frecuencia. Es decir, cuando recojas la medida de tu sensor, tendrás dicho "ruido" añadida a tu medición.

Si quieres jugar con ésto, nada mejor que el post que salió en paralelo cuando se estuvo discutiendo por aquí aumentar la frecuencia de muestreo del ADC.
Puedes usar el KST a tiempo real para saber que más cosas estas midiendo en la señal adquirida ("frecuencias").
http://arduino.cc/forum/index.php/topic,69995.0.html
http://arduino.cc/forum/index.php/topic,68855.0.html

Si tienes un ldr, puedes hacer el experimento. Tambien puedes probar a medir con el ldr la luz de una incandescente y en una fluorescente para ver diferencias.

El filtro sirve precisamente para quitar(atenuar) la parte que no te interesa medir en la señal adquirida (también hay conceptos como el aliasing, pero sin entrar en detalles).

Otro ejemplo, que a lo mejor es fácil de entender, es medir la aceleración de un cuerpo. Pongamos un coche. Instalas un acelerómetro dentro del coche. Lo que te interesa es medir la aceleración del mismo, pero en el sensor no distingue, otras fuentes como las inducidas por la carretera-neumático-suspensión ó la vibración del motor, etc también las medirás. Por ello tienes que eliminar dicho "ruido" de tu señal, ya que no te interesa esos datos para tu aplicación.

igor ehhh conceptos he leido bastante y los comprendo, pero mi nivel de programacion no esta como para lograr implementarlo.... por ejemplo no tengo idea en que parte debe ir el filtro........

otra cosa es que nose si mi codigo es lo mas rcomendado para la medicion ya que es un poco rustico si me dijeran alguna manera de poder estructurarlo mejor me vendria bien

JMN:
Con cualquier sensor para elminar el ruido ambiente, por ejemplo un sensor de distancias de infrarrojos de estos que se ven tanto, sharp creo que son. Es normal implementar un filtro fir paso bajos para eliminar los picos que puedas tener debido al ruido ambiente y promediar la medida.

Por ejemplo si tienes un programa que hace algo cuando el sensor lee x distancia, se puede disparar debido al ruido, implementando un filtro pasobajos previenes que pase ésto, ya que te comes los picos y promedias las medidas.

Por otro lado meter un filtro de este tipo también te supone meter un retardo en la señal que has de consideras en ciertos sistemas.

bueno lo del retardo de la señal lo he cosiderado, pero creo que es preferible tener un retardo en la señal a tener malas lecturas con el sensor.... claro que me gustaria tener el programa bie estructurado para evtar los mas posible retrasos....

y pues la verdad en lo que necesio ayuda es en eso en poder afnar bien el programa, solo que no quise abrir otro hilo ya que tenia este y pues tengo que evitar hacer un hilo por cada pregunta tonta que me salga.....

gracias a todos por conestar leere u poco de lo que me han comentado y vere si puedo hace algo

copachino, para implementar un filtro paso banda en Arduino por ejemplo puedes poner lo siguiente, está realizado con el código para Bessel de primer orden con frecuencia de corte 1 kHz.

float v[2];
float VariableFiltrada;

void loop() {

  v[0] = v[1];
  v[1] = (2.45237275253e-1 * Variableafiltrar) + (  0.5095254495 * v[0]);
  VariableFiltrada = v[0] + v[1];

}

Ahora no sé si hay algún experto en filtros que nos pudiera resolver algunas dudas. Las que yo tengo son:

¿En qué casos está más indicado el filtro Bessel o el Chebyshev?

Si se usan los filtros paso bajo de Bessel o Chebyshev, qué ventajas o inconvenientes tienen respecto a realizar la media de los últimos x valores?

El orden de los filtros imagino que se corresponde con la mayor o menor atenuación en las frecuencias de corte. Sin embargo al ir aumentando el orden, ¿qué inconvenientes nos produce? ¿Se produce mayor retardo en la señal?

Pues bueno de momento este es mi código "filtrado" con la ecuación de bessel de primer orden use las librerías que me pasaron para filtros.... uno no he probado el programa pero mañana espero poder hacerlo

Yo hice una prueba con la librería pero no me funcionó, me sacaba unos valores en otro orden de magnitud. Tampoco lo investigué mucho, tal vez era un error de programación por conversión entre distintos tipos de variables. Por no ponerme a investigar directamente puse el algoritmo que he puesto arriba y funciona bien.

No sé si hay alguien que controle el tema de filtros y pueda responder a las preguntas de mi anterior post.

Realizar la media de los "X" últimos valores, desde un punto de vista como filtro paso bajo, es malo. Pero por otro lado, computacionalmente es muy bueno. Ya que si por ejemplo, haces que tu "X" sea un número par, para dividir puedes usar una operación de shift (cada vez que desplazas una posición, multiplicas o divides por dos, según el sentido).

Al final, uno de los factores limitantes en sistemas de tiempo real, es la computación. Puede ser un filtro cojonudo, que si no va a dar tiempo a tu Arduino, a procesar las operaciones necesarias entre la toma de una muestra y la otra, no te sirve para nada.

Por ejemplo, hacer algo como:

memoria1=memoria2;
memoria2=memoria3;
memoria3=memoria4;
memoria4=analogRead(0);

salida_filtrada=(memoria1+memoria2+memoria3+memoria4)>>2;

Pues es bastante rápido. Es decir, de esta forma no se te queda parado tomando "X" muestras para luego usarlo en lo que quieras. Lo va haciendo al "vuelo".Asi tienes más tiempo para realizar otras operaciones en tu proceso.
Si lo que vas a controlar es la temperatura de una habitación, pues te puedes permitir altos tiempos de ciclo. Es un sistema que tiene una inercia altísima. Para que suba 1 grado una habitación, pasan minutos ó horas...
Por otro lado, si estas midiendo es las revoluciones de un motor, en la cual tienes que inyectar gasolina en el cilindro cuando estés a cierto lugar del punto muerto superior, pues te estás moviendo en tiempos muy pequeños...

Me refiero, que es un factor a tener en cuenta, no sólo el filtro en sí, si no la computación que requiere implementarlo.

Gracias Igor R. En el caso que ahora me llevaría creo que no sería muy crítico el tiempo de computación (claro que tampoco sé el tiempo que llevaría ejecutar un buen filtro). Se trata de la medida de los 8 canales de la emisora RC. Los datos recogidos pueden variar aproximadamente entre 1050 µs y 1870 µs siendo el centro 1460 µs. Ante un valor fijo de palanca la variación por ruido puede tomar valores entre 1448 µs y 1460 µs. Ahora lo tengo en plan sencillo promediando los últimos 6 valores pero me gustaría implementar algún filtro mejor.

bueno de momento comento mis avances:

el programa anterior estaba malisimo habian variables que no hacian nada, mal estructurado, mala matematica y mucho mas en fin lo probe lo compilo lo cargo pero al usarlo no hacia nada ni siquiera leia algo.... entonces me tome tiempo de leer mas detenidamente mi codigo y lo corregi un poco de nuevo es un codigo algo rustico pues es lo mas que puedo hacer con lo que nonosco...... si me dan consejos pra optimizar lo mas probable es que no sea como pero bueno puedo leer y aprender a usar sus consejos jejeje....... le puse algo de explicacion esta vez para facilitar la lectura del codigo....

volatile byte rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;

 void rpm_fun()
 {
   //cada rotacion esta funcion se activa de momento una ves   //
   //
      rpmcount++;
      
 }
void setup()
  {
   Serial.begin(9600);
   //Interrupt 0 es el pin 2 digital, 
   // (cambia de HIGH a LOW)
   attachInterrupt(0, rpm_fun, FALLING);
   


   rpmcount = 0;
   rpm = 0;
   timeold = 0;
   status = LOW;
 }

 void loop()
 {
  
   delay(1000);//actualiza las RPM cada segundo;
   detachInterrupt(0);
   //Nota que cambiare el calculo es: 60*1000/(millis() - timeold)*rpmcount segun los dientes que tenga
   //la rueda dentada de momento es para una una sola muestra por vuelta. un diente
   //dependiendo de lo dientes el factor 60 sera divido por ejemplo si son 10 dientes seria 6*1000
   rpm = 60*1000/(millis() - timeold)*rpmcount;
   timeold = millis();
   rpmcount = 0;
   
   //mando la salida al puerto serial
   Serial.println(rpm,DEC);
   
   //reinicia el roceso de interrupcion
   attachInterrupt(0, rpm_fun, FALLING);

  }

de momento no he metido nada de filtos que sigo a la investigacion de ellos....
espero elguien se tome su tiempo y me pueda decir algo sobre el codigo..

un saludo a todos

Hola comunidad

Interesante programa de filtros, estoy realizando un proyecto de procesamiento de señales y me gustaría saber como obtienen la frecuencia de corte para cada filtro, en mi caso quiero ingresar frecuencias de corte de 0,1Hz y 45Hz, seria de gran ayuda...

Esta librería que estoy utilizando, o si tiene otra me la cruzan...

Pueden ayudarme con es este filtro.... Me sale un error en un ejemplo de prueba, y es undefined reference to `SignalFilterOrder1::run(float)'

estos son los códigos:

CÓDIGO SignalFilterOrder1.cpp

//filtro pasa altos con frecuencia de corte de 0.05 Hz
#include <Arduino.h>
#include <SignalFilterOrder1.h>
/// Constructor
SignalFilterOrder1::SignalFilterOrder1()
{
 _v[0]=0.0;
 //_v[1]=0.0;
 //_v[2]=0.0;
}
/// runButterworth: Runs the actual filter: input=rawdata, output=filtered data
float SignalFilterOrder1::runButterworth(float data)
{ 
   _v[0] = _v[1];
   _v[1] = (9.999842922835e-1 * data) + (0.9999685846 * _v[0]);
   return (_v[1] - _v[0]);
}

CÓDIGO SignalFilterOrder1.h

//libreria de filtro butterworth de 0.05 Hz
#ifndef SignalFilterOrder1_h
#define SignalFilterOrder1_h
#include <Arduino.h>

class SignalFilterOrder1
{
 public:
   SignalFilterOrder1();
   int run(float data);
   
 private:
   float runButterworth(float data);
   float _v[2];

};
#endif

EJEMPLO DE PRUEBA:

#include <SignalFilterOrder1.h>
SignalFilterOrder1 Filter;
int value;
float val;
float filtered;
void setup(){
 Serial.begin(9600);
}
void loop(){
 value = analogRead(A0);
 val = value * 0.034;
 filtered = Filter.run(val);  
}

Hola, se que el postes un poco viejo pero las dudas siempre quedan y muchas veces varios tienen las mismas dudas asi que tratare de responder alguna de las dudas que vi aqui.

Primero, cada tipo de filtro tiene sus características, y saber cual utilizar dependerá de la aplicación en donde se utilice el mismo.

La característica de los filtros bessel son que tienen una respuesta de fase lineal, es decir, la fase de la señal varía linealmente a medida que aumenta la frecuencia. Esto es ventajoso para aplicaciones que requieran una fase invariante o para las aplicaciones en donde el retraso de grupo no sea algo critico.
Contra? pues, para poder obtener cierta atenuación a una determinada frecuencia, se requiere de un orden mayor del filtro, lo que conlleva a un coste computacional mayor (si se requiere atenuaciones abruptas)

Los filtro butterworth. su principal característica es que en la banda de paso (las frecuencias que queremos) tiene una respuesta maximamente plana. Sus aplicaciones podrian ser por ejemplo en procesos en donde la magnitud de la señal es fundamental y cambios mínimos en la misma no pueden ser tolerados. en bioseñales por ejemplo en donde las amplitudes no llegan a mas de unos cuantos miliVoltios.
Contra? Fase no lineal

Los filtros chebychev. Su principal característica es que para una atenuacion a una determinada frecuencia, requiere un orden de filtro menor en comparación con butterworth y bessel. Aplicaciones podrían ser en las que la magnitud y fase no son críticos, si no por ejemplo el coste computacional, (que se este trabajando con algun micro con poca memoria por ejemplo o baja velocidad) y se requiera de una garantía de supresión de ciertas frecuencias a una determinada atenuación.
Contra? Fase no lineal y riple en la banda de paso (variación en la magnitud de la nada de paso)
Este riple puede variar dependiendo del cálculo que se haga del filtro.

Un filtro de media móvil o filtro promediador es un filtro con características de tipo "pasa bajo" y se utiliza principalmente para "suavizar" la señal y tratar de eliminar los cambios abruptos que puedan ocurrir en la señal. Mientras mayor sea el número de muestras con que se realiza el promedio, mayor será el "suavizado", pero si se utilizan muchas muestras, este tipo de filtro puede llegar a distorsionar la señal real.

Bueno, estos son los principales filtros digitales y mas comunes. Existen otros mas complejos y me extendería mucho si nos ponemos a explicar en detalle cada uno de ellos.

Ahora, el orden del filtro: Mientras mayor sea el orden del filtro, mayor es la "caida" o la pendiente o el roll-off del filtro, hacia la banda de rechazo (la que queremos filtrar). Pero esto a su vez requiere un coste computacional mayor para su implementacion.

Frecuencia de corte: esta es la frecuencia en la que el filtro debería atenuar la señal por lo menos a la mitad de la potencia. Si se trata de un filtro pasa bajo, es la máxima frecuencia que quieres dejar "pasar" por el filtro; si es u filtro paso alto es la mínima frecuencia que quieres dejar pasar. Si se trata de un filtro pasa banda, se trata del rango de frecuencia en la que se encuentra tu señal, o que quieres dejar pasar, o de interés (Fminima - Fmáxima; desde 10 Hz hasta 200 Hz, etc); y si es rechaza banda o "Notch" o de ranura, es la frecuencia que deseas eliminar, o el rango de frecuencia que deseas eliminar (ej: eliminar 60 Hz o 50 Hz, que es la frecuencia de la línea eléctrica dependiendo del país, eliminar desde 500 Hz hasta 1500 Hz, etc).

Para poder diseñar un filtro, es necesario al menos estas 2 características (orden del filtro y frecuencia de corte) además del tipo de filtro (paso bajo/alto/banda, etc).

Se podría diseñar alguna librería en la que introduzcas estos valores y te regrese los valores del filtro pero creo que esto no es lo que quieres y además sería un poco complicado.

Para poder darte algun filtro necesitaría saber la aplicación para el mismo, o al menos la frecuencia de corte. MatLab tiene algunas funciones interesantes que te podrían ayudar a realizar este cálculo sin saber mucho de filtros si quieres probar.

Se me olvidaba, los filtros tambien se pueden clasificar segun su respuesta al impulso, pueden ser de tipo IIR (respuesta al impulso infinita) o FIR (respuesta al impulso finita). No vamos a entrar en detalle con esto ya que puede ser tedioso pero explico de la manera más basica para tratar que se entienda lo mejor posible:

Los filtros IIR necesitan un orden menor que los FIR para lograr la misma atenuacion a cierta frecuencia, pero estos no siempre pueden llegar a ser estables y además, la respuesta de la fase no es lineal. Otra característica explicada de forma simple es que para implementarlos, necesitarías guardar en memoria no sólo algunos valores de la entrada, si no tambien algunos de la salida (si, depende de salidas anteriores o pasadas).

Los filtros FIR siempre son estables y la mayoria tienen una respuesta de fase lineal pero necesitarían un orden mayor que los IIR para lograr la misma atenuación a cierta frecuencia. Estos sólo dependen de valores pasados de la entrada. no dependen de valores pasaos de la salida.

Los filtros butterworth y Chebychev son filtros de tipo IIR

Los filtros de Bessel y de media movil son filtros de tipo FIR

Los filtros digitales dependen tambien de la frecuencia de muestreo que estes utilizando, o en otras palabras, el tiempo de muestreo o periodo de muestreo (cada cuánto tiempo vuelves a tomar una muestra). Dependiendo de la frecuencia de muestreo, se calculan los coeficientes del filtro.

Por lo que "decirte un filtro" así como así puede que no te sirva para las especificaciones que tu necesitas.

Si lo que necesitas es un filtro para reducir un poco el ruido para un sensor de temperatura, o creo que leí el de distancia, un filtro de media movil podría servir perfectamente.

Te podría dar un ejemple de un filtro de media móvil de 5 muestras por ejemplo:

float x[5] = 0; // Las 5 muestras para su posterior procesado
float y = 0;                   // La salida del filtro

/* Los filtros de media movil pueden utilizarse con valores "futuros" a la muestra central y valores "pasados".
Puede utilizarse solo futuros, solo pasados o una combinacion de los dos. en este caso utilizaremos solo valores pasados*/

void setup{

serial.begin(9600);

//podemos inicialmente recoger 5 valores y despues ir actualizando los valores
for (int i=0; i<5; i++){
x[i] = analogread(PIN); //lee el pin del sensor, etc.
y = y + x[i];               // sumo los valores de las muestras
}
y = y/5;                     // Finalmente calculamos el promedio

x[4] = x[3];               // Actualizamos los valores de las muestras
x[3] = x[2];
x[2] = x[1];
x[1] = x[0];
}

void loop{
// Ahora podemos empezar a tomar muestras indefinidamente

x[0] = analogread(PIN;      // Empezamos a leer los valores

// Implementamos el filtro

y = (x[0] + x[1] + x[2] + x[3] + x[4])/5;

serial.prinln(y);              // Imprimimos en monitor serial

x[4] = x[3];                 // Actualizamos los valores de las muestras
x[3] = x[2];
x[2] = x[1];
x[1] = x[0];

}