cancel
Showing results for 
Search instead for 
Did you mean: 

Enabling FIFO on LSM6DSOX

amarco
Associate II

Hi, 

 

I'm trying to get the FIFO working on the LSM6DSOX on a custom board with a silicon labs microcontroller, communicating both through SPI.

 

I have checked the application note at https://www.st.com/resource/en/application_note/an5272-lsm6dsox-alwayson-3axis-accelerometer-and-3axis-gyroscope-stmicroelectronics.pdf and followed the example code at https://github.com/STMicroelectronics/STMems_Standard_C_drivers/blob/master/lsm6dsox_STdC/examples/lsm6dsox_fifo.c, but no success, so I'm wondering if I'm missing something or it's a hardware problem. 

 

I'm able to read the device id and communicate normaly with the IMU through SPI, retrieving acc and gyro readings without issues.

 

This is my code for enabling the FIFO:

 

  lsm6dsox_reset_set(&imu_dev, PROPERTY_ENABLE);
  uint8_t rst;
  do {
    lsm6dsox_reset_get(&imu_dev, &rst);
  } while (rst);

  /* Disable I3C interface */
  lsm6dsox_i3c_disable_set(&imu_dev, LSM6DSOX_I3C_DISABLE);
  /* Enable Block Data Update */
  lsm6dsox_block_data_update_set(&imu_dev, PROPERTY_ENABLE);
  /* Set full scale */
  lsm6dsox_xl_full_scale_set(&imu_dev, LSM6DSOX_2g);
  lsm6dsox_gy_full_scale_set(&imu_dev, LSM6DSOX_2000dps);
  /*
   * Set FIFO watermark (number of unread sensor data TAG + 6 bytes
   * stored in FIFO) to 10 samples
   */
  lsm6dsox_fifo_watermark_set(&imu_dev, 10);
  /* Set FIFO batch XL/Gyro ODR to 12.5Hz */
  lsm6dsox_fifo_xl_batch_set(&imu_dev, LSM6DSOX_XL_BATCHED_AT_12Hz5);
  lsm6dsox_fifo_gy_batch_set(&imu_dev, LSM6DSOX_GY_BATCHED_AT_12Hz5);
  /* Set FIFO mode to Stream mode (aka Continuous Mode) */
  lsm6dsox_fifo_mode_set(&imu_dev, LSM6DSOX_STREAM_MODE);
  /* Enable drdy 75 μs pulse: uncomment if interrupt must be pulsed */
  //lsm6dsox_data_ready_mode_set(&imu_dev, LSM6DSOX_DRDY_PULSED);
  /* Uncomment if interrupt generation on Free Fall INT1 pin */
//  lsm6dsox_pin_int1_route_t int1_route;
//  lsm6dsox_pin_int1_route_get(&imu_dev, &int1_route);
//  int1_route.fifo_th = PROPERTY_ENABLE;
//  int1_route.fifo_full = PROPERTY_ENABLE;
//  int1_route.fifo_ovr = PROPERTY_ENABLE;
//  int1_route.fifo_bdr = PROPERTY_ENABLE;
//  lsm6dsox_pin_int1_route_set(&imu_dev, int1_route);
  /* Uncomment if interrupt generation on Free Fall INT2 pin */
//  lsm6dsox_pin_int2_route_t int2_route;
//  lsm6dsox_pin_int2_route_get(&imu_dev, NULL, &int2_route);
//  int2_route.fifo_th = PROPERTY_ENABLE;
//  int2_route.fifo_bdr = PROPERTY_ENABLE;
//  int2_route.fifo_full = PROPERTY_ENABLE;
//  int2_route.fifo_ovr = PROPERTY_ENABLE;
//  lsm6dsox_pin_int2_route_set(&imu_dev, NULL, int2_route);
  /* Set Output Data Rate */
  lsm6dsox_xl_data_rate_set(&imu_dev, LSM6DSOX_XL_ODR_12Hz5);
  lsm6dsox_gy_data_rate_set(&imu_dev, LSM6DSOX_GY_ODR_12Hz5);

 

(the lines that are commented are not exactly the same on the sample, as they didn't match actual reg type declarations) and for reading the FIFO I have:

 

uint8_t imu_read_fifo(bool read_acc, bool read_gyro, uint8_t *buffer, uint8_t max_samples_read, uint8_t* samples_read){

  uint8_t wmflag = 0;

  lsm6dsox_fifo_wtm_flag_get(&imu_dev, &wmflag);

  while (!wmflag) {
      lsm6dsox_fifo_wtm_flag_get(&imu_dev, &wmflag);
  }
  *samples_read = 0;
  uint16_t fifo_num_samples;
  lsm6dsox_fifo_data_level_get(&imu_dev, &fifo_num_samples);
  *samples_read = 0;
  if (fifo_num_samples == 0){
      return SL_STATUS_OK;
  } else if (fifo_num_samples < max_samples_read){
      max_samples_read = fifo_num_samples;
  }

  uint8_t data_len = 0;
  while (*samples_read < max_samples_read){
      uint8_t* acc_data = &buffer[data_len];
      uint8_t* gyro_data = &buffer[data_len + read_acc ? 6 : 0];
      imu_read_fifo_measure_nc(read_acc, read_gyro, acc_data, gyro_data);
      data_len +=  read_acc ? 6 : 0;
      data_len +=  read_gyro ? 6 : 0;
      (*samples_read) ++;
  }
  //lsm6dsl_fifo_raw_data_get(&imu_dev, buffer, len);
}

void imu_read_fifo_measure_nc(bool read_acc, bool read_gyro, uint8_t *acc_data, uint8_t *gyro_data){
  uint8_t dummy_data[6];
  uint8_t sensor_tag;

  uint16_t fifo_num_samples;
  lsm6dsox_fifo_data_level_get(&imu_dev, &fifo_num_samples);

  while (fifo_num_samples && (read_acc || read_gyro)){
      lsm6dsox_fifo_sensor_tag_get(&imu_dev, &sensor_tag);
      switch (sensor_tag) {
        case LSM6DSOX_XL_NC_TAG:
          lsm6dsox_fifo_out_raw_get(&imu_dev, acc_data);
          read_acc = false;
          break;
        case LSM6DSOX_GYRO_NC_TAG:
          lsm6dsox_fifo_out_raw_get(&imu_dev, gyro_data);
          read_gyro = false;
          break;
        default:
          lsm6dsox_fifo_out_raw_get(&imu_dev, dummy_data);
      }
      fifo_num_samples --;
  }
}

 

But the watermark flag never changed and I get stuck in the while loop. I have tried also placing the execution on the reading part, but I didn't get anything when calling lsm6dsox_fifo_data_level_get.

 

If there is no a hardware problem, I think maybe I'm missing a trigger condition for the FIFO, or anything else is needed for enablling it.

 

I have searched elsewhere and I found references to use compression which require enabling something else, but I didn't found specific references to that being required for just using the FIFO (neither I would need the watermark or the interrupt, I just need to buffer some samples while I'm writing a previous batch on a flash memory which uses the same SPI line and can operate on a poll basis).

 

I also found something related to timestamping samples:

 

  lsm6dsox_fifo_timestamp_decimation_set(&imu_dev, LSM6DSOX_DEC_1);
  lsm6dsox_timestamp_set(&imu_dev, PROPERTY_ENABLE);
  lsm6dsox_fifo_timestamp_decimation_set(&imu_dev, LSM6DSOX_NO_DECIMATION);

 

Playing with this, I was able to trigger the watermark, and data_level_get returns non 0 content, but lsm6dsox_fifo_sensor_tag_get(&imu_dev, &sensor_tag) gives sensor_tag = 0x00 (by the way, the switch case on the lsm6dsox_fifo_sensor_tag_get function defaults to GYRO_NC_TAG, https://github.com/STMicroelectronics/lsm6dsox-pid/blob/3c2d02b69cb18de0cabd94c15dcd73aab6bd6edb/lsm6dsox_reg.c#L7584, what leads to misinterpret that a gyro reading is retrieved when the sensor_tag reports 0, which was my case). And lsm6dsox_fifo_out_raw_get also return 0x00 for the six bytes.

 

The setup is placed on my desk, I'm not moving it while I'm making the trials, but the direct acc and gyro readings are coherent with that (1G on the z axis, near 0 on the others and small values for the gyro) and no other code is being executed

 

Any help will be appreciated!

 

Regards,

Álvaro

 

5 REPLIES 5
Federica Bossi
ST Employee

Hi @amarco ,

You can look at our PID examples on Github. You can find several examples about the use of the FIFO.

Hope this helps.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
amarco
Associate II

Hi Federica,

 

Yes, that is the exact code I used to enable the FIFO, but can't get any data... I have tested the code on another board to discard an IMU malfunction, but I get the same behaviour, so I guess I missing something when configuring the FIFO.

 

Regards,

Álvaro

Federica Bossi
ST Employee

Hi @amarco ,

Have you tried to acquire the outputs not using the FIFO?

Just to exclude problems related to your hardware.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
amarco
Associate II

Hi Federica,

 

Yes, I can get the acc and gyro readings without issues

 

Regards,

Álvaro

amarco
Associate II

Hi, any update on this? Can someone verify wether the sample code on https://github.com/STMicroelectronics/STMems_Standard_C_drivers/blob/master/lsm6dsox_STdC/examples/lsm6dsox_fifo.c actually works?

Regards,

Álvaro