-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Winkelgeschwindigkeit Integrieren

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    03.06.2012
    Beiträge
    23

    Winkelgeschwindigkeit Integrieren

    Anzeige

    Hallo

    Ich versuche eine simple Integration von Winkelgeschwindigkeit eines Gyros um auf die Winkel zu kommen.
    Mir ist klar das das Integrieren auch das aufsummieren von Fehlern bedeutet und der Winkel innert einigen Sekunden nicht mehr stimmt.
    Mir geht es hier aber um das verstehen, später kommt dann eventuell das verrechnen von einem ACC.

    Ich habe nun viele Tage Gesucht und die Beispiele sehen immer gleich aus:

    Code:
    angle = angle + gyro * dt;
    Ich denke angle ist Winkel, gyro ist die Winkelgeschwindigkeit, dt die Zeit die ein Loop Durchgang benötigt.

    nur bin ich vermutlich zu Blind um die Rohdaten aufzubereiten.

    Die Hardware ist ein simpler Arduino uno mit dem 328.
    Breakout mit MPU6050 = http://www.sparkfun.com/products/11028
    Mit I2C ausgelesen lese ich nun folgende max -min werte = -32767 bis 32768.

    Wie muss ich nun die Werte aufarbeiten?

    Angefangen habe ich damit den Offset abzuziehen:
    Im Setup mache ich dies:

    Code:
     for (int i=0;i<500;i++) //mittelung von nullpunkt
        {
          accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
          gz_null = gz_null+gz;
        }
        gz_null = gz_null/500;
    Danach versuche ich das Integrieren:

    Code:
    #include "Wire.h"
    #include "I2Cdev.h"
    #include "MPU6050.h"
    MPU6050 accelgyro;
    int16_t ax, ay, az;
    int16_t gx, gy, gz;
    
    float gz_null=0;
    float winkel=0;
    
    
    void setup() {
       
        Wire.begin();
        Serial.begin(38400);
        accelgyro.initialize();
        
        
        for (int i=0;i<500;i++) //mittelung von nullpunkt
        {
          accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
          gz_null = gz_null+gz;
        }
        gz_null = gz_null/500;
        
        
    }
    
    void loop() {
      
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //MPU6050 auslesen
        gz = gz - gz_null; //offset abziehen
        winkel=winkel+gz*2.8; //Winkel Integrieren, winkel + winkel * 2.8ms (dauer zwischen 2 loop durchgängen.
        
        Serial.println(winkel); //Winkel ausgeben
        
    }
    Jetzt habe ich einen Wert, das sich schön ändert wenn ich den Gyro langsam um die Achse drehe, je nach Richtung nimmt dieser Wert zu oder ab.
    Aber wenn ich den Gyro schneller drehe, verschluckt sich das und die Werte ändern viel zu wenig.

    Habe ich nun kompletten Murks Programmiert?
    Muss ich die Gyro Rohdaten ( -32767 bis 32768 ) zuerst aufbereiten?
    Wie bekomme ich hier nun den Winkel in °?

    Gruss Tomatenbaum
    Geändert von Tomatenbaum (10.06.2012 um 18:00 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Hallo,

    ich selbst kann zwar kein C programmieren (bzw. nur schlecht), aber etwas fällt mir schon auf:
    In deiner Offset-Routine addierst du 500 mal den gleichen Wert und teilst dann durch 500. Das macht wenig Sinn, du müsstet in deiner For-Schleife den Sensor immer wieder neu auslesen. Ich benutze in meinen Koptern auch den MPU60X0 und bestimme den Offset wie folgt:
    1. Ich sample 50 Werte von jeder Achse (gyrox, gyroy und gyroz)
    2. Ich vergleiche alle Werte miteinander (also Gyrox(1) mit Gyrox(2), Gyrox(2) mit Gyrox(3), usw...) für jede Achse (also jeweils Gyrox, Gyroy & Gyroz)
    3. Wenn der Unterschied zwischen zwei benachbarten Werten eine bestimmte Schwelle überschreitet (bei mir: 3 (bei 2000°/s und 42Hz DLPF)), sample ich wieder neue 50 Werte
    4. Wenn der Unterschied geringer ist, addiere ich die 50 Werte und teile durch 50, so kann ich eine minimale Abweichung, welche die Grenze nicht überschreitet, trotzdem einigermassen ausgleichen

    Die Rohdaten musst du, bis auf das Abziehen des Offsets, nicht weiter aufbereiten. Welche Einstellungen hast du den im MPU gemacht bzgl. Empfindlichkeit und DLPF?

    Gruß
    Chris

    EDIT:
    Dass bei schnellen Drehungen die Winkeländerung zu langsam erfolgt, könnte daran liegen, dass du innerhalb der Main-loop Schleife die Daten über die serielle Schnittstelle ausgibst. Evtl. wäre es sinnvoller, dies nur alle xx-Durchläufe zu machen, etwa so (Pseudocode):
    Code:
    Byte: Cnt
    
    Mainloop:
       getSensorData()
       gz = gz - gz_null
       winkel = winkel + gz
       cnt = cnt + 1
       wenn cnt = 100 dann
          cnt = 0
          serialport.write(winkel)
       ende wenn
    Springe zu Mainloop
    Außerdem fällt mir noch das dt auf: IMHO braucht man das nicht zwingend, zumindest funktionierts in meinen Koptern auch hervorragend ohne diesen Parameter.
    Geändert von Che Guevara (10.06.2012 um 17:43 Uhr)

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    03.06.2012
    Beiträge
    23
    Danke

    zu 1: Habe das mit dem mitteln falsch gepostet, habe den Code noch mal richtig geschrieben.
    zu 2, 3, 4: Das mit dem Vergleich zweier Werte und eventuelles neu einlesen ist eine gute Idee, das werde ich auch so umsetzten.

    Wie meist du das, Einstellungen und Empfindlichkeit?
    Ich benutze diese Bibliothek:
    https://github.com/jrowberg/i2cdevli...rduino/MPU6050
    Dort habe ich nichts weiter eingestellt.

    Auf was soll ich achten?

    Edit: der Link zur Bibliothek stimmt nun.

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Man kann den MPU unterschiedlich konfigurieren bzgl. der maximalen Winkelgeschwindigkeit (2000°/s, 1000°/s, 500°/s, 250°/s) und bzgl. des DLPF (zwischen 256 & 5Hz in 6 Schritten beim Gyro).
    Was jetzt bei dir genau eingestellt wird, da bin ich ehrlich gesagt etwas zu faul, den ganzen Code zu durchsuchen...
    Hast du den schon probiert, den Winkel nur alle paar Durchläufe ausgeben zu lassen?

    Gruß
    Chris

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    03.06.2012
    Beiträge
    23
    Zitat Zitat von Che Guevara Beitrag anzeigen
    EDIT:
    Dass bei schnellen Drehungen die Winkeländerung zu langsam erfolgt, könnte daran liegen, dass du innerhalb der Main-loop Schleife die Daten über die serielle Schnittstelle ausgibst. Evtl. wäre es sinnvoller, dies nur alle xx-Durchläufe zu machen, etwa so (Pseudocode):
    Code:
    Byte: Cnt
    
    Mainloop:
       getSensorData()
       gz = gz - gz_null
       winkel = winkel + gz
       cnt = cnt + 1
       wenn cnt = 100 dann
          cnt = 0
          serialport.write(winkel)
       ende wenn
    Springe zu Mainloop
    Außerdem fällt mir noch das dt auf: IMHO braucht man das nicht zwingend, zumindest funktionierts in meinen Koptern auch hervorragend ohne diesen Parameter.
    Hmm, was ist das für eine Sprache?

    Habe das was du meinst mal geproggt:


    Code:
    #include "Wire.h"
    #include "I2Cdev.h"
    #include "MPU6050.h"
    MPU6050 accelgyro;
    int16_t ax, ay, az;
    int16_t gx, gy, gz;
    
    float gz_null=0;
    float winkel=0;
    unsigned long prev;
    
    
    void setup() {
       
        Wire.begin();
        Serial.begin(38400);
        accelgyro.initialize();
        
        
        for (int i=0;i<500;i++) //mittelung von nullpunkt
        {
          accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
          gz_null = gz_null+gz;
        }
        gz_null = gz_null/500;
        
        prev = millis();
        
    }
    
    void loop(){
      
        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //MPU6050 auslesen
    
    
        gz = gz - gz_null; //offset abziehen
        winkel=winkel+gz; //Winkel Integrieren, winkel + winkel * 2.8ms (dauer zwischen 2 loop durchgängen.
        
    
        if((millis() - prev)>100){
        prev =millis();
        Serial.println(winkel); //Winkel ausgeben
        }
    
     }
    Ist schon viel besser, auch bei schnellere Drehungen.
    Was mache ich aber nun mit diesem Wert, kann ich diesen nun gleich für einen PID Regler verwenden?

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Das ist Pseudocode, also gar keine Sprache
    Ich dachte mir doch, dass es an der Seriellen liegt...
    Nunja, da der MPU ja einen 3Achs ACC eingebaut hat, könntest du z.b. die Daten fusionieren (mithilfe eines Komplementärfilters oder Kalman oder...).
    Oder aber du nutzt diesen Winkel ohne den ACC, allerdings wird der nicht sehr lange stabil sein.
    Was genau hast du den vor?

    Gruß
    Chris

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    03.06.2012
    Beiträge
    23
    Zitat Zitat von Che Guevara Beitrag anzeigen
    Man kann den MPU unterschiedlich konfigurieren bzgl. der maximalen Winkelgeschwindigkeit (2000°/s, 1000°/s, 500°/s, 250°/s) und bzgl. des DLPF (zwischen 256 & 5Hz in 6 Schritten beim Gyro).
    Was jetzt bei dir genau eingestellt wird, da bin ich ehrlich gesagt etwas zu faul, den ganzen Code zu durchsuchen...
    Hast du den schon probiert, den Winkel nur alle paar Durchläufe ausgeben zu lassen?

    Gruß
    Chris
    Hmm, da muss ich mal in die Bibliothek schauen.
    Der ACC ist einfach, der Spuckt bei ACC Z 16000 aus wenn er ruhig auf dem Tisch liegt, also ist +-2G eingestellt.
    Bei den Gyros muss ich das erst herausfinden.
    Was hast du für deinen Kopter eingestellt?



    Zitat Zitat von Che Guevara Beitrag anzeigen
    Das ist Pseudocode, also gar keine Sprache
    Ich dachte mir doch, dass es an der Seriellen liegt...
    Nunja, da der MPU ja einen 3Achs ACC eingebaut hat, könntest du z.b. die Daten fusionieren (mithilfe eines Komplementärfilters oder Kalman oder...).
    Oder aber du nutzt diesen Winkel ohne den ACC, allerdings wird der nicht sehr lange stabil sein.
    Was genau hast du den vor?

    Gruß
    Chris
    Eigentlich will ich am Schluss einen kleinen Kopter mit einem Komplementärfilter in die Lüfte bewegen.
    Auch der Komplementärfilter hat einen *dt in der Fomel:

    Code:
    angle = (0.98)*(angle + gyro * dt) + (0.02)*(x_acc);
    ich Denke den dt ist also wichtig!

    Was meinst du?

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Also ich habe meinen MPU auf 2000°/s und 42Hz Tiefpass eingestellt, da hierbei das Rauschen minimal und die Performance noch gut ist. Vorher war ich bei 250°/s und 256Hz Tiefpass, da hat er öfters mal ein Rad geschlagen, obwohl ich das nicht wollte, sehr ärgerlich.....
    Der Tiefpass ist IMHO Pflicht und die max. Winkelgeschwindigkeits-einstellung würde ich auch eher in Richtung 2000 machen, da du dann den Kopter schneller drehen lassen kannst und er agiler ist... Irgendjemand hier im Forum meinte mal, dass der Sensor bei 250°/s eigentlich auch auf 2000°/s eingestellt ist und die Werte nur verstärkt werden. Das würde auch das deutlich höhere Rauschen erklären.

    Auch ich verwende (noch) einen Komplementärfilter in meinen Kopter, dieser benötigt bei mir auch kein dt. Meine Formel ist einfach (iwo ausm Netz):
    Code:
    Gyro_xangle = Gyro_xangle + Gyrox
    
    Gyro_xangle = Gyro_xangle * Gyro_influence
    ACC_xangle = ACC_x * Acc_influence
    Gyro_xangle = Gyro_xangle + ACC_xangle
    Möchtest du nur einen Hover-Mode integrieren oder auch HH?

    Gruß
    Chris

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    03.06.2012
    Beiträge
    23
    Danke für deine Erfahrungen.

    Sieht so aus als ob ich die MPU6050 Einstellungen in der Bibliothek anschauen muss.

    Also dein Code hat wirklich kein dt.

    Wie verwendest du dein Wert weiter?
    Direkt zum PD Regler?

    Ich versuche den einen Berühmten Komplementärfilter zu verstehen:

    http://web.mit.edu/scolton/www/filter.pdf

    Du kennst dieses Paper sicher.
    Nur das dt verwirrt mich nun, auf Seite 3 werden die Werte aufbereitet, eventuell hat das dt auch etwas mit dem Scale zu tun?

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Ich habe in meinen Koptern zwei Modi: Acro (HH) und Hover
    Beide besitzen einen PID-Regler. Im Acro-Mode wird der Fehler in der Winkelgeschwindigkeit mit p_gain multipliziert und auf die Motoren gebeben, außerdem wird der Fehler integriert und mit i_gain multipliziert. Und dann gibts noch den D-Anteil, der den Fehler mit dem vorherigen vergleicht und auch diesen wieder auf die Motoren gibt.
    Wenn du konkrettere Fragen hast, stell sie einfach, aber ich kann dir jetzt nicht alles erklären.

    Dieses Paper kenne ich nicht, sieht aber auf den ersten Blick ganz informativ aus.

    Gruß
    Chris

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. PID-Regler regelt Winkel anstatt Winkelgeschwindigkeit
    Von Che Guevara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 0
    Letzter Beitrag: 21.05.2011, 23:35
  2. ISP auf Platine integrieren....
    Von Cybered im Forum AVR Hardwarethemen
    Antworten: 13
    Letzter Beitrag: 12.02.2008, 21:31
  3. Gyrosignal integrieren?
    Von Hendrix85 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 04.01.2008, 18:04
  4. C compiler in AVR Studio 4.11 integrieren??
    Von Redsox im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 16.09.2005, 12:55
  5. avr-gcc in MSVC integrieren
    Von hahoyer im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 07.07.2005, 10:22

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •