Bosch Sensortec Community

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

    Possible bug in BMX160 API for TAP settings?

    Possible bug in BMX160 API for TAP settings?

    rdehart
    Established Member

    Hi

    I was trying to setup the TAP sensing on a BMX160 sensor, using the API from GitHub.

    I had trouble setting the sensitivity of the TAP sensing and getting a TAP  interrupt triggering on INT2. The only real difference in tap force to detect a tap, was by changing the Acc range. I'll create an issue on this if I have further issues with it.
    When I printed out the registers to ensure they are being set correctly, I saw that the TAP_INT[0] and TAP_INT[1] registers were not being updated according to my settings.
    Also the tap INT was being set on INT1 instead of INT2

    Here is my init code (without my fix):

     // --------------- Init BMX160 ---------------------
      bmi.id = BMI160_I2C_ADDR;
      bmi.interface = BMI160_I2C_INTF;
      bmi.read = I2C_0_readDataBlock;
      bmi.write = performDimWrite;
      bmi.delay_ms = delay_miliSec;
    
      bmm.dev_id = BMM150_DEFAULT_I2C_ADDRESS;
      bmm.intf = BMM150_I2C_INTF;
      bmm.read = bmm150_aux_read;
      bmm.write = bmm150_aux_write;
      bmm.delay_ms = delay_miliSec;
    
      rslt_ = bmi160_init(&bmi);
      printf("bmi160_init:%i\r\n", rslt_);
    
      bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
      bmi.aux_cfg.aux_i2c_addr = bmm.dev_id;
      bmi.aux_cfg.manual_enable = BMI160_ENABLE;
      bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3;
    
      rslt_ = bmi160_aux_init(&bmi);
      printf("bmi160_aux_init:%i\r\n", rslt_);
    
      rslt_ = bmm150_init(&bmm);
      printf("bmm150_init:%i\r\n", rslt_);
      
      //// --------------- Acc & Gryo ---------------------
      ////printf("Init:AccGyro\r\n");
      //// Configure accel and gyro sensors in normal mode
      
      bmi.accel_cfg.odr = BMI160_ACCEL_ODR_50HZ;
      bmi.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
      bmi.accel_cfg.bw = BMI160_ACCEL_BW_OSR4_AVG1;
      bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
    
      bmi.gyro_cfg.odr = BMI160_GYRO_ODR_50HZ;
      bmi.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
      bmi.gyro_cfg.bw = BMI160_GYRO_BW_OSR4_MODE;
      bmi.gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
    
      rslt_ = bmi160_set_sens_conf(&bmi);
      printf("bmi160_set_sens_conf:%i\r\n", rslt_);
    
    
      // Configure sensor interrupt (Data Ready)
      //printf("Init:DataReady\r\n");
      /* Select the Interrupt channel/pin */
      bmi_int_config.int_channel = BMI160_INT_CHANNEL_1;// Interrupt channel/pin 1
      /* Select the Interrupt type */
      bmi_int_config.int_type = BMI160_ACC_GYRO_DATA_RDY_INT;// Choosing Data Readay interrupt
      /* Select the interrupt channel/pin settings */
      bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
      bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
      bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
      bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
      bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
      bmi_int_config.int_pin_settg.latch_dur =BMI160_LATCH_DUR_NONE;// non-latched output
      /* Set the Data Ready interrupt */
      rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */
      printf("bmi160_set_int_config:%i\r\n", rslt_);
    
      // Configure sensor interrupt (Tap)
      //printf("Init:Tap\r\n");
      /* Select the Interrupt channel/pin */
      bmi_int_config.int_channel = BMI160_INT_CHANNEL_2;// Interrupt channel/pin 2
      /* Select the Interrupt type: Tap */
      bmi_int_config.int_type = BMI160_ACC_SINGLE_TAP_INT;// Choosing Step Detector interrupt
      /* Select the interrupt channel/pin settings */
      bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
      bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
      bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
      bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
      bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
      bmi_int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;// non-latched output
      /* Select the Step Detector interrupt parameters, Kindly use the recommended settings for step detector */
      bmi_int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE;// 1-enable, 0-disable the detector
      bmi_int_config.int_type_cfg.acc_tap_int.tap_data_src=BMI160_ENABLE; // use pre-filter
      bmi_int_config.int_type_cfg.acc_tap_int.tap_dur = 0b001;
      bmi_int_config.int_type_cfg.acc_tap_int.tap_quiet = BMI160_DISABLE;  // 30/20ms
      bmi_int_config.int_type_cfg.acc_tap_int.tap_shock = BMI160_DISABLE;  // 50/75ms
      bmi_int_config.int_type_cfg.acc_tap_int.tap_thr = 0b11111; // 125mg/2 = 62.5mg per bit (4g range)

    Here is the code that I ran directly after this init procedure to print out the registers:

      // check if Tap INT1 is enabled
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_2_ADDR ,  &rslt_, 1);
        printf("IntMap2=%x\r\n", rslt_ );
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_1_ADDR ,  &rslt_, 1);
        printf("IntMap1=%x\r\n", rslt_ );
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_0_ADDR ,  &rslt_, 1);
        printf("IntMap0=%x\r\n", rslt_ );
      
      // check if Tap detection is enabled
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_ENABLE_2_ADDR ,  &rslt_, 1);
        printf("IntEn2=%x\r\n", rslt_ );
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_ENABLE_1_ADDR ,  &rslt_, 1);
        printf("IntEn1=%x\r\n", rslt_ );
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_ENABLE_0_ADDR ,  &rslt_, 1);
        printf("IntEn0=%x\r\n", rslt_ );
      
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_TAP_0_ADDR ,  &rslt_, 1);
        printf("INT_TAP[0]=%x\r\n", rslt_ );
        I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_TAP_1_ADDR ,  &rslt_, 1);
        printf("INT_TAP[1]=%x\r\n", rslt_ );

    Here is the output of the printout:

    IntMap2=0
    IntMap1=80
    IntMap0=20
    IntEn2=0
    IntEn1=10
    IntEn0=20
    INT_TAP[0]=7
    INT_TAP[1]=a

     

    Then I had-coded the TAP registers, by changing the TAP init sequence to the following (before the printf sequence):

      // Configure sensor interrupt (Tap)
      //printf("Init:Tap\r\n");
      /* Select the Interrupt channel/pin */
      bmi_int_config.int_channel = BMI160_INT_CHANNEL_2;// Interrupt channel/pin 2
      /* Select the Interrupt type: Tap */
      bmi_int_config.int_type = BMI160_ACC_SINGLE_TAP_INT;// Choosing Step Detector interrupt
      /* Select the interrupt channel/pin settings */
      bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
      bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
      bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
      bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
      bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
      bmi_int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;// non-latched output
      /* Select the Step Detector interrupt parameters, Kindly use the recommended settings for step detector */
      bmi_int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE;// 1-enable, 0-disable the detector
      bmi_int_config.int_type_cfg.acc_tap_int.tap_data_src=BMI160_ENABLE; // use pre-filter
      bmi_int_config.int_type_cfg.acc_tap_int.tap_dur = 0b001;
      bmi_int_config.int_type_cfg.acc_tap_int.tap_quiet = BMI160_DISABLE;  // 30/20ms
      bmi_int_config.int_type_cfg.acc_tap_int.tap_shock = BMI160_DISABLE;  // 50/75ms
      bmi_int_config.int_type_cfg.acc_tap_int.tap_thr = 0b11111; // 125mg/2 = 62.5mg per bit (4g range)
      // Setup INT_TAP[0] correctly
      rslt_ = 0b00000111;
      performDimWrite(BMI160_I2C_ADDR, BMI160_INT_TAP_0_ADDR, &rslt_, 1 );
      // Setup INT_TAP[1] correctly
      rslt_ = 0b00001111;
      performDimWrite(BMI160_I2C_ADDR, BMI160_INT_TAP_1_ADDR, &rslt_, 1 );
      
      /* Set the Tap Detector interrupt */
      rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */  
      printf("bmi160_set_int_config:%i\r\n", rslt_);
      
      // correct INT channel for Tap. Bug in library
      // disable int1_s_tap
      I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_0_ADDR ,  &rslt_, 1);
      rslt_ = rslt_ & 0b11011111;
      performDimWrite(BMI160_I2C_ADDR, BMI160_INT_MAP_0_ADDR, &rslt_, 1 );
      // enable int2_s_tap
      I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_2_ADDR ,  &rslt_, 1);
      rslt_ = rslt_ | 0b00100000;
      performDimWrite(BMI160_I2C_ADDR, BMI160_INT_MAP_2_ADDR, &rslt_, 1 );

    which gave the following output:

    IntMap2=20
    IntMap1=80
    IntMap0=0
    IntEn2=0
    IntEn1=10
    IntEn0=20
    INT_TAP[0]=7
    INT_TAP[1]=f

     

    After hard-coding the registers, TAP sensing was generating an interrupt on INT2.

    Is there a bug in the API?

     

    2 REPLIES 2

    o_o
    Contributor
    Hi rdehart,

    I looked up the code for setting the interrupt mapping carefully. Although a bit obscure, the sensor API code seems to be correct.

    TAP[0]
    TAP duration is a parameter only used in the double-tap interrupt, therefore the value is not set in single-tap. It is normal to see a mismatch there between your setting and the readout. What is not normal, is that the reset value is 0x04 and you read out 0x07.

    TAP[1]
    TAP1 is the threshold. Default value is 0x0A, you are putting 0x1F in your data structure, but 0x0F with your direct register access.


    In all your sample code snippets so far, you seem to be missing the call to bmi160_set_int_config after filling the data structure for Tap interrupt config, is this simply the issue? If it isn't we would definitely need to see a logic analyzer trace of the bus activity to debug further.

    rdehart
    Established Member

    Hi o_o

    I added a function to print out the BMX160's registers, 1sec after init completed. This helped me to debug.

    I added bmi160_set_int_config just after the TAP config. This did help, but on its own did not solve my problem.

    What I found to be the final crucial step is the order of bmi160_set_int_config,bmi160_set_sens_conf and bmi160_set_power_mode. (I couldn't find where the GitHub README is clear on this).

    I originally had the order as follows (without bmi160_set_power_mode) - NOT WORKING:

    1. bmi160_init
    2. bmi160_set_sens_conf
    3. bmi160_set_int_config

    The registers were set correctly when I added (bmi160_set_power_mode) and set the order as follows - WORKING:

    1. bmi160_init
    2. bmi160_set_int_config
    3. bmi160_set_sens_conf
    4. bmi160_set_power_mode

     

    For those who need a guide, here is what my init code looks like:

    struct bmi160_dev bmi;
    
    // --------------- Init BMX160 ---------------------
    bmi.id = BMI160_I2C_ADDR;
    bmi.interface = BMI160_I2C_INTF;
    bmi.read = I2C_0_readDataBlock;
    bmi.write = performDimWrite;
    bmi.delay_ms = delay_miliSec;
    
    bmm.dev_id = BMM150_DEFAULT_I2C_ADDRESS;
    bmm.intf = BMM150_I2C_INTF;
    bmm.read = bmm150_aux_read;
    bmm.write = bmm150_aux_write;
    bmm.delay_ms = delay_miliSec;
    
    rslt_ = bmi160_init(&bmi);
    printf("bmi160_init:%i\r\n", rslt_);
    
    // --------------- Acc & Gryo ---------------------
    // Configure accel and gyro sensors in normal mode
    bmi.accel_cfg.odr = BMI160_ACCEL_ODR_50HZ;
    bmi.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
    bmi.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
    bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
    
    bmi.gyro_cfg.odr = BMI160_GYRO_ODR_50HZ;
    bmi.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
    bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
    bmi.gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
    
    struct bmi160_int_settg bmi_int_config;
    // Configure sensor interrupt (Data Ready)
    printf("Init:DataReady\r\n");
    /* Select the Interrupt channel/pin */
    bmi_int_config.int_channel = BMI160_INT_CHANNEL_1;// Interrupt channel/pin 1
    /* Select the interrupt channel/pin settings */
    bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
    bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
    bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
    bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
    bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
    bmi_int_config.int_pin_settg.latch_dur =BMI160_LATCH_DUR_NONE;// non-latched output
    /* Select the Interrupt type */
    bmi_int_config.int_type = BMI160_ACC_GYRO_DATA_RDY_INT;// Choosing Data Ready interrupt
    /* Set the Data Ready interrupt */
    rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */
    printf("bmi160_set_int_config:%i\r\n", rslt_);
    
    // Configure sensor interrupt (Tap)
    printf("Init:Tap\r\n");
    /* Select the Interrupt channel/pin */
    bmi_int_config.int_channel = BMI160_INT_CHANNEL_2;// Interrupt channel/pin 2
    /* Select the interrupt channel/pin settings */
    bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
    bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
    bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
    bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
    bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
    bmi_int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;// non-latched output
    /* Select the Interrupt type: Tap */
    bmi_int_config.int_type = BMI160_ACC_SINGLE_TAP_INT;// Choosing Step Detector interrupt
    /* Select the Step Detector interrupt parameters, Kindly use the recommended settings for step detector */
    bmi_int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE;// 1-enable, 0-disable the detector
    bmi_int_config.int_type_cfg.acc_tap_int.tap_data_src=BMI160_ENABLE; // use pre-filter
    // bmi_int_config.int_type_cfg.acc_tap_int.tap_dur = 1; // not applicable to single tap
    bmi_int_config.int_type_cfg.acc_tap_int.tap_quiet = BMI160_DISABLE;  // 30/20ms
    bmi_int_config.int_type_cfg.acc_tap_int.tap_shock = BMI160_DISABLE;  // 50/75ms
    bmi_int_config.int_type_cfg.acc_tap_int.tap_thr = 0b00001; // 125mg/2 = 62.5mg per bit (4g range)
    /* Set the Tap Detector interrupt */
    rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */
    printf("bmi160_set_int_config:%i\r\n", rslt_);
    
    /* Set the sensor configuration */
    rslt_ = bmi160_set_sens_conf(&bmi);
    printf("bmi160_set_sens_conf:%i\r\n", rslt_);
    
    /*  Set the Power mode  */
    rslt_ = bmi160_set_power_mode(&bmi);
    printf("bmi160_set_power_mode:%i\r\n", rslt_);

     

     Thanks for the help o_o

    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