07-03-2020 04:51 PM
Using a BMX160 connected over I2C to a Raspberry Pi I have the following two issues:
1. The magnetometer self-tests fail (both the normal and advanced test). On the contrary, the accelerometer and gyroscope self-tests succeed.
2. The Fast Offset Calibration for the accelerometer and gyroscope fails, with error -11.
Could you please provide any tips as to why this might be? Thank you in advance.
Code for setting up the sensor:
void calibrate_sensor()
{
struct bmi160_foc_conf foc_conf;
struct bmi160_offsets offsets;
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;
foc_conf.foc_gyr_en = BMI160_ENABLE;
foc_conf.gyro_off_en = BMI160_ENABLE;
//////// FIXME: This fails and returns -11
auto rslt = bmi160_start_foc(&foc_conf, &offsets, &m_bmi);
handle_potential_error(rslt, "bmi160_start_fox");
}
void test_sensor()
{
auto rslt = bmi160_perform_self_test(BMI160_ACCEL_ONLY, &m_bmi);
handle_potential_error(rslt, "bmi160_perform_self_test; accelerometer");
user_delay_ms(100);
rslt = bmi160_perform_self_test(BMI160_GYRO_ONLY, &m_bmi);
handle_potential_error(rslt, "bmi160_perform_self_test; gyroscope");
user_delay_ms(100);
////////FIXME: Test fails
rslt = bmm150_perform_self_test(BMM150_NORMAL_SELF_TEST, &m_bmm);
handle_potential_error(rslt, "bmm150_perform_self_test: magnetometer");
}
void setup_sensor()
{
int8_t rslt;
m_bmi.id = BMI160_I2C_ADDR;
m_bmi.interface = BMI160_I2C_INTF;
m_bmi.read = i2c_read;
m_bmi.write = i2c_write;
m_bmi.delay_ms = user_delay_ms;
rslt = bmi160_init(&m_bmi);
handle_potential_error(rslt, "bmi160_init");
/* Configure the BMM150 device structure by mapping user_aux_read and user_aux_write */
m_bmm.read = user_aux_read;
m_bmm.write = user_aux_write;
m_bmm.dev_id = BMM150_DEFAULT_I2C_ADDRESS;
/* Ensure that sensor.aux_cfg.aux_i2c_addr = bmm150.id for proper sensor operation */
m_bmm.delay_ms = user_delay_ms;
m_bmm.intf = BMM150_I2C_INTF;
/* Configure device structure for auxiliary sensor parameter */
m_bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE; // auxiliary sensor enable
m_bmi.aux_cfg.aux_i2c_addr = m_bmm.dev_id; // auxiliary sensor address
m_bmi.aux_cfg.manual_enable = BMI160_ENABLE; // setup mode enable
m_bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3 ;// burst read; 8 bytes
/* Initialize the auxiliary sensor interface */
rslt = bmi160_aux_init(&m_bmi);
handle_potential_error(rslt, "bmi160_aux_init");
/* Auxiliary sensor is enabled and can be accessed from this point */
/* Configure the desired settings in auxiliary BMM150 sensor
* using the bmm150 APIs */
/* Initialising the bmm150 sensor */
rslt = bmm150_init(&m_bmm);
handle_potential_error(rslt, "bmm150_init");
/* After the above function call, accel and gyro parameters in the device structure
are reset with default values, found in the datasheet of the sensor */
m_bmi.accel_cfg.odr = BMI160_ACCEL_ODR_25HZ; // Output data rate
m_bmi.accel_cfg.range = BMI160_ACCEL_RANGE_2G; // Range
m_bmi.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; // Bandwidth
m_bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; // Power mode
m_bmi.gyro_cfg.odr = BMI160_GYRO_ODR_25HZ; // Output data rate
m_bmi.gyro_cfg.range = BMI160_GYRO_RANGE_500_DPS; // Range
m_bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; // Bandwidth
m_bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; // Power mode
m_bmm.settings.preset_mode= BMM150_PRESETMODE_REGULAR;
rslt = bmm150_set_presetmode(&m_bmm);
handle_potential_error(rslt, "bmm150_set_presetmode");
// 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
m_bmm.settings.pwr_mode = BMM150_FORCED_MODE;
rslt = bmm150_set_op_mode(&m_bmm);
handle_potential_error(rslt, "bmm150_set_op_mode");
m_bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_25HZ; // Aux polling frequency
rslt = bmi160_config_aux_mode(&m_bmi);
handle_potential_error(rslt, "bmi160_config_aux_mode");
uint8_t aux_addr = BMM150_DATA_X_LSB; // BMM150 Mag data starts from register address 0x42
rslt = bmi160_set_aux_auto_mode(&aux_addr, &m_bmi);
handle_potential_error(rslt, "bmi160_set_aux_auto_mode");
rslt = bmi160_set_sens_conf(&m_bmi); // Set configuration
handle_potential_error(rslt, "bmi160_set_sens_conf");
}
I initiate the tests and calibration using the following snippet:
setup_sensor();
test_sensor();
setup_sensor();
calibrate_sensor();
07-10-2020 04:31 PM
I forgot to clarify that I can get accelerometer, gyroscope and magnetometer data from the device using the FIFO.
07-11-2020 12:50 AM
The delay in the trigger_foc is quite enough actually.
I realize there is no delay after change the sensor power mode. after change the power mode from sleep to normal, sensor will have a start up time around 55ms. So you need to wait after change sensor power mode before you trigger FOC command.
So you don't need to change delay time in trigger_foc. but in your main code, adding around 100ms delay after change power mode.
For magnetic self test, if you are able to get data, it should be ok.
maybe we need step by step debug here.
1. aux interface should be set as manual mode
2. after bmm150 init function (here you will read bmm150 chip to verify sensor is there. means you are able to communicate with bmm150 on aux bus)
3. start the bmm self test code (host need to write some register into bmm150 then read back some value).
I put the self test right after init just because in the init function, the aux interface was work as expected.