Bosch Sensortec Community

    Showing results for 
    Search instead for 
    Did you mean: 

    BHI260AP Calibration Problem

    BHI260AP Calibration Problem

    New Poster

    Hello, I have a problem to calibrate BHI260AP.

    I got the calibration profile with uint8_t array from bhy2_get_calibration_profile.


    I tried to adapt the calibration to the sensor before getting data, but it looks that it doesn't work.

    The reason that I say like it is,


    The arrays from bhy2_get_calibration_profile "before bhy2_set_calibration_profile" and "after bhy2_set_calibration_profile" is same.

    And the adapted calib_profile and the array "after bhy2_set_calibration_profile" is different. I thought that those two must be same before getting data.


    I leave the code under the question. calib_acc is calib profile to adapt, readed_acc is sensor's profile after adapted.

    I modified the example quartonian.c

    How can I solve this problem?

    Best regard,


    setup_interfaces(true, intf); /* Perform a power on reset */
    printf("INITIALIZE BHY\n");

    #ifdef BHY2_USE_I2C
    rslt = bhy2_init(BHY2_I2C_INTERFACE, bhy2_i2c_read, bhy2_i2c_write, bhy2_delay_us, BHY2_RD_WR_LEN, NULL, &bhy2);
    rslt = bhy2_init(BHY2_SPI_INTERFACE, bhy2_spi_read, bhy2_spi_write, bhy2_delay_us, BHY2_RD_WR_LEN, NULL, &bhy2);
    printf("INITIALIZE BHY ERR %d\n",rslt);
    print_api_error(rslt, &bhy2);

    rslt = bhy2_soft_reset(&bhy2);
    print_api_error(rslt, &bhy2);
    printf("bhy2_soft_reset %d\n", rslt);

    rslt = bhy2_get_product_id(&product_id, &bhy2);
    print_api_error(rslt, &bhy2);
    printf("bhy2_get_product_id %d\n", rslt);

    /* Check for a valid product ID */
    if (product_id != BHY2_PRODUCT_ID)
    printf("Product ID read %X. Expected %X\r\n", product_id, BHY2_PRODUCT_ID);
    printf("BHI260/BHA260 found. Product ID read %X\r\n", product_id);


    /* Check the interrupt pin and FIFO configurations. Disable status and debug */
    hintr_ctrl = BHY2_ICTL_DISABLE_DEBUG;

    hintr_ctrl = 0;

    rslt = bhy2_set_host_interrupt_ctrl(hintr_ctrl, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_get_host_interrupt_ctrl(&hintr_ctrl, &bhy2);
    print_api_error(rslt, &bhy2);

    printf("Host interrupt control\r\n");
    printf(" Wake up FIFO %s.\r\n", (hintr_ctrl & BHY2_ICTL_DISABLE_FIFO_W) ? "disabled" : "enabled");
    printf(" Non wake up FIFO %s.\r\n", (hintr_ctrl & BHY2_ICTL_DISABLE_FIFO_NW) ? "disabled" : "enabled");
    printf(" Status FIFO %s.\r\n", (hintr_ctrl & BHY2_ICTL_DISABLE_STATUS_FIFO) ? "disabled" : "enabled");
    printf(" Debugging %s.\r\n", (hintr_ctrl & BHY2_ICTL_DISABLE_DEBUG) ? "disabled" : "enabled");
    printf(" Fault %s.\r\n", (hintr_ctrl & BHY2_ICTL_DISABLE_FAULT) ? "disabled" : "enabled");
    printf(" Interrupt is %s.\r\n", (hintr_ctrl & BHY2_ICTL_ACTIVE_LOW) ? "active low" : "active high");
    printf(" Interrupt is %s triggered.\r\n", (hintr_ctrl & BHY2_ICTL_EDGE) ? "pulse" : "level");
    printf(" Interrupt pin drive is %s.\r\n", (hintr_ctrl & BHY2_ICTL_OPEN_DRAIN) ? "open drain" : "push-pull");

    /* Configure the host interface */
    hif_ctrl = 0;
    rslt = bhy2_set_host_intf_ctrl(hif_ctrl, &bhy2);
    print_api_error(rslt, &bhy2);

    /* Check if the sensor is ready to load firmware */
    rslt = bhy2_get_boot_status(&boot_status, &bhy2);
    print_api_error(rslt, &bhy2);

    if (boot_status & BHY2_BST_HOST_INTERFACE_READY)
    upload_firmware(boot_status, &bhy2);

    rslt = bhy2_get_kernel_version(&version, &bhy2);
    print_api_error(rslt, &bhy2);
    if ((rslt == BHY2_OK) && (version != 0))
    printf("Boot successful. Kernel version %u.\r\n", version);

    rslt = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT, parse_meta_event, NULL, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_register_fifo_parse_callback(BHY2_SYS_ID_META_EVENT_WU, parse_meta_event, NULL, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_register_fifo_parse_callback(QUAT_SENSOR_ID, parse_quaternion, NULL, &bhy2);
    print_api_error(rslt, &bhy2);

    rslt = bhy2_get_and_process_fifo(work_buffer, WORK_BUFFER_SIZE, &bhy2);
    print_api_error(rslt, &bhy2);
    printf("Host interface not ready. Exiting\r\n");


    return 0;

    char* file_acc = "/home/unistrrel/COINES/v2.7.0/examples/bhy2/examples/euler_cal/calib_acc_f.txt";
    char* file_gyro = "/home/unistrrel/COINES/v2.7.0/examples/bhy2/examples/euler_cal/calib_gyro_f.txt";
    char* file_mag = "/home/unistrrel/COINES/v2.7.0/examples/bhy2/examples/euler_cal/calib_mag_f.txt";
    char* file_sic = "/home/unistrrel/COINES/v2.7.0/examples/bhy2/examples/euler_cal/sic_mat_f.txt";

    FILE* f_acc;
    FILE* f_gyro;
    FILE* f_mag;
    FILE* f_sic;
    f_acc = fopen(file_acc, "r");
    f_gyro = fopen(file_gyro, "r");
    f_mag = fopen(file_mag, "r");
    f_sic = fopen(file_sic, "r");
    char read_acc[300];
    char read_gyro[1000];
    char read_mag[2000];
    char read_sic[300];
    fgets(read_acc, 300, f_acc);
    fgets(read_gyro, 1000, f_gyro);
    fgets(read_mag, 2000, f_mag);
    fgets(read_sic, 300, f_sic);


    char* mat_acc = strtok(read_acc, " ");
    for (int i = 0; i < 72; i++) {
    calib_acc[i] = atoi(mat_acc);
    mat_acc = strtok(NULL, " ");
    char* mat_gyro = strtok(read_gyro, " ");
    for (int i = 0; i < 200; i++) {
    calib_gyro[i] = atoi(mat_gyro);
    mat_gyro = strtok(NULL, " ");
    char* mat_mag = strtok(read_mag, " ");
    for (int i = 0; i < 408; i++) {
    calib_mag[i] = atoi(mat_mag);
    mat_mag = strtok(NULL, " ");
    char* mat_sic = strtok(read_sic, " ");
    for (int i = 0; i < 72; i++) {
    calib_sic[i] = atoi(mat_sic);
    mat_sic = strtok(NULL, " ");

    rslt = bhy2_set_calibration_profile(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, calib_acc, 72, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_set_calibration_profile(BHY2_PHYS_SENSOR_ID_GYROSCOPE, calib_gyro, 200, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_set_calibration_profile(BHY2_PHYS_SENSOR_ID_MAGNETOMETER, calib_mag, 408, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_set_sic_matrix(calib_sic, 72, &bhy2);
    print_api_error(rslt, &bhy2);


    /* Update the callback table to enable parsing of sensor data */
    rslt = bhy2_update_virtual_sensor_list(&bhy2);
    print_api_error(rslt, &bhy2);

    float sample_rate = 100.0; /* Read out data measured at 100Hz */
    uint32_t report_latency_ms = 0; /* Report immediately */
    rslt = bhy2_set_virt_sensor_cfg(QUAT_SENSOR_ID, sample_rate, report_latency_ms, &bhy2);
    print_api_error(rslt, &bhy2);

    uint8_t init_readed_acc[72];
    uint32_t act_len = 200;
    uint8_t readed_acc[72];

    rslt = bhy2_get_calibration_profile(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, init_readed_acc, 72, &act_len, &bhy2);
    rslt = bhy2_get_calibration_profile(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, readed_acc, 72, &act_len, &bhy2);
    print_api_error(rslt, &bhy2);

    for (int i = 0; i < 72; i++)
    printf("[%d]: %d %d\n", i, calib_acc[i], readed_acc[i]);



    2 REPLIES 2

    Community Moderator
    Community Moderator

    Hi Erion,

    In callback function, you can call bhy2_get_calibration_profile() function to save calibration profile until accuracy reach to 3.
    After next power on, you can call bhy2_set_calibration_profile() function to set previous saved calibration profile to BHI260.
    I uploaed a example on STM32 for your reference. I hope it will be helpful for you.

    Established Member

    We warm start the BHI260AP with calibration profile that we already saved when Acc and Gyro accuracies were 3. I have a few followup questions:

    - In running mode, the gyroscope accuracy drops to 2 or even 1 when the system is stationary for a few seconds, it may not go to 3 if shortly after drop the system moves. On the other hand Acceleromeyer accuracy drops to 1 when the system slowly tilts along roll or pitch angle to ~50 deg. I think these motions tricks the sensor that a calibration procedure is going on. We have also observed that calibration profile changes exactly when accuracy value switches. How can we disable the calibration such that the sensor only uses the already loaded profile ?

    - At different time or in slighly different environmental conditions, the warm-start does not make the accuracy to initialize to 3. However, we are no longer able to perform another round of proper 6 orientation calibration. How much error on Roll/Pitch we should tolerate in these conditions?

    - As mentioned in the application note "bst-bhi260_bhi360-an002.pdf", Roll/Pitch Dynamic accuracy is max 10deg when the sensor is well calibrated. Is there quantitative performance indicator like that for other accuracy levels?