Bosch Sensortec Community

    Showing results for 
    Search instead for 
    Did you mean: 

    BMI270 load init using I2C

    BMI270 load init using I2C

    New Poster

    I'm not able to successfully load init data into BMI270 chip using the code below. Since maximum bytes is 255, I load 32 bytes at the time. I get 0x02 as a result from reading 0x21 (status). I do not have any available SPI ports.

    These are the first register readouts:


    Any obvious errors? Greatful for any hints or trixes.

    uint16_t i;
    uint16_t j;
    uint32_t err_code;
    uint8_t d[33];
    uint32_t addr;

    bmi270_write(BMI2_PWR_CONF_ADDR, 0x00); // Power on

    bmi270_write(BMI2_CMD_REG_ADDR, 0xb6); // Reset

    bmi270_write(BMI2_INIT_CTRL_ADDR, 0x00); // init start

    for(i = 0; i < 256; i++)
    bmi270_write(BMI2_INIT_ADDR_0, 0);
    bmi270_write(BMI2_INIT_ADDR_1, i);

    d[0] = BMI2_INIT_DATA_ADDR;
    addr = i << 5;
    for(j = 0; j < 32; j++)
    d[j+1] = bmi270_config_file[addr + j];

    err_code = nrf_drv_twi_tx(&m_twi, BMI2_I2C_PRIM_ADDR, d, 33, false);

    bmi270_write(BMI2_INIT_CTRL_ADDR, 0x01);

    bmi270_write(BMI2_PWR_CONF_ADDR, 0x00); // Power on
    bmi270_write(BMI2_PWR_CTRL_ADDR, 0x0e); // Accelerometer and gyroscope on
    bmi270_write(BMI2_FIFO_CONFIG_1_ADDR, 0x00); // FIFO off

    bmi270_write(BMI2_PWR_CTRL_ADDR, 0x0e); // Accelerometer and gyroscope on
    bmi270_write(BMI2_ACC_CONF_ADDR, 0xbb); // Performance, Avg32, 100Hz
    bmi270_write(BMI2_ACC_RANGE_ADDR,0x00); // Range +- 2g
    bmi270_write(BMI2_GYR_CONF_ADDR, 0xcb); // Performance, normal operation, 200Hz
    bmi270_write(BMI2_GYR_RANGE_ADDR, 0x04); // Gyre range +- 125dps
    bmi270_write(BMI2_FIFO_DOWNS_ADDR, 0x00); // Filtering off
    bmi270_write(BMI2_FIFO_CONFIG_1_ADDR, 0xd0); // Store acc and Gyro in FIFO

    7 REPLIES 7


    I'm also having such problem. Please solve this asap!

    It seems like I've managed to make it work. These are the necessary steps:

    Implement the i2c write function. I used pigpio library which has exactly what we need: i2cWriteI2CBlockData. I've seen this function in many libraries - it's pretty common. 

    int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length) {

    /* Write to registers using I2C. Return 0 for a successful execution. */

    //int i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)
    int ret = i2cWriteI2CBlockData(i2cHnd, reg_addr, (char *) reg_data, length);
    if (ret != 0) {
    printf("*** ERROR in i2c_reg_write %d\n", ret); // do your error handing thing here
    return 1;
    return 0;


    Implement the i2c read function. I stopped experimenting with the details of read function immediately when this produced good results. Possibly the i2cReadI2CBlockData would work... But instead of that this one just increments the register address  and the position in the resulting buffer. Important to undestand that with this approach you won't be able to read back the freshly written config data. That has to be done through the BMI2_INIT_DATA_ADDR register in combination with BMI2_INIT_ADDR_0 and BMI2_INIT_ADDR_1. tldr, this one works.

    int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {

    /* Read from registers using I2C. Return 0 for a successful execution. */
    uint16_t count = 0;
    int res;
    while (count < length) {
    res = i2cReadByteData(i2cHnd, (reg_addr + count));
    if (res < 0) {
    printf("*** ERROR in i2c_reg_read %d\n", res);
    return 1;
    reg_data[count] = (uint8_t)(res & 0xff);
    return 0;

    EDIT: My first tests validate that i2cReadI2CBlockData can be used also. 

    int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length) {
    ret = i2cReadI2CBlockData(i2cHnd, reg_addr, (char *)reg_data, length);
    return (ret > 0) ? 0 : 1; // all good


    Then implement the delay_us( uint32_t period )  function. I used the nanosleep from #include <time.h>. The delay_us function's period - after converting it - ends up here. 

    long secs, nanoSec;
    timespec req, rem;
    req.tv_sec = secs;
    req.tv_nsec = nanoSec;
    while (nanosleep(&req, &rem));


    Right before the good old bmi270_init is called the device gets configured. Here we need to change the maximum size of the chunk we are able to send.  Change  read_write_len = 128  to M where M is the maximum number of bytes your I2C lib is able to send using i2cWriteI2CBlockData. In my case it's 32.

    dev.delay_us = delay_us;
    dev.read_write_len = 32; // ***** THIS must be changed according to the used I2C lib ***
    dev.intf = BMI2_I2C_INTERFACE;


    Last but not least you must open the proper I2C bus where the sensor is. Which usually involves some GPIO initialization. So in my case it is:



    ... call here the function which creates the device and calls bmi270_init(&device), etc ...

    ... the sensor works, you can have a cookie. ...



    This will produce good config result in address: BMI2_INTERNAL_STATUS_ADDR. Go for the message bits (3..0) particularly value 1 which is message: "init_ok".



    Thanks crmabs for the detailed tutorial !

    Still having issues with the initialization of the BMI270.
    Anyone could be so kind and provide a full working example code?