mikrocontroller.net

Forum: PC-Programmierung Daten Filtern (Mittelwertfilter)


Autor: Rene Pratsch (rene1989)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Ich habe einen Neigungssensor von dem ich Werte bekomme.
Nun haben aber die Werte der Neigung auch wenn sich der Sensor nicht 
bewegt einen Spielraum von 0.1-0.3 Grad in denen sich der Wert befindet.

Meine Lösung war ein Mittelwertfilter der immer 10Werte verwendet.
xincl01d[9] = xincl01d[8];
xincl01d[8] = xincl01d[7];
xincl01d[7] = xincl01d[6];
xincl01d[6] = xincl01d[5];
xincl01d[5] = xincl01d[4];
xincl01d[4] = xincl01d[3];
xincl01d[3] = xincl01d[2];
xincl01d[2] = xincl01d[1];
xincl01d[1] = xincl01d[0];
xincl01d[0] = xincl01;

xincl01=xincl01d[0]+xincl01d[1]+...+xincl01d[9];
xincl01 = (xincl01/10);

Gibt es einen besseren Lösungsweg für dieses Problem?
Oder meinen Code zu verbessern?

vielen Dank
mfg Rene

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int i;
int wert=0;
for(i = 0; i < 10; i++)
  wert += xincl01d[i];
wert /= 10;
Oder was willst du machen?

Autor: Rene Pratsch (rene1989)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok sorry etwas genauer:
...
float xincl01;
float xincl01d[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
...
while(1) {
  xincl01 = readXInclinationAdis(); // Sensor auslesen

  xincl01d[9] = xincl01d[8];
  xincl01d[8] = xincl01d[7];
  xincl01d[7] = xincl01d[6];
  xincl01d[6] = xincl01d[5];
  xincl01d[5] = xincl01d[4];
  xincl01d[4] = xincl01d[3];
  xincl01d[3] = xincl01d[2];
  xincl01d[2] = xincl01d[1];
  xincl01d[1] = xincl01d[0];
  xincl01d[0] = xincl01;       //aktueller Sensorwert

  xincl01=xincl01d[0]+xincl01d[1]+...+xincl01d[9]; //alle Addieren
  xincl01 = (xincl01/10);   //Mittelwert bilden

  USART_Transmit( xincl01 ); //an PC senden

}

am Schleifenanfang wird immer ein Wert aus dem Sensor gelesen.
Danach wird dieser in Das Array( xincl01d[0] = xincl01; ) gespeichert. 
Im nächsten Schleifendurchlauf werden alle Werte im Array um eins nach 
"hinten" verschoben und als erster Wert wieder der aktuelle Wert des 
Sensors eingetragen. So erhällt hat man immer die letzten 10 Werte des 
Sensors von denen man den Mittelwert bilden kann.

Meine Frage war ob man dies vereinfachen kann oder ob es andere, bessere 
Verfahren (Filter) gibt um mein Problem zu lösen.

danke

Autor: Slash-N (/n) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Das ist viel zu muehsam. Ein exponentieller Mittelwert, resp 
Tiefpass ist einfacher zu rechnen.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja dann kannst das mit der Mittelwert bildung ja trotzdem so machen 
wie von mir vorgeschlagen. Das die Werte einen nach hinten rutschen 
würde ich aber auch in einer Schleife machen. Dann ist es quasi ein 
6-Zeiler, das reicht doch oder?

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde es so machen:
float xincl01;
while(1) {
xincl01 = 0.9*xincl01 + 0.1*readXInclinationAdis(); // Sensor auslesen
USART_Transmit( xincl01 ); //an PC senden
}

Beide Faktoren addiert müssen 1 ergeben. Je kleiner der Faktor vor dem 
neuen Wert ist, desto stärker wird gefiltert.

Autor: Rene Pratsch (rene1989)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Benedikt

Dein Vorschlag hört sich gut an. So kann ich es machen das die letzten 
Werte stärker berücksichtigt werden.
Ich werde es gleich mal aufprobieren und dann hier posten

Danke mfg

Autor: haikar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Methode von Benedikt gewichtet natürlich die aktuellen Ergebnisse 
stärker entsprechend der gewählten Konstanten (hier 0.9), eben so wie 
das bei einem IIR-Filter erster Ordnung ist.
Wenn Du trotzdem Deine erste Variante mit dem gleitenden Mittelwert 
möchtest, kann das wesentlich effizienter mit einem Ringpuffer und dem 
aktualisieren der Summe in etwa so gemacht werden:
...
#define N_WINDOW 10

float xincl01d[N_WINDOW] = {};
float sum_window = 0;
int n = 0;
...
while(1) {
  const float x = readXInclinationAdis(); // Sensor auslesen
  float y;
 
  sum_window -= xinc101d[n];  //ältesten Wert rausschmeißen
  sum_window += x;
  xinc101d[n] = x;  //neuen Wert reinschreiben

  n++;
  if (n >= N_WINDOW)
     n = 0;

  y = sum_window/10;   //Mittelwert bilden

  USART_Transmit(y); //an PC senden
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.