Hallo
Ich möchte mit einen MPU 6050 und einen HMC5883L die X Y Z Winkel
auslesen.
Dafür lese ich beide Bausteine über I2C aus und vereinige die Daten des
Beschleunigungs-, Gyrosensors und des Magnetometers mittels Hoch- und
Tiefpässen.
Ich programmiere momentan einen Atmega16 mittels AVR Studio 5.1.
Warum AVR Studio 5.1? Weil wir das so in der Schule verwenden.
Aus den Daten des Beschleunigungssensors berechne ich mittels atan2 die
Winkel. Diese stimmen auch.
Aber wenn ich (für Testzwecke, ob das Ausgelesene überhaupt
funktioniert), die Daten des Gyrosensors zu einen Winkel berechnen will,
stimmt das Ergebnis nicht.
Im Anhang habe ich das C - File für den MPU angehängt.
Dort ist die Initialisierung drin und das Auslesen der Register.
Das Bild enthaltet Codezeilen, welche alle 10ms aufgerufen wird und die
Daten des MPU's über die hochgeladene Klasse ausliest.
Das Problem ist, dass die Winkel so keinen Sinn ergeben.
Sie erreichen einen sehr hohen Wert ca. +- 10000 und wenn ich ihn kurz
ruhig halte, geht der Winkel langsam gegen 0.
Kann mir jemand dort weiterhelfen?
Danke für eure Hilfe
Marcel
Was liefern die Sensoren?
Und wie wird daraus ein Winkel berechnet? Dazu finde ich den Code nicht.
Also wird die Winkelberechnung den Fehler in Zeile 42 haben.
Ich nehme direkt die Daten die ich "zusammenschifte" * 0.01 und addiere
diese immer in eine Variable.
Das ist nicht mein erster Gyro, daher weiß ich dass mann die Daten
"integrieren" muss. Darum multipliziere ich die Daten mit 1/100Hz.
Was wäre Zeile 42??
Ich kannte das bisher so, dass man in das Sensordatenblatt schaut, und
dann die Zahlenwerte entsprechend der Auflösung in SI-Werte umrechnet.
Nur für mich: was steht im Sensordatenblatt, ich habe es ja nicht hier.
Aber wenn das immer *100 und aufaddiert wird, dann scheint die Formel
richtig zu sein. Auf die Implementation haben wir ja immer noch keinen
Blick.
Zeile 42
http://de.wikipedia.org/wiki/42_%28Antwort%29
Ich habe das Datenblatt rauf und runter durchsucht und nichts gefunden.
Hat einer vlt. ein Beispielcode in c, für das Auslesen des Gyro bzw. die
Ausgelesen Daten richtig zu verarbeiten?
Marcel D. V. schrieb:> Hat einer vlt. ein Beispielcode in c, für das Auslesen des Gyro bzw. die> Ausgelesen Daten richtig zu verarbeiten?
Wie heißt es auf der Arduino Seite zum MPU6050 so richtig: "Reading raw
values is easy, the rest is not"
Aber offensichtlich haben sich genug gefunden und sogar die Umrechnung
vernünftig hinbekommen.
http://playground.arduino.cc/Main/MPU-6050
Was ist denn daran so schwierig, die Werte umzurechnen? Im Datenblatt
steht doch klar die Sensitivity.
Lustig wird es eher, wenn's an Zero-Bias-Kalibrierung und evtl.
Temperaturkompensation geht.
Ich habe schon alles versucht.
Ja ich habe den Sensor auf eine Sensitivity von +-2000°/s eingestellt.
Darum müsse ich die Daten des Sensors mit 2000/90 = 22.2222 dividieren.
Aber dann sind die Werte immer noch nicht richtig.
Etwas sehr komisches ist, dass der Ausgabewert immer wieder langsam
gegen 0 geht, wenn ich ihn ruhig halte.
Und ja ich summiere die Daten des Gyro's immer auf, aber der Winkel geht
trotzdem gegen 0.
Hat noch keiner von euch das alles schon einmal in C gemacht???
Denn ist halt am einfachsten alles in C anzusehen, anstatt alles in C++.
Marcel D. V. schrieb:> Und ja ich summiere die Daten des Gyro's immer auf, aber der Winkel geht> trotzdem gegen 0.
Irgendwie musst du mit der Drift/Offset eines Gyrosignals umgehen. Was
möchtest du denn rausbekommen?
Wo machst du denn die Integration und Umrechnung der Werte? Wenn alles
bei stillstehendem Gyro zu 0 konvergiert, haut da irgendwas nicht hin.
Poste doch mal deinen Code zur Integration und Kalibrierung.
Ich habe vorher eingebaut, dass ein Offset immer weggerechnet wird.
Dafür lese ich zu beginn einfach 1000 Werte aus und addiere diese dann
in eine Variable. Anschließend wird diese dann durch 1000 dividiert und
dann immer von den RAW Werten abgezogen.
Ich möchte schlussendlich mittels dem Gyro einen Winkel berechnen können
der sich von -180 bis +180 ° bewegt.
Wenn dies funktioniert kombiniere ich die Daten des Gyro's mit den Daten
des Beschleunigungssensor.
Marcel D. V. schrieb:> Hier ist die Kalibration und die Integration.>> Die Methode GetGyroX GetGyroY GetGyroZ geben einfach den ausgelesen> RawWert - berechneten Offset aus.
Und wo liegt dein problem mal den ganzen code zu posten?
Woher soll dein Compiler wissen, dass er realx, relay und realz nicht in
irgendwelche register packen darf, die den Kram mit der ISR nicht
überleben. Die müssen als volatile deklariert werden. Und die ganze
Rechnerei hat natürlich nicht in der ISR zu suchen.
Okay ich mache das volatile.
Ja ich weiß, dass das da nicht reingehört, aber das ist dort nur für
Testzwecke.
Ich probier es nachher mal aus und dann Bescheid.
Wegen der Sensivity ist schon richtig durch 22.2 zu dividieren oder?
(Sensitivity = +-2000)
Ich habe nun die realx, realy und realz Variable volatile gemacht, aber
konvergieren die Variablen gegen 0, wenn ich keine Bewegung mache.
(Und der Winkel stimmt mit 22.2 auch nicht.)
Marcel D. V. schrieb:> Wegen der Sensivity ist schon richtig durch 22.2 zu dividieren oder?> (Sensitivity = +-2000)
Rechne es doch einfach mal zu Fuß aus ob das plausibel ist. Der Wert vom
Gyro ist ein Maß für die Winkelgeschwindigkeit, irgendwas das sich
(möglicherweile mittels eines Faktors, siehe Datenblatt) in °/s
umrechnen lässt und dann wenn Du °/s hast und n Messungen pro Sekunde
machst teilst Du das nochmal durch n.
Also hast Du den Faktor (nennen wir in mal a) den Du brauchst zur
Umrechnung in °/s
1
Winkelgeschwindigkeit = Messwert * a
und außerdem hast Du n Messungen pro Sekunde, es hat sich also nach
jeder Messung um den folgenden Winkel weitergedreht:
1
Winkel = Winkelgeschwindigkeit * Zeit
2
Winkel = Messwert * a * Zeit
und weil Zeit [in Sekunden] = 1 / n
1
Winkel = Messwert * a / n
2
Winkel = Messwert * a / n
Rechne also mal zu Fuß aus ob zusammen mit dem Meßwert den der Sensor
liefert und dem Umrechnungsfaktor den Du verwendest tatsächlich ein
Winkel rauskommt der zu Deiner der tatsächlichen Drehung zwischen zwei
Messungen halbwegs plausibel ist.
Marcel D. V. schrieb:> Ja ich weiß, dass das da nicht reingehört, aber das ist dort nur für> Testzwecke.
Und es funktioniert so nicht! Aber lass mal drinn, eventuell gibts noch
einen trick wie du es lösen kannst ohne dies umzuschreiben
Marcel D. V. schrieb:> Ich möchte schlussendlich mittels dem Gyro einen Winkel berechnen können> der sich von -180 bis +180 ° bewegt.> Wenn dies funktioniert kombiniere ich die Daten des Gyro's mit den Daten> des Beschleunigungssensor.
Um die integrierten Gyro-Daten mit den Beschleunigungs-Daten
zusammenzubringen wirst Du auf jeden Fall Euler-Winkel oder besser
Quaternionen bemühen müssen.
Man kann z.B. einen Würfel durch unterschiedliche Drehoperationen wieder
in den Ausgangszustand drehen. Der ACC liefert dann wieder die selben
Werte wie vor der Operation. Getrennt nach XYZ aufintegrierte Gyro-Daten
können sie ziemlich beliebige Werte aufweisen.
Hä? schrieb:> Marcel D. V. schrieb:>> Ja ich weiß, dass das da nicht reingehört, aber das ist dort nur für>> Testzwecke.>> Und es funktioniert so nicht! Aber lass mal drinn, eventuell gibts noch> einen trick wie du es lösen kannst ohne dies umzuschreiben
Das ist nicht mein erster Gyro. Dort habe ich es zu Beginn auch so
gemacht und es hat funktioniert. Also schließe ich daraus, dass es so
auch möglich sein muss.
Und das kann auch nicht der Grund sein warum die Variablen nach 0
konvergieren.
Es muss irgendwas anderes sein.
Bernd K. schrieb:> Marcel D. V. schrieb:>>> Wegen der Sensivity ist schon richtig durch 22.2 zu dividieren oder?>> (Sensitivity = +-2000)>> Rechne es doch einfach mal zu Fuß aus ob das plausibel ist. Der Wert vom> Gyro ist ein Maß für die Winkelgeschwindigkeit, irgendwas das sich> (möglicherweile mittels eines Faktors, siehe Datenblatt) in °/s> umrechnen lässt und dann wenn Du °/s hast und n Messungen pro Sekunde> machst teilst Du das nochmal durch n.>> Also hast Du den Faktor (nennen wir in mal a) den Du brauchst zur> Umrechnung in °/s>>
1
> Winkelgeschwindigkeit = Messwert * a
2
>
>> und außerdem hast Du n Messungen pro Sekunde, es hat sich also nach> jeder Messung um den folgenden Winkel weitergedreht:>>
1
> Winkel = Winkelgeschwindigkeit * Zeit
2
> Winkel = Messwert * a * Zeit
3
>
>> und weil Zeit [in Sekunden] = 1 / n>>
1
> Winkel = Messwert * a / n
2
> Winkel = Messwert * a / n
3
>
>> Rechne also mal zu Fuß aus ob zusammen mit dem Meßwert den der Sensor> liefert und dem Umrechnungsfaktor den Du verwendest tatsächlich ein> Winkel rauskommt der zu Deiner der tatsächlichen Drehung zwischen zwei> Messungen halbwegs plausibel ist.
Das Problem ist, dass ich nicht weiß was a ist.
Und ich habe das Datenblatt schon komplett durchgesehen und bis jetzt
nichts dazu gefunden. (Habe es mal angehängt)
Marcel D. V. schrieb:> Das Problem ist, dass ich nicht weiß was a ist.> Und ich habe das Datenblatt schon komplett durchgesehen und bis jetzt> nichts dazu gefunden. (Habe es mal angehängt)
Das liegt wohl daran daß es noch ein zweites Datenblatt gibt mit den
Registerbeschreibungen etc.
Hier:
http://invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf
Ich tippe mal auf die Tabelle auf Seite 32:
1
FS_SEL Full Scale Range LSB Sensitivity
2
0 ±250°/s 131 LSB / °/s
3
1 ±500°/s 65.5 LSB / °/s
4
2 ±1000°/s 32.8 LSB / °/s
5
3 ±2000°/s 16.4 LSB / °/s
Also würd ich mal sagen bei FS_SEL=3 ±2000°/s hieße das 16.4 Einheiten
in diesem Register bedeuten 1°/s also
1
Winkelgeschwindiglkeit = (Messwert / 16.4) °/s
also in Deinem Falle mit 100 Messungen pro Sekunde:
Ich habe das mal so eingebaut, aber das Problem, dass der Winkel gegen 0
konvergiert ist leider dadurch nicht behoben.
Und ich habe keine Idee mehr, warum dies der Fall sein kann.
Marcel D. V. schrieb:> Ich habe das mal so eingebaut, aber das Problem, dass der Winkel gegen 0> konvergiert ist leider dadurch nicht behoben.
Wieso? Wenn Du es nicht mehr bewegst ist die Winkelgeschwindigkeit 0.
Das würde ich so erwarten, scheint also korrekt zu sein.
Bernd K. schrieb:> Wieso? Wenn Du es nicht mehr bewegst ist die Winkelgeschwindigkeit 0.> Das würde ich so erwarten, scheint also korrekt zu sein.
Klar. Ich dachte allerdings das Problem wäre, dass der integrierte Wert
gegen 0 konvergiert. Dann muss was faul sein.
greg schrieb:> Bernd K. schrieb:>> Wieso? Wenn Du es nicht mehr bewegst ist die Winkelgeschwindigkeit 0.>> Das würde ich so erwarten, scheint also korrekt zu sein.>> Klar. Ich dachte allerdings das Problem wäre, dass der integrierte Wert> gegen 0 konvergiert. Dann muss was faul sein.
Ja der integrierte Winkel geht gegen 0.
Das die Winkelgeschwindigkeit gegen 0 geht, wenn ich den Sensor nicht
bewege ist mir klar.
GetGyroX() gibt ein Integer als returnwert. Diese Integer wird dan
multipliziert mit 0,01. Immer wen sie Anfangen mit einen Wert Kleiner
dan 100, ist die Ergebnis 0 !! Versuch es mal mit ein float zu machen.
greg schrieb:> Deine Kalibrierung sieht mir auch problematisch aus. Bei 1000 Messungen> bekommst du leicht einen Overflow in der Summe zusammen.
Ja habe ich mir auch schon gedacht.
Darum werde ich dort glaub ich einfach eine int32 nehmen.
Das dürfte ausreichen.
RP6conrad schrieb:> GetGyroX() gibt ein Integer als returnwert. Diese Integer wird dan> multipliziert mit 0,01. Immer wen sie Anfangen mit einen Wert Kleiner> dan 100, ist die Ergebnis 0 !! Versuch es mal mit ein float zu machen.
Habe es nun mal ausprobiert und so wird die Variable wieder so >10000
O.o
Ich finde, dass sehr komisch.
Bei meinen anderen Gyro habe ich auch alles mit Integer gemacht und das
hat auch geklappt.
Es muss irgendein anderen Grund haben, dass der Winkel gegen 0
konvergiert.
Habe nun nochmals die Winkelgeschwindigkeiten angesehen.
--> Diese sind bei keiner Bewegung eig. 0.
Machmal kann es sein, dass die Werte so -2, -1, 0, 1, 2 betragen. (Sie
schwanken zwischen diesen Werten)
Aber diese fallen ja weg, wenn ich die Winkelgeschwindigkeiten mit 0,01
multipliziere.
Marcel D. V. schrieb:> wenn ich die Winkelgeschwindigkeiten mit 0,01> multipliziere.
* Du sollst nicht mit 0.01 multiplizieren sondern mit 1/1640 (siehe
Datenblatt)
* Nimm double und nicht integer
Bernd K. schrieb:> Marcel D. V. schrieb:>> wenn ich die Winkelgeschwindigkeiten mit 0,01>> multipliziere.>> * Du sollst nicht mit 0.01 multiplizieren sondern mit 1/1640 (siehe> Datenblatt)> * Nimm double und nicht integer
Gesagt getan.
Aber mit double habe ich das gleiche Problem mit den float Werten.
Die Werte sind im Bereich von 10000 - 20000.
Das ist wirklich sehr komisch O.o
Marcel D. V. schrieb:> Die Werte sind im Bereich von 10000 - 20000.> Das ist wirklich sehr komisch O.o
Wenn Du es langsam um X drehst, sagen wir mal du schaffst es halbwegs
genau 90° zu drehen in ziemlich genau einer Sekunde. Welchen Wert hat
während dieser Drehung das rohe ausgelesene GetGyroX()?
Nach meiner obigen Theorie mit dem wie ich das Datenblatt interpretiere
wäre der Messwert 90 * 16.4 = 1476
GetGyroX() sollte also ungefähr 1476 ausgeben während Du mit dieser
Geschwindigkeit drehst (vorausgesetzt natürlich Du hast die
Empfindlichkeit wirklich auf 2000°/s eingestellt). Kommt das hin oder
liegt das schon grob daneben?
Also dreh mal langsam 90° in eine Richtung während Du "einundzwanzig"
sagst und dann poste mal den Wert den es ausgibt.
Bernd K. schrieb:> Marcel D. V. schrieb:>>> Die Werte sind im Bereich von 10000 - 20000.>> Das ist wirklich sehr komisch O.o>> Wenn Du es langsam um X drehst, sagen wir mal du schaffst es halbwegs> genau 90° zu drehen in ziemlich genau einer Sekunde. Welchen Wert hat> während dieser Drehung das rohe ausgelesene GetGyroX()?>> Nach meiner obigen Theorie mit dem wie ich das Datenblatt interpretiere> wäre der Messwert 90 * 16.4 = 1476>> GetGyroX() sollte also ungefähr 1476 ausgeben während Du mit dieser> Geschwindigkeit drehst (vorausgesetzt natürlich Du hast die> Empfindlichkeit wirklich auf 2000°/s eingestellt). Kommt das hin oder> liegt das schon grob daneben?>> Also dreh mal langsam 90° in eine Richtung während Du "einundzwanzig"> sagst und dann poste mal den Wert den es ausgibt.
Es gibt so ca -1600 - -1800 bekomm ich raus.
Ich wenn ich so schnell ich kann den Sensor um 90° drehe.
Also kann da irgendwas nicht stimmen.
Habe nun was in der Initialisierung geändert, da es zuerst nicht
gestimmt hatte. Aber es kann sein, dass dort trotzdem noch nichts alles
in der Initialisierung stimmt. Ich werde das nachher nochmals checken.
Vielleicht sieht jemand anders auch noch einen Fehler?
Marcel D. V. schrieb:> Es gibt so ca -1600 - -1800 bekomm ich raus.> Ich wenn ich so schnell ich kann den Sensor um 90° drehe.> Also kann da irgendwas nicht stimmen.
Was kommt raus wenn Du ihn langsam (während einer Sekunde) drehst, nicht
"so schnell wie du kannst" sondern nach dem wert bei 90° / Sekunde hab
ich gefragt.
Wie sieht Deine GetGyroX() aus, poste die mal. Machst Du darin eventuell
schon irgendwelche Berechnungen? Denn wenn ja dann kann das ja alles
nicht stimmen, ich bezog mich auf die rohen Messwerte direkt aus den
Sensor-Registern.
Habe mich dort verschrieben.
Das war schon in 1er Sekunde.
Den Code habe ich schon öfters hochgeladen.
Die Methode GetGyroX() ist in der Klasse MPU-6050.c und dort werden
keine Berechnungen durchgeführt.
Marcel D. V. schrieb:> Das war schon in 1er Sekunde.
Na das kommt doch fast hin. 1476 solls sein und 1600 ist es. Wenn man
bedenkt daß Du wahrscheinlich nicht exakt genau 1 Sekunde und 90° genau
hinbekommst mit der bloßen Hand dann kommt das ungefähr hin, der Faktor
1/1640 stimmt also (bei 100 Hz).
Also muss der Fehler irgendwo anders versteckt sein. Auch können sich da
niemals 20000 in kurzer Zeit aufsummieren wenn Du diese Werte durch 1640
teilst vor dem Integrieren.
hallo zusammen,
ich hatte ein ähnliches Problem und habe es so gelöst: siehe gyro.c
die werte sind jetzt nicht die genauen Grade aber es komt dem zimlich
nahe.
jedoch ist hierbei immer noch ein kleiner Fehler drinnen, der zur Folge
hat, dass der Sensor, nach dem er eine Minute bewegt wurde einen Fehler
von 30° hat.
hoffe das Hilft dir weiter.
Weiß einer von euch wie das mit dem FIFO genau funktioniert?
wenn ich jetzt zb. gyrox und gyrox in den FIFO schreiben lassen
woher weiß ich jetzt welcher FIFO wert jetzt zu welcher Messung gehört
weil das ist auch ein wichtiger Aspekt der beim messen beachtet werden
muss, da ansonsten Fehler(wie jetzt bei mir) entstehe.
grüße
Basti
edit : Code datei