Skip to main content
Visitor II
November 28, 2019
Solved

LSM9DS1, FIFO, Duplicated data

  • November 28, 2019
  • 3 replies
  • 1568 views

Hi,

I'm acquiring gyros and accelerometers data through i2C bus, pulling the data from the FIFO asynchronously from the component acquisition frequency, but at a frequency close by (to avoid overfilling the FIFO).

Without metrological tools, I can still confirm readings are OK ( "g" on the axe pointing downward, sign of rotation etc ...).

However, when looking closer to the data, some are duplicated from one FIFO emptying to the next:0690X00000AsaAtQAJ.jpg

LSM is acquiring at 59.5Hz. I've tried to collect at several frequencies: 60Hz, 50Hz, 40Hz or 200Hz. Behavior occurrence vary, but is always present. Also, as visible on the table, it is not systematic, but when happening it is always first sample compare to last sample of previous batch.

Before reading the FIFO, I'm checking STATUS_REG for new data, and FIFO_SRC for FIFO size. Which, btw, highlights the Temp, Acc and gyro data are not writing in a single shoot into the FIFO.

I'm struggling on this topic for several days now. I'm about to write a turn around to compare last recorded sample to the first one of a new batch: but it is ugly.

Anyone encounter such behavior, or could provide any tips about what I'm doing wrong?

Below some extract from my code and LSM configuration.

Tanks in advance.

//LSM9DS1 configuration
#define CTRL_REG1_G_IxDflt 0b01000000 /* ACC & Gyro OutputDataRate= 59.5Hz; BW=16Hz; FullScale= 245dps */
#define CTRL_REG8_IxDflt 0b01000100 /* Normal reboot mode, No update until MSB read; Reg. addr. auto. inc.; LITTLE Endian mode, IT pinS active High, push-pull; 4-wire SPI, no reset requested */
#define CTRL_REG9_IxDflt 0b00000010 /* Enable FIFO, and NO!!! FIFO for TEMP data*/
#define FIFO_CTRL_IxDflt 0b00100000 /* Fill in fifo until full, then stop. No custom threshold for fifo*/
//Other settings remain at default values
 
int ReadSensor(sDevAccGyro *sIMU)
{
	uint8_t szBuf[14] = {0};
	
	struct i2c_rdwr_ioctl_data sI2cDataSet;
	struct i2c_msg sMsgList[4];
	//preparing i2c_rdwr_ioctl_data and i2c_msg structures
	//in order to use ioctl() with I2C_RDWR option
	//Good exemple: http://www.merkles.com/Using_I2C/5_struct_i2c_msg.html 
 
	
	//Reading New data flags and FIFO size
	//Custom fonction to acces LSM (based on LINUX Read() methode)
	ReadI2cRegister( iHandeler, iDeviceAddr, STATUS_REG_Addr, szBuf);
	ReadI2cRegister( iHandeler, iDeviceAddr, FIFO_SRC_Addr, (szBuf+1),false);
	int iStatus = szBuf[0];
	int iSamplesNb = (szBuf[1] & 0b00111111);
	
	//FIFO empting loop
	for (int i = 0; i < iSamplesNb; i++ )
	{
		//Avoid to read FIFO while new data are fiding in
		if( !(0x0 == iSamplesNb) && !(0x7 == iStatus) )
			return -3;
		
		ioctl(iHandeler, I2C_RDWR, &sI2cDataSet);
		//recovering data from sI2cDataSet structure
		//...
		ReadI2cRegister( iHandeler, iDeviceAddr, STATUS_REG_Addr, szBuf);
		iStatus = szBuf[0];
		memset(szBuf, 0x00, sizeof(szBuf));
	}
}

PS: there are some similarities with this post:

https://community.st.com/s/question/0D50X0000AxCwVUSQ0/lis2dh-fifo-documentation-and-usage-questions

    This topic has been closed for replies.
    Best answer by wpaul

    Hi,

    Issue is fixed :)

    It cames from the use of the "ioctl(iHandeler, I2C_RDWR, &sI2cDataSet);" methode. When returning to a regular posix read() methode, all worked well (obviously it take more time).

    At last to answer to @Eleon BORLINI​ question: LSM9DS1 datasheet mention "Temperature sensor output = 0 (typ.) at 25 °C, temperature sensitivity: 16 LSB/°C". So my sensor temperature was some 35°C, which is reasonable, the component being close to my µP.

    Cheers

    3 replies

    ST Employee
    November 28, 2019

    Hi @wpaul​ , one question before going deep in the request... are you really working at about 170 degrees Celsius? Regards

    wpaulAuthor
    Visitor II
    December 2, 2019

    Hi @Eleon BORLINI​ 

    Sorry I was away for a while.

    No, temperature is room temperature, some 22°C. The 170 came straight from the LSM9DS1. I believe it is shown in some tens of degree, but there must be some scale factor. I have some records made in a temperature chamber, so it will give me more insight about.

    Regards

    wpaulAuthorAnswer
    Visitor II
    January 10, 2020

    Hi,

    Issue is fixed :)

    It cames from the use of the "ioctl(iHandeler, I2C_RDWR, &sI2cDataSet);" methode. When returning to a regular posix read() methode, all worked well (obviously it take more time).

    At last to answer to @Eleon BORLINI​ question: LSM9DS1 datasheet mention "Temperature sensor output = 0 (typ.) at 25 °C, temperature sensitivity: 16 LSB/°C". So my sensor temperature was some 35°C, which is reasonable, the component being close to my µP.

    Cheers

    ST Employee
    January 13, 2020

    Hi @wpaul​ , maybe the use of "ioctl(iHandeler, I2C_RDWR, &sI2cDataSet);" method for FIFO asynchronous mode missed a few samples during the reading, or you were too fast in reading the FIFO and the data was not yet updated... did you try to set the BDU bit in CTRL_REG8 (22h) before switching method? Regards

    wpaulAuthor
    Visitor II
    January 13, 2020

    Hi,

    Thank you for the return.

    Yes, BDU is ON.

    I'm missing details about how the "ioctl(...,I2C_RDWR,...)" work in the background.

    If by any chance you are familiar with and could share some insight, it would be highly    appreciated.

    Kind regards

    FYI: Below the structure transmitted to the method, based on info coming from http://www.merkles.com/Using_I2C/5_struct_i2c_msg.html and around.

    	struct i2c_rdwr_ioctl_data i2cDataSet;
    	struct i2c_msg msgList[4];
     
    	//Setting up first @register to read
    	msgList[0].addr = sIMU->iDeviceAddr; 	//Slave address
    	msgList[0].flags = 0;					//I2C write operation
    	msgList[0].len = 1;
    	msgList[0].buf = ucDataBank;			//TEMP @ register
     
    	//Setting up room for data set to read
    	msgList[1].addr = sIMU->iDeviceAddr;
    	msgList[1].flags = I2C_M_RD;			//I2C read operation
    	msgList[1].len = 14;					//Reading all date registers (TEMP_LSB, MSB, Gyro_X_L, _MSB, G_Y_L, _M, G_Z_L, _M, ACC_X_LSB, _MSB, ACC_Y_L, _MSB, A_Z_L, _M)
    	msgList[1].buf = cBuf;
     
    	//Wrapping all message into i2c_rdwr_ioctl_data type structure
    	i2cDataSet.msgs = msgList;
    	i2cDataSet.nmsgs = 2;