Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are always zero

    DroneKid
    Established Member

    Re: BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are alw

    Thank you for reference code, I updated my code with help of yours:

    #include "bmi160_wrapper.h"
    
    #define PRINTIF_DEBUG 0
    
    struct bmi160_dev sensor;
    struct bmi160_sensor_data accel;
    struct bmi160_sensor_data gyro;
    struct bmi160_foc_conf foc_conf;
    struct bmi160_offsets offsets;
    struct bmi160_int_settg int_config;
    
    int8_t resultDebug;
    
    int8_t BMI160_init() {
    
    	int8_t rslt;
    
        sensor.id = 0;
        sensor.intf = BMI160_I2C_INTF;
        sensor.read = SensorAPI_I2Cx_Read;
        sensor.write = SensorAPI_I2Cx_Write;
        sensor.delay_ms = HAL_Delay;
        sensor.read_write_len = 32;
    
        rslt = bmi160_soft_reset(&sensor);
        sensor.delay_ms(200);
        rslt = bmi160_init(&sensor);
    
        /********************************************************************/
    
        uint8_t reg_addr = BMI160_CHIP_ID_ADDR;
        uint8_t chipID = 0;
        uint16_t len = 1;
        rslt = bmi160_get_regs(reg_addr, &chipID, len, &sensor);
    
        printf("BMI160 init succesful, Chip ID (must be 209): %d\r\n", chipID);
    
        /********************************************************************/
    
        /* Select the Output data rate, range of accelerometer sensor */
        sensor.accel_cfg.odr = BMI160_ACCEL_ODR_800HZ;
        sensor.delay_ms(100);
        sensor.accel_cfg.range = BMI160_ACCEL_RANGE_8G;
        sensor.delay_ms(100);
    
        /* Select the power mode of accelerometer sensor */
        sensor.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
        sensor.delay_ms(100);
        sensor.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
        sensor.delay_ms(100);
    
    
        /* Select the Output data rate, range of Gyroscope sensor */
        sensor.gyro_cfg.odr = BMI160_GYRO_ODR_800HZ;
        sensor.delay_ms(100);
        sensor.gyro_cfg.range = BMI160_GYRO_RANGE_500_DPS;
        sensor.delay_ms(100);
    
        /* Select the power mode of Gyroscope sensor */
        sensor.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
        sensor.delay_ms(100);
        sensor.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
        sensor.delay_ms(100);
    
        /* Set the sensor configuration */
        rslt = bmi160_set_sens_conf(&sensor);
    
        /********************************************************************/
    
        rslt = start_foc();
    	printf("FOC Debug: %d\r\n", rslt);
    
    	/********************************************************************/
    
        /* Select the Interrupt channel/pin */
        int_config.int_channel = BMI160_INT_CHANNEL_1;// Interrupt channel/pin 1
    
        /* Select the Interrupt type */
        int_config.int_type = BMI160_ACC_GYRO_DATA_RDY_INT;// Choosing Any motion interrupt
        /* Select the interrupt channel/pin settings */
        int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
        int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
        int_config.int_pin_settg.output_type = BMI160_DISABLE;// Choosing active low output
        int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing edge triggered output
        int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
        int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;// non-latched output
    
        /* Set the Any-motion interrupt */
        rslt = bmi160_set_int_config(&int_config, &sensor); /* sensor is an instance of the structure bmi160_dev  */
    
        return rslt;
    }
    
    int8_t start_foc()
    {
    	int8_t rslt = 0;
    
    	/* Enable FOC for accel with target values of z = 1g ; x,y as 0g */
    	foc_conf.acc_off_en = BMI160_ENABLE;
    	foc_conf.foc_acc_x  = BMI160_FOC_ACCEL_0G;
    	foc_conf.foc_acc_y  = BMI160_FOC_ACCEL_0G;
    	foc_conf.foc_acc_z  = BMI160_FOC_ACCEL_POSITIVE_G;
    	sensor.delay_ms(100);
    
    	/* Enable FOC for gyro */
    	foc_conf.foc_gyr_en = BMI160_ENABLE;
    	foc_conf.gyro_off_en = BMI160_ENABLE;
    	sensor.delay_ms(100);
    
    	rslt = bmi160_start_foc(&foc_conf, &offsets, &sensor);
    
    	if (rslt == BMI160_OK)
    	{
    		printf("\n FOC DONE SUCCESSFULLY\r\n");
    		printf("\n OFFSET VALUES AFTER FOC : ");
    		printf("\n OFFSET VALUES ACCEL X : %d ",offsets.off_acc_x);
    		printf("\n OFFSET VALUES ACCEL Y : %d ",offsets.off_acc_y);
    		printf("\n OFFSET VALUES ACCEL Z : %d ",offsets.off_acc_z);
    		printf("\n OFFSET VALUES GYRO  X : %d ",offsets.off_gyro_x);
    		printf("\n OFFSET VALUES GYRO  Y : %d ",offsets.off_gyro_y);
    		printf("\n OFFSET VALUES GYRO  Z : %d\r\n",offsets.off_gyro_z);
    	}
    	else
    	{
    		printf("FOC failed\r\n");
    	}
    
    	/* After start of FOC offsets will be updated automatically and
    	 * the data will be very much close to the target values of measurement */
    
    	return rslt;
    }
    
    
    //BMI160_t *dataStruct
    int8_t bmi160ReadAccelGyro(){
    
    	int8_t rslt;
    
    	rslt = bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &accel, &gyro, &sensor);
    
    	if (PRINTIF_DEBUG){
    		printf("Accel X: %d\r\n", accel.x);
    		printf("Accel Y: %d\r\n", accel.y);
    		printf("Accel Z: %d\r\n", accel.z);
    
    		printf("Gyro X: %d\r\n", gyro.x);
    		printf("Gyro Y: %d\r\n", gyro.y);
    		printf("Gyro Z: %d\r\n", gyro.z);
    
    		printf("* * * * * * * * * * * * * * *\r\n");
    	}
    
    	return rslt;
    
    }

     

    Both FOC and Interrupt pin seems working. I measured the INT1 pin with an oscilloscope. In the example code I posted above, I set the ODRs to 800 Hz. I got values close to exactly 800 Hz from the oscilloscope.

    Everything seems to be working fine now. Could you check the code too? Would it be healthier to read Accel and Gyro data from FIFO instead of reading the current method?

    I am also considering using BMI160 in quadcopter. Would FOC be a sufficient calibration for this or do I need a more detailed calibration?

    Thank you.

    André
    Established Member

    Re: BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are alw

    how do you synchronize the call to bmi160ReadAccelGyro() and the interrupt service routine?  You can't call bmi160ReadAccelGyro() from the ISR so some semaphore is required that you poll on a regular interval somehow from the main() loop.

    The best way I think is to use a RTOS task which gets  a signal of the DRDY and fetches the data which will be always there and than goes back to sleep while it waits for the next signal.

    Using the fifo releases you of a lot of headache: you can set the size of the fifo and generate a fifo watermark interrupt on a configurable watermark level. So when you get the fifo watermark Interrupt and signal that to ie a waiting RTOS task than that task can fetch many many readings in one I2C call. You proces that data and wait for the next fifo watermark ISR/signal.  This is very usefull when using the BMX in a low power application : the processor can go to low power mode and wakes up when is gets the fifo watermark interrupt,  Note that the BMX can also gather samples while being in low power modus. 

    I might be wrong but this is my understanding of the datasheet. Please correct ne if I am wrong

     

    André

    bmi160ReadAccelGyro

     

    DroneKid
    Established Member

    Re: BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are alw

    I didn't implement my library to any RTOS application yet. I just test it on standart STM32CubeIDE project. I made something like that. When data is ready, INT1 pins goes from HIGH to LOW. 

     

    if(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_9) == 0) {
    	result = bmi160ReadAccelGyro(&BMI160);
    	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
    	FILTER_STATE = NEW_DATA_ARRIVED;
    }

     

     

    I will implement this core library with some sensor fusion and semaphore to RTOS

    BSTRobin
    Community Moderator

    Re: BMI160 & STM32 Strange Behaviour - Sensor Succesfully Inits but Accel and Gyro Reads are alw

    Hi DroneKid,

    As you set ODR to 800 Hz, you first need to confirm how long you need the data so that you can better decide which way to read the data.

    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