Gibt es Signalglättungsbibliotheken für Arduino?

14

Ich arbeite an einem mobilen Roboter, der über eine drahtlose 2,4-GHz-Verbindung gesteuert wird. Der Empfänger ist mit dem Arduino Uno verbunden, der als Hauptcontroller an Bord dient. Der kritischste (und wichtigste) Eingangskanal, der vom Empfänger kommt, erzeugt ein sehr verrauschtes Signal, was zu vielen geringfügigen Änderungen am Ausgang der Aktuatoren führt, obwohl diese nicht benötigt werden.

Bildbeschreibung hier eingeben
                    Darstellung der Eingabe des Arduino in einem Intervall von 30 Sekunden.

Ich suche Bibliotheken, die effizient glätten können. Gibt es irgendwelche Signalglättungsbibliotheken für das Arduino (Uno)?

Ascheshr
quelle
Ich weiß nicht, ob Sie diese Art von Bibliotheken finden können, aber ich befürchte, dass diese möglicherweise zu viel CPU-Leistung für ein Arduino benötigen. Ich würde lieber mit einer elektronischen Lösung (Tiefpassfilter) gehen, wenn möglich.
jfpoilpret
Ich bin mit jfpoilpret dabei. Ich denke, Sie brauchen eine elektronische Lösung. Ich würde versuchen, einen Stabilisierungskondensator (einfaches Tiefpassfilter). Ich gehe davon aus, dass Sie einen ADC-Kanal verwenden, daher sollten Sie eine Kappe von diesem Kanal auf Masse legen. Beginnen Sie mit Werten um 100pf und arbeiten Sie von dort aus.
John b

Antworten:

8

Microsmooth ist eine leichte Signalglättungsbibliothek, die derzeit von mir entwickelt wird.

Es wird noch daran gearbeitet und das Ziel ist es, es in Bezug auf das Gedächtnis leicht und schnell zu machen. Die Bibliothek bietet mehrere Filter zum Glätten:

  • Einfacher gleitender Durchschnitt
  • Exponentieller gleitender Durchschnitt
  • Kumulativer gleitender Durchschnitt
  • Savitzky Golay Filter
  • Ramer Douglas Pecker Algorithmus
  • Kalmogorov Zurbenko Filter

Laden Sie die Bibliothek herunter und fügen Sie sie dem Quellverzeichnis hinzu, um sie zu verwenden. Fügen Sie Ihrer Quelldatei außerdem die folgende Zeile hinzu:

#include "microsmooth.h"
Ascheshr
quelle
Hallo, ich habe Probleme mit Ihrer Bibliothek. Sie würden nicht "Bibliothek importieren ..." verwenden, um Ihre Bibliothek zu importieren, oder? Ich habe versucht, nur den Quellcode in meinen .ino-Ordner zu kopieren, aber es wird eine Fehlermeldung angezeigt, dass automicrosmooth.h fehlt, Serial not defined ist und ';' fehlt. Funktioniert diese Bibliothek noch? Danke
waspinator
@waspinator Entschuldigung. Fehler behoben. Danke für die Rückmeldung!
Asheeshr
7

Ich glaube, ich sehe viele Single-Sample-Rauschspitzen in Ihrem verrauschten Signal.

Mit dem Medianfilter lassen sich Rauschspitzen bei einer Stichprobe besser beseitigen als mit jedem linearen Filter. (Es ist besser als jedes Tiefpassfilter, jeder gleitende Durchschnitt, jeder gewichtete gleitende Durchschnitt usw. in Bezug auf seine Reaktionszeit und seine Fähigkeit, solche Störspitzen-Ausreißer bei einer einzelnen Stichprobe zu ignorieren.)

Es gibt in der Tat viele signalglättende Bibliotheken für den Arduino, von denen viele einen Medianfilter enthalten.

Signalglättungsbibliotheken bei arduino.cc:

Signalglättungsbibliotheken bei github:

Würde so etwas in Ihrem Roboter funktionieren? (Der Median von 3 benötigt sehr wenig CPU-Leistung und ist daher schnell):

/*
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
quelle
4

Haben Sie einen Tiefpassfilter ausprobiert? Ich habe hier ein anderes Beispiel gefunden .

In beiden Bibliotheken wird eine Liste der Daten angezeigt, die vom analogen Sensor Ihrer Wahl gelesen werden und deren Durchschnitt ermittelt wird. Jeder neue Sensorwert wird zur Liste hinzugefügt und der letzte wird wie folgt verworfen:

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
Der Doktor
quelle
Ziemlich genau das, was ein einfacher FIR-Filter mit allen auf 1 eingestellten Abgriffswerten tut. Das Spielen mit den Abgriffswerten kann das Signal weiter verbessern, erfordert jedoch eine höhere Mathematik.
jippie
Hinweis: Der zweite Link berechnet den kumulierten gleitenden Durchschnitt, der für die Steuerung des Stellantriebs nicht praktikabel ist. Dies gilt insbesondere für häufiges Starten und Stoppen. Das geglättete Signal liegt immer ziemlich weit hinter dem Spitzenwert des tatsächlichen Signals.
Asheeshr
2

Sie können dies mit einem Tiefpassfilter digital filtern:

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

Ändern Sie 0,99, um die Grenzfrequenz zu ändern (näher an 1,0 liegt die niedrigere Frequenz). Der tatsächliche Ausdruck für diesen Wert ist exp (-2 * pi * f / fs), wobei f die gewünschte Grenzfrequenz und fs die Frequenz ist, mit der die Daten abgetastet werden.

Ein anderer Typ eines "digitalen Filters" ist ein Ereignisfilter. Es funktioniert gut bei Daten mit Ausreißern. zB 9,9,8,10,9,25,9. Ein Ereignisfilter gibt den häufigsten Wert zurück. Statistisch gesehen ist dies der Modus.

Statistische Mittelwerte wie Mittelwert, Modus usw. können mithilfe der Arduino Average Library berechnet werden .

Ein Beispiel aus der Arduino-Bibliothek bezieht sich auf:

#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
quelle
1
Beachten Sie, dass dies sehr langsam sein wird, da es viele implizite Casts für Floating und Back ausführt.
Connor Wolf