Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

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

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

    Tokke93
    New Poster

    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-.... 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 3

    BSTRobin
    Community Moderator
    Community Moderator

    Hi Tokke93,

    It seems your software code didn't run normally after your software migration on your platform.
    I uploaded example code on STM32 for your reference, hope it will be helpful for you.

    Hi Robin, 

    Thank you for your reference code. I have been exploring it but without any luck. 
    The input parameters of bmm150_aux_mag_data does not align with the ones you input in bmi160_task.c in function vGetMagData. My compiler (SES) complains and it needs the mag_data as well. Therefore, I believe that there is a Inconsistency between drivers as seen in BMI160/BMM150 drivers not consistent with user guides . Can you check if I make the correct assumption and maybe guide me in how to debug this further? 

    Below you can find the schematic I have on my PCBA: 

    Tokke93_1-1706286697541.png

     


    Without the auxiliary interface and directly communicating with the magnetometer (case where I cutted SB2&4 and connect SB1&3), I am able to get correct data out of the magnetometer sensor. However, I would like to use the fifo watermark interrupt with fifo data containing the 9 DoF. Is there any example code for this as well?

    Kind regards, 
    Tom 

     

    BSTRobin
    Community Moderator
    Community Moderator

    Hi Tokke93,

    After check your hardware schematic, when using the auxiliary interface, A3(SCK) of BMM150 should be connected to pin 3(ASCL) of BMI160, and B4(SDI) of BMM150 should be connected to pin 2(ASDA) of BMI160. Your hardware circuit connection is reversed.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist