05-21-2020 12:08 PM
We're using the BMI270 with a BMM150 attached to the I2C auxilliary port. When I enable just the BMI270 accelerometer and gyro, everything works as expected, reading the FIFO produces the correct number of samples per second. As soon as I enable the auxilliary sensor, I get strange behaviour where the sample rate for the accelerometer and gyro seems to drop to 1 to 2 samples per second.
Code snippets for the configuration below. Samples per second is determined by reading a FIFO frame every 500 ms and using the
bmi2_extract_accel
etc functions.
/* Setup accelerometer data rate, range */
{
bmi2_sens_config config = {};
config.type = BMI2_ACCEL;
config.cfg.acc.odr = BMI2_ACC_ODR_100HZ;
config.cfg.acc.bwp = BMI2_ACC_OSR4_AVG1;
config.cfg.acc.range = BMI2_ACC_RANGE_8G;
bmi2_set_sensor_config(&config, 1u, device_);
}
/* Setup gyroscope data rate, range */
{
bmi2_sens_config config = {};
config.type = BMI2_GYRO;
config.cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
config.cfg.gyr.range = BMI2_GYR_RANGE_250;
config.cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE;
config.cfg.gyr.noise_perf = 0u;
bmi2_set_sensor_config(&config, 1u, device_);
}
/* Configure auxilliary sensor - BMM150 */
{
const uint8_t device_address = 0x13u;
bmi2_sens_config aux_sens_config = {};
aux_sens_config.type = BMI2_AUX;
aux_sens_config.cfg.aux.aux_en = BMI2_ENABLE;
aux_sens_config.cfg.aux.manual_en = BMI2_DISABLE;
aux_sens_config.cfg.aux.odr = BMI2_AUX_ODR_25HZ;
aux_sens_config.cfg.aux.aux_rd_burst = 6u; /* 3 axes * 2 bytes */
aux_sens_config.cfg.aux.read_addr = 0x42; /* 0x42 - MAG LSB X */
aux_sens_config.cfg.aux.i2c_device_addr = device_address;
bmi2_set_sensor_config(&aux_sens_config, 1u, device_);
}
/* Configure FIFO */
uint16_t config = BMI2_FIFO_HEADER_EN | BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN | BMI2_FIFO_AUX_EN;
bmi2_set_fifo_config(config, BMI2_ENABLE, device_); res != BMI2_OK );
Solved! Go to Solution.
05-21-2020 07:46 PM
I put a working example code of sensor intialize here fore your reference (without FIFO since your FIFO configure is correct) .
if you initiliaze all three sensor correctly, the FIFO data should contain the correct data rate for both accel, gyro and mag .
static void init_bmi2xy_bmm150(void)
{
/* Variable to define error */
int8_t rslt;
const uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX};
struct bmi2_sens_config config[3] = {
[0].type = BMI2_ACCEL,
[1].type = BMI2_GYRO,
[2].type = BMI2_AUX,
};
printf("Please wait for config. file to be uploaded during BMI2xy initialization ...\n");
fflush(stdout);
/* Upload config. file */
if (bmi2_init(&bmi2dev) == BMI2_OK)
{
printf("BMI2xy initialization success !\n");
printf("Chip ID - 0x%x\n", bmi2dev.chip_id);
}
else
{
printf("BMI2xy initialization failure !\n");
printf("Config file - Sensor mismatch !!\n");
exit(COINES_E_FAILURE);
}
/* Enable accel. , gyro. mag. sensors */
if (bmi2_sensor_enable(sensor_list, 3, &bmi2dev) == BMI2_OK)
{
/*acc*/
config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE;
config[0].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2;
config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; //IMU work for 100HZ
config[0].cfg.acc.range = BMI2_ACC_RANGE_2G;
/*gyro*/
config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE;
config[1].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000;
config[1].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE;
config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000;
config[1].cfg.gyr.ois_range = BMI2_GYR_OIS_2000;
/*mag*/
/*The initial configuration of the auxiliary sensor should be done in manual mode.Then, switch to data mode to read data.*/
config[2].cfg.aux.aux_en = BMI2_ENABLE;
config[2].cfg.aux.manual_en = BMI2_ENABLE;
config[2].cfg.aux.odr = BMI2_AUX_ODR_50HZ;
config[2].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS;
config[2].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3;
/* Set accel. , gyro. and mag. configuration */
if (bmi2_set_sensor_config(config, 3, &bmi2dev) == BMI2_OK)
printf("Accel./Gyro/Mag configuration write success !\n");
else
printf("Accel./Gyro/Mag configuration write failure !\n");
/* Initialize bmm150:should be done in aux man mode */
rslt = bmm150_init(&bmm150);
if (rslt != BMI2_OK)
{
printf("BMM150 init,Error code: %d\n", rslt);
}
/* Set the power mode to either normal or forced mode */
rslt = bmm150_set_op_mode(&bmm150);
bmm150.settings.pwr_mode = BMM150_FORCED_MODE;
if (rslt != BMI2_OK)
{
printf("BMM150 set op mode,Error code: %d\n", rslt);
}
/* Switch to data mode for reading data*/
config[2].cfg.aux.manual_en = BMI2_DISABLE;
/* Configure read address to read Magnetic field data from that address */
config[2].cfg.aux.read_addr = BMI_AUX_MAG_DATA_ADDR;
config[2].cfg.aux.aux_rd_burst = BMI2_AUX_READ_LEN_3;
/* Set the data mode and the auxiliary read address */
rslt = bmi2_set_sensor_config(config, 3, &bmi2dev);
if (rslt != BMI2_OK)
{
printf("BMI2 set config,Error code: %d\n", rslt);
}
}
}
05-21-2020 08:21 PM
Thank you for the reply. I didn't quite see what I was doing wrong in my config though? Do all the the sensor configs need to be written at once like you've done? I assumed I could configure one by one?
05-21-2020 10:47 PM
Actually I think my issue is not in the sampling rate, but in the parsing of the FIFO frame. The FIFO seems to contain the correct number of bytes, but when I extract the accelerometer etc data it retrieves only a few readings because it encounters and invalid frame type and discards the rest of the buffer. Am I doing something wrong here?
void Bmi270Application::ReadFifo()
{
bmi2_fifo_frame frame = {};
frame.data = fifo_data_;
frame.header_enable = true;
{
uint16_t length;
bmi2_get_fifo_length(&length, device_);
DS_ALWAYS("{} bytes in fifo", length);
frame.length = std::min((uint16_t)std::size(fifo_data_), length);
}
if ( auto res = bmi2_read_fifo_data(&frame, device_); res != BMI2_OK )
{
display_error("Failed to read fifo", res);
return;
}
{
std::array<bmi2_sens_axes_data, 400> acceleration_data;
uint16_t accel_reading_count = acceleration_data.size();
auto res =
bmi2_extract_accel(acceleration_data.data(), &accel_reading_count, &frame, device_);
if (res < 0)
{
display_error("Failed to extract accel data", res);
return;
}
DS_ALWAYS("Got {} accelerometer samples", accel_reading_count);
DS_ALWAYS("Accel x:{} y:{} z:{}",
acceleration_data[0].x,
acceleration_data[0].y,
acceleration_data[0].z);
}
{
std::array<bmi2_sens_axes_data, 400> gyro_data;
uint16_t reading_count = gyro_data.size();
auto res =
bmi2_extract_gyro(gyro_data.data(), &reading_count, &frame, device_);
if (res < 0)
{
display_error("Failed to extract Gyro data", res);
return;
}
DS_ALWAYS("Got {} gyro samples", reading_count);
DS_ALWAYS("Gyro x:{} y:{} z:{}", gyro_data[0].x, gyro_data[0].y, gyro_data[0].z);
}
if ( use_aux_)
{
std::array<bmi2_aux_fifo_data, 400> data;
uint16_t reading_count = data.size();
auto res =
bmi2_extract_aux(data.data(), &reading_count, &frame, device_);
if (res < 0)
{
display_error("Failed to extract Gyro data", res);
return;
}
DS_ALWAYS("Got {} aux samples", reading_count);
aux_sensor_data_frame f;
memcpy(f.raw, data[0].data, std::min(sizeof(f.raw), sizeof(data[0].data)));
DS_ALWAYS("Mag x:{} y:{} z:{}", f.mag.x, f.mag.y, f.mag.z);
}
}
05-23-2020 01:34 AM
Can you print out the frame header which you parse error to cause the function exited?
Your implementation looks fine and our API is considering all possible FIFO frame header situation in our API code.
It will only finish parsing if they met 0x8080 as padding bytes under FIFO header mode.