Dear, I am using the BMM150 in auxiliary mode with the BMI160 through I2C. I have followed the https://github.com/boschsensortec/BMI160_driver/wiki/How-to-use-an-auxiliary-sensor-or-magnetometer-with-the-BMI160. explanation on how to integrate it and I have created the following code: #define ACC_FRAMES 10 /* 10 Frames are available every 100ms @ 100Hz */
#define GYR_FRAMES 10
#define MAG_FRAMES 10
/* 10 frames containing a 1 byte header, 6 bytes of accelerometer,
* 6 bytes of gyroscope and 8 bytes of magnetometer data. This results in
* 21 bytes per frame. Additional 40 bytes in case sensor time readout is enabled */
#define FIFO_SIZE 250
struct bmi160_dev inertial_sensor;
struct bmm150_dev mag_sensor;
struct bmm150_settings mag_sensor_settings;
struct bmi160_aux_data auxil_data[MAG_FRAMES];
struct bmm150_mag_data magneto_data[MAG_FRAMES];
struct bmi160_fifo_frame fifo_frame; // needed to make global as used in fifo config and fifo read
/* Declare memory to store the raw FIFO buffer information */
uint8_t fifo_buff[FIFO_SIZE];
/*! Variable that holds the I2C device address or SPI chip selection */
static uint8_t dev_addr;
struct bmi160_sensor_data gyro_data[GYR_FRAMES];
struct bmi160_sensor_data accel_data[ACC_FRAMES];
void inertial_mag_sensor_init(void)
{
int8_t rslt;
// BMI160 via I2C
inertial_sensor.id = BMI160_I2C_ADDR;
inertial_sensor.interface = BMI160_I2C_INTF;
inertial_sensor.read = inertial_sensor_i2c_read;
inertial_sensor.write = inertial_sensor_i2c_write;
inertial_sensor.delay_ms = inertial_sensor_delay_ms;
//magnetometer_sensor.chip_id = BMM150_CHIP_ID;
dev_addr = BMM150_DEFAULT_I2C_ADDRESS;
mag_sensor.intf = BMM150_I2C_INTF;
mag_sensor.read = bmm150_aux_read;
mag_sensor.write = bmm150_aux_write;
/* Assign device address to interface pointer */
mag_sensor.intf_ptr = &dev_addr;
mag_sensor.delay_us = mag_delay_us;
rslt = bmi160_init(&inertial_sensor);
if (rslt == BMI160_OK)
{
NRF_LOG_INFO("Inertial sensor initialized.");
}
else
{
NRF_LOG_INFO("Inertial sensor not initialized.");
}
/* Configure the BMI160's auxiliary interface for the BMM150 */
inertial_sensor.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
inertial_sensor.aux_cfg.aux_i2c_addr = BMI160_AUX_BMM150_I2C_ADDR; //bmm.dev_id;
inertial_sensor.aux_cfg.manual_enable = BMI160_ENABLE; /* Manual mode */
inertial_sensor.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3; /* 8 bytes */
rslt = bmi160_aux_init(&inertial_sensor);
/* Check rslt for any error codes */
if (rslt == BMI160_OK)
{
NRF_LOG_INFO("Inertial sensor auxiliary interface for the BMM150 initialized.");
}
else
{
NRF_LOG_INFO("Inertial sensor auxiliary interface for the BMM150 not initialized.");
}
rslt = bmm150_init(&mag_sensor);
if (rslt == BMM150_OK)
{
NRF_LOG_INFO("Magnetometer initialized.");
}
else
{
NRF_LOG_INFO("Magnetometer not initialized. Return value: %i", rslt);
}
nrf_mtx_init(&imu_data_mtx);
}
int8_t inertial_mag_sensor_config(void)
{
int8_t rslt;
/*Configuring accel and gyro sensors in normal mode */
/* Select the Output data rate, range of accelerometer sensor */
inertial_sensor.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
inertial_sensor.accel_cfg.range = BMI160_ACCEL_RANGE_4G; // To avoid overshoot when going over + or -
// 1G.
inertial_sensor.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; // No oversampling --> equidistant points
// over time, just normal mode. See p20
// datasheet. AVG = 4 means 4 averaging
// cycles
/* Select the power mode of accelerometer sensor */
inertial_sensor.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
/* Select the Output data rate, range of Gyroscope sensor */
inertial_sensor.gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
inertial_sensor.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;// See ABLE-1822 for reason of change from 500 to 2000 DPS
inertial_sensor.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; // No oversampling --> equidistant points
// over time, just normal mode. See p21
// datasheet
/* Select the power mode of Gyroscope sensor */
inertial_sensor.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
/* Set the sensor configuration */
rslt = bmi160_set_sens_conf(&inertial_sensor);
if (rslt == BMI160_OK)
{
NRF_LOG_INFO("Inertial sensor configured.");
}
else
{
NRF_LOG_INFO("Inertial sensor not configured.");
}
/* Configure the magnetometer. The regular preset supports up to 100Hz in Forced mode */
mag_sensor_settings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt = bmm150_set_presetmode(&mag_sensor_settings, &mag_sensor);
if (rslt == BMM150_OK)
{
NRF_LOG_INFO("Magnetometer is in preset mode");
}
else
{
NRF_LOG_INFO("Magnetometer could not be brought in preset 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 */
mag_sensor_settings.pwr_mode = BMM150_POWERMODE_FORCED;
rslt = bmm150_set_op_mode(&mag_sensor_settings, &mag_sensor);
if (rslt == BMM150_OK)
{
NRF_LOG_INFO("Magnetometer is in forced operation mode");
}
else
{
NRF_LOG_INFO("Magnetometer could not be brought in forced operation mode");
}
uint8_t bmm150_data_start = BMM150_REG_DATA_X_LSB;
inertial_sensor.aux_cfg.aux_odr = BMI160_AUX_ODR_100HZ;
rslt = bmi160_set_aux_auto_mode(&bmm150_data_start, &inertial_sensor);
/* Check rslt for any error codes */
if (rslt == BMI160_OK)
{
NRF_LOG_INFO("Data start has been set");
}
else
{
NRF_LOG_INFO("Data start could not be set");
}
return rslt;
}
int8_t inertial_mag_sensor_fifo_config(struct bmi160_dev* dev)
{
int8_t rslt = 0;
/* Modify the FIFO buffer instance and link to the device instance */
fifo_frame.data = fifo_buff;
fifo_frame.length = FIFO_SIZE;
//fifo_frame.fifo_header_enable = 0; // 1- Enable, 0-disable FIFO header usage
//fifo_frame.fifo_time_enable = 0; // 1- Enable, 0-disable sensor time usage
dev->fifo = &fifo_frame;
/* Disable other FIFO settings */
rslt = bmi160_set_fifo_config(BMI160_FIFO_CONFIG_1_MASK, BMI160_DISABLE, dev);
uint8_t fifo_config = BMI160_FIFO_HEADER | BMI160_FIFO_AUX | BMI160_FIFO_ACCEL | BMI160_FIFO_GYRO;
/* Configure the sensor's FIFO settings */
rslt = bmi160_set_fifo_config(fifo_config, BMI160_ENABLE, dev);
if (rslt == BMI160_OK)
{
NRF_LOG_INFO("IMU and magneto fifo configured.");
}
else
{
NRF_LOG_INFO("Error while doing IMU and magneto fifo configuration.");
}
return rslt;
}
void inertial_mag_sensor_test_data_read(void)
{
int8_t rslt = 0;
/* 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 */
inertial_sensor.fifo->length = FIFO_SIZE;
rslt = bmi160_get_fifo_data(&inertial_sensor);
/* Check rslt for any error codes */
uint8_t aux_inst = MAG_FRAMES, gyr_inst = GYR_FRAMES, acc_inst = ACC_FRAMES;
rslt = bmi160_extract_aux(auxil_data, &aux_inst, &inertial_sensor);
/* Check rslt for any error codes */
rslt = bmi160_extract_gyro(gyro_data, &gyr_inst, &inertial_sensor);
/* Check rslt for any error codes */
rslt = bmi160_extract_accel(accel_data, &acc_inst, &inertial_sensor);
/* Check rslt for any error codes */
for ( uint8_t i = 0; i < acc_inst; i++)
{
NRF_LOG_INFO("Accel data gx:%d\tgy:%d\tgz:%d\n", accel_data[i].x, accel_data[i].y, accel_data[i].z);
NRF_LOG_INFO("Gyro data gx:%d\tgy:%d\tgz:%d\n", gyro_data[i].x, gyro_data[i].y, gyro_data[i].z);
rslt = bmm150_aux_mag_data(&auxil_data[i].data[0], &magneto_data[i], &mag_sensor);
NRF_LOG_INFO("Mag data gx:%d\tgy:%d\tgz:%d\n", magneto_data[i].x, magneto_data[i].y, magneto_data[i].z);
}
} I am able to properly communicate and initialize the BMM150 through the BMI160, however, the data I get out of the function is keeping the magnetometer data at a constant number: <info> app: Mag data gx:-32768 gy:-32768 gz:-32768 whereas the accelerometer and gyroscope data are outputted properly. Could someone guide me what I am doing wrong, so I receive as well the magnetometer data? Thanks in advance. Kind regards, Tom
... View more