¿Hay alguna biblioteca de suavizado de señal para Arduino?

14

Estoy trabajando en un robot móvil controlado a través de un enlace inalámbrico de 2,4 GHz. El receptor está conectado al Arduino Uno, que sirve a bordo como controlador principal. El canal de entrada más crítico (y principal) que proviene del receptor produce una señal muy ruidosa, lo que conduce a muchos cambios menores en la salida de los actuadores, aunque estos no son necesarios.

ingrese la descripción de la imagen aquí
                    Trazado de la entrada del Arduino en un intervalo de 30 segundos.

Estoy buscando bibliotecas que puedan realizar un suavizado eficiente. ¿Hay alguna biblioteca de suavizado de señal disponible para Arduino (Uno)?

Asheeshr
fuente
No sé si puede encontrar este tipo de bibliotecas, pero me temo que podrían necesitar mucha CPU para un Arduino. Prefiero ir con una solución electrónica (filtro de paso bajo) si es posible.
jfpoilpret
Estoy con jfpoilpret en esto. Creo que necesitas una solución electrónica. Probaría un condensador de estabilización (filtro de paso bajo simple). Supongo que está utilizando un canal adc, por lo que debe poner un límite de este canal a tierra. Comience con valores de alrededor de 100pf y continúe desde allí.
John b

Respuestas:

8

Microsmooth es una biblioteca de suavizado de señales liviana que estoy desarrollando actualmente.

Todavía se está trabajando y el objetivo es hacerlo ligero en términos de memoria y rápido. La biblioteca proporciona múltiples filtros para suavizar:

  • Media móvil simple
  • Media móvil exponencial
  • Promedio móvil acumulativo
  • Filtro Savitzky Golay
  • Algoritmo Ramer Douglas Pecker
  • Kalmogorov Zurbenko Filter

Para usar la biblioteca, descárguela y agréguela al directorio de origen. Además, agregue la siguiente línea a su archivo fuente:

#include "microsmooth.h"
Asheeshr
fuente
Hola, tengo problemas para usar tu biblioteca. No utilizarías "Importar biblioteca ..." para importar tu biblioteca, ¿verdad? Intenté simplemente copiar la fuente en mi carpeta .ino, pero recibo errores sobre la falta de automicrosmooth.h, la serie no se define y falta ';'. ¿Esta biblioteca aún funciona? Gracias
waspinator
@waspinator Lo siento por eso. Se corrigieron los errores. ¡Gracias por la respuesta!
asheeshr
7

Creo que veo muchos picos de ruido de muestra única en su señal ruidosa.

El filtro mediano funciona mejor para eliminar los picos de ruido de muestra única que cualquier filtro lineal. (Es mejor que cualquier filtro de paso bajo, promedio móvil, promedio móvil ponderado, etc. en términos de su tiempo de respuesta y su capacidad para ignorar tales valores atípicos de pico de ruido de muestra única).

De hecho, hay muchas bibliotecas de suavizado de señal para Arduino, muchas de las cuales incluyen un filtro mediano.

bibliotecas de suavizado de señal en arduino.cc:

bibliotecas de suavizado de señal en github:

¿Algo como esto funcionaría en tu robot? (La mediana de 3 requiere muy poca potencia de CPU y, por lo tanto, es rápida):

/*
median_filter.ino
2014-03-25: started by David Cary
*/

int median_of_3( int a, int b, int c ){
    int the_max = max( max( a, b ), c );
    int the_min = min( min( a, b ), c );
    // unnecessarily clever code
    int the_median = the_max ^ the_min ^ a ^ b ^ c;
    return( the_median );
}

int newest = 0;
int recent = 0;
int oldest = 0;

void setup()
{
    Serial.begin(9600);
    // read first value, initialize with it.
    oldest = random(200);
    recent = oldest;
    newest = recent;
    Serial.println("median filter example: ");
}

void loop()
{
    // drop oldest value and shift in latest value
    oldest = recent;
    recent = newest;
    newest = random(200);

    Serial.print("new value: ");
    Serial.print(newest, DEC);

    int median = median_of_3( oldest, recent, newest );

    Serial.print("smoothed value: ");
    Serial.print(median, DEC);
    Serial.println("");

    delay(5000);
}
David Cary
fuente
4

¿Has probado un filtro de paso bajo? Encontré un ejemplo aquí y otro aquí .

Ambas bibliotecas tienen una lista de datos que se leen desde el sensor analógico de su elección que se promedia. Cada nuevo valor del sensor se agrega a la lista, y el último se descarta de esta manera:

List: 3 4 3 3 4 3 5 3 2 3 4 3 
new reading added. old one thrown out
      /--                     /--
List: 5 3 4 3 3 4 3 5 3 2 3 4
list averaged
TheDoctor
fuente
Más o menos lo que hace un filtro FIR simple con todos los valores de tap configurados en 1. Jugar con los valores de tap puede mejorar aún más la señal, pero requiere una mayor matemática.
jippie
Nota: El segundo enlace calcula el promedio móvil acumulativo que no es una opción práctica para el control del actuador, especialmente una que puede involucrar arranques y paradas frecuentes. La señal suavizada siempre seguirá el valor pico de la señal real por un margen considerable.
asheeshr
2

Puede filtrar esto digitalmente usando un filtro de paso bajo:

int valueFilt = (1-0.99)*value + 0.99*valueFilt;

Cambie 0.99 para cambiar la frecuencia de corte (más cerca de 1.0 es la frecuencia más baja). La expresión real para ese valor es exp (-2 * pi * f / fs) donde f es la frecuencia de corte que desea y fs es la frecuencia con la que se muestrean los datos.

Otro tipo de "filtro digital" es un filtro de eventos. Funciona bien en datos que tienen valores atípicos; por ejemplo, 9,9,8,10,9,25,9. Un filtro de eventos devuelve el valor más frecuente. Estadísticamente este es el modo.

Los promedios estadísticos como la media, el modo, etc. se pueden calcular utilizando la biblioteca de Arduino Average .

Un ejemplo tomado de la página de la Biblioteca Arduino se refiere a:

#include <Average.h>
#define CNT 600
int d[CNT];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int i;

  for(i=0; i<CNT; i++)
  {
    d[i] = random(500);
  }  

  Serial.print("Mean: ");
  Serial.print(mean(d,CNT),DEC);
  Serial.print(" Mode: ");
  Serial.print(mode(d,CNT),DEC);
  Serial.print(" Max: ");
  Serial.print(maximum(d,CNT),DEC);
  Serial.print(" Min: ");
  Serial.print(minimum(d,CNT),DEC);
  Serial.print(" Standard deviation: ");
  Serial.print(stddev(d,CNT),4);
  Serial.println("");
  Serial.println("");

  delay(5000);
}
akellyirl
fuente
1
Tenga en cuenta que esto será muy lento, ya que está haciendo muchos lanzamientos implícitos para flotar y retroceder.
Connor Wolf