www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mit Gyro (MLX90609) Neigung bestimmen


Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

benutze den MLX90609 von Melexis 
(http://www.melexis.com/Sensor_ICs_Inertia/General/...) 
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?

Autor: Michael H. (morph1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :/

Autor: Michael Lenz (hochbett)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?...) 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?...

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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...)
Soll das den Fehler beschreiben der beim integrieren auftrit?

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Michael Lenz (hochbett)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...)
> 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

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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?

Autor: Patrick L. (crashdemon)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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]

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast wrote:
> GYRO und SENSOREN
> http://www.sander-electronic.de/be00040.html

Habe schon einen Gyro!

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe auch noch frage wie ich das mit dem Integrieren softwaretechnisch 
lösen kann, von meinem Verständniss her wäre das so:
int i;

for(i = 0; i < 1024; i++)
{
    GyroMesswertSumme += GyroMesswert; 
}

Mittelwert = GyroMesswertSumme / 1024;

Würde das so gehen?

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat den keiner eine Antwort / Lösung?

Autor: Maria (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Maria (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Maria (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Arno H. (arno_h)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Arno H. (arno_h)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Aufbau kann also nur in einer Richtung geneigt werden, ok.

Arno

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arno H. wrote:
> Dein Aufbau kann also nur in einer Richtung geneigt werden, ok.
>
> Arno

Jup

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Patrick L. (crashdemon)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Maria (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Patrick L. (crashdemon)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Patrick L. (crashdemon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
// Globale Variablen
uint16_t n = 0; // Aktueller Taktzähler 
uint16_t nBefore = 0; // Taktzähler davor
uint16_t gMeasRaw = 0; // Rohdaten vom Gyro
int16_t fMeas = 0.0; // Über die Zeit Integrierte Daten des Gyros
float fDt = 0.0; // Taktzähler Differenz zwischen n und nBefore

ISR(TIMER0_OVF_vect) // Aufruf bei Interrupt von Timer0 (8 Bit)
{
    n++;
}

float GyroAngle(void)
{
    gMeasRaw = 0; // Rohdaten vom Gyrometer
    fDt = n - nBefore; // Zeitdifferenz zwischen den Messungen

    if(fDt < 0) // Wenn Variable übergelaufen da 16Bit int
    {
        fDt = (((2^16) - nBefore) + n); // Zeit berechnen der Variable
    }

    // CPU_TAKT (4Mhz) / Vorteiler (64) = 62,5KHz = 16us
    fDt = fDt * 0.000016; // Taktzyklen mit Periodendauer multiplizieren
    nBefore = n; // Aktueller Counterwert, für nächste Messung speichern

    GyroAdcSetMode(); // 2. Modi setzen, ADC Wandlung  
    GyroAdcRead(&gMeasRaw); // 3. Ergebnis der Messung lesen
    fMeas += (((gMeasRaw  - 0x3F0) / 3.2) * fDt); // Winkel des Gyro in deg/sec

    return fMeas;
}

int main(void)
{
    char gChar[4] = "";
    int16_t gAngle = 0;

    TCCR0 |= (1 << CS01) | (1 << CS00); // Vorteiler 3 (Takt 62,5kHz)
    TIMSK |= (1 << TOIE0); // Timer 0 Overflow Interrupt

    GyroSetMode(); // 1. Gyro "scharf stellen"
    sei(); // Globale Interrupts einschalten

    while(1)
    {
        gAngle= GyroAngle(); // Funktion die Winkel ermittelt
        USART_send(itoa(gAngle, gChar, 10)); // Per USART senden
    }

    GyroSetSleep(); // 4. Gyro schlafen legen
    return 0; // Wird niemals erreicht
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.