Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BMI160 High-G and FIFO Watermark Interrupt

    BMI160 High-G and FIFO Watermark Interrupt

    dbeckwith
    New Poster

    I have a BMI160 configured to provide the FIFO Watermark interrupt and high-g wakeup interrupt on channels 1 and 2 respectively.  When the device starts I see the FIFO watermark fire and it's gathering approximately 40 frames.  After the high-g interrupt fires then every subsiquent FIFO high watermark interrupt only gathers 4 frames of data. Why is this occuring and what can be done so the number of frames gathered goes back to 40.  I want to maximumize the time between high watermark interrupts to reduce load on my system.

    I have tried adusting the number of frames requested and flushing the FIFO this doesn't seem to make a difference.

    Here is the configuration (note I2C result checks have been removed for clarity)

     

    static void configureSensorDefaults(struct bmi160_dev* dev) {
     /* Select the Output data rate, range of accelerometer sensor */
      dev->accel_cfg.odr = BMI160_ACCEL_ODR_200HZ;
      dev->accel_cfg.range = BMI160_ACCEL_RANGE_4G;
      dev->accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
    
      /* Select the power mode of accelerometer sensor */
      dev->accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
    
      /* Select the Output data rate, range of Gyroscope sensor */
      dev->gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
      dev->gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;
      dev->gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
    
      /* Select the power mode of Gyroscope sensor */
      dev->gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
    
      int8_t result = bmi160_set_sens_conf(dev);
    }
    
    static void configureAccelFifo(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_BUFFER_LEN_BYTES;
      dev->fifo = &fifo_frame;
    
      /* Configure the sensor's FIFO settings */
      rslt = bmi160_set_fifo_config(BMI160_FIFO_ACCEL, BMI160_ENABLE, dev);
    
      /* Set the FIFO watermark level for the interrupt */
      rslt = bmi160_set_fifo_wm(69, dev);  // Note the watermark is in units of words (4 bytes) so 69
                                           // * 4 is 276
    }
    
    static void configureSensorInterrupts(struct bmi160_dev* dev) {
      int8_t result;
      struct bmi160_int_settg int_config;
    
      int_config.int_channel = BMI160_INT_CHANNEL_1;  // Interrupt channel/pin 1
    
      /* Select the Interrupt type */
      int_config.int_type = BMI160_ACC_GYRO_FIFO_WATERMARK_INT;  // Choosing watermark interrupt
      /* Select the interrupt channel/pin settings */
      int_config.int_pin_settg.output_en =
          BMI160_ENABLE;  // Enabling interrupt pins to act as output pin
      int_config.int_pin_settg.output_mode =
          BMI160_DISABLE;  // Choosing push-pull mode for interrupt pin
      int_config.int_pin_settg.output_type = BMI160_ENABLE;  // Choosing active high output
      int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;    // Choosing edge triggered output
      int_config.int_pin_settg.input_en = BMI160_DISABLE;    // Disabling interrupt pin to act as input
      int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;  // non-latched output
    
      /* Select the FIFO interrupt parameters */
      int_config.fifo_WTM_int_en = BMI160_ENABLE;  // 1- Enable, 0- Disable the watermark interrupt
    
      result = bmi160_set_int_config(&int_config, dev);
    
      /* Select the Interrupt channel/pin */
      int_config.int_channel = BMI160_INT_CHANNEL_2;  // Interrupt channel/pin 2
    
      /* Select the Interrupt type */
      int_config.int_type = BMI160_ACC_HIGH_G_INT;  // Choosing High-g interrupt
    
      /* Select the interrupt channel/pin settings */
      int_config.int_pin_settg.output_en =
          BMI160_ENABLE;  // Enabling interrupt pins to act as output pin
      int_config.int_pin_settg.output_mode =
          BMI160_DISABLE;  // Choosing push-pull mode for interrupt pin
      int_config.int_pin_settg.output_type = BMI160_ENABLE;        // Choosing active high output
      int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;          // Choosing edge triggered output
      int_config.int_pin_settg.input_en = BMI160_DISABLE;          // Disabling interrupt pin to act as
      int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;  // non-latched output
    
      int_config.int_type_cfg.acc_high_g_int.high_g_x = BMI160_ENABLE;
      int_config.int_type_cfg.acc_high_g_int.high_g_y = BMI160_ENABLE;
      int_config.int_type_cfg.acc_high_g_int.high_g_z = BMI160_ENABLE;
      int_config.int_type_cfg.acc_high_g_int.high_data_src=BMI160_DISABLE;
      int_config.int_type_cfg.acc_high_g_int.high_thres = 64;  // 1 g @ (value * 15.63mg for 4 g range)
      int_config.int_type_cfg.acc_high_g_int.high_dur = 7;     // 20 ms [(value + 1) * 2.5ms]
    
      result = bmi160_set_int_config(&int_config, dev);
    }

     

     

    Interrupt Handler:

     

    void interruptHandler(bool val, void* ctx) {
      struct bmi160_dev* dev = ctx;
      union bmi160_int_status int_status;
      int8_t rslt;
    
      rslt = bmi160_get_int_status(BMI160_INT_STATUS_1, &int_status, dev);
    
      if (int_status.bit.fwm == 1) {
        printf("FIFO high water mark interrupt");
      }
    
      if (int_status.bit.high_g == 1) {
        printf("High-G interrupt");
      }
    
      uint8_t data = 0x00;
      rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);  // disable the WM interrupt
    
      /* Declare instances of the sensor data structure to store the parsed FIFO data */
      struct bmi160_sensor_data accel_data[66];  // 896 bytes / ~7bytes per frame ~ 128 data frames
      uint8_t accel_frames_req = 66;
      uint8_t accel_index;
    
      /* Read data from the sensor's FIFO and store it the FIFO buffer,"fifo_buff" */
      LE_DEBUG("USER REQUESTED FIFO LENGTH : %d", dev->fifo->length);
    
      rslt = bmi160_get_fifo_data(dev);
      if (rslt == BMI160_OK) {
        printf("AVAILABLE FIFO LENGTH : %d", dev->fifo->length);
        /* Parse the FIFO data to extract gyro data from the FIFO buffer */
        printf("REQUESTED ACCEL DATA FRAMES : %d", accel_frames_req);
        rslt = bmi160_extract_accel(accel_data, &accel_frames_req, dev);
    
        if (rslt == BMI160_OK) {
          printf("AVAILABLE ACCEL DATA FRAMES : %d", accel_frames_req);
    
          /* Print the parsed gyro data from the FIFO buffer */
          for (accel_index = 0; accel_index < accel_frames_req; accel_index++) {
            printf("FIFO FRM [%d]: %d, %d, %d", accel_index, accel_data[accel_index].x,
                     accel_data[accel_index].y, accel_data[accel_index].z);
          }
       }
    }
    
      data = (BMI160_FIFO_WATERMARK_INT_EN_MASK | BMI160_HIGH_G_Z_INT_EN_MASK |
              BMI160_HIGH_G_Y_INT_EN_MASK | BMI160_HIGH_G_X_INT_EN_MASK);
      rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);  // enable the WM, and High-G interrupts
    
    }

     

     

    2 REPLIES 2

    Vincent
    Community Moderator
    Community Moderator

    It looks like a combination condition to trigger this case:

    1. in your interrupt handler funcion,  you will always call bmi160_get_fifo_data whatever interrupt received.

    2. in the funciton bmi160_get_fifo_data,  the API will call get_fifo_byte_counter to get the available FIFO bytes to read

    3.  if dev->fifo->Length is bigger than avaiable bytes to read, then Length will be given a small value.

    4.  Then you will read FIFO by dev->fifo->Length

    5.   In case, the bytes available is bigger than dev->fifo->Length. it will still keep the value.

    6.   when you high-g interrupt happened,  you also call bmi160_get_fifo_data.  Then only 4 frames available that time.   Then original your dev->fifo->Length is bigger than this value.  it will be reset as 4 frames bytes.

    7.    later on, for fifo water marker interrupt, even you have big bytes available, you will still read 4 frames because dev->fifo->Length  will not be given a bigger value

    8. then you keep read 4 frames afterwards. 

    BTW, you only enable accel data into FIFO, so each frame should be 6 bytes (without header).

     

    André
    Established Member

    one note: you should use bmi160_set_int_config() to set the specific interrupts because the bmx160 driver will make calls  to

    enable_fifo_wtm_int(int_config, dev);
    set_intr_pin_config(int_config, dev);
    map_hardware_interrupt(int_config, dev);

    to configure the interrupt correctly.

     

    By calling bmi160_set_regs you evade this which could lead to issues later on.  The whole idea is that the driver hides these details. So it is good practice not to call these low level functions from your code.

    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