Bosch Sensortec Community

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

    BHI160b Shuttle Board with STM32

    BHI160b Shuttle Board with STM32

    belaya
    Established Member

    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

    belaya
    Established Member

    I had an idea and looked a little bit closer to the Sensor Configuration. Because i want to enable the Rotation Vector, i searched in the datasheet which Sensors i need to activate to generate sensor ouput for the rotation vector. Actually i couldnt find it in the datasheet but in the code i obviously used the magnetometer because of mapping the matrix for the magnetometer. I thought maybe the Magnetometer wasn't connected to the supply voltage, but all sensors are enabled by default and the magnetometer was connected to the supply voltage. Then i changed the firmware from :

     

    #include ".\firmware\Bosch_PCB_7183_di03_BMI160-7183_di03.2.1.11696_170103.h"

     

    to

     

    #include ".\firmware\Bosch_PCB_7183_di03_BMI160_BMM150-7183_di03.2.1.11696_170103.h"

     

    And after that change i started to have continously readings, the interrupt fires and data has been transmitted.

    success.png

    I attached the I2C capture log file to this Post.

    I also can send the Quaternions via UART to my serial port to the pc!

    HAL_UART_Transmit(&huart2,(uint8_t*)out_buffer, 42, HAL_MAX_DELAY);

    The problem was the firmware, if i want to use the Game rotation vector which is a Sensor fusion without the Magnetometer, should i use the old Firmware?

     

     

    Vincent
    Community Moderator
    Community Moderator

    Yes.  if you just need game rotation,  you can use first FW.  if you need rotation vector,  you need second FW. 

    Rotation vector is 9DoF sensor fusion which required magnetic sensor.

    Game rotation is 6DoF sensor fusion which only need IMU data. 

    belaya
    Established Member

    Thank you very much for your help!

    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