I’ve been trying to identify a proper guide to implement FIFO with XIAO BLE Sense. I’ve tried to follow the guide here (SparkFun_LSM6DS3) but the code seems to be stuck at “Clearning FIFO Buffer” print statement. Though the IMU.begin() function works correctly, the FIFO does not seem to fill up. Furthermore the myIMU.fifoGetStatus() & 0x8000 seems to always equal 0.
I’ve attached my code below:
#include <Wire.h>
#include <LSM6DS3.h>
LSM6DS3 myIMU(I2C_MODE, 0x6A);
float ax, ay, az;
float gx, gy, gz;
uint8_t readData = 0; // for IMU status read
uint16_t i = 0 ;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
// See LSM6D3.cpp:351
myIMU.settings.gyroRange = 2000;
myIMU.settings.accelRange = 4;
myIMU.settings.gyroFifoEnabled = 1; //Set to include gyro in FIFO
myIMU.settings.gyroFifoDecimation = 1; //set 1 for on /1
myIMU.settings.accelFifoEnabled = 1; //Set to include accelerometer in the FIFO
myIMU.settings.accelFifoDecimation = 1; //set 1 for on /1
//FIFO control settings
myIMU.settings.fifoThreshold = 1600; //Can be 0 to 4096 (16 bit bytes)
myIMU.settings.fifoSampleRate = 1600; //Hz. Can be: 10, 25, 50, 100, 200, 400, 800, 1600, 3300, 6600
myIMU.settings.fifoModeWord = 6; //FIFO mode.
if( myIMU.begin() != 0 )
{
Serial.println("Problem starting the sensor with CS @ Pin 10.");
}
else
{
Serial.println("Sensor with CS @ Pin 10 started.");
}
Wire1.setClock(400000UL); // I2C1 SCL=400kHz
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL2_G, 0x8C); //1.66kHz 2000dps
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, 0x8A); //1.66kHz 4G
// Set gyroscope power mode to high performance and bandwidth to 16 mHz
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL7_G, 0x00);
// Set the ODR config register to ODR/4
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL8_XL, 0x09);
Serial.print("Configuring FIFO with no error checking...");
myIMU.fifoBegin();
Serial.print("Done!\n");
Serial.print("Clearing out the FIFO...");
myIMU.fifoClear();
Serial.print("Done!\n");
}
void loop()
{
float temp; //This is to hold read data
uint16_t tempUnsigned;
while( ( myIMU.fifoGetStatus() & 0x8000 ) == 0 ) {Serial.println(myIMU.fifoGetStatus() & 0x8000 );}; //Wait for watermark
Serial.print("Loop"); Serial.print(i); Serial.println();
i++;
digitalWrite(LED_RED, LOW);
uint8_t dataBuff[6];
unsigned int timestamp = micros();
while( ( myIMU.fifoGetStatus() & 0x1000 ) == 0 ) {
dataBuff[0] = myIMU.calcGyro(myIMU.fifoRead());
dataBuff[1] = myIMU.calcGyro(myIMU.fifoRead());
dataBuff[2] = myIMU.calcGyro(myIMU.fifoRead());
dataBuff[3] = myIMU.calcAccel(myIMU.fifoRead());
dataBuff[4] = myIMU.calcAccel(myIMU.fifoRead());
dataBuff[5] = myIMU.calcAccel(myIMU.fifoRead());
delay(10); //Wait for the serial buffer to clear (~50 bytes worth of time @ 57600baud)
}
Serial.println(micros() - timestamp);
timestamp = micros();
tempUnsigned = myIMU.fifoGetStatus();
Serial.print("\nFifo Status 1 and 2 (16 bits): 0x");
Serial.println(tempUnsigned, HEX);
Serial.print("\n");
Serial.println(micros() - timestamp); // read 6 float data 1400uS
delay(5000);
}
Could someone please use this thread to point me to resources or explain the best way to implement FIFO for 1600 ODR for each accelerometer & gyroscope values. Hopefully, this will be a guide for others facing the same problem too.
I’m using the Seeed Arduino LSM6DS3 library (Board: XIAO nRF52840 Sense). I have both the mbed and non-mbed libraries installed (using non-mbed above). However, since there’s no proper documentation within the XIAO Seed Arduino Github for FIFO implementation, I’ve been following the Sparkfun github example with the Seeed Arduino LSM6DS3 library import (Linked above).
That’s interesting. But my code still seems to be stuck at
Serial.print("Clearing out the FIFO...");
myIMU.fifoClear();
For some reason, the code does not budge forward from this point. I’ve tried restarting the board, but no luck.
Update: So interestingly, I started playing with this line of code
myIMU.settings.gyroFifoDecimation = 1; //set 1 for on /1
myIMU.settings.accelFifoDecimation = 1; //set 1 for on /1
and now the code works for only FIFO sample rates up to 200Hz. Anything above 200Hz produces the first error. For values below 200Hz I’m facing the second problem as I mentioned in the original post.
myIMU.fifoGetStatus() & 0x8000 seems to always equals 0.
This causes the program to be stuck inside the while loop waiting for the FIFOGetStatus() to fill up, and the FIFO buffer never fills up.
This is in regards to the sample rate of the FIFO. In steady state, the output throughput must be greater than the input throughput to avoid overflow; it takes about 3ms to output 6 words of data over I2C, so the maximum sample rate of the FIFO is 300Hz, or 200Hz if you can set it. If SPI could be used, it would be possible to sample at a much faster rate.
Well, it kinda sucks that the internal IMU is hardwired to I2C within the XIAO. Would the assumption still stand if the I2C rate is increased to 400kHz or greater using the Wire.h library?
This is helpful! I tried explicitly setting the I2C rate to 800kHz and was able to acquire data by setting FIFO sample rate to 400 Hz, but that seems to be the limit.
At this point, before I debug any further, I would like to know whether if it is even possible to obtain a set of 1600 samples each (1600 each for ax, ay, az, gx, gy, gz) every second using the XIAO’s internal IMU?
According to the nRF52840 datasheet “6.29.9.1 TWI interface electrical specifications”, the I2C bit rate is up to 400 kbps.
Both gyro and accel should be able to sample at 1.66 kHz inside the IMU, but not read out over I2C. I am curious as to why such a fast sampling rate is necessary.
I’m using the XIAO to perform hand tracking using an RNN model to map the IMU LCS to WCS. In order to detect finger taps, the sampling rate has to be > 1.6kHz for reliable hand tracking (according to research papers). I thought the XIAO would satisfy all the requirements given its small size and IMU capabilities. But, I didn’t realize that the internal I2C would be a bottleneck.
I recommend connecting an IMU to XIAO_BLE via SPI.
The SPI transfer rate is 19.5 uS/byte for mbed or 5.6 uS/byte for non-mbed, based on the actual measurements in the link below.
When reading 12 bytes (6 data) from the FIFO, I think the FIFO can be sampled at 4.2 kHz or 14.8 kHz.