Bosch Sensortec Community

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

    Requirements to get Euler Angles from BHI260AP

    Requirements to get Euler Angles from BHI260AP

    monbot
    Member

    I would like to get euler angles from the BHI260AP sensor using only the built in acc/gyro sensor.

    1. In the datasheet (Table 88, p119), it is explained that an external magnetic sensor is required to obtain Euler angles.
    Is the magnetic sensor mandatory?

    monbot_0-1672972990524.png


    2. If I only use the built-in sensor, which firmware should I use?
    Can I use the firmware below?
    https://github.com/boschsensortec/BHY2-Sensor-API/blob/master/firmware/bhi260ap/BHI260AP.fw.h

    5 REPLIES 5

    BSTRobin
    Community Moderator
    Community Moderator

    Hi monbot,

    If you only use acce, gyro on hardware. You could't use orientation virtual sensor ID, because orientation virtual sensor ID require 9doF(accel, gyro, mag). But you could use game rotation vector which require 6doF(accel, gyro).

    For choosing to load firmware, you can refer to the following code.
    #define BHI260_6DOF
    //#define BHI260_BMM150_9DOF
    //#define BHI260_SELF_LEARNING
    //#define BHI260_PDR

    #if defined(BHI260_BMM150_9DOF)
    #include "firmware/bhi260ap/BHI260AP_BMM150.fw.h"//BHI260AP+BMM150, AUX interface
    #elif defined(BHI260_6DOF)
    #include "firmware/bhi260ap/BHI260AP.fw.h"//BHI260AP without BMM150
    #elif defined(BHI260_SELF_LEARNING)
    #include "firmware/bhi260ap_klio/BHI260AP_klio.fw.h"//BHI260AP klio
    #elif defined(BHI260_PDR)
    #include "firmware/bhi260ap_pdr/BHI260AP_PDR.fw.h"//BHI260AP PDR
    #endif

    To get euler angles data with 6doF(accel, gyro), you could refer the example code like this.

    rslt = bhy2_register_fifo_parse_callback(BHY2_SENSOR_ID_GAMERV, parse_quaternion, (void*)&gamerv_accuracy, &bhy2);
    print_api_error(rslt, &bhy2);
    rslt = bhy2_set_virt_sensor_cfg(BHY2_SENSOR_ID_GAMERV, sample_rate, report_latency_ms, &bhy2);
    print_api_error(rslt, &bhy2);
    PDEBUG("Enable %s at %.2fHz.\r\n", get_sensor_name(BHY2_SENSOR_ID_GAMERV), sample_rate);

    You could get quaternion data in parse_quaternion() callback fuction. Then you could convert quaternion data to euler angles data by yourself.

    Thank you for answer.
    I have an additional question.

    Does the calibration of the internal sensors (acc/gyro) happen automatically on the BHI260AP module at boot time?

    If a user applies (mounts) the BHI260AP module to a custom board,
    does the user need to calibrate to obtain angle (game rotation vector) information?

    I couldn't find the command to run the calibration in the datasheet.

    BSTRobin
    Community Moderator
    Community Moderator

    Hi monbot,

    Calibration was automatically run on BHI260AP firmware. You could refer the following example code to use it. In callback function, wait until accuracy reachs to 3, then get calibration profile and save it. Call bhy2_set_calibration_profile() function to set calibration profile after next power on start.

    uint8_t bhi260_calib_prof[512];
    uint16_t bhi260_prof_len = 512;
    uint16_t acc_prof_len = 72;
    const uint8_t acc_calib_prof[72] = {0x01,0x52,0x00,0x04,0x7f,0x30,0x01,0x40,0x04,0x00,0x6f,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x0b,0x80,0x10,0xbf,0x00,0x01,0x00,0x00,0xf0,0xa2,0x00,0x42,0x00,0x41,0x00,0x03,0x0b,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x06,0x80,0x10,0xbf,0x00,0x01,0x00,0x00,0xf0,0xa2,0x00,0x42,0x00,0x41,0x00,0x03,0x06,0x00,0x08,0x00,0x00,0x02,0x00,0x3e,0x00,0x00,0x20,0x00,0x48,0x00};
    uint16_t gyro_prof_len = 200;
    const uint8_t gyro_calib_prof[200] = {0x01,0x52,0x00,0x04,0x7f,0xb0,0x01,0x40,0x0e,0x00,0x6f,0x00,0x00,0x00,0xff,0x00,0x00,0x54,0x0c,0x38,0x10,0xbf,0x3c,0x01,0xd0,0xd4,0x40,0xe1,0x09,0xc0,0x90,0xc0,0x00,0x03,0x0c,0x00,0x08,0x00,0x00,0x02,0x00,0xf4,0x0c,0x2f,0x10,0xbf,0x69,0x04,0x71,0x47,0x42,0xe0,0xf2,0xc0,0x11,0xc0,0x00,0x00,0x0c,0x80,0x08,0x3f,0x00,0x07,0x00,0x54,0x0c,0x38,0x10,0xbf,0x3c,0x08,0xd0,0xd4,0x40,0xe1,0x09,0xc0,0x90,0xc0,0x00,0x76,0x0c,0x80,0x10,0xbf,0xe3,0x09,0x75,0x76,0x45,0xf7,0x9f,0xc0,0x02,0xc0,0x00,0x44,0x0c,0x21,0x10,0x3f,0xa7,0x0a,0x34,0xb0,0xb9,0xc2,0x26,0xc0,0x94,0xbf,0x00,0x47,0x0c,0x29,0x10,0xc0,0x4d,0x0b,0x28,0x1e,0x97,0x15,0x96,0xc1,0xb8,0xc0,0x00,0x5d,0x0c,0x11,0x10,0x40,0x45,0x0c,0x17,0xea,0x44,0x8e,0x90,0xc0,0x26,0x3e,0x00,0x08,0x0c,0x00,0x08,0x00,0x00,0x0d,0x00,0x08,0x0c,0x00,0x08,0x00,0x00,0x0e,0x00,0x00,0x0c,0x20,0x08,0x41,0x00,0x0f,0x00,0x54,0x07,0x38,0x10,0xbf,0x3c,0x01,0xd0,0xd4,0x40,0xe1,0x09,0xc0,0x90,0xc0,0x00,0x03,0x07,0x00,0x08,0x00,0x00,0x02,0x00,0x94,0x00,0x00,0x21,0x00,0x7e,0x00};


    rslt = bhy2_register_fifo_parse_callback(BHY2_SENSOR_ID_ACC_WU, parse_acc_gyro_mag_3axis_s16, (void*)&acc_accuracy, &bhy2);
    print_api_error(rslt, &bhy2);

    rslt = bhy2_register_fifo_parse_callback(BHY2_SENSOR_ID_GYRO_WU, parse_acc_gyro_mag_3axis_s16, (void*)&gyro_accuracy, &bhy2);
    print_api_error(rslt, &bhy2);

    //bhy2_set_calibration_profile(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, acc_calib_prof, acc_prof_len, &bhy2);
    rslt = bhy2_set_virt_sensor_cfg(BHY2_SENSOR_ID_ACC_WU, sample_rate, report_latency_ms, &bhy2);
    print_api_error(rslt, &bhy2);
    PDEBUG("Enable %s at %.2fHz.\r\n", get_sensor_name(BHY2_SENSOR_ID_ACC_WU), sample_rate);

    //bhy2_set_calibration_profile(BHY2_PHYS_SENSOR_ID_GYROSCOPE, gyro_calib_prof, gyro_prof_len, &bhy2);
    rslt = bhy2_set_virt_sensor_cfg(BHY2_SENSOR_ID_GYRO_WU, sample_rate, report_latency_ms, &bhy2);
    print_api_error(rslt, &bhy2);
    PDEBUG("Enable %s at %.2fHz.\r\n", get_sensor_name(BHY2_SENSOR_ID_GYRO_WU), sample_rate);


    static void parse_acc_gyro_mag_3axis_s16(const struct bhy2_fifo_parse_data_info *callback_info, void *callback_ref)
    {
    struct bhy2_data_xyz data;
    int i;
    uint32_t actual_len;
    uint8_t *accuracy = (uint8_t*)callback_ref;

    if (accuracy)
    {
    bhy2_parse_xyz(callback_info->data_ptr, &data);

    if(callback_info->sensor_id == BHY2_SENSOR_ID_ACC_WU)
    {
    PDEBUG(",ACC,x,%d,y,%d,z,%d,accuracy,%u\r\n",
    data.x,
    data.y,
    data.z,
    *accuracy);
    if(*accuracy == 3)
    {
    memset(bhi260_calib_prof, 0, sizeof(bhi260_calib_prof));
    actual_len = 0;
    bhy2_get_calibration_profile(BHY2_PHYS_SENSOR_ID_ACCELEROMETER, bhi260_calib_prof, bhi260_prof_len, &actual_len, &bhy2);
    PDEBUG("BHY2_PHYS_SENSOR_ID_ACCELEROMETER profile----------------------------bhi260_prof_len=%d, actual_len=%d---------------------\r\n", bhi260_prof_len, actual_len);
    for(i=0; i < actual_len; i++)
    {
    PDEBUG("0x%02x,", bhi260_calib_prof[i]);
    }
    PDEBUG("\r\n");
    }
    }
    else if(callback_info->sensor_id == BHY2_SENSOR_ID_GYRO_WU)
    {
    PDEBUG(",GYRO,x,%d,y,%d,z,%d,accuracy,%u\r\n",
    data.x,
    data.y,
    data.z,
    *accuracy);
    if(*accuracy == 3)
    {
    memset(bhi260_calib_prof, 0, sizeof(bhi260_calib_prof));
    actual_len = 0;
    bhy2_get_calibration_profile(BHY2_PHYS_SENSOR_ID_GYROSCOPE, bhi260_calib_prof, bhi260_prof_len, &actual_len, &bhy2);
    PDEBUG("BHY2_PHYS_SENSOR_ID_GYROSCOPE profile----------------------------bhi260_prof_len=%d, actual_len=%d---------------------\r\n", bhi260_prof_len, actual_len);
    for(i=0; i < actual_len; i++)
    {
    PDEBUG("0x%02x,", bhi260_calib_prof[i]);
    }
    PDEBUG("\r\n");
    }
    }
    else if(callback_info->sensor_id == BHY2_SENSOR_ID_MAG_WU)
    {
    PDEBUG(",MAG,x,%d,y,%d,z,%d,accuracy,%u,\r\n",
    data.x,
    data.y,
    data.z,
    *accuracy);
    if(*accuracy == 3)
    {
    memset(bhi260_calib_prof, 0, sizeof(bhi260_calib_prof));
    actual_len = 0;
    bhy2_get_calibration_profile(BHY2_PHYS_SENSOR_ID_MAGNETOMETER, bhi260_calib_prof, bhi260_prof_len, &actual_len, &bhy2);
    PDEBUG("BHY2_PHYS_SENSOR_ID_MAGNETOMETER profile----------------------------bhi260_prof_len=%d, actual_len=%d---------------------\r\n", bhi260_prof_len, actual_len);
    for(i=0; i < actual_len; i++)
    {
    PDEBUG("0x%02x,", bhi260_calib_prof[i]);
    }
    PDEBUG("\r\n");
    }
    }

    }
    else
    {
    PDEBUG("Null reference\r\r\n");
    }
    }

     

    By the way, would you like to design a product with BHI260AP?

    Thank you for answer.


    1. By the way, would you like to design a product with BHI260AP?
    ==> Yes. First of all, we are going to evaluate the BHI260AP shuttle board 3.0 by connecting it to our custom AP board through SPI I/F. Then, if there is no problem, we will apply the BHI260AP chip to our products.

     

    2. If calibration is done automatically, isn't the result (calibration profile) also applied automatically?
    I may have misunderstood as I am new to IMU sensors.

    Is my understanding correct?
    - Calibration is automatically executed in the BHI260AP firmware.
    - However, the calibration result is not automatically applied.
    - Therefore, it is necessary to get the calibration result from the BHI260AP chip, save it to the AP board, and apply it to BHI260AP chip, whenever booting.

    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