Bosch Sensortec Community

    Showing results for 
    Search instead for 
    Did you mean: 

    BMX160 + BSXlite absolute orientation/heading problem

    BMX160 + BSXlite absolute orientation/heading problem

    New Poster

    Our team has been implementing the BMX160 with BSXlite as a lower power replacement for the BNO055. Currently we have an issue where rotating the device quickly causes the quaternion output of the BSXlite library to lose its heading and it will lose north/south direction. Rotating it slowly causes the heading to be retained but quick movements of a half-circle rotation will result in the heading (north/south reference) to change.

    I have the accelerometer ODR set to 100Hz, gyro ODR set to 100Hz and mag ODR set to 25Hz. I am calling bsx_dostep() and bsx_get_orientdata_quat() at 50Hz. The gyro settings in the BSX documentation call for 500_DPS as the range setting however this appears to result in output that registers a half rotation for every one real-world rotation. Sensor timestamps show that data is being fed in at 50Hz as expected. magcalibaccuracy continues to show 0.

    Here is the init code:

    /* Initialize your host interface to the BMI160 */
    	//uint8_t read_val = 0;    //commented out while variable is not used
        /* This example uses I2C as the host interface */ = BMX160_I2C_ADDR; = (bmi160_com_fptr_t) &bmx160_i2c_read;
        bmi.write = (bmi160_com_fptr_t) &bmx160_i2c_write;
        bmi.delay_ms = (bmi160_delay_fptr_t) &nrf_delay_ms;
        bmi.interface = BMI160_I2C_INTF;
        /* The BMM150 API tunnels through the auxiliary interface of the BMI160 */
        /* Check the pins of the BMM150 for the right I2C address */
    	bmm.chip_id = BMM150_CHIP_ID;
        bmm.intf = BMM150_I2C_INTF; = (bmm150_read_fptr_t) &bmm150_aux_read;
        bmm.write = (bmm150_write_fptr_t) &bmm150_aux_write;
        bmm.delay_us = (bmm150_delay_us_fptr_t) &my_delay_us;
    	bmm.intf_ptr = &bmi;
        rslt = bmi160_init(&bmi);
        /* Check rslt for any error codes */
    	/* Check rslt for any error codes */
        /* Configure the accelerometer */
        bmi.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
        bmi.accel_cfg.range = BMI160_ACCEL_RANGE_2G; = BMI160_ACCEL_BW_NORMAL_AVG4;
        bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
        /* Configure the gyroscope */
        bmi.gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
        bmi.gyro_cfg.range = BMI160_GYRO_RANGE_250_DPS; = BMI160_GYRO_BW_NORMAL_MODE;
        bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
        rslt = bmi160_set_sens_conf(&bmi);
        /* Check rslt for any error codes */
        /* Configure the BMI160's auxiliary interface for the BMM150 */
        bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
        bmi.aux_cfg.aux_i2c_addr = BMM150_DEFAULT_I2C_ADDRESS;
        bmi.aux_cfg.manual_enable = BMI160_ENABLE; /* Manual mode */
        bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3; /* 8 bytes */
        rslt = bmi160_aux_init(&bmi);
    	/* Check rslt for any error codes */
    	//NRF_LOG_INFO("BMM150 INIT");
        rslt = bmm150_init(&bmm);
        /* Configure the magnetometer. The regular preset supports up to 100Hz in Forced mode */
        bmm_settings.preset_mode = BMM150_PRESETMODE_REGULAR;
        rslt = bmm150_set_presetmode(&bmm_settings, &bmm);
        /* Check rslt for any error codes */
        /* It is important that the last write to the BMM150 sets the forced mode.
         * This is because the BMI160 writes the last value to the auxiliary sensor 
         * after every read */
        bmm_settings.pwr_mode = BMM150_POWERMODE_FORCED;
        rslt = bmm150_set_op_mode(&bmm_settings, &bmm);
        /* Check rslt for any error codes */
        uint8_t bmm150_data_start = BMM150_REG_DATA_X_LSB;
        bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_25HZ;
        rslt = bmi160_set_aux_auto_mode(&bmm150_data_start, &bmi);
    	if (rslt != BMI160_OK)
        /* Check rslt for any error codes */
    	// INIT BSX-LITE to generate quaternions from imu data
    	initParam_t s_input;
    	s_input.accelspec = str_accSensorSpec;
    	s_input.gyrospec = str_gyroSensorSpec;
    	s_input.magspec = str_magSensorSpec;
    	s_input.usecase = str_useCaseSpec;
    	BSX_S8 init_status;
    	init_status = bsx_init(&s_input);
    	if(init_status != BSX_STATE_OK)
    		NRF_LOG_INFO("BSX Initialization Failed...");
    	ts_workingModes s_workingModes;
    	//ts_HWsensorSwitchList HWsensorSwitchList;     //commented out while variable is not used
    	s_workingModes.opMode = BSX_WORKINGMODE_NDOF_GEORV_FMC_OFF;
    	//bsx_get_hwdependency(s_workingModes, &HWsensorSwitchList);
        //uint8_t fifo_config = BMI160_FIFO_HEADER | BMI160_FIFO_AUX |  BMI160_FIFO_ACCEL | BMI160_FIFO_GYRO;


    Here is the code where we feed data into dostep():

    /* Check rslt for any error codes */
    	bmi160_get_sensor_data(BMI160_BOTH_ACCEL_AND_GYRO | BMI160_TIME_SEL, &accel_data[0], &gyro_data[0], &bmi);
    	rslt = bmm150_read_mag_data(&mag_data[0], &bmm);
  = accel_data[0].x; = accel_data[0].y; = accel_data[0].z;
    	libraryinput_ts.acc.time_stamp = accel_data[0].sensortime * 39; = gyro_data[0].x; = gyro_data[0].y; = gyro_data[0].z;
    	libraryinput_ts.gyro.time_stamp = gyro_data[0].sensortime * 39; = mag_data[0].x; = mag_data[0].y; = mag_data[0].z;
    	libraryinput_ts.mag.time_stamp = gyro_data[0].sensortime * 39;
    	ts_dataquatf32 quatD;
    	BSX_S8 ret_val = bsx_get_orientdata_quat(&quatD);
    	quat_data->w = quatD.w * 32767;
    	quat_data->x = quatD.x * 32767;
    	quat_data->y = quatD.y * 32767;
    	quat_data->z = quatD.z * 32767;


    4 REPLIES 4

    New Poster

    To add, we seem to be experiencing an issue related to

    Our gyro range needs to be set to 250_DPS in order to get motion that is close correct. 500_DPS as recommended in the integration guide seems to give half-rotations in the quaternion output for every 1 real-world rotation. However that post seems to indicate they are running BSXlite at 100fps, the guide says BSXlite only supports 50Hz.

    Community Moderator
    Community Moderator

    Hello Amoore, 


    I'm a little bit confused since DPS and ODR are different unit. 

    Yes, we support 500 DPS and 50 Hz ODR for orientation sensor. 

    What is the main problem for you? 


    The issue is:

    1.) Our device will maintain correct absolute orientation/heading when rotated slowly but when rotated quickly north and south will drift and it will continue to shift around. It will always reorient correctly with respect to gravity but it will lose its ability to determine north/south direction. Restated, when the device is pointed back to its starting point (orientation) after some quick motion the axes parallel to the ground will not be in the same position.

    2.) The gyroscope settings that work best are with a range of 250_DPS. This appears incorrect as the BSXlite guide states 500_DPS is correct but this setting (with 500_DPS) results in quaternion movements that are half the rotation of the real-world device. Could this be related to issue 1?

    Community Moderator
    Community Moderator



    Sorry for late response. 

    Did you solve this issue?