Hallo,
für ein aktuelles Projekt haben wir uns Platinen ätzen lassen, auf dem
Board sind ein HMC5883L und ein Mega644p, verbunden über I2C.
Zum testen habe ich es schematisch wie im Arduino Beispiel Code gemacht:
Hier http://www.sparkfun.com/products/10530 -> Documents -> Example Code
Benutzten tue ich außerdem die I2C Lib von Peter Fleury.
Wenn ich den Kompass drehe, zeigt er immer nur Werte von 280 Grad bis
360 Grad an.
Hier ein paar Beispiele (immer um 90° weiter gedreht):
1.
Heading: 309
X: -9
Y: 11
Z: 6
2.
Heading: 351
X: -14
Y: 2
Z: 7
3.
Heading: 339
X: -27
Y: 10
Z: 7
4.
Heading: 325
X: -23
Y: 16
Z: 6
Das Heading berechne ich so:
angle = atan2((double)y,(double)x) * 180 / 3.14159265 + 180;
Hier der Code:
die Main.c (Hier werden die Funktionen nur ausgefürhrt, die I2c
funktionen sind weiter unten)
1
#define F_CPU 20000000UL
2
#define BAUD 115200UL
3
#include<util/delay.h>
4
#include<avr/io.h>
5
#include<stdio.h>
6
#include<stdlib.h>
7
#include<math.h>
8
#include"compass.h"
9
10
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
11
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
12
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
13
14
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
15
#warning Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
Das Programm ist nur so zum testen zusammen gefuscht.
In der compass_init(), wird lediglich das Register 0x02 auf 0x00
gesetzt, für den Continuous-measurement mode mit 15Hz (default).
Die compass_get_axis(...) wird alle 3 Sekunden ausgeführt, also das
passt locker mit 15Hz. In der Funktion wird erst der Register Indexer
auf 0x03 gesetzt und ab da dann 8 Bytes ausgelesen und in Varibalen
gespeichert.
Aber irgentwie passt das mit den Werten alles nicht.
habt ihr ne Idee was falsch sein könnte? Wie gesagt habe ich das alles
nur aus nem Arduino Beispielcode und sollte eigentlich Funtzten.
Danke schon mal im voraus.
MfG
Philipp
wie ist i2c_readAck deklariert?
wenn nur ein 8-Bit-Wert zurückgegeben wird (so sieht es aus), schieb man
den beim shiften ohne Typecast ins Nirvana..
*x = i2c_readAck()<<8;
Ich würde mal
*x = ((int)i2c_readAck())<<8;
probieren..
oder vielleicht so:
unsigned char *pbyte;
pbyte = x;
*pbyte = i2c_readAck();
*(pbyte+1) = i2c_readAck();
oder halt
*(pbyte+1) = i2c_readAck();
*pbyte = i2c_readAck();
dann das gleiche mit z und y
So isses wieder wie vorher, andersherum, sehen sind die Achsen schon im
Tausender Bereich, so wies sein soll, aber ein vernünftiges Heading
bekommen wir trotzdem immer noch nicht raus.
MfG
Philipp
Hi, Philipp,
> Wenn ich den Kompass drehe, zeigt er immer nur Werte von 280 Grad bis> 360 Grad an.
Das ist typisches Symptom für Fehlkalibrierung: Der Sensor misst nicht
nur das geomagnetische Feld, sondern auch die magnetischen Felder, die
von magnetischen Remanenzen in Stahl und Eisen erzeugt werden sowie von
elektrischen Strömen.
Mancher Autofahrer kauft sich einen neckischen Kompass und wundert sich,
dass das Einschalten der Heckscheibenheizung den Nordpol ferngesteuert
springen, und der Nordwert mit dem Gas einstellen lässt.
Dagegen hilft:
1. Stationäre Kalibrierfehler: Neukalibrierung mitsamt der gesamten
mobilen Plattform (für die häufigsten Fälle siehe Anhang).
2. Nicht-stationäre Fehler durch veränderliche Stromflüsse auf der
Platine: Außerordentlich problematisch. Ansatz zur Minimierung: Sensor
zur Messung eines solchen Stromflusses, dann dessen Beitrag aus den X-,
Y- und Z-Komponente heraus rechnen.
Nicht ohne Grund werden Kompasse in Flugzeugen und Schiffen in extremen
Positionen montiert, von tief im Kiel bis zum Ende der Tragfläche.
Ciao
Wolfgang Horn
Hi, Philipp, zweiter Punkt.
> Das Heading berechne ich so:> angle = atan2((double)y,(double)x) * 180 / 3.14159265 + 180;
Deine Formel ist schön einfach. Ich hatte für denselben Zweck eine mit
Fallunterscheidungen, je nach Quadranten habe ich die Vorzeichen
gewechselt.
Ciao
Wolfgang Horn
Philipp Maricek schrieb:> Hier ein paar Beispiele (immer um 90° weiter gedreht):> 1.> Heading: 309> X: -9> Y: 11> Z: 6> ...
Bei deinen Y-Werten ist die Verstärkung im Vergleich zu X fast einen
Faktor 2 zu niedrig und du hast Offsets von x0=-18 und y0=-10 auf deinen
Werten. Das einfachste ist, wenn du den Sensor einmal langsam um 360°
drehst und deine XY-Wertepaare in ein XY-Diagramm einträgst. Das
Erdmagnetfeld beschreibt dann idealerweise einen Kreis und der
Permanentmagnetvektor deines Aufbaus verschiebt den Mittelpunkt aus dem
Ursprung.
Wenn deine Daten auf einem Ursprungskreis liegen, kannst du mit dem Atan
anfangen zu rechnen.
Hallo,
hab nochmaln bisschen getestet, und festgestellt, dass die x,y,z
Register wahrscheinluch vertauscht sind. Ich muss noch rausfinden, wie
genau.
MfG
Philipp
Ich verwende einen sehr ähnlichen Code mit dem HMC5883L und habe das
gleiche Problem, dass meine Berechnete Richtung sich nicht ändert, egal
wie ich den Sensor drehe.
Hast du mittlerweile eine Lösung gefunden?
Hallo,
hat mittlerweile jemand eine Lösung des Problems? Bei mir kommen leider
auch nur Werte oberhalb 280...
... habt ihr MSB und LSB als signed int oder unsigned int laufen?
Vielen Dank schon mal für Eure Hilfe!!! :-)
Euer Code?
Und bevor ihr versucht den Winkel auszurechnen, wie sehen die RAW Daten
denn aus? Ergeben die Sinn? Was passiert wenn ihr eure Platine um 360
Grad um eine Achse dreht? Lasst euch die Werte per RS232 oder LCD
ständig ausgeben.
Was passiert wenn ihr einen schwachen Magnet von weit außen annähert?
Habt ihr magnetisierbare Objekte in dichter nähe? (Eisen, Schrauben,
Lautsprecher, ...)
Habt ihr den IC selber gelötet oder fertig auf einer Platine bestellt?
Falls selbst gelötet, habt ihr beim Schaltungsentwurf die im Datenblatt
stehenden Dinge beachtet?
Hier mein Code der auf einem PIC24 funktioniert. Ich habe ihn nicht
exakt getestet, da ich den Magnetsensor bisher nicht gebraucht habe,
jedoch hat er bei den Tests sinnvolle Werte geliefert und auch der
Winkel wurde sinnvoll berechnet.
Die Formel für den Winkel ist die selbe die der Threadstarter benutzt
und entstammt aus einer Homepage die ich bei der Formel angegeben habe.
Vielleicht solltet ihr die Homepage mal genauer durcharbeiten, denn dort
stehen auch weitere nütliche Links.
"Vielleicht solltet ihr die Homepage mal genauer durcharbeiten, denn
dort
stehen auch weitere nütliche Links."
404 - Page not found...
Gibts das noch irgendwo anders?
Habe das gleiche Problem.
Ok, das erste Problem, dass da irgendwelche sinnlosen, wilden Kurswerte
berechnet wurden, alle zwischen 240 und 310 Grad, hat sich erledigt. Ich
sollte einfach lesen lernen und darauf achten, in welcher Reihenfolge
die x-, y- und z-Werte aus dem Sensor kommen...
Was jetzt noch bleibt ist, dass die Kurswerte noch heftig rumeiern.
Also wenn ich den Kompass um 90 Grad drehe erwarte ich eigentlich auch
eine Änderung der Gradzahl um diesen Betrag.
Wenn ich das aber mache (Orientierung an der Tischkante, immer 90 Grad
weitergedreht, ebene Fläche) kommen diese Werte raus (auf den nächsten
5er gerundet):
x y z kurs
130 125 -435 40
-230 35 -430 170
-155 -335 -435 245
195 -275 -450 305
Statt immer ca 90 Grad sind die Differenzen zwischen 60 und 130 Grad.
Im Moment bin ich ein bisschen überfragt, wie ich diese großen
Abweichungen kompensieren kann.
Der relevante Teil des Codes ist:
Init des HMC:
i2c_start_wait(COMPASS_ADDR_WRITE);
i2c_write(0x02);
i2c_write(0x00);
i2c_stop();
i2c_start_wait(COMPASS_ADDR_WRITE);
i2c_write(0x01);
i2c_write(0x20);
i2c_stop();
i2c_start_wait(COMPASS_ADDR_WRITE);
i2c_write(0x00);
i2c_write(0x10);
i2c_stop();
_delay_ms(6);
Berechnung in der Hauptschleife, wird mit 15 Hz ausgeführt:
i2c_start_wait(COMPASS_ADDR_WRITE);
i2c_write(0x03);
i2c_stop();
i2c_start_wait(COMPASS_ADDR_READ);
x_raw = i2c_read(1); x_raw <<= 8;
x_raw |= i2c_read(1);
z_raw = i2c_read(1); z_raw <<= 8;
z_raw |= i2c_read(1);
y_raw = i2c_read(1); y_raw <<= 8;
y_raw |= i2c_read(0);
i2c_stop();
float heading = 0;
heading = atan2((double)y_raw,(double)x_raw);
heading = heading * 180 / M_PI;
if (heading < 0) heading = heading + 360;
if (heading >= 360) heading = heading - 360;
Ich hoffe, ihr habt dazu eine Idee.
LG
Da ich das gleiche Problem kürzlich auch hatte ...
Dein Problem ist, dass dein Sensor nicht kalibriert ist.
D.h. in der Umgebung in der er eingebaut ist bzw momentan getestet wird
musst du offset Werte ermitteln und hinterlegen.
Schreib ein Kalibrier-Programm, welches ständig den größten und
kleinsten Messwert jeder Achse speichert
if (messwert-x < min-x ) min-x = messwert-x...
Nachdem du deinen Sensor in jede erdenkliche Lage gebracht hast, weißt
du nun in welche Richtung dein Offset geht.
-420 bis 420 wäre ein offset=0
-440 bis 400 ergibt offset=-20
Nach deiner Kalibrierung kannst du nun bei jedem Messwert in deiner
Anwendung -20 abziehen ... Also jeden Messwert dieser Achse +20 rechnen.
Dann stimmt dein Winkel hoffentlich.
Evtl. noch die Magnetfeldkorrektur für deine geografische Lage
hinterlegen um vom mag Norden auf geo Norden zu kommen - fertig.
Hoffe das hilft - gib bitte feedback
wahhh ich könnt dich jetzt sowas von abknutschen... wenn du ne Frau
wärst ;)
Der Tipp war goldrichtig, jetzt zeigt er sauber die richtigen Werte an.
Danke!
Hab immer nicht verstanden, was die in den Quellcodes vom Multiwiikopter
oder bei MicroKopter da mit der Konstante nach dem Abgleich machen bzw
wie die die ermitteln, aber jetzt hats klick gemacht :)
Nochmal vielen vielen Dank!
Haha :-)
Kein Problem!
Falls du rausfindest wie man die Neigung mit in die Rechnung einbezieht
... Ich habe noch einen ACC und Gyro mit kalman-filter und PID fertig
... Aber mit dem Magnetfeld bin ich noch nicht so sehr zufrieden.
Zwar bekomme ich nun ordentliche Werte zwischen 0 und 360, aber ich bin
der Meinung, dass Norden doch noch 20° daneben ist...?!
Kalibrierung allerdings auf Tisch mit PC(WLAN, Bluetooth...), Handy und
vielen elektr. Geräten.
Wo/wie hast du kalibriert?
Moses schrieb:> Im Moment bin ich ein bisschen überfragt, wie ich diese großen> Abweichungen kompensieren kann.
Erstmal solltest du das ein bisschen genauer messen. Zeichne doch
einfach mal die (x,y,z) Datenpunkte auf, während du den Kompaß langsam
in allen Raumrichtungen drehst. Jeweils zwei der Parameter gegeneinander
geplottet müssen einen Kreis ergeben. Erst wenn da saubere Kreise
rauskommen, macht es Sinn daraus Winkel zu berechnen.
Auf dem Schreibtisch, mindestens 30 cm von allen elektrischen Geräten
entfernt.
Für die Praxis nachher muss ich dann eh eine Routine einbauen, die die
Minimal- und Maximalwerte ermittelt und daraus das Offset bestimmt.
Mir gings jetzt erstmal um die generelle Lösung des Problems.
Die Neigungskompensation ist dann der nächste Schritt. Gedacht ist das
Ganze für einen Quadrokopter. Von der Steuerplatine bekomme ich die
aktuellen Neigungswerte in x- und y-Richtung (Gyro und ACC bereits
fusioniert). Die muss ich mir dann noch normieren und dann werde ich das
mal mit diesen Formeln hier versuchen:
Ich glaube wir sollten Kontakt bleiben - baue auch einen quadcopter.
Momentan hängt das aber etwas mit der tiltcompensation bei mir.
Falls du Hilfe brauchst bei Gyro, Acc, Kalmanfilter, PID ... Habe ich
soweit alles laufen.
Die gleichen Formeln habe ich auch im Controller aber irgendwie stimmt
da was nicht. Kann auch daran liegen, dass die falschen Werte verrechnet
werden. Ist ein komplettes board (gy80) - vielleicht sind die Achsen
nicht so wirklich kompatibel - z.B. Winkelx+ entspricht magx- oder so.
Werde mir das heute anschauen - Wenn du das hinbekommst melde dich mal
bitte ;-)
Moses schrieb:> Für die Praxis nachher muss ich dann eh eine Routine einbauen, die die> Minimal- und Maximalwerte ermittelt und daraus das Offset bestimmt.
Offset reicht nicht, die Skalierungsfaktoren der Achsen müssen auch
stimmen.
Ok ... Habe im Datenblatt die Antwort gefunden (siehe Anhang)
Nachdem msb&lsb kombiniert wurden wird der scale_factor multipliziert.
Bei +-1.3 Ga z.B. 0.92
Mit diesen Werten dann Offset bestimmen und bei jeder Messung abziehen.
Wenn ich mich irre korrigiert mich bitte.
Hallo Michael,
hast du dafür mal ein konkretes Beispiel? Mit der Skalierung stehe ich
noch etwas auf dem Schlauch.
Der Self-Test zeigt doch meines Erachtens nur, ob die ausgegebenen Werte
bei der gewählten Verstärkung (Gain) innerhalb akzeptabler Grenzen
liegen. Wenn nicht, muss man Gain so viele Stufen runterdrehen, bis es
passt. Und wenn die Werte viel zu klein sind, dann eben Gain etwas nach
oben.
Oder haben ich das falsch verstanden?
Dieses Beispiel im Datenblatt
1
If Gain = 6, self test limits are:
2
Low Limit = 243 * 330/390 = 206
3
High Limit = 575 * 330/390 = 487
zeigt doch nur, wie man die in den Spezifikationen für Gain=5 (+- 4.7
Ga) angegebenen Grenzwerte für andere Verstärkungen berechnet, also
Grenzwert für Gain=5 mal neuer Verstärkungsfaktor geteilt durch Faktor
für Gain=5 gibt den Grenzwert für die aktuelle Verstärkung.
Damit muss man doch im praktischen Betrieb nachher nicht mehr arbeiten,
oder?
Was später vielleicht noch interessant wäre ist die
Temperaturkompensation. Wenn ich das richtig verstanden habe muss mann
dazu einfach immer wieder mal für ein paar Zyklen (bei 15 Hz ist das ja
grad mal ein Wimpernschlag und das auch nur alle paar Sekunden) in den
Selftestmodus schalten und den Maximalwert mit dem Referenzwert für eine
bestimmte Temperatur vergleichen. Aktueller Maximalwert / Referenzwert =
Faktor, mit dem dann alle Messwerte im Normalmodus multipliziert werden.
Danach dann wieder in den Normalmodus schalten.
Klingt einfach und ist es hoffentlich auch...
LG
Moses schrieb:> Hallo Michael,> hast du dafür mal ein konkretes Beispiel? Mit der Skalierung stehe ich> noch etwas auf dem Schlauch.
Das habe ich einen Post weiter oben beschrieben. Schau dir das Bild dazu
an. Du erhälst vom Sensor msb und lsb, machst eine 16bit draus und dann
kommt der Faktor 0.92 (für +-1.3Ga, andere siehe Bild) dazu.
Damit ist alles getan - jetzt kann der Winkel berechnet werden.
Der Self test zeigt dir (nehme ich an):
...ob du msb & lsb korrekt kombiniert hast.
...ob du, wie du selbst beschrieben hast, mehr oder weniger Gain
benötigst
...ob die Temp anders ist.
Ich würde mal behaupten, dass man den Selftest während des Fluges nicht
benötigt - ich lasse mich aber gern eines besseren belehren.
Bisher habe ich die genaue Anwendung des Selftests nicht verstanden.
Nun, jede Achse mit 0.92 zu multiplizieren macht doch eigentlich nur
zusätzlichen Aufwand für den µC (Kommazahlen, igitt...).
Und am Ende ist es doch egal, ob man atn2(100/100) oder atn2(92/92)
rechnet, der Faktor in der Klammer ist der gleiche.
Auch bei den Kompensationsformeln für die Neigung sollte das doch kein
Problem sein. Mit dem Faktor kommt Xh und Yh eben um den Faktor 0.92
kleiner raus und in der Winkelberechnung fliegt der Faktor doch eh raus.
Oder bin ich da jetzt auf dem falschen Dampfer?
Zur Temperaturkompensierung: Das ist wohl dann sinnvoll, wenn man im
Schatten bei ungefähr Zimmertemperatur startet und dann in die pralle
Sonne geht. In dem Beispiel im Datenblatt ist ja eine recht große
Differenz (mal eben um 100 runter mit dem Wert). Aber die absolute
Differenz ist ja auch unerheblich. Interessanter ist, wie groß die
Unterschiede zwischen den Achsen bei Zu- bzw Abnahme werden. Also ob bei
dem gleichen Temperaturunterschied die eine Achse um 100 abnimmt während
die andere vielleicht nur 80 weniger zeigt. Dann passt die Gradzahl am
Ende nicht mehr. Ich denke mal, das muss man einfach ausprobieren und
wenn die Differenzen zu groß werden eben auch im Flug gelegentlich für
ein paar Takte in den Selftest schalten, um die Werte des Selftests mit
den Referenzwerten bei Zimmertemperatur zu vergleichen und danach
entsprechend zu korrigieren.
LG
Auch wenn hier nichts mehr passiert ist wollte ich doch nochmal
Rückmeldung zum aktuellen Stand geben.
Nach längerer Pause (zu viel um die Ohren...) habe ich mich jetzt
nochmal an den Kompass gesetzt und siehe da, es funktioniert.
Als Formeln für die Neigungskompensation habe ich jetzt folgende
verwendet:
Pitch und roll bekomme ich von der Steuerung des Copters, der Winkel
ändert sich bei Neigung jetzt praktisch nicht mehr.
Als nächstes werde ich die Formeln nochmal testen, die ich weiter oben
genannt hatte. Die hatte ich erst verworfen weil der Winkel mit denen
total rumgesponnen hat, dann aber bemerkt, dass ich mich bei einer
vertippt hatte und yh statt xh genommen hatte. Damit konnte es ja nicht
funktionieren.
Wie gesagt, Test steht noch aus.
Als nächstes muss jetzt die Regelung her und dann ab damit in die Luft.
LG
Hallo!
Ich spiele auch grade mit einem HCM5883L rum.
1) Vielen Dank für die Beiträge hier, sie haben mir sehr geholfen.
2) Faszinierend was der Sensor für so wenig Geld leistet!
3) Ich glaube bei dieser Formel:
angle = atan2((double)y,(double)x) * 180 / 3.14159265 + 180;
muss es am Ende +179 heißen da man sonst einen Winkel von 360 und 0
erhält.
Ich hoffe das die Beteiligten dieses Threads selbigen noch beobachten da
ich mich gerne weiter austauschen würde!
Gruß
Hallo nochmal!
Auf die Gefahr hin mich hier zu weit aus dem Fenster zu lehnen:
Eine Neigungs-Kompensation? Wozu denn? Die Verhältnisse der Vektoren X
und Y bleiben doch immer gleich?
Gruß
Ja ich würde sagen das war zu weit ;)
Probier es mal ohne Kompensation aus und neige den Sensor ...
Dann ist Norden überall - aber nicht im Norden.
Hintergrund ist, dass der gemessene Anteil X & Y dann real mit der
Z-Komponente überlagert ist. Diesen Anteil musst du natürlich mit
beachten um X & Y im richtigen Maß zu korrigieren.
Randy!
Ich stimme Dir 100% zu! :-)
Jetzt fehlt nur noch eine Berechnung der Lage im Raum nach dem Prinzip:
Der Einfluss von Z auf X und Y ist ja vorhersehbar!
Wer hat die Formel? :-) :-) :-)
Gruß
Randy Stiegler schrieb:> Schreib ein Kalibrier-Programm, welches ständig den größten und> kleinsten Messwert jeder Achse speichert> if (messwert-x < min-x ) min-x = messwert-x...
Hallo,
sorry wenn ich noch mal Nachfrage.
Ein "Offset" von ~500 ist bisschen zu viel des guten oder :D?
Den Offset ermittle ich folgendermaßen: