Skip to main content
added 119 characters in body
Source Link
ocrdu
  • 9.3k
  • 23
  • 32
  • 42

I think I'm reading the gyroscope correctly, but it seems like the values are only changedchanging when the sensor is moving, and when it stops, the orientation goes back to 0,0 0,0 0. 

Is this normal? I though the sensor keepswould keep track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading the sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c) {
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if (check == 104) {
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        // data = 0x03;
     
    // HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
         
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az) {
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz) {
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}
 

I think I'm reading the gyroscope correctly, but it seems like the values are only changed when the sensor is moving, and when it stops, the orientation goes back to 0,0,0. Is this normal? I though the sensor keeps track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}
 

I think I'm reading the gyroscope correctly, but it seems like the values are only changing when the sensor is moving, and when it stops, the orientation goes back to 0, 0, 0. 

Is this normal? I though the sensor would keep track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading the sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c) {
  uint8_t check, data = 0;
  HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

  // If the device is present
  if (check == 104) {
    // Write 0x0 to power management register to wake up the sensor
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
    HAL_Delay(100);

    // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
    // data = 0x03;
     
    // HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

    // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
    data = 0x07;
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

    // Set gyroscope full scale range
    // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
    uint8_t config = check & ~0xE0;
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
    config = check & ~0x18;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
    data = 0x0;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

    // Set accelerometer configuration
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
    config = check & ~0xE0;
         
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
    config = check & ~0x18;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
    data = 0x0;
     
    HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
  }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az) {
  uint8_t accel_data[6];

  // Get High register reading, shift 8 bits and OR with low register reading
  HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
  HAL_Delay(100);

  int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
  int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
  int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

  // convert raw values to g's
  Ax = accel_X_raw / 16384.0;
  Ay = accel_Y_raw / 16384.0;
  Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz) {
  uint8_t gyro_data[6];

  // Get High register reading, shift 8 bits and OR with low reading
  HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
  HAL_Delay(100);

  int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
  int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
  int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

  // convert raw values to deg/s
  Gx = gyro_X_raw / 131.0;
  Gy = gyro_Y_raw / 131.0;
  Gz = gyro_Z_raw / 131.0;
}
added 64 characters in body
Source Link
ocrdu
  • 9.3k
  • 23
  • 32
  • 42

So I've been playing around with an MPU6050 MPU6050 (GY-521 board) with a nucleo l476rgNucleo L476RG. 

I think I'm reading the gyroscope correctly, but it seems like the values are only changed when the sensor is moving, and when it stops, the orientation goes back to 0,0,0. Is this normal? I though the sensor keeps track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}

With the sensor on a bread board on my table, if I rotate it 90 degrees clock wise90° clockwise only and then leave it, this is what the output looks like:

Should the Gz value not stay at -90 degrees90°?

Thanks for the help.

So I've been playing around with an MPU6050 (GY-521 board) with a nucleo l476rg. I think I'm reading the gyroscope correctly, but it seems like the values are only changed when the sensor is moving, and when it stops the orientation goes back to 0,0,0. Is this normal? I though the sensor keeps track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}

With the sensor on a bread board on my table, if I rotate it 90 degrees clock wise only and then leave it this is what the output looks like:

Should the Gz value not stay at -90 degrees?

Thanks for the help.

I've been playing around with an MPU6050 (GY-521 board) with a Nucleo L476RG. 

I think I'm reading the gyroscope correctly, but it seems like the values are only changed when the sensor is moving, and when it stops, the orientation goes back to 0,0,0. Is this normal? I though the sensor keeps track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}

With the sensor on a bread board on my table, if I rotate it 90° clockwise only and then leave it, this is what the output looks like:

Should the Gz value not stay at -90°?

Source Link

MPU6050 losing orientation

So I've been playing around with an MPU6050 (GY-521 board) with a nucleo l476rg. I think I'm reading the gyroscope correctly, but it seems like the values are only changed when the sensor is moving, and when it stops the orientation goes back to 0,0,0. Is this normal? I though the sensor keeps track of the orientation with respect to its initial reference frame. This is how I'm initializing and reading sensor data:

void mpu6050::init(I2C_HandleTypeDef& hi2c){
    uint8_t check, data = 0;
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000);

    // If the device is present
    if(check == 104){
        // Write 0x0 to power management register to wake up the sensor
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &data, 1, 1000);
        HAL_Delay(100);

        // Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively
        //data = 0x03;
        //HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, CONFIG_REG, 1, &data, 1, 1000);

        // Set data output rate for 1khz, formula is: sample rate = gyro output rate / (1 + reg val)
        data = 0x07;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &data, 1, 1000);

        // Set gyroscope full scale range
        // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &check, 1, 1000);
        uint8_t config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &data, 1, 1000);

        // Set accelerometer configuration
        HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &check, 1, 1000);
        config = check & ~0xE0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear self-test bits [7:5]
        config = check & ~0x18;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &config, 1, 1000); // Clear AFS bits [4:3]
        data = 0x0;
        HAL_I2C_Mem_Write(&hi2c, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &data, 1, 1000);
    }
}

// Read accelerometer registers
// Each axis for accel readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_accel(I2C_HandleTypeDef& hi2c, float& Ax, float& Ay, float& Az){
    uint8_t accel_data[6];

    // Get High register reading, shift 8 bits and OR with low register reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, accel_data, 6, 1000);
    HAL_Delay(100);

    int16_t accel_X_raw = (int16_t)((accel_data[0] << 8) | accel_data[1]);
    int16_t accel_Y_raw = (int16_t)((accel_data[2] << 8) | accel_data[3]);
    int16_t accel_Z_raw = (int16_t)((accel_data[4] << 8) | accel_data[5]);

    // convert raw values to g's
    Ax = accel_X_raw / 16384.0;
    Ay = accel_Y_raw / 16384.0;
    Az = accel_Z_raw / 16384.0;
}

// Read gyroscope registers
// Each axis for gyro readings is split between high and low registers
// There's a total of 6 bytes of data (1 for each register) to read
void mpu6050::read_gyro(I2C_HandleTypeDef& hi2c, float& Gx, float& Gy, float& Gz){
    uint8_t gyro_data[6];

    // Get High register reading, shift 8 bits and OR with low reading
    HAL_I2C_Mem_Read(&hi2c, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, gyro_data, 6, 1000);
    HAL_Delay(100);

    int16_t gyro_X_raw = (int16_t)((gyro_data[0] << 8) | gyro_data[1]);
    int16_t gyro_Y_raw = (int16_t)((gyro_data[2] << 8) | gyro_data[3]);
    int16_t gyro_Z_raw = (int16_t)((gyro_data[4] << 8) | gyro_data[5]);

    // convert raw values to deg/s
    Gx = gyro_X_raw / 131.0;
    Gy = gyro_Y_raw / 131.0;
    Gz = gyro_Z_raw / 131.0;
}

With the sensor on a bread board on my table, if I rotate it 90 degrees clock wise only and then leave it this is what the output looks like:

enter image description here

Should the Gz value not stay at -90 degrees?

Thanks for the help.