Skip to main content
Explorer
November 18, 2023
Question

Enabling FIFO on LSM6DSOX

  • November 18, 2023
  • 11 replies
  • 5518 views

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

 

    This topic has been closed for replies.

    11 replies

    Visitor II
    January 27, 2025

    OK, results are in...
    FIFO STATUS before/after reading data: 0x8009 / 0x0000

    Upper bit is the FIFO_WTM_IA and since I use a watermark of 9 that fits the bottom 10 bits showing 9.

    amarcoAuthor
    Explorer
    January 28, 2025

    Hi Kirreaa,

    I have been doing some tries with the interrupt, and I found that when I was setting the fifo stream mode, after reading the value I get a bypass value, thus it appears to be a misconfiguration on the communication on the SPI line and I was reading always 0x00... (just for making a quick try...)

    I tried with another hardware configuration, and I was able to pass the watermark flag loop, thus I think my initial problem was in the block_data_update+reg_status2 reading (I also found the note in the dataset warning about it's required reading both registers when bloc_data_update enabled).

    Now I'm facing troubles with the lsm6dsox_fifo_data_level_get(&imu_dev, &fifo_num_samples), as it gets also 0 samples stored, but I will investigate that later...

    Thankyou very much for pointing me on the block_data_update!

     

    Regards,

    Álvaro