- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 8 von 8

Thema: MPU-6000 per SPI ansteuern

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Hi!

    Danke, für die schnelle Antwort.
    Ich habe schon viele Beiträge von dir durchgelesen, um an Informationen zu kommen, das war schonmal hilfreich
    Die verschiedenen Modi habe ich alle durchprobiert, ist immer das gleiche Ergebnis.
    Aber so brauche ich ab jetzt nur noch Modus 0 versuchen.
    Wenn ich das im Datenblatt richtig verstanden habe ist das Initialisieren nicht zwangsläufig notwendig, um Register auszulesen, aber das werde ich definitiv noch machen, wenn die Kommunikation an sich läuft.
    Fehlen in deiner Funktion nicht noch Wartezeiten und die Steuerung der CS Leitung?
    Oder kümmert sich der Xmega da automatisch drum?

    mfg
    Olaf

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    Jein, lt. DB sollte man gleich die Initialisierung machen, damit der MPU bei CS = High nicht in den I2C Modus fällt. Das ist aber eher eine Sicherheitsmaßnahme, die nicht unbedingt sein muss, das kann also hier nicht der Fehler sein.
    Die CS Leitung setze ich außerhalb der Funktion, da ich ja sonst immer nur ein Byte senden / empfangen könnnte.
    Hier mal meine Lese-Routine:
    Code:
        uint8_t dump;
        MpuCsLow;
        dump = SpiTransfer(0xBB);
        ax.bytes.byte2 = SpiTransfer(0x00);
        ax.bytes.byte1 = SpiTransfer(0x00);
        ay.bytes.byte2 = SpiTransfer(0x00);
        ay.bytes.byte1 = SpiTransfer(0x00);
        az.bytes.byte2 = SpiTransfer(0x00);
        az.bytes.byte1 = SpiTransfer(0x00);
        t.bytes.byte2 = SpiTransfer(0x00);
        t.bytes.byte1 = SpiTransfer(0x00);
        gx.bytes.byte2 = SpiTransfer(0x00);
        gx.bytes.byte1 = SpiTransfer(0x00);
        gy.bytes.byte2 = SpiTransfer(0x00);
        gy.bytes.byte1 = SpiTransfer(0x00);
        gz.bytes.byte2 = SpiTransfer(0x00);
        gz.bytes.byte1 = SpiTransfer(0x00);
        MpuCsHigh;
    Wo sollten den da Wartezeiten sein? bzw. für was? Ich hab da keine.

    Gruß
    Chris

    EDIT:
    Hab hier mal schnell was zusammengezimmert, sollte funktionieren, musst nur noch ne Ausgabe o.ä. einbauen.
    Code:
    /*
        MPU6000 SPI Test
    */
    
    #define F_CPU 32000000UL
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <string.h>
    #include <util/twi.h>
    #include <math.h>
    #include <avr/eeprom.h>
    #include <stdlib.h>
    
    
    
    #define MpuCsLow (PORTC.OUTCLR = PIN4_bm)
    #define MpuCsHigh (PORTC.OUTSET = PIN4_bm)
    
    
    typedef union{
        int16_t integer;
        struct{
            uint8_t byte1;
            uint8_t byte2;
        }bytes;
    }int16byte;
    
    
    int main(void);
    
    void InitClock(void);
    void InitSpi(void);
    
    uint8_t SpiTransfer(uint8_t data);
    
    void InitMpu(void);
    void ReadMpu(void);
    
    
    
    int16byte ax;
    int16byte ay;
    int16byte az;
    int16byte t;
    int16byte gx;
    int16byte gy;
    int16byte gz;
    
    int16_t GyroX;
    int16_t GyroY;
    int16_t GyroZ;
    int16_t Temperature;
    int16_t AccX;
    int16_t AccY;
    int16_t AccZ;
    
    
    int main(void)
    {
        InitClock();
        InitSpi();
        
        _delay_ms(50);
        InitMpu();
        _delay_ms(50);
        
        //16MHz SPI
        SPIC.CTRL = SPI_CLK2X_bm | SPI_ENABLE_bm | SPI_MASTER_bm | SPI_PRESCALER_DIV4_gc;
        
        while(1)
        {
            ReadMpu();
            //Print Data
            
            _delay_ms(10);
        }
    }
    
    
    void InitClock(void)
    {
        OSC.CTRL |= OSC_RC32MEN_bm;
        while(!(OSC.STATUS & OSC_RC32MRDY_bm));
        CCP = CCP_IOREG_gc;
        CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
    }
    
    void InitSpi(void)
    {
        PORTC.DIRSET = PIN7_bm | PIN5_bm | PIN4_bm;
        
        //1MHz SPI
        SPIC.CTRL = SPI_CLK2X_bm | SPI_ENABLE_bm | SPI_MASTER_bm | SPI_PRESCALER_DIV64_gc;
        
        MpuCsHigh;
    }
    
    uint8_t SpiTransfer(uint8_t data)
    {
        uint8_t dump;
        SPIC.DATA = data;
        while(!(SPIC.STATUS & SPI_IF_bm))
        dump = SPIC.STATUS;
        return SPIC.DATA;
    }
    
    void InitMpu(void)
    {
        uint8_t dump;
    
        MpuCsLow;
        dump = SpiTransfer(106);
        dump = SpiTransfer(0x10);
        MpuCsHigh;
        _delay_ms(1);
        MpuCsLow;
        dump = SpiTransfer(25);
        dump = SpiTransfer(0x00);
        MpuCsHigh;
        _delay_ms(1);
        MpuCsLow;
        dump = SpiTransfer(26);
        dump = SpiTransfer(0x03);
        MpuCsHigh;
        _delay_ms(1);
        MpuCsLow;
        dump = SpiTransfer(27);
        dump = SpiTransfer(0x18);
        MpuCsHigh;
        _delay_ms(1);
        MpuCsLow;
        dump = SpiTransfer(28);
        dump = SpiTransfer(0x00);
        MpuCsHigh;
        _delay_ms(1);
        MpuCsLow;
        dump = SpiTransfer(107);
        dump = SpiTransfer(0x03);
        MpuCsHigh;
    }
    
    void ReadMpu(void)
    {
        uint8_t dump;
        MpuCsLow;
        dump = SpiTransfer(0xBB);
        ax.bytes.byte2 = SpiTransfer(0x00);
        ax.bytes.byte1 = SpiTransfer(0x00);
        ay.bytes.byte2 = SpiTransfer(0x00);
        ay.bytes.byte1 = SpiTransfer(0x00);
        az.bytes.byte2 = SpiTransfer(0x00);
        az.bytes.byte1 = SpiTransfer(0x00);
        t.bytes.byte2 = SpiTransfer(0x00);
        t.bytes.byte1 = SpiTransfer(0x00);
        gx.bytes.byte2 = SpiTransfer(0x00);
        gx.bytes.byte1 = SpiTransfer(0x00);
        gy.bytes.byte2 = SpiTransfer(0x00);
        gy.bytes.byte1 = SpiTransfer(0x00);
        gz.bytes.byte2 = SpiTransfer(0x00);
        gz.bytes.byte1 = SpiTransfer(0x00);
        MpuCsHigh;    
        
        GyroX = gx.integer;
        GyroY = gy.integer;
        GyroZ = gz.integer;
        Temperature = t.integer;
        AccX = ax.integer;
        AccY = ay.integer;
        AccZ = az.integer;
    }
    Geändert von Che Guevara (24.11.2014 um 14:45 Uhr)

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Danke schonmal, das WhoAmI Register auslesen funktioniert Problemlos, ich bekomme die 0x68.
    Die Register von Beschleunigungssensor, Temperatursensor und Gyroskop enthalten momentan nur Nullen.
    Morgen werde ich mal versuchen den MPU erst zu Initialisieren.

    Dann lag ich ja schonmal richtig mit CS.
    Also laut Datenblatt ist nachdem CS auf low gezogen wird eine kurze Wartezeit nötig, bevor Daten übertragen werden können, bei mir funktioniert es aber auch ohne.
    Jetzt bin ich erstmal beruhigt, dass der MPU noch funktioniert

    mfg
    Olaf

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Hi!
    Danke, dein Programm hat mir sehr geholfen, danke dafür.
    Ich habe es leider etwas zu spät gesehen und zu dem Zeitpunkt schon ein eigenes Programm fertig gehabt, dass nicht ganz funktioniert hat.
    Dann habe ich deine Initialisierung für den MPU6000 übernommen und noch ein Software Reset mit Wartezeit vor der Initialisierung eingefügt und jetzt funktioniert die Auswertung fehlerfrei.

    Jetzt habe ich nur ein kleines Problem.
    Ich Schreibe alle Werte des Sensors in uint8_t variablen, so wie du.
    Über den UART lasse ich mir z.B. die beiden Bytes, vom der Z-Achse des Beschleunigungssensors ausgeben.
    Problem ist, dass ich einen recht kleinen Wert herausbekomme, wenn ich den Sensor gerade auf den Tisch lege, sollte ich ja eigentlich 1G Erdbeschleunigung messen.
    Ich erhalte jedoch den Wert 2060 (High Byte: 0x08 Low Byte: 0x0C), was 0.126g entspräche.
    Ich erziele ein sehr ähnliches Resultat auf der X und Y Achse mit minimaler Abweichung.
    Und Umgekehrt erhalte ich den Wert - 2036 (High Byte 0xF8 Low Byte: 0x0C).

    Also prinzipiell stimmt alles schätze ich, nur wird die Skalierung irgendwie falsch sein.
    Im Regsiter 28 stelle ich mit 0x00 ein, dass die Full Range +/- 2g beträgt.
    Ist meine Rechnung zur Berechnung der Beschleunigung in g richtig?

    Code:
    (2060/32768) * 2g= 0.126g
    Liegt da der Fehler oder denke ich gerade vollkommen falsch?

    Edit:
    Zur Kontrolle habe ich auch den Temperatursensor ausgewertet.
    Dabei erhalte ich einen Wert von 26,5°C.
    Ich denke, der ist realistisch, da ich in der Werkstatt 25°C Raumtemperatur habe und mir vorstellen kann, dass sich das IC beim Betrieb erwärmt.

    Edit2:
    Wenn ich die zu messende Achse Parallel zur Erde ausrichte erhalte ich 0g so, wie es sein soll.


    mfg
    Olaf
    Geändert von crabtack (25.11.2014 um 14:15 Uhr)

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    Hi,

    also der Wert ist definitiv falsch! Bei +1G sollte der Wert bei ca. 16384 (0x4000) liegen. Hast du mein Programm übernommen oder ein eigenes? Wenns nicht meins ist, stell mal deins rein.

    Gruß
    Chris

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.09.2009
    Ort
    Geilenkirchen
    Beiträge
    419
    Hi,

    Ich habe mein Programm verwendet.
    Heute habe ich dein Programm probiert und es um einen Software Reset erweitert, das funktionierte fehlerfrei, ich habe die 0x4000 erhalten.
    Anschließend habe ich es mit meinem Programm verglichen und in meinem Programm nach jedem schreiben in ein Register 1mS Wartezeit eingefügt, jetzt funktioniert es und ich kann von -1G bis +1G messen, wenn ich den Sensor drehe.
    Vielen Dank schonmal dafür.
    Jetzt wirds erst richtig Witzig, mit der Sensorfusion

    Edit: Die Idee mit dem Union ist genial, werde ich auch so machen.


    mfg
    Olaf
    Geändert von crabtack (26.11.2014 um 07:05 Uhr)

Ähnliche Themen

  1. Mpu-6050
    Von inka im Forum Robby RP6
    Antworten: 12
    Letzter Beitrag: 29.05.2013, 09:41
  2. Digitalpotio über SPI ansteuern
    Von shedepe im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 17.04.2013, 18:53
  3. Digitalpotio über SPI ansteuern
    Von shedepe im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 13.04.2013, 19:32
  4. Problem mit MPU-6050
    Von ni.c im Forum Sensoren / Sensorik
    Antworten: 0
    Letzter Beitrag: 06.04.2012, 11:53
  5. Max 7221 über SPI ansteuern --> Probleme :(
    Von Razer im Forum C - Programmierung (GCC u.a.)
    Antworten: 5
    Letzter Beitrag: 02.05.2006, 16:16

Berechtigungen

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

Solar Speicher und Akkus Tests