Promediar señales de sensores

Buenas, estoy con un arduino donde programe para que leyera las señales de 6 sensores distintos, los graficara y guardase en un csv. El problema es que presentan mucho ruido. Para poder solucionar esto se e ocurrio que promediase los ultimos datos enviados. El tema es que no se como guardar esos ultimos datos, como meterlos en un array y que distinga cual dato es cual. Para explicarme mejor, la variable que manda el valor de la señal se llama tempDatos, lo que no se me ocurrio ni encontre como hacerlo, es como guardar, por ejemplo, los ultimos 5 tempDatos (en un ciclo for por ejemplo), y que no guarde siempre el mismo, de modo que pueda tomar esos ultimos 5 datos y dividirlos por 5. Basicamente la idea es que tome 5 datos, los promedie y el valor graficado sea ese resultado.

O sea una especie de promedio dinámico, o movil.
Como estas de memoria en tu sketch, sime cuando compilas cuanta SRAM te queda disponible?

Lo que debes hacer es definir un vector tan grande como los datos que desees promediar y hacer un desplazamientos de datos
Por ejemplo el Vector Sensor(5) (6 datos a promediar)
y mover los valores según un criterio de tiempo (Hay que respetar el orden de desplazamiento)

Sensor(5)=Sensor(4)
Sensor(4)=Sensor(3)
Sensor(3)=Sensor(2)
Sensor(2)=Sensor(1)
Sensor(1)=Sensor(0)
lectura_sensor=Sensor(0)
De esa manera en cada pasada de la subrrutina se almacena un valor nuevo y se descarta el mas viejo (FIFO)
Saludos

pero Seniikas, dice tener 6 sensores asi que esa FIFO hay que hacerlo con 6 vectores, no uno como aparentas sugerir o yo lo malentendí?

Bueno, yo di la explicación para un sensor, es trivial replicarlo por seis. Si se quiere complicar la vida puede crear una clase que los promedie.

Ahh okay, disculpa.

No tienes por que disculparte. Ya que estamos con el tema de suavizado de señales ,el promediar tiene el inconveniente de perder información y solo se utiliza si la señal deriva lentamente en el tiempo, si la variación es rápida hay que utilizar otras técnicas como promedios pesados, dando mas importancia a los últimos datos o suavizado exponenciales.

sip, la variacion es casi instantanea. Entonces deberia utilizar otro tipo de promedio decis? Yo tengo dos opciones en mi programa: una donde se aplica una especie de derivada donde si se ve una linea mas definida, y la otra donde veo el cociente de resistencias (Ro/RL), es decir el dato crudo. Ese dato me tira mucho ruido y quiero suavizarlo, ya que de este modo incluso puedo ver mejor si se mantiene la linea de base o varia.

Puedes contarnos mas sobre como estas tomando las mediciones?
Porque establecer la fuente de ruido ayudaría a minimizarlo. Tal vez haya algún error en la forma en que mides, o como dispones las conexiones.
Un esquema y una foto de cómo esta realizado ayudaría.

Luego si puedes capturar los sensores con el ruido actual y subirlo en un archivo, tmb podriamos pensar en la mejor manera de suavizar las lecturas usando lo que ya tienes si no puede mejorarse.

Tengo unos sensores hechos por mi. Lo que hago es conectarlos a las entradas analogicas del arduino, donde tienen un codigo simple para tomarla. Luego con processing y una libreria que encontre, grafico los datos.

Asi es como se ve la grafica de los datos. la parte ancha es la señal en crudo (excepto los ultimos dos que tienen una curva de calibracion) y la linea final, es la derivada mencionada anteriormente. Yo pienso que la fuente del ruido es la variacion que tienen estos sensores en su resistencia.

Puedo pasarte un archivo csv con con las señales que he tomado para chequear las calibraciones y repetitividad que tienen lo sensores si queres.

En cuanto al esquema o foto, te referis a una foto de como esta todo conectado?

Tal vez no me explique bien, lo que no debe variar rápidamente es la magnitud a medir, no la señal en crudo. Por ejemplo si se mide la temperatura de un cuarto, no se espera que suba y baje un grado cada mili segundo. En este caso promediar varios valores para eliminar ruido es lo correcto. En cambio si lo que se esta midiendo un evento rápido, como por ejemplo un transitorio de un condensador, hacer un promedio de mediciones seria un error y suavizar una curva requiere filtros mas especializados.
¿En cual caso estas?

Estoy en el segundo ya que se trata de sensores de gases. Los tengo en una camara cerrada y termalizada de modo que la temperatura no afecte la señal y los gases pasen mejor. Como base uso nitrogeno y le inyecto oxigeno, tengo cambios rapidos.

qLNmMhQb4OE.png

En el comentario anterior no se subio la imagen asi que pongo solamente el link.

Una inyeccion de oxigeno tiene esta pinta:

eso pasa en un par de segundos, la subida de la señal.

El ejemplo que diste antes, seria tomar esas variables, sumarlas y dividirlas por N, verdad?

Estas en el horno :slight_smile: ¿Tiene que tratarse la señal on line? Me parece mejor solución un pos tratamiento de la señal utilizando un script en R

Seniikas:
El ejemplo que diste antes, seria tomar esas variables, sumarlas y dividirlas por N, verdad?

Efectivamente, pero en tu caso no te serviría promediar valores en el tiempo. En todos los casos parecen ser eventos lineales, probablemente un tratamiento de cuadrados mínimos sea lo mejor (por lo menos en la calibración) y en el caso de la inyección ¿cual es la información valiosa? ¿ el escalón o la forma de la curva?

Completamente de acuerdo con PeterKanTropus. Eso es para un post procesamiento y para algo mas potente que Arduino.

Es evidente que dispones de los valores en forma de archivo para poder graficarlos.
Si pudiedras compartirlos ademas de dar mayor información sobre la naturaleza de la medición para poder entender el contexto de lo que haces y el porqué de lo que vemos.

Lo que haría sería trabajar en un entorno tipo MATLAB o LABVIEW con esos datos y buscar la respuesta que espero. Luego de resolverlo intentaría ver si es realizable con Arduino.

EDITO: he estado investigando y lo que sugiere PeterKanTropus es el mejor enfoque. Cuadrados mínimos.

Lo valioso es el valor que da Y, (ya calibrado), porque diria por ejemplo la concentracion de oxigeno. La forma de la curva es asi, simplemente para llegar a una linea estable donde pueda darle un valor con un patron que tengo. Utilizo el Origin para ver las curvas sacar mas o menos una linea media y asi poder calibrarlo, por eso la forma, pero lo ideal en estos tipos de uso es que sean picos definidos, casi como una cromatografia.

Entonces tendria que arreglarlo por cuadrados minimos? Toda calibracion que haga, es puramente en software.

A ver si entendí bien. estas buscando medir una concentración en un analito en una muestra, inyectándola a un flujo y midiéndola con un sensor de salida proporcional a la concentración del analito. Utilizando una curva de calibración de igual matriz pero con concentraciones conocidas del analito. En ese caso descarta también cuadrado mínimos, la técnica a utilizar debería ser la integración, lo que necesitas es saber el área debajo de la curva,

Casi jajaja. Pero si, va por ahi. Asi es como esta programado otro sistema (que uso, no que haya hecho). En este lo que estoy haciendo es utilizar Nitrogeno como carrier, Teniendo una concentracion de oxigeno menor al 1%. Mediante un control, le hago entrar una cantidad conocida de oxigeno, 5%, 8%, 10%, etc, de modo de calcular el valor de esa resistencia, o sea el cociente de resistencias, la resistencia que da en el momento, y la inicial que seria con nitrogeno puro. Con esos valores hago una curva de calibración y la inserto en mi codigo. Cuando hago el chequeo, da mas o menos bien. El tema es que al tener tanta dispersión la señal, digamos muy "ancha" entre los valores de Y, se hace dificil calcular un valor medio, o cual seria el valor mas adecuado. La idea es poder suavizar esa linea de modo de tener un valor mas preciso.

¿pero por que se ve un decaimiento de la señal en el tiempo? según tu modelo deberías trabajar en la "meseta" de una señal.Cualquier medición que hagas fuera de la meseta seria imprecisa, ¿o existe una gran diferencia de las señales entre las diferentes concentraciones de manera que el decaimiento no afecte el valor calculado? de ser así un promedio sobre todos los valores seria suficiente. Igualmente en un primer paso deberías demostrar que el error es aleatorio con técnicas de residuos sobre un ajuste de cuadrados mínimos lineal. Si el error responde de alguna otra manera, como por ejemplo un error sinusoidal de ruido eléctrico, la cosa se complica y deberías apelar a filtros mas sofisticado, como transformadas rápidas de fourier. No te voy a mentir, toco de oído en el tema de procesamiento de señales y lo poco que vi fue hace mas de 20 años y nunca lo aprendí bien :slight_smile: .

Seniikas:
Casi jajaja. Pero si, va por ahi. Asi es como esta programado otro sistema (que uso, no que haya hecho). En este lo que estoy haciendo es utilizar Nitrogeno como carrier, Teniendo una concentracion de oxigeno menor al 1%. Mediante un control, le hago entrar una cantidad conocida de oxigeno, 5%, 8%, 10%, etc, de modo de calcular el valor de esa resistencia, o sea el cociente de resistencias, la resistencia que da en el momento, y la inicial que seria con nitrogeno puro. Con esos valores hago una curva de calibración y la inserto en mi codigo. Cuando hago el chequeo, da mas o menos bien. El tema es que al tener tanta dispersión la señal, digamos muy "ancha" entre los valores de Y, se hace dificil calcular un valor medio, o cual seria el valor mas adecuado. La idea es poder suavizar esa linea de modo de tener un valor mas preciso.

Empiezo a recordar.... estas utilizando la técnica de agregado patrón.