AdSense

Sunday 21 July 2013

Read acceleration sensor MPU-6050 with Raspberry PI

(Deutsche Version) To read the MPU-6050 via a Raspberry PI, a I²C library is needed. I used the bcm2835 library (http://www.airspayce.com/mikem/bcm2835/). To read the acceleration, i used the following C code. It is very important to disable the sleep mode (set register 107 to 0), otherwise the sensor will not work properly.

If you want to use an ATMega instead of a Raspberry PI, see this post.

#include <bcm2835.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main (int atgc, char** argv)
{
    bcm2835_init();
    bcm2835_i2c_begin();

    char addr = 0x68;

    //I found this address somewhere in the internet...
    char buf[1];
    char regaddr[2];
    int x = 0;
    int ret;

    bcm2835_i2c_setSlaveAddress(addr);

    //disable sleep mode!!!!!

    regaddr[0] = 107;
    regaddr[1] = 0;
    //This is the basic operation to write to an register
    //regaddr[0] is the register address
    //regaddr[1] is the value
    bcm2835_i2c_write(regaddr, 2);
   
    regaddr[0] = 59;
    ret = BCM2835_I2C_REASON_ERROR_DATA;
    while(ret != BCM2835_I2C_REASON_OK)
    {
        //This is the basic operation to read an register
        //regaddr[0] is the register address
        //buf[0] is the value
        bcm2835_i2c_write(regaddr, 1);
        ret = bcm2835_i2c_read(buf, 1);
    }
    x = buf[0]<<8;

    regaddr[0] = 60;
    ret = BCM2835_I2C_REASON_ERROR_DATA;
    while(buf[0] == 99)
    {
        bcm2835_i2c_write(regaddr, 1);
        ret = bcm2835_i2c_read(buf, 1);
    }
    x += buf[0];


    //because of the sign, we have here 32-bit integers,
    //the value is 16-bit signed.

    if (x & 1<<15)
    {
        x -= 1<<16;
    }

    double x_val = x;
    x_val = x_val / 16384;

    //This is only valid if the accel-mode is +- 2g
    //The range can be controlled via the 
    //GYRO_CONFIG and ACCEL_CONFIG registers

    printf("accel: %g\n", x_val);

    bcm2835_i2c_end();
}


All other applications should be simple with this code, the Register Map will provide further information: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

4 comments:

  1. Hi there I found it very interesting however it failed to compile.

    pi@pi ~ $ sudo gcc -o gyro gyro.c -lwiringPi
    /tmp/ccWjCIjg.o: In function `main':
    gyro.c:(.text+0x14): undefined reference to `bcm2835_init'
    gyro.c:(.text+0x18): undefined reference to `bcm2835_i2c_begin'
    gyro.c:(.text+0x34): undefined reference to `bcm2835_i2c_setSlaveAddress'
    gyro.c:(.text+0x54): undefined reference to `bcm2835_i2c_write'
    gyro.c:(.text+0x78): undefined reference to `bcm2835_i2c_write'
    gyro.c:(.text+0x88): undefined reference to `bcm2835_i2c_read'
    gyro.c:(.text+0xcc): undefined reference to `bcm2835_i2c_write'
    gyro.c:(.text+0xdc): undefined reference to `bcm2835_i2c_read'
    gyro.c:(.text+0x150): undefined reference to `bcm2835_i2c_end'
    collect2: ld returned 1 exit status

    ReplyDelete
  2. Hi,
    I think you need to link the library during compile: -l bcm2835
    Respectively for your example:
    sudo gcc -o gyro gyro.c -lwiringPi -l bcm2835

    ReplyDelete
  3. I do not understand the while(but[0]==99) : We do have to read the LSB anytime though?

    ReplyDelete
    Replies
    1. I am also curious about where and why author used such number there, but I am using ret != BCM2835_I2C_REASON_OK instead and it works just as well.

      Delete