10-06-2020 08:15 PM - edited 10-06-2020 09:10 PM
Hello,
I am testing the BMX160 shuttle board and trying to get accelerometer, gyroscope and magnetometer data off it using BMI160/BMM150 driver provided. I'm able to get accelerometer and gyroscope data, but am not able to interact with the magnetometer. I'm following the user guide in the BMI160 driver readme and on the BMI160 wiki, but both appear to be out of date.
In particular, the things that are out-of-date are:
I've done my best to adapt the example code to the updated drivers, but still am not able to get magnetometer data. Relevant sections of my code are below. None of the driver functions are returning error codes. I am using v3.8.1 of the BMI160 drivers and v2.0.0 of the BMM150 drivers. Any clues about where I am mis-stepping or how to debug this issue would be appreciated.
//wrapper functions for bmm150
int8_t user_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, bmi160_dev *dev)
{
int8_t rslt;
rslt = bmi160_aux_read(reg_addr, aux_data, len, dev);
return rslt;
}
/*wrapper function to match the signature of bmm150.write */
int8_t user_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, bmi160_dev *dev)
{
int8_t rslt;
rslt = bmi160_aux_write(reg_addr, aux_data, len, dev);
return rslt;
}
void main()
{
int8_t rslt = BMI160_OK;
//configure bmi160
struct bmi160_dev bmi160;
bmi160.id = BMI160_I2C_ADDR;
bmi160.interface = BMI160_I2C_INTF;
bmi160.read = (bmi160_com_fptr_t) &i2c_read;
bmi160.write = (bmi160_com_fptr_t) &i2c_write;
bmi160.delay_ms = (bmi160_delay_fptr_t) &delay;
rslt = bmi160_init(&bmi160);
//accel and gyro configuration
bmi160.accel_cfg.odr = BMI160_ACCEL_ODR_25HZ;
bmi160.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
bmi160.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
bmi160.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
bmi160.gyro_cfg.odr = BMI160_GYRO_ODR_25HZ;
bmi160.gyro_cfg.range = BMI160_GYRO_RANGE_250_DPS;
bmi160.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
bmi160.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
rslt = bmi160_set_sens_conf(&bmi160);
//auxillary interface
bmi160.aux_cfg.aux_sensor_enable = 1;
bmi160.aux_cfg.aux_i2c_addr = BMI160_AUX_BMM150_I2C_ADDR;
bmi160.aux_cfg.manual_enable = 1;
bmi160.aux_cfg.aux_rd_burst_len = 2;
rslt = bmi160_aux_init(&bmi160);
//bmm150 configuration
struct bmm150_dev bmm150;
bmm150.read = (bmm150_read_fptr_t) &user_aux_read;
bmm150.write = (bmm150_write_fptr_t) &user_aux_write;
bmm150.delay_us = (bmm150_delay_us_fptr_t) &delayMicroseconds;
bmm150.intf = BMM150_I2C_INTF;
bmm150.intf_ptr = &bmi160;
rslt = bmm150_init(&bmm150);
//bmm150 settings
struct bmm150_settings settings;
settings.pwr_mode = BMM150_POWERMODE_FORCED;
settings.preset_mode= BMM150_PRESETMODE_REGULAR;
rslt = bmm150_set_op_mode(&settings, &bmm150);
rslt = bmm150_set_presetmode(&settings, &bmm150);
//auxillary data rate
bmi160.aux_cfg.aux_odr = BMI160_AUX_ODR_200HZ;
rslt = bmi160_config_aux_mode(&bmi160);
//set auto mode
uint8_t aux_addr = 0x42;
rslt = bmi160_set_aux_auto_mode(&aux_addr, &bmi160);
//output data structures
uint8_t mag_data[8] = {0};
struct bmi160_sensor_data accel;
struct bmi160_sensor_data gyro;
struct bmm150_mag_data magn;
//get sensor data
while(1)
{
rslt = bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL | BMI160_TIME_SEL), &accel, &gyro, &bmi160);
rslt = bmi160_read_aux_data_auto_mode(mag_data, &bmi160);
rslt = bmm150_aux_mag_data(mag_data, &magn, &bmm150);
}
}
Solved! Go to Solution.
10-07-2020 03:03 AM
10-08-2020 07:59 PM
Thanks, I will review this and see what I get.
05-18-2021 12:00 PM
Hi Liam,
How did you et on with this part.
Just saw your old post and I too have run insto similar issues.
https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMX160-driver/m-p/18349/highlight/false#...
But I made changes and their example seems to compile and do something; no error codes returned from API call so one can only assume its OK.
But I am not sure of data readings I have got. I added time config to fifo confg; yet API calls still show sensor time zero.
I checked the number of samples being returned as the fifo is parsed and the returned fifo size.
Example says the number of bytes used in the fifo should be returned; yet I always see 250 returned.
When I change the delay for the fifo processing loop from 100mS->40mS->10mS I expected to see the number of samples returned drop; but this is not the case.
I then added the api call to soft reset the device before the example; just in case the device was not picking up new configurations.
void doABmx160Test(void)
{
int8_t rslt;
uint32_t i;
struct bmm150_settings bmmSettings;
struct bmm150_mag_data magData;
/* Initialize your host interface to the BMI160 */
twi_init();
/* This example uses I2C as the host interface */
bmi.id = BMI160_I2C_ADDR;
bmi.read = &bhy_i2c_read;
bmi.write = &bhy_i2c_write;
bmi.delay_ms = &nrf_delay_ms;
bmi.intf = BMI160_I2C_INTF;
rslt = bmi160_soft_reset( &bmi );
ASSERT( rslt == BMI160_OK);
rslt = bmi160_init(&bmi);
ASSERT( rslt == BMI160_OK );
/* The BMM150 API tunnels through the auxiliary interface of the BMI160 */
/* Check the pins of the BMM150 for the right I2C address */
// No field of this name !!!bmm.dev_id = BMM150_DEFAULT_I2C_ADDRESS;
bmm.chip_id = 0;
bmm.intf = BMM150_I2C_INTF;
bmm.intf_ptr = BMM150_DEFAULT_I2C_ADDRESS; // Not used; but keeps BMM driver happy
bmm.read = bmm150_aux_read;
bmm.write = bmm150_aux_write;
bmm.delay_us = &bmm150_user_delay_us;
/* 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);
ASSERT( rslt == BMI160_OK );
rslt = bmm150_init(&bmm);
ASSERT( rslt == BMM150_OK );
/* Configure the accelerometer */
bmi.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
bmi.accel_cfg.range = BMI160_ACCEL_RANGE_16G;
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_2000_DPS;
bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
rslt = bmi160_set_sens_conf(&bmi);
ASSERT( rslt == BMI160_OK );
/* Configure the magnetometer. The regular preset supports up to 100Hz in Forced mode */
bmmSettings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt = bmm150_set_presetmode( &bmmSettings, &bmm);
ASSERT( rslt == BMM150_OK );
/* 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 */
bmmSettings.pwr_mode = BMM150_POWERMODE_FORCED;
rslt = bmm150_set_op_mode( &bmmSettings, &bmm);
ASSERT( rslt == BMM150_OK );
uint8_t bmm150_data_start = BMM150_REG_DATA_X_LSB;
bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_100HZ;
rslt = bmi160_set_aux_auto_mode(&bmm150_data_start, &bmi);
ASSERT( rslt == BMI160_OK );
/* Link the FIFO memory location */
fifo_frame.data = fifo_buff;
fifo_frame.length = FIFO_SIZE;
bmi.fifo = &fifo_frame;
/* Clear all existing FIFO configurations */
rslt = bmi160_set_fifo_config(BMI160_FIFO_CONFIG_1_MASK , BMI160_DISABLE, &bmi);
ASSERT( rslt == BMI160_OK );
//uint8_t fifo_config = BMI160_FIFO_TIME | BMI160_FIFO_HEADER | BMI160_FIFO_AUX | BMI160_FIFO_ACCEL | BMI160_FIFO_GYRO;
uint8_t fifo_config = BMI160_FIFO_HEADER | BMI160_FIFO_AUX | BMI160_FIFO_ACCEL | BMI160_FIFO_GYRO;
rslt = bmi160_set_fifo_config(fifo_config, BMI160_ENABLE, &bmi);
ASSERT( rslt == BMI160_OK );
i = 0;
while(rslt == 0) {
/* Wait for 100ms for the FIFO to fill */
//nrf_delay_ms(100);
nrf_delay_ms(10);
/* It is VERY important to reload the length of the FIFO memory as after the
* call to bmi160_get_fifo_data(), the bmi.fifo->length contains the
* number of bytes read from the FIFO */
bmi.fifo->length = FIFO_SIZE;
rslt = bmi160_get_fifo_data(&bmi);
ASSERT( rslt == BMI160_OK );
uint8_t aux_inst = MAG_FRAMES, gyr_inst = GYR_FRAMES, acc_inst = ACC_FRAMES;
rslt = bmi160_extract_aux(aux_data, &aux_inst, &bmi);
ASSERT( rslt == BMI160_OK );
rslt = bmi160_extract_gyro(gyro_data, &gyr_inst, &bmi);
ASSERT( rslt == BMI160_OK );
rslt = bmi160_extract_accel(accel_data, &acc_inst, &bmi);
ASSERT( rslt == BMI160_OK );
for (uint8_t i = 0; i < aux_inst; i++) {
rslt = bmm150_aux_mag_data(&aux_data[i].data[0], &magData, &bmm);
ASSERT( rslt == BMM150_OK );
}
NRF_LOG_INFO("%d %d %d %d", acc_inst, gyr_inst, aux_inst, bmi.fifo->length );
//if( (i % 10) == 0 ){
//NRF_LOG_INFO("%u", i )
//if( acc_inst > 0 ){
for( i=0; i<acc_inst; i++ ){
//NRF_LOG_INFO("ACC x %d y %d z %d t %u", accel_data[0].x, accel_data[0].y, accel_data[0].z, accel_data[0].sensortime );
//printf("%6.6d %6.6d %6.6d %d\r", accel_data[i].x, accel_data[i].y, accel_data[i].z, accel_data[i].sensortime );
}
if( gyr_inst > 0 ){
//NRF_LOG_INFO("GYR x %d y %d z %d t %u", gyro_data[0].x, gyro_data[0].y, gyro_data[0].z, gyro_data[0].sensortime );
}
if( aux_inst > 0 ){
//NRF_LOG_INFO("MAG x %d y %d z %d", magData.x, magData.y, magData.z );
//printf("%6.6d %6.6d %6.6d\r", magData.x, magData.y, magData.z );
}
NRF_LOG_FLUSH();
//}
i++;
}
}
This made no difference....
<info> app: 5 5 1 250
<info> app: 1 5 1 250
<info> app: 1 4 1 250
<info> app: 5 5 1 250
<info> app: 5 5 1 250
<info> app: 3 3 1 250
<info> app: 5 5 1 250
<info> app: 5 5 1 250
<info> app: 2 2 1 250
<info> app: 5 9 1 250
<info> app: 5 5 1 250
<info> app: 5 5 1 250
<info> app: 5 5 1 250
<info> app: 5 5 1 250
<info> app: 5 6 1 250
<info> app: 5 6 1 250
<info> app: 5 5 1 250
<info> app: 4 4 1 250