Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    BMI270 - incorrect number of samples in FIFO when auxiliary sensor is enabled

    BMI270 - incorrect number of samples in FIFO when auxiliary sensor is enabled

    alastair
    Member

    We're using the BMI270 with a BMM150 attached to the I2C auxilliary port. When I enable just the BMI270 accelerometer and gyro, everything works as expected, reading the FIFO produces the correct number of samples per second. As soon as I enable the auxilliary sensor, I get strange behaviour where the sample rate for the accelerometer and gyro seems to drop to 1 to 2 samples per second.

    Code snippets for the configuration below. Samples per second is determined by reading a FIFO frame every 500 ms and using the 

    bmi2_extract_accel

    etc functions.

    /* Setup accelerometer data rate, range */
    {
    bmi2_sens_config config = {};
    config.type = BMI2_ACCEL;
    config.cfg.acc.odr = BMI2_ACC_ODR_100HZ;
    config.cfg.acc.bwp = BMI2_ACC_OSR4_AVG1;
    config.cfg.acc.range = BMI2_ACC_RANGE_8G;
    bmi2_set_sensor_config(&config, 1u, device_);
    }

    /* Setup gyroscope data rate, range */
    {
    bmi2_sens_config config = {};
    config.type = BMI2_GYRO;
    config.cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
    config.cfg.gyr.range = BMI2_GYR_RANGE_250;
    config.cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE;
    config.cfg.gyr.noise_perf = 0u;
    bmi2_set_sensor_config(&config, 1u, device_);
    }

    /* Configure auxilliary sensor - BMM150 */
    {
    const uint8_t device_address = 0x13u;
    bmi2_sens_config aux_sens_config = {};
    aux_sens_config.type = BMI2_AUX;
    aux_sens_config.cfg.aux.aux_en = BMI2_ENABLE;
    aux_sens_config.cfg.aux.manual_en = BMI2_DISABLE;
    aux_sens_config.cfg.aux.odr = BMI2_AUX_ODR_25HZ;
    aux_sens_config.cfg.aux.aux_rd_burst = 6u; /* 3 axes * 2 bytes */
    aux_sens_config.cfg.aux.read_addr = 0x42; /* 0x42 - MAG LSB X */
    aux_sens_config.cfg.aux.i2c_device_addr = device_address;
    bmi2_set_sensor_config(&aux_sens_config, 1u, device_);
    }

    /* Configure FIFO */
    uint16_t config = BMI2_FIFO_HEADER_EN | BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN | BMI2_FIFO_AUX_EN;
    bmi2_set_fifo_config(config, BMI2_ENABLE, device_); res != BMI2_OK );

     

     

    10 REPLIES 10

    Vincent
    Community Moderator
    Community Moderator

    I put a working example code of sensor intialize here fore your reference (without FIFO since your FIFO configure is correct) .

    if you initiliaze all three sensor correctly,  the FIFO data should contain the correct data rate for both accel, gyro and mag .

    static void init_bmi2xy_bmm150(void)
    {
    /* Variable to define error */
    int8_t rslt;
    const uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX};
    struct bmi2_sens_config config[3] = {
    [0].type = BMI2_ACCEL,
    [1].type = BMI2_GYRO,
    [2].type = BMI2_AUX,
    };

    printf("Please wait for config. file to be uploaded during BMI2xy initialization ...\n");
    fflush(stdout);

    /* Upload config. file */
    if (bmi2_init(&bmi2dev) == BMI2_OK)
    {
    printf("BMI2xy initialization success !\n");
    printf("Chip ID - 0x%x\n", bmi2dev.chip_id);
    }
    else
    {
    printf("BMI2xy initialization failure !\n");
    printf("Config file - Sensor mismatch !!\n");
    exit(COINES_E_FAILURE);
    }

    /* Enable accel. , gyro. mag. sensors */
    if (bmi2_sensor_enable(sensor_list, 3, &bmi2dev) == BMI2_OK)
    {
    /*acc*/
    config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE;
    config[0].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2;
    config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; //IMU work for 100HZ
    config[0].cfg.acc.range = BMI2_ACC_RANGE_2G;

    /*gyro*/
    config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE;
    config[1].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000;
    config[1].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE;
    config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
    config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000;
    config[1].cfg.gyr.ois_range = BMI2_GYR_OIS_2000;

    /*mag*/
    /*The initial configuration of the auxiliary sensor should be done in manual mode.Then, switch to data mode to read data.*/
    config[2].cfg.aux.aux_en = BMI2_ENABLE;
    config[2].cfg.aux.manual_en = BMI2_ENABLE;
    config[2].cfg.aux.odr = BMI2_AUX_ODR_50HZ;
    config[2].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS;
    config[2].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3;

    /* Set accel. , gyro. and mag. configuration */
    if (bmi2_set_sensor_config(config, 3, &bmi2dev) == BMI2_OK)
    printf("Accel./Gyro/Mag configuration write success !\n");
    else
    printf("Accel./Gyro/Mag configuration write failure !\n");

    /* Initialize bmm150:should be done in aux man mode */
    rslt = bmm150_init(&bmm150);
    if (rslt != BMI2_OK)
    {
    printf("BMM150 init,Error code: %d\n", rslt);
    }
    /* Set the power mode to either normal or forced mode */
    rslt = bmm150_set_op_mode(&bmm150);
    bmm150.settings.pwr_mode = BMM150_FORCED_MODE;
    if (rslt != BMI2_OK)
    {
    printf("BMM150 set op mode,Error code: %d\n", rslt);
    }

    /* Switch to data mode for reading data*/
    config[2].cfg.aux.manual_en = BMI2_DISABLE;
    /* Configure read address to read Magnetic field data from that address */
    config[2].cfg.aux.read_addr = BMI_AUX_MAG_DATA_ADDR;
    config[2].cfg.aux.aux_rd_burst = BMI2_AUX_READ_LEN_3;
    /* Set the data mode and the auxiliary read address */
    rslt = bmi2_set_sensor_config(config, 3, &bmi2dev);
    if (rslt != BMI2_OK)
    {
    printf("BMI2 set config,Error code: %d\n", rslt);
    }
    }
    }

     

    Thank you for the reply. I didn't quite see what I was doing wrong in my config though? Do all the the sensor configs need to be written at once like you've done? I assumed I could configure one by one?

    Actually I think my issue is not in the sampling rate, but in the parsing of the FIFO frame. The FIFO seems to contain the correct number of bytes, but when I extract the accelerometer etc data it retrieves only a few readings because it encounters and invalid frame type and discards the rest of the buffer. Am I doing something wrong here?

    void Bmi270Application::ReadFifo()
    {
    bmi2_fifo_frame frame = {};
    frame.data = fifo_data_;
    frame.header_enable = true;

    {
    uint16_t length;
    bmi2_get_fifo_length(&length, device_);
    DS_ALWAYS("{} bytes in fifo", length);
    frame.length = std::min((uint16_t)std::size(fifo_data_), length);
    }
    if ( auto res = bmi2_read_fifo_data(&frame, device_); res != BMI2_OK )
    {
    display_error("Failed to read fifo", res);
    return;
    }
    {
    std::array<bmi2_sens_axes_data, 400> acceleration_data;
    uint16_t accel_reading_count = acceleration_data.size();
    auto res =
    bmi2_extract_accel(acceleration_data.data(), &accel_reading_count, &frame, device_);
    if (res < 0)
    {
    display_error("Failed to extract accel data", res);
    return;
    }

    DS_ALWAYS("Got {} accelerometer samples", accel_reading_count);
    DS_ALWAYS("Accel x:{} y:{} z:{}",
    acceleration_data[0].x,
    acceleration_data[0].y,
    acceleration_data[0].z);
    }
    {
    std::array<bmi2_sens_axes_data, 400> gyro_data;
    uint16_t reading_count = gyro_data.size();
    auto res =
    bmi2_extract_gyro(gyro_data.data(), &reading_count, &frame, device_);
    if (res < 0)
    {
    display_error("Failed to extract Gyro data", res);
    return;
    }

    DS_ALWAYS("Got {} gyro samples", reading_count);
    DS_ALWAYS("Gyro x:{} y:{} z:{}", gyro_data[0].x, gyro_data[0].y, gyro_data[0].z);
    }
    if ( use_aux_)
    {
    std::array<bmi2_aux_fifo_data, 400> data;
    uint16_t reading_count = data.size();
    auto res =
    bmi2_extract_aux(data.data(), &reading_count, &frame, device_);
    if (res < 0)
    {
    display_error("Failed to extract Gyro data", res);
    return;
    }

    DS_ALWAYS("Got {} aux samples", reading_count);
    aux_sensor_data_frame f;
    memcpy(f.raw, data[0].data, std::min(sizeof(f.raw), sizeof(data[0].data)));
    DS_ALWAYS("Mag x:{} y:{} z:{}", f.mag.x, f.mag.y, f.mag.z);
    }

    }

     

    Vincent
    Community Moderator
    Community Moderator

    Can you print out the frame header which you parse error to cause the function exited?

    Your implementation looks fine and our API is considering all possible FIFO frame header situation in our API code. 

    It will only finish parsing if they met 0x8080 as padding bytes under FIFO header mode. 

    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