Existem bibliotecas de suavização de sinal para o Arduino?

14

Estou trabalhando em um robô móvel controlado por um link sem fio de 2,4 GHz. O receptor está conectado ao Arduino Uno, que serve a bordo como controlador principal. O canal de entrada mais crítico (e principal) proveniente do receptor produz um sinal muito barulhento, o que leva a muitas pequenas alterações na saída dos atuadores, mesmo que não sejam necessárias.

insira a descrição da imagem aqui
                    Traçar a entrada do Arduino em um intervalo de 30 segundos.

Estou procurando bibliotecas que possam executar uma suavização eficiente. Existem bibliotecas de suavização de sinal disponíveis para o Arduino (Uno)?

asheeshr
fonte
Não sei se você pode encontrar esse tipo de bibliotecas, mas receio que elas precisem de muita energia da CPU para um Arduino. Prefiro usar uma solução eletrônica (filtro passa-baixo), se possível.
Jfpoilpret
Estou com jfpoilpret nisso. Eu acho que você precisa de uma solução eletrônica. Eu tentaria um capacitor de estabilização, (filtro passa-baixo simples). Presumo que você esteja usando um canal adc, portanto, você deve colocar um limite desse canal no chão. Comece com valores em torno de 100pf e trabalhe a partir daí.
John b

Respostas:

8

Microsmooth é uma biblioteca de suavização de sinais de baixo peso atualmente sendo desenvolvida por mim.

Ele ainda está sendo trabalhado e o objetivo é torná-lo leve em termos de memória e rápido. A biblioteca fornece vários filtros para suavização:

  • Média Móvel Simples
  • Média Móvel Exponencial
  • Média Móvel Acumulada
  • Savitzky Golay Filter
  • Algoritmo de Ramer Douglas Pecker
  • Kalmogorov Zurbenko Filter

Para usar a biblioteca, faça o download e adicione-o ao diretório de origem. Além disso, adicione a seguinte linha ao seu arquivo de origem:

#include "microsmooth.h"
asheeshr
fonte
Olá, estou com problemas para usar sua biblioteca. Você não usaria "Importar Biblioteca ..." para importar sua biblioteca, certo? Tentei apenas copiar a fonte para minha pasta .ino, mas estou recebendo erros sobre a falta do automicrosmooth.h, o serial não sendo definido e a falta de ';'. Esta biblioteca ainda está funcionando? Graças
Waspinator
@waspinator Desculpe por isso. Corrigidos os erros. Obrigado pelo feedback!
Asheeshr
7

Acho que vejo muitos picos de ruído de amostra única no seu sinal barulhento.

O filtro mediano se sai melhor em eliminar picos de ruído de amostra única do que qualquer filtro linear. (É melhor do que qualquer filtro passa-baixo, média móvel, média móvel ponderada, etc. em termos de tempo de resposta e capacidade de ignorar esses outliers de picos de ruído de amostra única).

De fato, existem muitas bibliotecas de suavização de sinal para o Arduino, muitas das quais incluem um filtro mediano.

bibliotecas de suavização de sinal em arduino.cc:

bibliotecas de suavização de sinal no github:

Algo assim funcionaria no seu robô? (A mediana de 3 requer muito pouca energia da CPU e, portanto, 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
fonte
4

Você já tentou um filtro passa-baixo? Encontrei um exemplo aqui e outro aqui .

Ambas as bibliotecas têm uma lista de dados lidos do sensor analógico de sua escolha, que é calculado em média. Cada novo valor de sensor é adicionado à lista e o último é descartado, assim:

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
O médico
fonte
Praticamente o que um filtro FIR simples faz com todos os valores de derivação configurados como 1. A brinca com os valores de derivações pode melhorar ainda mais o sinal, mas requer matemática mais alta.
jippie
Nota: O segundo link calcula a média móvel cumulativa, que não é uma opção prática para o controle do atuador, especialmente um que pode envolver partidas e paradas frequentes. O sinal suavizado sempre seguirá o valor de pico do sinal real em uma margem bastante.
asheeshr
2

Você pode filtrar isso digitalmente usando um filtro passa-baixo:

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

Altere 0,99 para alterar a frequência de corte (mais próximo de 1,0 é a frequência mais baixa). A expressão real para esse valor é exp (-2 * pi * f / fs), em que f é a frequência de corte desejada e fs é a frequência em que os dados são amostrados.

Outro tipo de "filtro digital" é um filtro de eventos. Funciona bem em dados com outliers; por exemplo 9,9,8,10,9,25,9. Um filtro de eventos retorna o valor mais frequente. Estatisticamente, este é o modo.

As médias estatísticas, como Média, Modo etc. podem ser calculadas usando a Biblioteca Média do Arduino .

Um exemplo retirado da página da Biblioteca do Arduino se refere 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
fonte
1
Observe que isso será muito lento, pois está fazendo muitas conversões implícitas para flutuar e voltar.
Connor Lobo