Important Cookie Information

This website uses absolutely necessary cookies. If you consent to the use of convenience cookies, please click “Yes, I agree.” By clicking on “Privacy Settings.” you can change this setting at any time and withdraw your given consent. Icon down see more You can find detailled information in our Privacy Policy Icon forward-right
Icon up see less

Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMI08x Design Guide

    Introduction

    This document is intended as a reference guide on how to design using Bosch Sensortec’s BMI08x series IMU.

    It describes the main features of the BMI08x family, available evaluation tools and software, reference design, layout recommendations, and gives instructions on how to test the BMI08x family’s functionality using sample codes, and how to demonstrate and evaluate it with COINES.

    Selecting the right part

    The BMI08x family has two products: BMI085 and BMI088, which are ideally suited for high-performance consumer applications.

    The BMI085 is designed for virtual augmented and mixed reality applications, high-end gaming, platform stabilization applications such as image stabilization, as well as indoor navigation and dead reckoning, such as robotics applications.

    The BMI088 is designed for applications in harsh vibration environments such as drones and robotics. The IMU is designed to effectively suppress vibration above several hundred Hz, which may occasionally occur due to resonance on the PCB or the structure of the total system.

    Table 1 shows an overview of the features.

                                                                              Table 1: Overview of the features

    Untitled1.png

    Key features

    This section describes the key features of the BMI08x family.

    • Good stability of TCO, TCS, bias and stress
    • Low latency
    • BMI088 has vibration robustness and suppression
    • BMI085 has integrated accelerometer and gyroscope data synchronization function

     Differences between products

    The main differences between the BMI08x family products are the accelerometer part and the overall performance of the MEMS element.                                                       

                                                                                   Table 2: Main differences

    Untitled1.png

    Available evaluation tools and software

    To best evaluate the BMI08x family, the following combination of evaluation tools is recommended:

    Hardware reference design

    Figure 1 and Figure 2 show the I2C and SPI reference designs for BMI085 and BMI088

    23.png

                                                                                          Figure 1: I2C connection

    34.png

                                                                          Figure 2: SPI connection

    Bill of materials

    Table 3 lists the bill of necessary materials.                                                         

                                                                               Table 3: Bill of materials56.pngLayout recommendations

    Because the BMI08x sensor family contains tiny mechanical structures inside the package, care must be taken during the layout phase to ensure optimum performance. The complete handing and soldering guide can be found on the Bosch Sensortec’s website.

    The typical manufacturing procedures for the BMI08x IMU are described in the following sections.

    Recommended layout rules

    The recommended layout rules are as follows:

    • PCB land width = LGA solder pin width
    • PCB land length = LGA solder pin length + 0.1mm on each side
    • Solder mask opening width = PCB land width + 0.05mm on each side
    • Solder mask opening length = PCB land

        Landing Pattern

    The BMI08x family has the same landing pattern. The following dimensioning is recommended.

    78.png                                           Figure 3: Recommended landing pattern (top view, in mm)

    Typical Layout

    Figure 4 shows the typical layout.

    89.png

                                                                                         Figure 4: Typical layout

     Manufacturing notes

    Table 4 lists the recommendations for the manufacture.

                                                                              Table 4: Manufacture recommendations

    98.pngFirst power-on

    This chapter describes how to test the BMI08x family’s functionality and performance after powering it on for the first time.

    To properly initialize the device, the user must decide which interface to use (I2C or SPI) during hardware design. With the PS pin, the user can determine which interface the sensor should listen to. The gyroscope part of the BMI08x initializes its I/O pins according to the selection given by the PS pin. The accelerometer part starts and remains in I2C mode. When a rising edge is detected on the CSB1 pin (chip select of the accelerometer), the accelerometer part switches to SPI mode and remains until the next power-up reset. To switch the accelerometer to SPI mode, the user can perform a dummy SPI read operation during the initialization phase.

    After the power-on reset, the gyroscope enters normal mode, while the accelerometer enters suspend mode. To switch the accelerometer to normal mode, do the following:

    1. Power up the sensor.
    2. Wait for 1ms
    3. Enter normal mode by writing ‘4’ to ACC_PWR_CTRL.
    4. Wait for 50ms. The accelerometer enters normal mode.

    Below are some example codes for performing tests based on BMI08x shuttle board and API, using the COINES software as the host. To test the BMI08x family’s functionality, do the following:

    1) Initialize the sensor driver API interface (based on GenAPI and COINES as example)

    /*!
     *  @brief this internal API is used to set the sensor driver interface to
     *  read/write the data.
     *
     *  @param[in] void
     *
     *  @return void
     *
     */
    static void init_bmi08x_sensor_driver_interface(void)
    {
    #if BMI08x_INTERFACE_I2C==1
        /* I2C setup */
        /* link read/write/delay function of host system to appropriate
         * bmi08x function call prototypes */
        bmi08xdev.write = coines_write_i2c;
        bmi08xdev.read = coines_read_i2c;
        bmi08xdev.delay_ms = coines_delay_msec;
        /* set correct i2c address */
        bmi08xdev.accel_id = (unsigned char) BMI08x_ACCEL_DEV_ADDR;
        bmi08xdev.gyro_id = (unsigned char) BMI08x_GYRO_DEV_ADDR;
        bmi08xdev.intf = BMI08X_I2C_INTF;
    #endif
    #if BMI08x_INTERFACE_SPI==1
        /* SPI setup */
        /* link read/write/delay function of host system to appropriate
         *  bmi08x function call prototypes */
        bmi08xdev.write = coines_write_spi;
        bmi08xdev.read = coines_read_spi;
        bmi08xdev.delay_ms = coines_delay_msec;
        bmi08xdev.intf = BMI08X_SPI_INTF;
        bmi08xdev.accel_id = COINES_SHUTTLE_PIN_8;
        bmi08xdev.gyro_id = COINES_SHUTTLE_PIN_14;
    #endif
    }

    2)  Set up the communication between Bosch Sensortec application board 2.0 and PC, and get the board hardware and software information.

    struct coines_board_info board_info;
        int16_t rslt;
    
        rslt = coines_open_comm_intf(COINES_COMM_INTF_USB);
    
        if (rslt < 0)
        {
            printf("\n Unable to connect with Application Board ! \n"
                   " 1. Check if the board is connected and powered on. \n"
                   " 2. Check if Application Board USB driver is installed. \n"
                   " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n");
            exit(rslt);
        }
        rslt = coines_get_board_info(&board_info);
    
        if (rslt == COINES_SUCCESS)
        {
            if ((board_info.shuttle_id != BMI085_SHUTTLE_ID) && (board_info.shuttle_id != BMI088_SHUTTLE_ID))
            {
    
                printf("! Warning invalid sensor shuttle \n ,"
                       "This application will not support this sensor \n");
                exit(COINES_E_FAILURE);
            }
        }

    3)Initialize the sensor interface, protocol, and power on VDD and VDDIO.

    /*********************************************************************/
    /* functions */
    /*!
     *  @brief This internal API is used to initialize the sensor interface depending
     *   on selection either SPI or I2C.
     *
     *  @param[in] void
     *
     *  @return void
     *
     */
    static void init_sensor_interface(void)
    {
        /* Switch VDD for sensor off */
        coines_set_shuttleboard_vdd_vddio_config(0, 0);
        coines_delay_msec(10);
    #if BMI08x_INTERFACE_I2C==1
        /* set the sensor interface as I2C with 400kHz speed*/
        coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE);
        coines_delay_msec(10);
        /* PS pin is made high for selecting I2C protocol*/
        coines_set_pin_config(COINES_SHUTTLE_PIN_9, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH);
    #endif
    #if BMI08x_INTERFACE_SPI==1
        /* CS pin is made high for selecting SPI protocol*/
        coines_set_pin_config(COINES_SHUTTLE_PIN_8, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH);
        /* CS pin is made high for selecting SPI protocol*/
        coines_set_pin_config(COINES_SHUTTLE_PIN_14, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH);
        /* PS pin is made low for selecting SPI protocol*/
        coines_set_pin_config(COINES_SHUTTLE_PIN_9, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW);
        coines_delay_msec(10);
        coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3);
    #endif
        coines_delay_msec(10);
        /* Switch VDD for sensor on */
        coines_set_shuttleboard_vdd_vddio_config(3300, 3300);
    }

    4) After a delay of approximately 200ms, call the BMI08x API to initialize the BMI08x, including its power mode, ODR, bandwidth, range.

    /*!
     *  @brief This internal API is used to initialize the bmi08x sensor
     *  settings like power mode and OSRS settings.
     *
     *  @param[in] void
     *
     *  @return void
     *
     */
    static void init_bmi08x(void)
    {
        if (bmi08a_init(&bmi08xdev) == BMI08X_OK && bmi08g_init(&bmi08xdev) == BMI08X_OK)
        {
            printf("BMI08x initialization success !\n");
            printf("Accel chip ID - 0x%x\n", bmi08xdev.accel_chip_id);
            printf("Gyro chip ID - 0x%x\n", bmi08xdev.gyro_chip_id);
        }
        else
        {
            printf("BMI08x initialization failure !\n");
            exit(COINES_E_FAILURE);
        }
        bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ;
    #if BMI08X_FEATURE_BMI085 == 1
        bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G;
    #elif BMI08X_FEATURE_BMI088 == 1
        bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G;
    #endif
        bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; //user_accel_power_modes[user_bmi088_accel_low_power];
        bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; /* Bandwidth and OSR are same */
    
        bmi08a_set_power_mode(&bmi08xdev);
        coines_delay_msec(10);
        bmi08a_set_meas_conf(&bmi08xdev);
        coines_delay_msec(10);
    
        bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ;
        bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS;
        bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ;
        bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL;
    
        bmi08g_set_power_mode(&bmi08xdev);
        coines_delay_msec(10);
        bmi08g_set_meas_conf(&bmi08xdev);
        coines_delay_msec(10);
    
    }

    5. Call the BMI08x API to read Acc and Gyro data in a while loop.

    int times_to_read = 0;
        while (times_to_read < 10)
        {
    
            bmi08a_get_data(&bmi08x_accel, &bmi08xdev);
            printf("ax:%d ay:%d az:%d\n", bmi08x_accel.x, bmi08x_accel.y, bmi08x_accel.z);
            bmi08g_get_data(&bmi08x_gyro, &bmi08xdev);
            printf("gx:%d gy:%d gz:%d\n", bmi08x_gyro.x, bmi08x_gyro.y, bmi08x_gyro.z);
            fflush(stdout);
            coines_delay_msec(10);
            times_to_read = times_to_read + 1;
        }
        coines_close_comm_intf(COINES_COMM_INTF_USB);

    Calibration

    Both accelerometer part and gyroscope part of the BMI08x are pre-trimmed at the factory. However, the soldering process and PCB bending due to assembly can result in offset changing; therefore, it is recommended to calibrate the sensor after assembling the device into the device housing.

    The acceleration sensor offset consists of two parts: the static “unwanted” offset mainly due to soldering drift, and the offset generated when an acceleration is applied to the sensor. The latter depends on the applied acceleration and its magnitude if defined by the sensor’s sensitivity. However, the sensitivity has a certain tolerance (typ. <1%). This means that in order to compensate for the static offset, the sensor must be oriented in such a way that no external acceleration is applied to the sensing axis. As gravity also causes a sensor signal, the sensing axis must be oriented perpendicular to the gravity field.

    The compensation process described below focuses on the x/y-axis. The z-axis can also be compensated in the same way, but the user has to consider the applied gravity. Alternatively, the process can be repeated after turning the device, with the z-axis perpendicular to the gravity vector.

    1. Place your sensor (the system with the sensor inside) on a well-defined surface, for example, a horizontal table. The expected sensor output for the x/y-axis should be 0 mg.
    2. Set the sensor to the lowest g-range (BMI085 to 2G, BMI088 to 3G)
    3. Measure the sensor output to ensure the sensor is fully at rest, without vibrations, inclinations, big temperature changes or strong VDD fluctuations. It is advisable to take several values and generate the average over the values (e.g. 1000 values).
    4. Consider the resolution of BMI085 and BMI088, and save the offset in LSB or mg.
    5. Subtract the offset from the future accelerometer sensor data.

    The gyroscope part of the BMI08x has outstanding offset performance and very high offset stability. However, small offsets may still occur and change over the operation time (mainly due to changes in the operation temperature).

    As the needs vary from application to application, the application should take care of the offset compensation. To do this, the application has to ensure that the gyroscope is fully at rest when compensating for the offset. Only at rest the static offset can be separated from any motion-based offset. This can be achieved for example by monitoring the accelerometer signals of all axes and checking the noise of each axis. If the noise is below certain threshold (application specific), the application can assume that the sensor is at rest.

    While monitoring, the device remains at rest and the host can read sensor values, for example, for ten seconds. The average of the gathered values per axis shows the residual offset and can be subtracted from any future the sensor data.

    Example code

    The code below shows how to read the BMI08x sensor data via BMI08x API and COINES system.

    /*!
     *  @brief This internal API is used to read sensor data
     *
     *  @param[in] void
     *
     *  @return void
     *
     */
    void read_sensor_data(void)
    {
        int16_t rslt;
        int counter = 0;
        uint8_t lsb, msb;
        int16_t ax, ay, az, gx, gy, gz;
        uint32_t valid_sample_count = 0;
        int idx = 0;
        int buffer_index = 0;
        while (counter < 1000)
        {
            memset(&bmi08x_accel_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE);
            rslt = coines_read_stream_sensor_data(1, 1, &bmi08x_accel_stream_buffer[0], &valid_sample_count);
            if (rslt == COINES_SUCCESS)
            {
                buffer_index = 0;
                for (idx = 0; idx < valid_sample_count; idx++)
                {
    #if BMI08x_INTERFACE_SPI==1
                    buffer_index++; //dummy byte; ignore for spi
    #endif
                    lsb = bmi08x_accel_stream_buffer[buffer_index++];
                    msb = bmi08x_accel_stream_buffer[buffer_index++];
                    ax = (msb << 😎 | lsb;
    
                    lsb = bmi08x_accel_stream_buffer[buffer_index++];
                    msb = bmi08x_accel_stream_buffer[buffer_index++];
                    ay = (msb << 😎 | lsb;
    
                    lsb = bmi08x_accel_stream_buffer[buffer_index++];
                    msb = bmi08x_accel_stream_buffer[buffer_index++];
                    az = (msb << 😎 | lsb;
    
                    printf("ax: %-5d \t ay: %-5d \t az: %-5d\n", ax, ay, az);
                    fflush(stdout);
                }
            }
            memset(&bmi08x_gyro_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE);
            rslt = coines_read_stream_sensor_data(2, 1, &bmi08x_gyro_stream_buffer[0], &valid_sample_count);
            if (rslt == COINES_SUCCESS)
            {
                buffer_index = 0;
                for (idx = 0; idx < valid_sample_count; idx++)
                {
    
                    lsb = bmi08x_gyro_stream_buffer[buffer_index++];
                    msb = bmi08x_gyro_stream_buffer[buffer_index++];
                    gx = (msb << 😎 | lsb;
    
                    lsb = bmi08x_gyro_stream_buffer[buffer_index++];
                    msb = bmi08x_gyro_stream_buffer[buffer_index++];
                    gy = (msb << 😎 | lsb;
    
                    lsb = bmi08x_gyro_stream_buffer[buffer_index++];
                    msb = bmi08x_gyro_stream_buffer[buffer_index++];
                    gz = (msb << 😎 | lsb;
    
                    printf("gx: %-5d \t gy: %-5d \t gz: %-5d\n", gx, gy, gz);
                    fflush(stdout);
                }
            }
            coines_delay_msec(1);
            counter++;
        }
    }
    

     Further reads

    Version history
    Revision #:
    15 of 15
    Last update:
    a week ago
    Updated by:
     
    Contributors
    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