Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    BMI160/BMM150 drivers not consistent with user guides

    BMI160/BMM150 drivers not consistent with user guides

    liamsm
    Member

    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:

    1. The wrapper functions no longer take the device id, and now takes a bmi160_dev struct
    2. The bmm150_dev type no longer has an id or settings attribute, and takes instead an interface pointer
    3. The bmm150_dev object now uses a microsecond delay function, not a millisecond delay function
    4. The bmm150_set_op_mode and bmm150_set_presetmode functions now take a separate bmm150_settings struct

    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);
    }
    }

     

    3 REPLIES 3

    Minhwan
    Community Moderator
    Community Moderator

    Hello, 

     

    Thank you for info. 

    I also noticed this issue, and let team know. 

    If you have COINES and our application board 2.0, you can check with my code. 

    Please let me know if you have further quesitons. 

    Thank you. 

    Thanks, I will review this and see what I get.

    owain-incus
    Established Member

    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

     

    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