Bosch Sensortec Community

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

    BHI260 - Calibration State - BSX Algorithm Parameters

    BHI260 - Calibration State - BSX Algorithm Parameters

    btruden_henway
    Long-established Member

    Hi,

    I'm working with a BHI260 chip. As a host, I'm using an STM32L433 microcontroller. I don't use the BHY API on the host, I've written my own communication code.

    I've successfully uploaded the firmware to the BHI, and I'm also successfully getting the Gravity and Game Rotation Vector measurements at 25Hz.

    Now I want to get the calibration state of the accelerometer and the gyroscope. According to the datasheet, to get that information I have to send the Get Parameter Status Command (Section 13.3 in the datasheet) following the Host Command Protocol (Section 4.4 in the datasheet).

    The parameters that I have to read are 0x0201 and 0x0203 as shown below:

    btruden_henway_0-1645816890728.png

    As indicated in the 3rd column of the table, the accelerometer, and gyroscope content is returned inside a BSX State Exchange Structure. According to the datasheet, this is the format:

    btruden_henway_2-1645817629315.png

    So, If I send the Parameter Status Command [0x1201] (The first "1" of the 0x1201 os for indicating the "Read" operation) I should expect to get the calibration state value of the accelerometer within the Block data of the BSX State Exchange Structure sent by the BHI chip on the response of my command (taken from the Status and Debug FIFO).

    But unfortunately, in the datasheet, there's no definition of how's the data arranged within the Block data. So I don't know exactly which byte of the Block Data is telling me the calibration state of the accelerometer.

    Here I have the real measurements. I send the Parameter Status Command [0x1201] and I get the following data from the BHI chip:

    btruden_henway_1-1645820540077.png

    BlockData[0]:   0x1	
    BlockData[1]:   0x50	
    BlockData[2]:   0x0	
    BlockData[3]:   0x4	
    BlockData[4]:   0x7f	
    BlockData[5]:   0x90	
    BlockData[6]:   0x1	
    BlockData[7]:   0x40	
    BlockData[8]:   0x6	
    BlockData[9]:   0x0	
    BlockData[10]:  0x6f	
    BlockData[11]:  0x0	
    BlockData[12]:  0x0	
    BlockData[13]:  0x0	
    BlockData[14]:  0xff	
    BlockData[15]:  0x0	
    BlockData[16]:  0x0	
    BlockData[17]:  0x0	
    BlockData[18]:  0xb	
    BlockData[19]:  0x0	
    BlockData[20]:  0x10	
    BlockData[21]:  0x0	
    BlockData[22]:  0x0	
    BlockData[23]:  0x1	
    BlockData[24]:  0x0	
    BlockData[25]:  0x0	
    BlockData[26]:  0x0	
    BlockData[27]:  0x0	
    BlockData[28]:  0x0	
    BlockData[29]:  0x0	
    BlockData[30]:  0x0	
    BlockData[31]:  0x0	
    BlockData[32]:  0x0	
    BlockData[33]:  0x0	
    BlockData[34]:  0xb	
    BlockData[35]:  0x0	
    BlockData[36]:  0x8	
    BlockData[37]:  0x0	
    BlockData[38]:  0x0	
    BlockData[39]:  0x4	
    BlockData[40]:  0x0	
    BlockData[41]:  0x0	
    BlockData[42]:  0xb	
    BlockData[43]:  0x0	
    BlockData[44]:  0x58	
    BlockData[45]:  0x0	
    BlockData[46]:  0x0	
    BlockData[47]:  0x9	
    BlockData[48]:  0x0	
    BlockData[49]:  0x0	
    BlockData[50]:  0x0	
    BlockData[51]:  0x0	
    BlockData[52]:  0x0	
    BlockData[53]:  0x0	
    BlockData[54]:  0x0	
    BlockData[55]:  0x0	
    BlockData[56]:  0x0	
    BlockData[57]:  0x0	
    BlockData[58]:  0x0	
    BlockData[59]:  0x0		
    BlockData[60]:  0x0		
    BlockData[61]:  0x0		
    BlockData[62]:  0x0		
    BlockData[63]:  0x0

     

    Which of the Block Data bytes (0 to 63) contains the accelerometer calibration state?

    Thanks!

    7 REPLIES 7

    BSTRobin
    Community Moderator
    Community Moderator

    Hello btruden_henway,

    Did you use BHI260AB or BHI260AP?

    btruden_henway
    Long-established Member

    Hi BSTRobin,

    I used BHI260AB.

    BR

    Hello btruden_henway,

    You could get sensor calibration status from the following example code.

    BHY2_ASSERT(bhy2_register_fifo_parse_callback(BHY2_SENSOR_ID_ACC, parse_3axis_s16, &parse_table, &bhy2));
    BHY2_ASSERT(bhy2_register_fifo_parse_callback(BHY2_SENSOR_ID_GYRO, parse_3axis_s16, &parse_table, &bhy2));

    void parse_3axis_s16(const struct bhy2_fifo_parse_data_info *callback_info, void *callback_ref)
    {
    struct bhy2_data_xyz data;
    uint32_t s, ns;

    if (callback_ref)
    {
    struct parse_ref *parse_table = (struct parse_ref*)callback_ref;
    verbose = *(parse_table->verbose);
    float scaling_factor;

    scaling_factor = parse_table->sensor[callback_info->sensor_id].scaling_factor;

    bhy2_parse_xyz(callback_info->data_ptr, &data);

    time_to_s_ns(*callback_info->time_stamp, &s, &ns);

    INFO("SID: %u; T: %u.%09u; x: %f, y: %f, z: %f; acc: %u\r\n",
    callback_info->sensor_id,
    s,
    ns,
    data.x * scaling_factor,
    data.y * scaling_factor,
    data.z * scaling_factor,
    parse_table->sensor[callback_info->sensor_id].accuracy);
    }
    else
    {
    ERROR("Null reference\r\r\n");
    }
    }

    btruden_henway
    Long-established Member

    Hi BSTRobin,

    I've studied the API in search of the calibration state in the BSX Algorithm Parameters. 

    The function that gets the BSX State Exchange Structure is the following:

    /**
     * @brief Function to get the calibration profile of a BSX virtual sensor
     * @param[in] sensor_id     : Sensor ID of the virtual sensor
     * @param[out] calib_prof   : Reference to the data buffer to store the calibration profile
     * @param[in] prof_len      : Length of the data buffer
     * @param[out] actual_len   : Actual length of the calibration profile
     * @param[in] dev           : Device reference
     * @return API error codes
     */
    int8_t bhy2_get_calibration_profile(uint8_t sensor_id,
                                        uint8_t *calib_prof,
                                        uint16_t prof_len,
                                        uint32_t *actual_len,
                                        struct bhy2_dev *dev);

     The implementation is the following:

    int8_t bhy2_get_calibration_profile(uint8_t sensor_id,
                                        uint8_t *calib_prof,
                                        uint16_t prof_len,
                                        uint32_t *actual_len,
                                        struct bhy2_dev *dev)
    {
        int8_t rslt = BHY2_OK;
    
        if ((dev == NULL) || (calib_prof == NULL) || (actual_len == NULL))
        {
            rslt = BHY2_E_NULL_PTR;
        }
        else
        {
            rslt = bhy2_hif_get_bsx_state((uint16_t)(BHY2_PARAM_CALIB_STATE_BASE | sensor_id),
                                          calib_prof,
                                          prof_len,
                                          actual_len,
                                          &dev->hif);
        }
    
        return rslt;
    }

    It calls the bhy2_hif_get_bsx_state function. Below are the details about that function:

    /**
     * @brief Function to get the BSX state of a BSX parameter
     * @param[in] param_id      : Parameter ID of the BSX parameter
     * @param[out] bsx_state    : Reference to teh data buffer to store the BSX state
     * @param[in] state_len     : Length of the buffer
     * @param[out] actual_len   : Actual length of the BSX state
     * @param[in] hif           : HIF device reference
     * @return API error codes
     */
    int8_t bhy2_hif_get_bsx_state(uint16_t param_id,
                                  uint8_t *bsx_state,
                                  uint32_t state_len,
                                  uint32_t *actual_len,
                                  struct bhy2_hif_dev *hif);

    The implementation:

    int8_t bhy2_hif_get_bsx_state(uint16_t param_id,
                                  uint8_t *bsx_state,
                                  uint32_t state_len,
                                  uint32_t *actual_len,
                                  struct bhy2_hif_dev *hif)
    {
        uint8_t complete_flag = 0;
        uint8_t section_num = 0;
        uint16_t tmp_state_len = 0;
        uint32_t read_len;
        int8_t rslt;
        uint8_t tmp_bsx_state_buf[BHY2_BSX_STATE_STRUCT_LEN];
    
        while (complete_flag == 0)
        {
            rslt = bhy2_hif_get_parameter(param_id, tmp_bsx_state_buf, BHY2_BSX_STATE_STRUCT_LEN, &read_len, hif);
            if (rslt != BHY2_OK)
            {
                break;
            }
    
            if (read_len != BHY2_BSX_STATE_STRUCT_LEN)
            {
                rslt = BHY2_E_INVALID_PARAM;
                break;
            }
    
            complete_flag = tmp_bsx_state_buf[0] & BHY2_BSX_STATE_TRANSFER_COMPLETE;
            section_num = tmp_bsx_state_buf[0] & 0x7F;
            tmp_state_len = BHY2_LE2U16(&tmp_bsx_state_buf[2]);
            if (tmp_state_len == 0)
            {
                rslt = BHY2_E_INVALID_PARAM;
                break;
            }
    
            *actual_len = tmp_state_len; /* Report actual length, in case of invalid buffer */
    
            if (state_len < tmp_state_len)
            {
                rslt = BHY2_E_BUFFER;
                break;
            }
            memcpy(&bsx_state[section_num * BHY2_BSX_STATE_BLOCK_LEN], &tmp_bsx_state_buf[4], tmp_bsx_state_buf[1]);
        }
    
        return rslt;
    }

    As you can see, in the end, it copies (using the memcpy function) the raw blocks of data taken from the BSX State Exchange Structure into the given buffer (in this case the bsx_state buffer).

    But the problem is that it doesn't parse the final buffer. So I can't see how it should be done. 

    And again, it's not explained on the datasheet.

    Please, if it's necessary, elevate this question to reach a deeper level of support, since it seems to be some information missing.

    In addition, if you have some code example that uses the  bhy2_get_calibration_profile() function and that parses the returned buffer of data, it would be useful as well.

    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