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 */
bmi.id = BMX160_I2C_ADDR;
bmi.read = (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;
bmm.read = (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;
//NRF_LOG_INFO("INIT");
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;
bmi.accel_cfg.bw = 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;
bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
//NRF_LOG_INFO("SENSE CONF");
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 */
//NRF_LOG_INFO("AUX INIT");
rslt = bmi160_aux_init(&bmi);
bmi.delay_ms(100);
/* 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 */
//NRF_LOG_INFO("SET POWER MODE");
/* 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)
{
NRF_LOG_INFO("AUTO MODE DID NOT WORK");
}
/* Check rslt for any error codes */
// NRF_LOG_INFO("BEGIN BSX INIT");
// 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...");
return;
}
//NRF_LOG_INFO("BSX INITIALIZED");
ts_workingModes s_workingModes;
//ts_HWsensorSwitchList HWsensorSwitchList; //commented out while variable is not used
s_workingModes.opMode = BSX_WORKINGMODE_NDOF_GEORV_FMC_OFF;
bsx_set_workingmode(&s_workingModes);
//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);
libraryinput_ts.acc.data.x = accel_data[0].x;
libraryinput_ts.acc.data.y = accel_data[0].y;
libraryinput_ts.acc.data.z = accel_data[0].z;
libraryinput_ts.acc.time_stamp = accel_data[0].sensortime * 39;
libraryinput_ts.gyro.data.x = gyro_data[0].x;
libraryinput_ts.gyro.data.y = gyro_data[0].y;
libraryinput_ts.gyro.data.z = gyro_data[0].z;
libraryinput_ts.gyro.time_stamp = gyro_data[0].sensortime * 39;
libraryinput_ts.mag.data.x = mag_data[0].x;
libraryinput_ts.mag.data.y = mag_data[0].y;
libraryinput_ts.mag.data.z = mag_data[0].z;
libraryinput_ts.mag.time_stamp = gyro_data[0].sensortime * 39;
bsx_dostep(&libraryinput_ts);
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;
... View more