Tiefpassfilter für Kompasskurs

Gast #4569537
Lesenswert?
• ▲
▼
Moin!

Ich bekomme von einem externen Kompassmodul einen fertig berechneten 
Kompass-Wert (0.0 bis 359.9 Grad) über eine serielle Schnittstelle (als 
ASCII mit einer Dezimalstelle und einem Zeilenende als Abschluss).

Der Wert ist allerdings mit einem Rauschen von etwa 2 Grad Spitze-Spitze 
überlagert und taugt noch nicht zur direkten Anzeige - das wackelt zu 
viel.

Da die Messfrequenz ungefähr 30 Hertz beträgt und mein Messobjekt nicht 
besonders dynamisch ist, könnte ich über ungefähr 20 bis 40 Werte 
tiefpassfiltern. Das habe ich auch schon umgesetzt und es funktioniert 
auch ganz gut, die Anzeige schwankt nur um 0.1 Grad.

Allerdings gibt es an einer Stelle (logischerweise) ein Problem: Wenn 
der Wert bei Nordkurs zwischen 359 bis 1 Grad schwankt, erhalte ich als 
Ergebnis aus dem Tiefpaßfilter 180 Grad als Anzeige. Das ist nun ganz 
und gar ein unerwünschtes Verhalten!

Wie kann man diese Filterung eleganter lösen, so dass ein stabiler 
Kompasswert herauskommt, insbesondere wenn sich das Messobjekt langsam 
dreht? Sprich - wie filtert man einen Messwert, der eine Diskontinuität 
im Bereich hat?
Gast #4569542
Lesenswert?
• ▲
▼
Moinsen!

Rechne intern einfach die Umdrehunen mit. Anschließend kannst du den 
Winkel z.B. durch eine Modulo Operation wieder berechnen.

Etwas so:
1
if((letzterWert<90)&&(wert>180)) umdrehungen--;
2
else
3
if((letzterWert>270)&&(wert<180))umdrehungen++;
4

5
wert += umdrehungen * 360;
6
wert = tiefpass(wert);
7
wert = wert%360;
Gast #4569543
Lesenswert?
• ▲
▼
... der lieber mit diesen Parametern:
1
if((letzterWert<90)&&(wert>270)) umdrehungen--;
2
else
3
if((letzterWert>270)&&(wert<90))umdrehungen++;
4

5
wert += umdrehungen * 360;
6
wert = tiefpass(wert);
7
wert = wert%360;
#4569705
Lesenswert?
• ▲
▼
Scheint mir auch die eleganteste Lösung zu sein. Falls du sin & cos 
einigermaßen brauchbar berechnen kannst.

Ansonsten könntest du deinen Wertebereich um 180° drehen, sobald es in 
die Nähe der 0° geht, damit die Diskontinuität dann woanders liegt.
Schwierig wird es, da den Grenzwert einzustellen, denn genau da tritt 
wieder ein Schalten auf. Vermutlich möchte man das glatte, gefilterte 
Signal als Entscheidungsgrundlage nehmen und etwas Hysterese einbauen. 
Das wird vermutlich schwieriger, als es klingt...
sollte aber auch machbar sein.
Gast #4569875
Lesenswert?
• ▲
▼
Joe F. schrieb:
> Ein Median-Filter wäre auch noch eine Möglichkeit.
> Da kommt immer ein sinnvoller Wert heraus.

Das ist doch Unfug.

Es kommt zwar kein um rund 180° falscher Wert raus, aber bei Anwendung 
auf Kompasskurse im Bereich 360/0° werden gerade die richtigen Werte 
(nahe 0/360°) durch die Medianberechung rausgeschmissen. Als Ergebnis 
aus dem Median kommt nämlich in dem Fall einer raus, der gerade von 
0/360° weit weg liegt :-(
#4569878
Lesenswert?
• ▲
▼
Wolfgang schrieb:
> Als Ergebnis
> aus dem Median kommt nämlich in dem Fall einer raus, der gerade von
> 0/360° weit weg liegt :-(

Nein, denn man nimmt natürlich den Wert, der in der Mitte der Liste 
liegt.

Nachtrag:
Achso, du hast natürlich recht. Sorry.

Medianfilter ist Quatsch.

Was Sinn machen würde, ist den am häufigsten auftretenden Wert zu 
nehmen.
#4569890
Lesenswert?
• ▲
▼
Andere Idee:

Du berechnest für jeden eingehenden Wert die Abweichung vom aktuell 
angezeigten Kurs (kann dann auch negativ sein).

Wenn die Abweichung des Messwertes >180° ist, nimmst du einen Überlauf 
über 0° an, und ziehst 360° ab.
Wenn die Abweichung <-180° ist, addierst du 360°.

Diese Abweichungen mittelst du, rechnest dieses Mittel zum aktuellen 
Kurs dazu, und bringst das Ergebnis wieder in den Wertebereich 0.0-359.9
(<0 -> +360.0 , >=360 -> -360.0)
Das ist dann der neue Kurs.
(Firma: HEGRO GmbH) #4569917
Lesenswert?
• ▲
▼
Das trifft sich gerade prima, mache nämlich just in diesem Moment etwas 
Ähnliches. N Kompass ist aber nicht dabei :>

Wolfgang schrieb:
> Rechne mit cos(KpK) und sin(KpK). Da tritt keine Diskontinuität auf.
Hättest du Lust und Zeit das zu erläutern?

EDIT: Nach etwas googlen habe ich das hier gefunden:

                   sum_i_from_1_to_N sin(a[i])
a = arctangent ---------------------------
                   sum_i_from_1_to_N cos(a[i])
Angehängte Dateien:
#4570019
Lesenswert?
• ▲
▼
Hier die reine Integer-Lösung (mit 0.1° Auflösung)

1
#define COMPASS_VALUES 30
2
#define TEST_DIRECTION 3599  // 359.9°  
3

4
int compass[COMPASS_VALUES];  
5
int i;
6
int d;
7
int d_sum;
8
int course;
9

10
// create random input values
11
for (i=0; i<COMPASS_VALUES; i++)
12
{
13
  compass[i] = TEST_DIRECTION + rand()%5 - 2;  // main direction +/- 0.2°
14
  if (compass[i] >= 3600) compass[i] -= 3600;
15
  if (compass[i] <     0) compass[i] += 3600;
16
  printf("%2d: %3d.%1d\n", i, compass[i]/10, compass[i]%10);
17
}
18

19
// calculate average course derivation
20
course = compass[0];
21
d_sum = 0;
22
for (i=1; i<COMPASS_VALUES; i++)
23
{
24
  d = compass[i] - course;
25
  if (d >  1800) d -= 3600;
26
  if (d < -1800) d += 3600;
27
  d_sum += d;
28
}
29
d_sum  += COMPASS_VALUES / 2;  // round (add 0.5)
30
d_sum  /= (COMPASS_VALUES);
31
course += d_sum;
32

33
// normalize
34
if (course >= 3600) course -= 3600;
35
if (course <     0) course += 3600;
36

37
// output
38
printf("Course: %3d.%1d°\n", course/10, course%10);

Ergebnis:
1
 0: 359.7
2
 1:   0.1
3
 2:   0.0
4
 3: 359.9
5
 4:   0.0
6
 5: 359.9
7
 6: 359.8
8
 7:   0.0
9
 8: 359.7
10
 9: 359.8
11
10: 359.7
12
11: 359.8
13
12:   0.1
14
13: 359.7
15
14:   0.0
16
15: 359.9
17
16: 359.7
18
17:   0.1
19
18: 359.9
20
19: 359.9
21
20: 359.8
22
21:   0.1
23
22:   0.1
24
23: 359.9
25
24:   0.1
26
25:   0.1
27
26: 359.7
28
27: 359.8
29
28: 359.9
30
29:   0.1
31
Course: 359.9°
Gast #4570286
Lesenswert?
• ▲
▼
Reginald L. schrieb:
> Wolfgang schrieb:
>> Rechne mit cos(KpK) und sin(KpK). Da tritt keine Diskontinuität auf.
> Hättest du Lust und Zeit das zu erläutern?

Guck dir den Kurvenverlauf von sin(x) und cos(x) in der Nähe von 0°/360° 
an. Da ist alles wunderschön stetig. So ganz unproblematisch ist eine 
Mittelung bei den Umkehrpunkten aber auch nicht (z.B. cos(x) für x nahe 
0).

Die Idee von Joe F. ist aber viel praktischer, weil keiner wegen einer 
simplen Mittelung trigonometrische Funktionen hoch und runter rechnen 
möchte.

Joe F. schrieb:
> Andere Idee: ...
(Firma: HEGRO GmbH) #4571110
Lesenswert?
• ▲
▼
Wolfgang schrieb:
> Mit dieser Einstellung wird es auch weiterhin gelingen, Fortschritte in
> der Rechnerleistung sinnlos durch Faulheit bei der Programmierung und
> Entwicklung von Algorithmen zu verpulvern.

Du kannst ruhig weiterhin stundenlang an der Entwicklung eines 
Algorithmus sitzen um deinen 4x3GHz Rechner dann mit dem kleinen 
EinMalEins zu malträtieren :)

Es dient letztendlich als Mittel zum Zweck. Möchte man sowas in einen 
kleinen langsamen 8-Bitter implementieren stellt sich die Frage 
inwieweit die "Faulheit" noch taugt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren