Forum: PC-Programmierung Daten Filtern (Mittelwertfilter)


von Rene P. (rene1989)


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.
1
xincl01d[9] = xincl01d[8];
2
xincl01d[8] = xincl01d[7];
3
xincl01d[7] = xincl01d[6];
4
xincl01d[6] = xincl01d[5];
5
xincl01d[5] = xincl01d[4];
6
xincl01d[4] = xincl01d[3];
7
xincl01d[3] = xincl01d[2];
8
xincl01d[2] = xincl01d[1];
9
xincl01d[1] = xincl01d[0];
10
xincl01d[0] = xincl01;
11
12
xincl01=xincl01d[0]+xincl01d[1]+...+xincl01d[9];
13
xincl01 = (xincl01/10);

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

vielen Dank
mfg Rene

von Timmo H. (masterfx)


Lesenswert?

1
int i;
2
int wert=0;
3
for(i = 0; i < 10; i++)
4
  wert += xincl01d[i];
5
wert /= 10;
Oder was willst du machen?

von Rene P. (rene1989)


Lesenswert?

ok sorry etwas genauer:
1
...
2
float xincl01;
3
float xincl01d[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4
...
5
while(1) {
6
  xincl01 = readXInclinationAdis(); // Sensor auslesen
7
8
  xincl01d[9] = xincl01d[8];
9
  xincl01d[8] = xincl01d[7];
10
  xincl01d[7] = xincl01d[6];
11
  xincl01d[6] = xincl01d[5];
12
  xincl01d[5] = xincl01d[4];
13
  xincl01d[4] = xincl01d[3];
14
  xincl01d[3] = xincl01d[2];
15
  xincl01d[2] = xincl01d[1];
16
  xincl01d[1] = xincl01d[0];
17
  xincl01d[0] = xincl01;       //aktueller Sensorwert
18
19
  xincl01=xincl01d[0]+xincl01d[1]+...+xincl01d[9]; //alle Addieren
20
  xincl01 = (xincl01/10);   //Mittelwert bilden
21
22
  USART_Transmit( xincl01 ); //an PC senden
23
24
}

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

von Slash-N (/n) (Gast)


Lesenswert?

Ja. Das ist viel zu muehsam. Ein exponentieller Mittelwert, resp 
Tiefpass ist einfacher zu rechnen.

von Timmo H. (masterfx)


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?

von Benedikt K. (benedikt)


Lesenswert?

Ich würde es so machen:
1
float xincl01;
2
while(1) {
3
xincl01 = 0.9*xincl01 + 0.1*readXInclinationAdis(); // Sensor auslesen
4
USART_Transmit( xincl01 ); //an PC senden
5
}

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

von Rene P. (rene1989)


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

von haikar (Gast)


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:
1
...
2
#define N_WINDOW 10
3
4
float xincl01d[N_WINDOW] = {};
5
float sum_window = 0;
6
int n = 0;
7
...
8
while(1) {
9
  const float x = readXInclinationAdis(); // Sensor auslesen
10
  float y;
11
 
12
  sum_window -= xinc101d[n];  //ältesten Wert rausschmeißen
13
  sum_window += x;
14
  xinc101d[n] = x;  //neuen Wert reinschreiben
15
16
  n++;
17
  if (n >= N_WINDOW)
18
     n = 0;
19
20
  y = sum_window/10;   //Mittelwert bilden
21
22
  USART_Transmit(y); //an PC senden
23
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.