Esistono librerie di smussamento del segnale per Arduino?


14

Sto lavorando su un robot mobile controllato tramite un collegamento wireless a 2,4 GHz. Il ricevitore è collegato all'Arduino Uno che funge da controller principale. Il canale di ingresso più critico (e principale) proveniente dal ricevitore produce un segnale molto rumoroso, che porta a molti piccoli cambiamenti nell'uscita degli attuatori, anche se questi non sono necessari.

inserisci qui la descrizione dell'immagine
                    Trama dell'input dell'Arduino in un intervallo di 30 secondi.

Sto cercando librerie in grado di eseguire un livellamento efficiente. Sono disponibili librerie di smussamento del segnale per Arduino (Uno)?


Non so se riesci a trovare questo tipo di librerie, ma temo che potrebbero aver bisogno di molta potenza della CPU per un Arduino. Preferirei scegliere una soluzione elettronica (filtro passa-basso) se possibile.
jfpoilpret,

Sono con jfpoilpret su questo. Penso che tu abbia bisogno di una soluzione elettronica. Vorrei provare un condensatore di stabilizzazione, (semplice filtro passa basso). Suppongo che tu stia utilizzando un canale adc, quindi dovresti mettere a terra un limite da questo canale. Inizia con valori intorno a 100pf e procedi da lì.
Giovanni b,

Risposte:


8

Microsmooth è una libreria di livellamento del segnale leggera attualmente in fase di sviluppo da parte mia.

Si sta ancora lavorando e l'obiettivo è renderlo leggero in termini di memoria e veloce. La libreria fornisce più filtri per il livellamento:

  • Media mobile semplice
  • Media mobile esponenziale
  • Media mobile cumulativa
  • Filtro Golitz Savitzky
  • Algoritmo di Ramer Douglas Pecker
  • Kalmogorov Zurbenko Filter

Per utilizzare la libreria, scaricare e aggiungerla alla directory di origine. Inoltre, aggiungi la seguente riga al tuo file sorgente:

#include "microsmooth.h"

Ciao, ho problemi con l'uso della tua libreria. Non useresti "Importa libreria ..." per importare la tua libreria, giusto? Ho provato a copiare il sorgente nella mia cartella .ino, ma sto ricevendo errori sulla mancanza di automicrosmooth.h, il Serial non è stato definito e la mancanza di ';'. Questa libreria funziona ancora? Grazie
waspinator,

@waspinator Mi dispiace per quello. Risolti gli errori. Grazie per il feedback!
asheeshr,

7

Penso di vedere molti picchi di rumore a campione singolo nel tuo segnale rumoroso.

Il filtro mediano fa meglio a eliminare i picchi di rumore a campione singolo rispetto a qualsiasi filtro lineare. (È migliore di qualsiasi filtro passa basso, media mobile, media mobile ponderata, ecc. In termini di tempo di risposta e capacità di ignorare tali valori anomali di picco del singolo campione).

Esistono, infatti, molte librerie di smussamento del segnale per Arduino, molte delle quali includono un filtro mediano.

librerie di smoothing del segnale su arduino.cc:

librerie di smoothing del segnale su github:

Qualcosa del genere funzionerebbe nel tuo robot? (La mediana del 3 richiede pochissima potenza della CPU, e quindi veloce):

/*
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);
}

4

Hai provato un filtro passa basso? Ho trovato un esempio qui un altro qui .

Entrambe queste librerie hanno un elenco di dati letti dal sensore analogico di tua scelta, che viene calcolato come media. Ogni nuovo valore del sensore viene aggiunto all'elenco e l'ultimo viene eliminato, in questo modo:

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

Praticamente quello che fa un semplice filtro FIR con tutti i valori di tap impostati su 1. Giocare con i valori di tap può migliorare ulteriormente il segnale, ma richiede una matematica più alta.
jippie,

Nota: il secondo collegamento calcola la media mobile cumulativa che non è una scelta pratica per il controllo dell'attuatore, in particolare uno che può comportare frequenti avviamenti e arresti. Il segnale livellato seguirà sempre il valore di picco del segnale effettivo di un bel margine.
asheeshr,

2

Puoi filtrarlo digitalmente usando un filtro passa basso:

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

Cambiare lo 0.99 per cambiare la frequenza di taglio (più vicino a 1.0 è la frequenza più bassa). L'espressione effettiva per quel valore è exp (-2 * pi * f / fs) dove f è la frequenza di taglio desiderata e fs è la frequenza con cui vengono campionati i dati.

Un altro tipo di "filtro digitale" è un filtro eventi. Funziona bene su dati che hanno valori anomali; ad es. 9,9,8,10,9,25,9. Un filtro eventi restituisce il valore più frequente. Statisticamente questa è la modalità.

Medie statistiche come Media, Modalità ecc. Possono essere calcolate utilizzando la Libreria media di Arduino .

Un esempio tratto dalla pagina della Libreria Arduino riferito 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);
}

1
Nota che questo sarà molto lento, dal momento che sta facendo molti lanci impliciti per fluttuare e tornare indietro.
Connor Wolf,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.