2 Replies Latest reply on Nov 18, 2015 4:58 AM by Frederic Philips

    Weird Problem when measuring MPU9150 IMU sensor

    Frederic Philips

      Hi guys,

      So I am trying to get measurements from the MPU-9150 sensor from Invensense using the Intel Edison. I am able to communicate with the sensor and the values seem sensible.

      But after a specific number of cycles, I measure only a zero from all data registers. This error is repeatable: When I try to read the Accelerometer and Gyro data(6 data registers), the data stream stops exactly at 84 cycles. If I try to read jus the Accelerometer values, it stops at double the no. of cycles i.e. 168. I sense some data is overflowing, but couldn't figure out yet.

      Looking for your reply and Thanks!

      Cheers,

      Frederic

      Code:

      MPU9150.h

      //Self Test registers R/W
      #define SELF_TEST_X  0x0D
      #define SELF_TEST_Y  0x0E
      #define SELF_TEST_Z  0x0F
      #define SELF_TEST_A  0x0A
      
      //Configuration Registers
      #define SMPRT_DIV    0x19 //Sample Rate Divider
      #define CONFIG       0x1A //FSYNC & DLPF config
      #define GYRO_CONFIG  0x1B //Self-Test & Scale select
      #define ACCEL_CONFIG 0x1C //Self-Test & Scale select
      
      //Interrupt Registers
      #define INT_ENABLE   0x38
      #define INT_STATUS   0x3A
      
      //Accelerometer Measurement Registers
      #define ACCEL_XOUT_H 0x3B
      #define ACCEL_XOUT_L 0x3C
      #define ACCEL_YOUT_H 0x3D
      #define ACCEL_YOUT_L 0x3E
      #define ACCEL_ZOUT_H 0x3F
      #define ACCEL_ZOUT_L 0x40
      
      //Temperature Measurement Registers
      //Temperature in degrees C = (TEMP_OUT Register Value as a signed quantity)/340 + 35
      #define TEMP_OUT_H   0x41
      #define TEMP_OUT_L   0x42
      
      //Gyroscope Measurement Registers
      #define GYRO_XOUT_H  0x43
      #define GYRO_XOUT_L  0x44
      #define GYRO_YOUT_H  0x45
      #define GYRO_YOUT_L  0x46
      #define GYRO_ZOUT_H  0x47
      #define GYRO_ZOUT_L  0x48
      
      //Power Management Registers
      #define PWR_MGMT_1   0x6B
      #define PWR_MGMT_2   0x6C
      
      //Device i.d. Register
      #define WHO_AM_I     0x75
      
      /*
      R1 - 0x69
      R2 - 0x68
      */
      #define MPU_ADDR     0x68
      
      //Reset the Registers and Power
      #define PWR_RESET    0x80
      #define DEVICE_ON    0x00
      
      //Accelerometer Scale
      #define ACCEL_2G     0x00
      #define ACCEL_4G     0x08
      #define ACCEL_8G     0x10
      #define ACCEL_16G    0x18
      
      //Gyroscope Scale
      #define GYRO_250     0x00
      #define GYRO_500     0x08
      #define GYRO_1000    0x10
      #define GYRO_2000    0x18
      
      #define SAMPLE_RATE  0x00
      
      #define DLPF_CFG     0x01
      

       

      MPU9150.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <signal.h>
      #include "mraa.h"
      #include "MPU9150.h"
      
      void MPU9150_I2C_Init(void);
      void MPU9150_I2C_Config(void);
      void MPU9150_I2C_Write(uint8_t address, uint8_t value);
      void MPU9150_I2C_Read(uint8_t address, uint8_t *value);
      int16_t MPU9150_Get_Measurement(uint8_t addrL, uint8_t addrH);
      void sig_handler(int signum);
      
      sig_atomic_t volatile isrunning = 1;
      
      //Acceleometer Measurement Storage Variables
      int16_t Accel_X = 0;
      int16_t Accel_Y = 0;
      int16_t Accel_Z = 0;
      
      //Gyroscope Measurement Storage Variables
      int16_t Gyro_X = 0;
      int16_t Gyro_Y = 0;
      int16_t Gyro_Z = 0;
      
      //Temperature Measurement Storage Variable
      float Temperature = 0;
      
      //Variable to Store LOW and HIGH Register values
      uint8_t Measurement_L = 0;
      uint8_t Measurement_H = 0;
      
      int main(int argc, char **argv)
      {
          printf("--------------------------------------------------\n");
          printf("------------------eGlove Project------------------\n");
          printf("--------------------------------------------------\n");
          sleep(1); //1s delay
          
          signal(SIGINT, &sig_handler);
          usleep(1000); //1ms delay
          
          MPU9150_I2C_Init();
          sleep(1); //1s delay
      
          MPU9150_I2C_Config();    
          sleep(1); //1s delay
          
          while(isrunning)
          {
              //Get Accelerometer Measurements
              Accel_X = MPU9150_Get_Measurement(ACCEL_XOUT_L, ACCEL_XOUT_H);
          Accel_Y = MPU9150_Get_Measurement(ACCEL_YOUT_L, ACCEL_YOUT_H);
          Accel_Z = MPU9150_Get_Measurement(ACCEL_ZOUT_L, ACCEL_ZOUT_H);
      
              //Get Gyroscope Measurements
          Gyro_X = MPU9150_Get_Measurement(GYRO_XOUT_L, GYRO_XOUT_H);
          Gyro_Y = MPU9150_Get_Measurement(GYRO_YOUT_L, GYRO_YOUT_H);
          Gyro_Z = MPU9150_Get_Measurement(GYRO_ZOUT_L, GYRO_ZOUT_H);
              
              //Print Accelerometer Values
              printf("Accelerometer:\n X:%d\n Y:%d\n Z:%d\n ", Accel_X, Accel_Y, Accel_Z);
              
              //Print Gyroscope Values
          printf("Gyroscope:\n X:%d\n Y:%d\n Z:%d\n ", Gyro_X, Gyro_Y,Gyro_Z);
              
              //Sample Readings every second
              sleep(1); //1s delay
          }
          return MRAA_SUCCESS;
      }
      
      void MPU9150_I2C_Init(void)
      {
          mraa_init();
          mraa_i2c_context mpu9150_i2c;
          mpu9150_i2c = mraa_i2c_init(1);
          
        if (mpu9150_i2c == NULL) 
          {
              printf("MPU9150 I2C initialization failed, exit...\n");
              exit(1);
          }
          
          printf("MPU9150 I2C initialized successfully\n");
          
          mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
          printf("MPU9150 I2C Address set to 0x%x\n", MPU_ADDR);
      }
      
      void MPU9150_I2C_Config(void)
      {
          mraa_i2c_context mpu9150_i2c;
          mpu9150_i2c = mraa_i2c_init(1);
          
          //Reset all the Registers
        mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
          MPU9150_I2C_Write(PWR_MGMT_1, PWR_RESET);
          printf("MPU9150 Reset\n");
          sleep(1); //1s delay
          
          mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
           MPU9150_I2C_Write(PWR_MGMT_1, DEVICE_ON);
          printf("MPU9150 Switched ON\n");
          sleep(1); //1s delay
          
          mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
        uint8_t data = mraa_i2c_read_byte_data(mpu9150_i2c, WHO_AM_I);
        printf("Who am I: 0x%x\n", data);
          sleep(1); //1s delay
          
           MPU9150_I2C_Write(SMPRT_DIV, SAMPLE_RATE);
          
           MPU9150_I2C_Write(CONFIG, DLPF_CFG);
      
           //Set the Gyroscope Scale to 250°/s
           MPU9150_I2C_Write(GYRO_CONFIG, GYRO_500);
          
          //Set the Accelerometer Scale to 2G
           MPU9150_I2C_Write(ACCEL_CONFIG, ACCEL_2G);
          
          printf("Initialization Complete: All Systems are GO!!!\n");
      }
      
      void MPU9150_I2C_Write(uint8_t address, uint8_t value)
      {
          mraa_i2c_context mpu9150_i2c;
          mpu9150_i2c = mraa_i2c_init(1);
          
          //Set MPU Device Address
          mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
          
          //Write Command and Data
          mraa_i2c_write_byte_data(mpu9150_i2c, value, address);
      }
      
      void MPU9150_I2C_Read(uint8_t address, uint8_t *value)
      {
          mraa_i2c_context mpu9150_i2c;
          mpu9150_i2c = mraa_i2c_init(1);
          
          //Set ALS Device Address
          mraa_i2c_address(mpu9150_i2c, MPU_ADDR);
          
          //Write Command and Read Data
          *value = mraa_i2c_read_byte_data(mpu9150_i2c, address);
      }
      
      int16_t MPU9150_Get_Measurement(uint8_t addrL, uint8_t addrH)
      {    
          //Read & Store the Lower Byte
          MPU9150_I2C_Read(addrL, &Measurement_L);
          
          //Read & Store the Higher Byte
          MPU9150_I2C_Read(addrH, &Measurement_H);
        
        return (int16_t)((Measurement_H << 8) + Measurement_L);
      }
      
      //Signal Handler
      void sig_handler(int signum)
      {
          if(signum == SIGINT)
          {
              isrunning = 0;
          }
      }
      

       

      Console Screenshot:

      screenshot.jpg

       

      Reference:

      MPU-9150 Product Specification: http://43zrtwysvxb2gf29r5o0athu.wpengine.netdna-cdn.com/wp-content/uploads/2015/02/MPU-9150-Datasheet.pdf

      MPU-9150 Register Map: http://43zrtwysvxb2gf29r5o0athu.wpengine.netdna-cdn.com/wp-content/uploads/2015/02/MPU-9150-Register-Map.pdf