Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMI088 data not making any sense

    BMI088 data not making any sense

    nyameaama
    New Poster

    I have written this basic driver for BMI088 for ESP32 with ESP-IDF in which I am able to read registers from the sensor.

    #include "bmi088.h"
    #include <stdio.h>
    #include <stdint.h>
    #include <math.h>
    #include "esp_timer.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_log.h"
    #include "driver/i2c.h"

    #define I2C_MASTER_SCL_IO 22 /*!< GPIO number used for I2C master clock */
    #define I2C_MASTER_SDA_IO 21 /*!< GPIO number used for I2C master data */
    #define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
    #define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
    #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
    #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
    #define I2C_MASTER_TIMEOUT_MS 1000

    #define BM1088_ACCEL_ADDRESS 0x18 /*!< Slave address of the BM1088_acceleromter sensor SD01 pull to GND */
    #define BM1088_GYRO_ADDRESS 0x68 /*!< Slave address of the BM1088 gyroscope sensor SD02 pull to GND*/
    int16_t ret = 0;

    /*! Earth's gravity in m/s^2 */
    #define GRAVITY_EARTH (9.80665f)

    static const char *TAG = "BM1088 Module";

    /**
    * @brief Memory locations to store BM1088 accel and gyro Sensors data
    */
    uint8_t accel_x[2] = {0};
    uint8_t accel_y[2] = {0};
    uint8_t accel_z[2] = {0};

    uint8_t gyro_x[2] = {0};
    uint8_t gyro_y[2] = {0};
    uint8_t gyro_z[2] = {0};

    /**
    * @brief Convertion of BM1088 accel and gyro Sensors data into signed integer
    */
    float accel_x_int16 = 0;
    float accel_y_int16 = 0;
    float accel_z_int16 = 0;


    float gyro_x_int16 = 0;
    float gyro_y_int16 = 0;
    float gyro_z_int16 = 0;


    /**
    * @brief Convertion of BM1088 accel and gyro Sensors signed integer into acceleration
    */
    float accel_x_in_mg = 0;
    float accel_y_in_mg = 0;
    float accel_z_in_mg = 0;

    /**
    * @brief calculate BM1088 data in signed form from LSB into Degree per second
    */
    float gyro_x_in_degree = 0;
    float gyro_y_in_degree = 0;
    float gyro_z_in_degree = 0;

    /**
    * @brief Initialize angles
    */
    double yaw = 0.0;
    double pitch = 0.0;
    double roll = 0.0;

    /**
    * @brief Initialize previous angles
    */
    double prev_yaw = 0.0;
    double prev_pitch = 0.0;
    double prev_roll = 0.0;

    /**
    * @brief Initialize the previous timestamp
    */
    int64_t previous_timestamp = 0;

    /* Initialize other variables */
    double pitch_acc = 0.0;
    double roll_acc = 0.0;
    double gyro_x_rad = 0.0;
    double gyro_y_rad = 0.0;
    double gyro_z_rad = 0.0;

    /**
    * @brief BM1088 IMU Register Addresses
    */
    typedef enum
    {
    ACC_CHIP_ID = 0X00,
    ACC_ERR_REG = 0X02,
    ACC_STATUS = 0X03,
    ACC_X_LSB = 0X12,
    ACC_X_MSB = 0X13,
    ACC_Y_LSB = 0X14,
    ACC_Y_MSB = 0X15,
    ACC_Z_LSB = 0X16,
    ACC_Z_MSB = 0X17,
    ACC_CONF = 0X40,
    ACC_RANGE = 0X41,
    ACC_SELF_TEST = 0X6D,
    ACC_PWR_CONF = 0X7C,
    ACC_PWR_CTRL = 0X7D,
    ACC_SOFT_REST = 0X7E,
    GYRO_CHIP_ID = 0X00,
    GYRO_X_LSB = 0X02,
    GYRO_X_MSB = 0X03,
    GYRO_Y_LSB = 0X04,
    GYRO_Y_MSB = 0X05,
    GYRO_Z_LSB = 0X06,
    GYRO_Z_MSB = 0X07,
    GYRO_RANGE = 0X0F,
    GYRO_BANDWIDTH = 0X10,
    GYRO_LPM1 = 0X11,
    GYRO_SOFT_REST = 0X14,
    GYRO_SELF_TEST = 0X3C,

    }mpu_register_address;

    void BMI088_IMU::IMU_INIT(){
    uint8_t data[2];
    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C initialized successfully");

    /* Read the BM1088 GYRO_CHIP_ID REGISTER, on power up the register should have the value 0x0F */
    ESP_ERROR_CHECK(bm1088_gyro_read(GYRO_CHIP_ID, data, 1));
    ESP_LOGI(TAG, "GYRO_CHIP_ID_REGISTER_VALUE = %X", data[0]);

    /* Read the BM1088 ACC_PWR_CTRL REGISTER to check power on reset */
    uint8_t check_por[2];
    ESP_ERROR_CHECK(bm1088_accel_read(ACC_PWR_CTRL, check_por, 1));
    vTaskDelay(1/ portTICK_PERIOD_MS);

    /* Enable accel module by writing 0x04 to power control register */
    uint8_t acc_pwr_ctr = 0x04;
    acc_pwr_ctr |= check_por[0];

    ESP_ERROR_CHECK(bm1088_accel_write_byte(ACC_PWR_CTRL, acc_pwr_ctr));
    vTaskDelay(50/ portTICK_PERIOD_MS);
    ESP_ERROR_CHECK(bm1088_accel_read(ACC_PWR_CTRL, check_por, 1));

    if (check_por[0] == acc_pwr_ctr)
    {
    ESP_LOGI(TAG, "Accelerometer configured successfully");
    }
    else ESP_LOGI(TAG, "Accelerometer not configured ");
    }

    /**
    * @brief Read a sequence of bytes from a BM1088 accel sensor registers
    */
    esp_err_t BMI088_IMU::bm1088_accel_read(uint8_t reg_addr, uint8_t *data, size_t len){
    for (size_t i = 0; i < len; i++) {
    ret = i2c_master_write_read_device(i2c_port_t(I2C_MASTER_NUM), BM1088_ACCEL_ADDRESS, (&reg_addr + i), 1,
    (data + i), 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS );
    }
    return ret;
    }

    /**
    * @brief Read a sequence of bytes from a BM1088 gyro sensor registers
    */
    esp_err_t BMI088_IMU::bm1088_gyro_read(uint8_t reg_addr, uint8_t *data, size_t len){
    for (size_t i = 0; i < len; i++) {
    ret = i2c_master_write_read_device(i2c_port_t(I2C_MASTER_NUM), BM1088_GYRO_ADDRESS, (&reg_addr + i), 1,
    (data + i), 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS );
    }
    return ret;
    }

    /**
    * @brief Write a byte to a BM1088 accel sensor register
    */
    esp_err_t BMI088_IMU::bm1088_accel_write_byte(uint8_t reg_addr, uint8_t data){
    uint8_t write_buf[2] = {reg_addr, data};

    ret = i2c_master_write_to_device(i2c_port_t(I2C_MASTER_NUM), BM1088_ACCEL_ADDRESS, write_buf, sizeof(write_buf),
    I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
    }

    /**
    * @brief Write a byte to a BM1088 gyro sensor register
    */
    esp_err_t BMI088_IMU::bm1088_gyro_write_byte(uint8_t reg_addr, uint8_t data){
    uint8_t write_buf[2] = {reg_addr, data};

    ret = i2c_master_write_to_device(i2c_port_t(I2C_MASTER_NUM), BM1088_GYRO_ADDRESS, write_buf, sizeof(write_buf),
    I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
    }

    /**
    * @brief i2c master initialization
    */
    esp_err_t BMI088_IMU::i2c_master_init(void){
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_MASTER_SDA_IO;
    conf.scl_io_num = I2C_MASTER_SCL_IO;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
    conf.clk_flags = 0;


    i2c_param_config(i2c_port_t(i2c_master_port), &conf);

    return i2c_driver_install(i2c_port_t(i2c_master_port), conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
    }

    /*!
    * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at
    * range 2G, 4G, 8G or 16G.
    */
    float BMI088_IMU::lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width)
    {
    double power = 2;

    float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f));

    return (GRAVITY_EARTH * val * g_range) / half_scale;
    }

    /*!
    * @brief This function converts lsb to degree per second for 16 bit gyro at
    * range 125, 250, 500, 1000 or 2000dps.
    */
    float BMI088_IMU::lsb_to_dps(int16_t val, float dps, uint8_t bit_width)
    {
    double power = 2;

    float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f));

    return (dps / (half_scale)) * (val);
    }

    /*!
    * @brief This function reads raw accel_x LSB data and converts to degree per second
    */
    double BMI088_IMU::accel_read_rawX(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_accel_read(ACC_X_LSB, accel_x, 2));
    lsb = accel_x[0];
    msb = accel_x[1];
    msblsb = (msb << 😎 | lsb;
    float x_original_int = ((int16_t) msblsb); /* Data in X axis */
    float x = lsb_to_mps2(x_original_int, 24, 16);
    return x;
    }

    /*!
    * @brief This function reads raw accel_y LSB data and converts to degree per second
    */
    double BMI088_IMU::accel_read_rawY(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_accel_read(ACC_Y_LSB, accel_y, 2));
    lsb = accel_y[0];
    msb = accel_y[1];
    msblsb = (msb << 😎 | lsb;
    float y_original_int = ((int16_t) msblsb); /* Data in Y axis */
    float y = lsb_to_mps2(y_original_int, 24, 16);
    return y;
    }

    /*!
    * @brief This function reads raw accel_z LSB data and converts to degree per second
    */
    double BMI088_IMU::accel_read_rawZ(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_accel_read(ACC_Z_LSB, accel_z, 2));
    lsb = accel_z[0];
    msb = accel_z[1];
    msblsb = (msb << 😎 | lsb;
    float z_original_int = ((int16_t) msblsb); /* Data in Z axis */
    float z = lsb_to_mps2(z_original_int, 24, 16);
    return z;
    }

    /*!
    * @brief This function reads raw gyro_x LSB data and converts to degree per second
    */
    double BMI088_IMU::gyro_read_rawX(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_gyro_read(GYRO_X_LSB, gyro_x, 2));
    lsb = gyro_x[0];
    msb = gyro_x[1];
    msblsb = (msb << 😎 | lsb;
    float x_original_int = ((int16_t) msblsb); /* Data in X axis */
    float x = lsb_to_dps(x_original_int, (float)250, 16);
    return x;
    }

    /*!
    * @brief This function reads raw gyro_y LSB data and converts to degree per second
    */
    double BMI088_IMU::gyro_read_rawY(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_gyro_read(GYRO_Y_LSB, gyro_y, 2));
    lsb = gyro_y[0];
    msb = gyro_y[1];
    msblsb = (msb << 😎 | lsb;
    float y_original_int = ((int16_t) msblsb); /* Data in Y axis */
    float y = lsb_to_dps(y_original_int, (float)250, 16);
    return y;
    }

    /*!
    * @brief This function reads raw gyro_z LSB data and converts to degree per second
    */
    double BMI088_IMU::gyro_read_rawZ(){
    uint8_t lsb, msb;
    uint16_t msblsb;
    ESP_ERROR_CHECK(bm1088_gyro_read(GYRO_Z_LSB, gyro_z, 2));
    lsb = gyro_z[0];
    msb = gyro_z[1];
    msblsb = (msb << 😎 | lsb;
    float z_original_int = ((int16_t) msblsb); /* Data in Z axis */
    float z = lsb_to_dps(z_original_int, (float)250, 16);
    return z;
    }

    double BMI088_IMU::angle_read_pitch(){
    double x_Buff = gyro_read_rawX();
    double y_Buff = gyro_read_rawY();
    double z_Buff = gyro_read_rawZ();
    double pitch = atan2((- x_Buff) , sqrt(y_Buff * y_Buff + z_Buff * z_Buff)) * 57.3;
    return pitch;
    }

    double BMI088_IMU::angle_read_roll(){
    double y_Buff = gyro_read_rawY();
    double z_Buff = gyro_read_rawZ();
    double roll = atan2(y_Buff , z_Buff) * 57.3;
    return roll;
    }

    double BMI088_IMU::angle_read_yaw(){
    return 0;
    }


    Output:
    I (332) app_start: Starting scheduler on CPU0
    I (337) app_start: Starting scheduler on CPU1
    I (337) main_task: Started on CPU0
    I (347) main_task: Calling app_main()
    I (347) BM1088 Module: I2C initialized successfully
    I (347) BM1088 Module: GYRO_CHIP_ID_REGISTER_VALUE = F
    I (407) BM1088 Module: Accelerometer configured successfully
    I (407) BM1088 Module: accel_read_rawX = 1.824382
    I (407) BM1088 Module: accel_read_rawY = -228.284729
    I (407) BM1088 Module: accel_read_rawZ = -229.283112
    I (617) BM1088 Module: accel_read_rawX = 1.723825
    I (617) BM1088 Module: accel_read_rawY = -228.291916
    I (617) BM1088 Module: accel_read_rawZ = -229.168182
    I (817) BM1088 Module: accel_read_rawX = 1.766921
    I (817) BM1088 Module: accel_read_rawY = -228.356567
    I (817) BM1088 Module: accel_read_rawZ = -229.161026
    I (1017) BM1088 Module: accel_read_rawX = 0.682347
    I (1017) BM1088 Module: accel_read_rawY = -229.003006
    I (1017) BM1088 Module: accel_read_rawZ = -229.448318
    I (1217) BM1088 Module: accel_read_rawX = 0.624887
    I (1217) BM1088 Module: accel_read_rawY = -228.722870
    I (1217) BM1088 Module: accel_read_rawZ = -229.017365
    I (1417) BM1088 Module: accel_read_rawX = 1.795651
    I (1417) BM1088 Module: accel_read_rawY = -228.291916
    I (1417) BM1088 Module: accel_read_rawZ = -229.225662
    I (1617) BM1088 Module: accel_read_rawX = 0.215478
    I (1617) BM1088 Module: accel_read_rawY = -229.139465
    I (1617) BM1088 Module: accel_read_rawZ = -228.378113
    I (1817) BM1088 Module: accel_read_rawX = 1.292869
    I (1817) BM1088 Module: accel_read_rawY = -228.090790
    I (1817) BM1088 Module: accel_read_rawZ = -228.234467


    However, the output data I get does not make sense. What am I doing wrong?

    1 REPLY 1

    BSTRobin
    Community Moderator
    Community Moderator

    Hi nyameaama,

    You can refer to BMI088 sensor API & example on github https://github.com/boschsensortec/BMI08x-Sensor-API/tree/master/examples

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist