Bosch Sensortec Community

    SOLVED

    BHI160b Shuttle Board with STM32

    Highlighted
    Established Member

    BHI160b Shuttle Board with STM32

    Hi,

    i am trying to read quaternion's out of the BHI160b, that's why i purchased the BHI160b shuttle Board from Bosch. I want to connect it with my NUCLEO-F411RE from STM. So i implemented the library into my STM project. The next step was to figure out how to use the HAL_I2C functions to communicate with the sensor. I changed the read/write operations in the driver's file bhy_support.c like this:

    uint8_t GTXBuffer[256];
    
    int8_t SensorAPI_I2Cx_Read(uint8_t slave_address7, uint8_t subaddress, uint8_t *pBuffer, uint16_t ReadNumbr)
    {
    uint16_t DevAddress = slave_address7 << 1;
    
    // send register address
    HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, &subaddress, 1, BUS_TIMEOUT);
    HAL_I2C_Master_Receive(&I2C_HANDLE, DevAddress, pBuffer, ReadNumbr, BUS_TIMEOUT);
    return 0;
    }
    
    int8_t SensorAPI_I2Cx_Write(uint8_t slave_address7, uint8_t subaddress, uint8_t *pBuffer, uint16_t WriteNumbr)
    {
    uint16_t DevAddress = slave_address7 << 1;
    
    GTXBuffer[0] = subaddress;
    memcpy(&GTXBuffer[1], pBuffer, WriteNumbr);
    
    // send register address
    HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, GTXBuffer, WriteNumbr+1, BUS_TIMEOUT);
    return 0;
    }

    I connected the Shuttle Board to my NUCLEO board like this:

    ShuttleBoard Connector.png

    ___J1___|___NUCLEO___
       1/2  |    3.3V
        3   |    GND
       17   |    PB7 -> I2C1_SCL
       18   |    PB6 -> I2C1_SDA 
       21   |    PB5 -> DI/BHI160_INT

    In my main loop i startet to initialize BHI160 Sensor with the function bhy_initialize_support();:

    int main(void)
    {
      /* MCU Configuration--------------------------------------------------------*/
    
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_I2C1_Init();
    
      /* USER CODE BEGIN 2 */
    
      bhy_initialize_support();
    
      /* USER CODE END 2 */
    
      while (1)
      {
                /* USER CODE END WHILE */
    	  int8_t ret;
    
    	      /* BHY Variable*/
    	      uint8_t                    *fifoptr           = NULL;
    	      uint8_t                    bytes_left_in_fifo = 0;
    	      uint16_t                   bytes_remaining    = 0;
    	      uint16_t                   bytes_read         = 0;
    	      bhy_data_generic_t         fifo_packet;
    	      bhy_data_type_t            packet_type;
    	      BHY_RETURN_FUNCTION_TYPE   result;
    
    	      /* the remapping matrix for BHA or BHI here should be configured according to its placement on customer's PCB. */
    	      /* for details, please check 'Application Notes Axes remapping of BHA250(B)/BHI160(B)' document. */
    	      int8_t                     bhy_mapping_matrix_config[3*3] = {0,1,0,-1,0,0,0,0,1};
    	      /* the remapping matrix for Magnetometer should be configured according to its placement on customer's PCB.  */
    	      /* for details, please check 'Application Notes Axes remapping of BHA250(B)/BHI160(B)' document. */
    	      int8_t                     mag_mapping_matrix_config[3*3] = {0,1,0,1,0,0,0,0,-1};
    	      /* the sic matrix should be calculated for customer platform by logging uncalibrated magnetometer data. */
    	      /* the sic matrix here is only an example array (identity matrix). Customer should generate their own matrix. */
    	      /* This affects magnetometer fusion performance. */
    	      float sic_array[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
    
    		/* To get the customized version number in firmware, it is necessary to read Parameter Page 2, index 125 */
    	    /* to get this information. This feature is only supported for customized firmware. To get this customized */
    	    /* firmware, you need to contact your local FAE of Bosch Sensortec. */
    	    //struct cus_version_t      bhy_cus_version;
    
    		while (HAL_GPIO_ReadPin(BHI160_INT_GPIO_Port, BHI160_INT_Pin) == GPIO_PIN_RESET);
    	    /* init the bhy chip */
    	    if(bhy_driver_init(&bhy1_fw))
    	    {
    	        //DEBUG("Fail to init bhy\n");
    	    }
    
    	    /* wait for the bhy trigger the interrupt pin go down and up again */
    
    		//while (HAL_GPIO_ReadPin(BHI160_INT_GPIO_Port, BHI160_INT_Pin) == GPIO_PIN_SET);
    
    	    HAL_Delay(100);
    
    		while (HAL_GPIO_ReadPin(BHI160_INT_GPIO_Port, BHI160_INT_Pin) == GPIO_PIN_RESET);
    
    	    /* To get the customized version number in firmware, it is necessary to read Parameter Page 2, index 125 */
    	    /* to get this information. This feature is only supported for customized firmware. To get this customized */
    	    /* firmware, you need to contact your local FAE of Bosch Sensortec. */
    	    //bhy_read_parameter_page(BHY_PAGE_2, PAGE2_CUS_FIRMWARE_VERSION, (uint8_t*)&bhy_cus_version, sizeof(struct cus_version_t));
    	    //DEBUG("cus version base:%d major:%d minor:%d\n", bhy_cus_version.base, bhy_cus_version.major, bhy_cus_version.minor);
    
    	    /* the remapping matrix for BHI and Magmetometer should be configured here to make sure rotation vector is */
    	    /* calculated in a correct coordinates system. */
    	    bhy_mapping_matrix_set(PHYSICAL_SENSOR_INDEX_ACC, bhy_mapping_matrix_config);
    	    bhy_mapping_matrix_set(PHYSICAL_SENSOR_INDEX_MAG, mag_mapping_matrix_config);
    	    bhy_mapping_matrix_set(PHYSICAL_SENSOR_INDEX_GYRO, bhy_mapping_matrix_config);
    	    /* This sic matrix setting affects magnetometer fusion performance. */
    	    bhy_set_sic_matrix(sic_array);
    
    	    /* install the callback function for parse fifo data */
    	    if(bhy_install_sensor_callback(VS_TYPE_ROTATION_VECTOR, VS_WAKEUP, sensors_callback_rotation_vector))
    	    {
    	        //DEBUG("Fail to install sensor callback\n");
    	    }
    
    	    /* enables the virtual sensor */
    	    if(bhy_enable_virtual_sensor(VS_TYPE_ROTATION_VECTOR, VS_WAKEUP, ROTATION_VECTOR_SAMPLE_RATE, 0, VS_FLUSH_NONE, 0, 0))
    	    {
    	        //DEBUG("Fail to enable sensor id=%d\n", VS_TYPE_ROTATION_VECTOR);
    	    }
    
    
    
    	    /* continuously read and parse the fifo */
    	    while (1)
    	    {
    
    	        /* wait until the interrupt fires */
    	        /* unless we already know there are bytes remaining in the fifo */
    	        while (!HAL_GPIO_ReadPin(BHI160_INT_GPIO_Port, BHI160_INT_Pin) && !bytes_remaining)
    	        {
    	        }
    
    	        bhy_read_fifo(fifo + bytes_left_in_fifo, FIFO_SIZE - bytes_left_in_fifo, &bytes_read, &bytes_remaining);
    	        bytes_read           += bytes_left_in_fifo;
    	        fifoptr              = fifo;
    	        packet_type          = BHY_DATA_TYPE_PADDING;
    
    
    	        do
    	        {
    	            /* this function will call callbacks that are registered */
    	            result = bhy_parse_next_fifo_packet(&fifoptr, &bytes_read, &fifo_packet, &packet_type);
    
    	            /* prints all the debug packets */
    	            if (packet_type == BHY_DATA_TYPE_DEBUG)
    	            {
    	                bhy_print_debug_packet(&fifo_packet.data_debug, bhy_printf);
    	            }
    
    	            /* the logic here is that if doing a partial parsing of the fifo, then we should not parse  */
    	            /* the last 18 bytes (max length of a packet) so that we don't try to parse an incomplete   */
    	            /* packet */
    	        } while ((result == BHY_SUCCESS) && (bytes_read > (bytes_remaining ? MAX_PACKET_LENGTH : 0)));
    
    	        bytes_left_in_fifo = 0;
    
    	        if (bytes_remaining)
    	        {
    	            /* shifts the remaining bytes to the beginning of the buffer */
    	            while (bytes_left_in_fifo < bytes_read)
    	            {
    	                fifo[bytes_left_in_fifo++] = *(fifoptr++);
    	            }
    	        }
    	    }
    
        /* USER CODE BEGIN 3 */
        }
    }

    When my programm jumps into the function it checks the product_id of the sensor and returns * return BHY_SUCCESS;* which means that the I2C connection is working!

    Bosch also provides some example code for different sensor readings here. Because i want my rotation data in quaternion's i looked at the rotation_vector_example.c example. There are two functions static void sensors_callback_rotation_vector() and void demo_sensor(), but i cant get this code to work. I put the demo_sensor() in to my main loop and have the Sensor_callback_rotation_vector()  in my main.c file. Maybe there is an other way to use this driver? In the documentation they say that the driver helps you in 3 phases to read out data: initialization, configuration and data readout. But i cant figure out how to actually do it!

    22 REPLIES 22
    Highlighted
    Community Moderator

    Re: BHI160b Shuttle Board with STM32

    On the HW connection,  i will suggest you connect SA_GPIO7 (pin 15) to either VDDIO or GND according to the I2C address you select.  

    What is the result of function call "bhy_driver_init".  if it is also successful,  this means BHI160B sensor is intialized correctly. 

    The main code from your paste looks like copy the example code,  which should work correctly if bus communication is corret and sensor initialized successfully. 

    in your main code, you already finish the intialize part code and configure part code,  the call back is the read out funciton. 

    So if you have no data output,  i need to know exactly which step you are failed now.  and the detail error code

     

     

    Highlighted
    Established Member

    Re: BHI160b Shuttle Board with STM32

    Hey,

    i followed your suggenstion and connected the SA_GPIO7 PIN to GND of my NUCLEO board because i use the i2c address #define BHY_I2C_ADDR1 (0x28). Then i started a debug session with the following results. In the function bhy_driver_init(), i first checked the result of the function call bhy_initialize_support().

    bhy_initialize_support.png

    This function returns "BHY_SUCCESS" and jumps back into the bhy_driver_init() function. After the support initialization, the programm loads the ram patch to the BHI160b. The Firmware i use is called "Bosch_PCB_7183_di03_BMI160-7183_di03.2.1.11696_170103.h". The result of the bhy_driver_init() function looks like this.

    bhy_driver_init.PNG

    As you can see the result is -14 which looks like the initializations was not successfull!

    A also have another question. I use the i2c1 which was initialized in the main like this I2C_HandleTypeDef hi2c1; . I use this i2c interface in the bhy_support.c for the read and write operations, i added the line extern I2C_HandleTypeDef hi2c1;  in the file main.h. Is this the right approach to extend this function to the file bhy_support.c ?

     

    Highlighted
    Established Member

    Re: BHI160b Shuttle Board with STM32

    Actually i figured out that after the successfull bhy_initialize_support() function, Line 165 result += bhy_initialize_from_rom(bhy_fw_data, /*bhy_fw_len*/tmp_fw_len);  is executed three times. After the first run the result is -6, after the second my result is -10 and after the third time i got -14. So this part "if (result == BHY_SUCCESS)" is never executed. Seems like my Firmware Download doesn't work properly....

    Highlighted
    Community Moderator

    Re: BHI160b Shuttle Board with STM32

    From the description,  the I2C write function looks like not working properly even the code looks fine.

    Can you check with logic analyzer on your I2C bus for write action and also paste here?

    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