Hallo, benutze den MLX90609 von Melexis (http://www.melexis.com/Sensor_ICs_Inertia/General/MLX90609_582.aspx) den ich per SPI digital auslese, dass scheint auch recht gut zu funktionieren, allerdings möchte ich ich aus den 11Bit Messwert den mir der Sensor gibt, den Winkel rausrechnen, wie mache ich das? Im Datenblatt steht was von Voutar(mV) = (25/12) * ADCcode + 400 weis nicht ob das hilft?
sorry is ein wenig OT, aber woher hast du den bezogen? an solchen bauteilen hätt ich großes interesse, kann aber bei meinen haus und hof lieferanten nichts vergleichbares finden :/
Hallo Patrick, > allerdings möchte ich ich aus den 11Bit Messwert den mir > der Sensor gibt, den > Winkel rausrechnen, wie mache ich das? Jetzt weiß ich nicht, ob Dein Problem ein Problem mit den Anschlüssen ist oder ein prinzipielles. Ein solcher Sensor gibt die Winkelgeschwindigkeit an. Um den Winkel zu erhalten, mußt Du die Meßwerte zeitlich integrieren. Dabei tritt dann das Problem auf, daß der Drift des Sensors sich in einer Änderung der Drehgeschwindigkeit äußert, das heißt in einem mit der Zeit linear ansteigenden Fehler des Drehwinkels. Gruß, Michael
Michael H. wrote: > sorry is ein wenig OT, aber woher hast du den bezogen? an solchen > bauteilen hätt ich großes interesse, kann aber bei meinen haus und hof > lieferanten nichts vergleichbares finden :/ habe den von der insel über das internet gekauft bei sparkfun, in deutschland wüsste ich jetzt nicht wo man den kaufen könnte, vorteil bei sparkfun ist das dieser schon auf einen board verlötet ist (http://www.sparkfun.com/commerce/product_info.php?products_id=8372) was das ganze für mich erheblich erleichtert. Wenn du fit im SMD löten bist, kannst du ihn naturlich auch roh bestellen http://www.sparkfun.com/commerce/product_info.php?products_id=8294
> Jetzt weiß ich nicht, ob Dein Problem ein Problem mit den Anschlüssen > ist oder ein prinzipielles. > Ein solcher Sensor gibt die Winkelgeschwindigkeit an. Um den Winkel zu > erhalten, mußt Du die Meßwerte zeitlich integrieren. > > Dabei tritt dann das Problem auf, daß der Drift des Sensors sich in > einer Änderung der Drehgeschwindigkeit äußert, das heißt in einem mit > der Zeit linear ansteigenden Fehler des Drehwinkels. ja ich habe da warscheinlich noch einige verständnis probleme, wenn ich das bis jetzt richtig verstanden müsste ich etwas in der art wie (Summe über die Zeit) += (Wert bei Null Grad) - (Aktueller Messwert), den Wert bei Null Grad müsste ich dann jeweils über einen Beschleunigungssenor kalibrieren? Was genau meint man den mit Drift? (http://www.google.de/search?hl=de&client=firefox-a&rls=org.mozilla%3Ade%3Aofficial&hs=Ywh&q=define%3Adrift&btnG=Suche&meta=) Soll das den Fehler beschreiben der beim integrieren auftrit?
Ich vermute das man von dem Messwert den man erhält, den Zero Rate Output (Bias) abziehen muss der bei diesem Sensor bei 1008 liegt, und dann muss ich glaube ich über den Initial Scale Factor (sensitivity) irgendwie den Winkel ausrechnen. Habe hier was interessantes gefunden: http://tom.pycke.be/mav/70/gyroscope-to-roll-pitch-and-yaw
Hallo Patrick, > ja ich habe da warscheinlich noch einige verständnis probleme, wenn ich > das bis jetzt richtig verstanden müsste ich etwas in der art wie (Summe > über die Zeit) += (Wert bei Null Grad) - (Aktueller Messwert), den Wert > bei Null Grad müsste ich dann jeweils über einen Beschleunigungssenor > kalibrieren? Ein Drehratensensor (englisch: angular rate sensor) gibt die Drehgeschwindigkeit an, also irgendwas in der Einheit "Grad pro Sekunde". Wenn Du daraus den Winkel bekommen willst, mußt Du den Anfangswinkel kennen und die Änderungen zeitlich aufsummieren. > Was genau meint man den mit Drift? > (http://www.google.de/search?hl=de&client=firefox-a&rls=org.mozilla%3Ade%3Aofficial&hs=Ywh&q=define%3Adrift&btnG=Suche&meta=) > Soll das den Fehler beschreiben der beim integrieren auftrit? Ja genau. Normalerweise sollte die Ausgangsspannung bei 0°/s einen konstanten Wert haben - ich vermute, in Deinem Fall ist das 2,5V. Durch einen Drift (z. B. Temperaturdrift) könnte Anzeige bei 0°/s aber auch beispielsweise auf 2,51V steigen. Wenn die 0°/s durch die Temperaturerhöhung bei 2,51V liegt, erkennst Du eine Drehung, obwohl keine da ist. Zur Erkennung der Neigung ist ein Beschleunigungssensor auf jeden Fall besser geeignet. Gruß, Michael
> Zur Erkennung der Neigung ist ein Beschleunigungssensor auf jeden Fall > besser geeignet. Ja, eine dreiachsen Beschleunigungs habe ich auch in meinem Aufbau, ich denke ich werde es so machen. Sobald der Beschleunigungssensor Nulllage misst, sprich Null Grad, setze ich den Wert des Gyro auf Null Grad, sobald der Testaufbau geneigt wird, Summiere ich die Ausgangswerte des Gyros auf, denke ich? Würde das so funktionieren?
Hallo habe eine neue Theorie wie ich auf meinen Winkel mittels Gyro komme, die Antwort die ich vom Gyro bekomme ist 11 Bits groß (2^11 ~ 2048) also hätte ich als maximalen wert den ich bekommen könnte 2048, allerdings ist das aus konstruktionstechnischen gründen nicht möglich, wenn ich das datenblatt (ausschnitt siehe anhang) richtig gelesen habe, hier begrenzt "output full scale" auf 1920. Der Parameter "Zero rate output" gibt mir allerdings meinen Nullpunkt an von 1008, also müsste ich diesen Wert von meinem Messwert abziehen, alle Neigungen die dann an dem Gyro ausgeführt werden, würden ja relativ zum nullpunkt auftreten, dementsprechend müsste dann mein wert in einem normalen wert liegen, jetzt muss ich nur noch diesen wert durch den "Initial Scale Factor" von 3,2 teilen, dann müsste ich doch auf meinen Winkel kommen. Winkel = [[[Messwert per SPI (11 Bit)] - 1008] / 3,2]
gast wrote: > GYRO und SENSOREN > http://www.sander-electronic.de/be00040.html Habe schon einen Gyro!
Hallo, habe auch noch frage wie ich das mit dem Integrieren softwaretechnisch lösen kann, von meinem Verständniss her wäre das so:
1 | int i; |
2 | |
3 | for(i = 0; i < 1024; i++) |
4 | {
|
5 | GyroMesswertSumme += GyroMesswert; |
6 | }
|
7 | |
8 | Mittelwert = GyroMesswertSumme / 1024; |
Würde das so gehen?
Mann braucht ein festes Zeitraster fDt [s] mit der der Sensorwert fGyro aufsummiert wird. fGyro am besten in [rad per second] normiert. fAngle += fGyro * fDt; Danch muss man noch den Fall grösser +-PI behandeln. if (fabs(fAngle) > M_PI) fAngle = copysign(2 * M_PI - fabs(fAngle), -fAngle); Anmerkung: Diese Aufsummierung driftet weg und taugt nur für kurze Zeit. Wenn man die Lage zur Erdoberfläche haben will ist ein 3-achsiges Accelerometer (LIS2LV02DQ) besser geeignet.
Maria wrote: > Mann braucht ein festes Zeitraster fDt [s] mit der der Sensorwert fGyro > aufsummiert wird. fGyro am besten in [rad per second] normiert. > > fAngle += fGyro * fDt; > > Danch muss man noch den Fall grösser +-PI behandeln. > > if (fabs(fAngle) > M_PI) > fAngle = copysign(2 * M_PI - fabs(fAngle), -fAngle); > > Anmerkung: > Diese Aufsummierung driftet weg und taugt nur für kurze Zeit. Wenn man > die Lage zur Erdoberfläche haben will ist ein 3-achsiges Accelerometer > (LIS2LV02DQ) besser geeignet. Danke für die schnelle Antwort, das ist genau das was ich gesucht habe, allerdings habe ich dazu noch zwei Fragen. Folgender Code würde ja den jeweiligen Wert des Gyros (fGyro) mit dem Zeitraster (fDt) multiplizieren und das stetig auf fAngle aufsummieren. Jetzt die Fragen dazu: Würde dann nicht fAngle irgendwann sehr groß werden? Wie muss ich fDt wählen, kann das ein von mir selbst bestimmter Wert sein, oder muss der z.B. in Abhängigkeit des Intervalls in dem der Gyro abgefragt wird gewählt werden? Zu der Anmerkung: Ja, ich benutze eine Kombination aus 3-achsiges Accelerometer und 1-Achsen Gyro, die bei zeiten auch Kalman gefiltert werden.
fDt ist das Intervall in dem der Gyro abgefragt wird. Es muss kein konstanter Wert sein aber die richtige Zeit zwischen zwei Abfragen. Die nachfolgende Zeile ist ungetestet. Sie wandelt den mlx90609 Wert in [rad/sec]. fGyro = ((sGyroRaw & 0x0FFF) - (1008 << 1)) / (2 * 3.2) * (M_PI/180.0);
Maria wrote: > fDt ist das Intervall in dem der Gyro abgefragt wird. Es muss kein > konstanter Wert sein aber die richtige Zeit zwischen zwei Abfragen. > > Die nachfolgende Zeile ist ungetestet. Sie wandelt den mlx90609 Wert in > [rad/sec]. > > fGyro = ((sGyroRaw & 0x0FFF) - (1008 << 1)) / (2 * 3.2) * (M_PI/180.0); Ja, so in der Art hatte ich es auch schon, nur hat mir da das letzte drittel gefehlt, noch eine Frage zu den Zahlen (2 * 3.2) bei 3.2 scheint es sich um den Scale Factor zu handeln, nur wieso wird dieser mit 2 multipliziert? fGyro = ((sGyroRaw & 0x0FFF) >> 1) - 0x3F0; // // 12Bit ausmaskieren und um 1Bit nach rechts schieben, Null Bezug Abziehen THX
Eigentlich ist das gleich. 2 * 3.2 ist so wie 3.2 << 1 Ich wollte das kleinste Bit von GyroRaw nicht vernichten. Vielleicht bauen die mal einen ADC in den Gyro der auch dieses Bit bringt.
Mit einem Gyro mit einer Achse kannst du doch auch nur die Rotation um eine Achse messen. Wie ermittelst du da die Neigung des LFz? Meines Wissens benötigst du zumindestens die Entsprechung eines künstlichen Horizonts und eigentlich auch einen Gyro für die Gierachse zur Lageorientierung im Raum, oder übersehe ich da was? Arno
Arno H. wrote: > Mit einem Gyro mit einer Achse kannst du doch auch nur die Rotation um > eine Achse messen. > Wie ermittelst du da die Neigung des LFz? > Meines Wissens benötigst du zumindestens die Entsprechung eines > künstlichen Horizonts und eigentlich auch einen Gyro für die Gierachse > zur Lageorientierung im Raum, oder übersehe ich da was? Ja, du übersiehst das ich den Gyro nicht alleine einsetze, wie schon des öfteren beschrieben, nutze ich unteranderen einen dreiachsen Beschleunigungssensor, mit dem ich ja dann meinen Horizont habe, denn ich aus dem Verhältnis von zwei Achsen berechne: Winkel des Beschl. = (atan((y - 512.0) / 102.4) / (((z - 512.0) / 102.4))) * (180.0 / M_PI); // Zweiachsige Winkelbestimmung Somit weiß ich wo ich meine Null Grad habe und kann dahingehen den Gyro Offset einstellen, sodass ich wenn der Beschleunigungssensor Null Grad ausgiebt, der Wert des Gyros "nullgesetzt" werden kann, wird der Versuchsaufbau geneigt, wird einfach die abweichung vom Nullpunkt aufaddiert. mfg crashdemon
Dein Aufbau kann also nur in einer Richtung geneigt werden, ok. Arno
Arno H. wrote: > Dein Aufbau kann also nur in einer Richtung geneigt werden, ok. > > Arno Jup
So hatte mal wieder ein wenig Zeit mich weiter mit dem Problem zu beschäftigen, habe jetzt folgende Formel benutzt: fMeas += ((gMeas / 6.4) * fDt) * (180.0 / M_PI); // Winkel des Gyro in deg/sec Wobei: float fDt = 0.000008; gMeas = ((GyroMeasRaw & 0x0FFF) >> 1) - 0x3F0; Das will allerdings nicht so wirklich funktionieren die Werte sind teilweise doch sehr am schwanken. Dann habe ich noch von einem Runge-Kutta Verfahren (http://tom.pycke.be/mav/70/gyroscope-to-roll-pitch-and-yaw) gelesen, hat das hier schoneinmal jemand erfolgreich eingesetzt?
So ich habe jetzt mal die Rohen Messwerte meines Gyros per UART an meinen Recner geschickt und dann über Hyperterm aufgezeichnet und in eine excel-Tabelle verwurstet, die ich mal im Anhang drangehängt habe, wäre schön wenn sich das mal jemand ansehen könnte und wir sagen kann ob das mit dem Integrierten Messwert richtig umgesetzt ist?
Ich habe mir die Messwerte nicht angeschaut aber dafür einige Bemerkungen. Das Zeitintervall ist viel zu klein. Die Grenzfrequenz des Sensors ist 75Hz also reicht es alle 5-10ms eine Messprobe zu nehmen (0.005s). Timer! Dann würde ich für Testzwecke dieses schreiben: int16_t gMeas = ((GyroMeasRaw & 0x0FF0) >> 1) - 0x3F0; Damit werden unteren Bits gelöscht, die Sache wird unempfindlicher, und bei ruhendem Sensor sollte gMeas auch 0 sein. Es wird also 0 Aufsummierung. Hast du gMeas als int16_t deklariert? Wenn du jetzt den Sensor um 90 Grad drehst dann sollte sich der aufsummierte Winkel um M_PI / 2 ändern.
Maria wrote: > Ich habe mir die Messwerte nicht angeschaut aber dafür einige > Bemerkungen. > > Das Zeitintervall ist viel zu klein. Die Grenzfrequenz des Sensors ist > 75Hz also reicht es alle 5-10ms eine Messprobe zu nehmen (0.005s). > Timer! > > Dann würde ich für Testzwecke dieses schreiben: > > int16_t gMeas = ((GyroMeasRaw & 0x0FF0) >> 1) - 0x3F0; > > Damit werden unteren Bits gelöscht, die Sache wird unempfindlicher, und > bei ruhendem Sensor sollte gMeas auch 0 sein. Es wird also 0 > Aufsummierung. > > Hast du gMeas als int16_t deklariert? > > Wenn du jetzt den Sensor um 90 Grad drehst dann sollte sich der > aufsummierte Winkel um M_PI / 2 ändern. Habe gMeas zur Zeit als float, werde aber mal deinen Rat befolgen und ihn als int deklarieren damit die Nachkommastellen wegfallen. Das mit dem sicherstellen das in einem bestimmten Intervall die Messwerte ermittelt werden, das ist für mich noch ein bisschen Tricky, ich werde versuchen das über einen Timer zu lösen.
So ich hab mir jetzt mal einen Timer gebastelt mit dem ich die Differenz der vorherigen und der jetzigen Messung errechnen kann, das war ja das Zeitraster wovon du gesprochen hattest. Wäre schön wenn da mal jemand drüber schauen kann, da es bei mir noch nicht so richtig funktioniert.
1 | // Globale Variablen
|
2 | uint16_t n = 0; // Aktueller Taktzähler |
3 | uint16_t nBefore = 0; // Taktzähler davor |
4 | uint16_t gMeasRaw = 0; // Rohdaten vom Gyro |
5 | int16_t fMeas = 0.0; // Über die Zeit Integrierte Daten des Gyros |
6 | float fDt = 0.0; // Taktzähler Differenz zwischen n und nBefore |
7 | |
8 | ISR(TIMER0_OVF_vect) // Aufruf bei Interrupt von Timer0 (8 Bit) |
9 | {
|
10 | n++; |
11 | }
|
12 | |
13 | float GyroAngle(void) |
14 | {
|
15 | gMeasRaw = 0; // Rohdaten vom Gyrometer |
16 | fDt = n - nBefore; // Zeitdifferenz zwischen den Messungen |
17 | |
18 | if(fDt < 0) // Wenn Variable übergelaufen da 16Bit int |
19 | {
|
20 | fDt = (((2^16) - nBefore) + n); // Zeit berechnen der Variable |
21 | }
|
22 | |
23 | // CPU_TAKT (4Mhz) / Vorteiler (64) = 62,5KHz = 16us
|
24 | fDt = fDt * 0.000016; // Taktzyklen mit Periodendauer multiplizieren |
25 | nBefore = n; // Aktueller Counterwert, für nächste Messung speichern |
26 | |
27 | GyroAdcSetMode(); // 2. Modi setzen, ADC Wandlung |
28 | GyroAdcRead(&gMeasRaw); // 3. Ergebnis der Messung lesen |
29 | fMeas += (((gMeasRaw - 0x3F0) / 3.2) * fDt); // Winkel des Gyro in deg/sec |
30 | |
31 | return fMeas; |
32 | }
|
33 | |
34 | int main(void) |
35 | {
|
36 | char gChar[4] = ""; |
37 | int16_t gAngle = 0; |
38 | |
39 | TCCR0 |= (1 << CS01) | (1 << CS00); // Vorteiler 3 (Takt 62,5kHz) |
40 | TIMSK |= (1 << TOIE0); // Timer 0 Overflow Interrupt |
41 | |
42 | GyroSetMode(); // 1. Gyro "scharf stellen" |
43 | sei(); // Globale Interrupts einschalten |
44 | |
45 | while(1) |
46 | {
|
47 | gAngle= GyroAngle(); // Funktion die Winkel ermittelt |
48 | USART_send(itoa(gAngle, gChar, 10)); // Per USART senden |
49 | }
|
50 | |
51 | GyroSetSleep(); // 4. Gyro schlafen legen |
52 | return 0; // Wird niemals erreicht |
53 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.