BMM150 outputting -32768 while using it in auxiliary mode with BMI160

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 

3 replies