I designed a board containing a number of MEMS sensors (LSM6DSM, LPS22HH, etc), and had it manufactured by PCBWay.
The board is intended to hook up to a Single Board embedded Linux machine via an i2c bus. The board also incorporates an ESP32S2, which at this time is not being used. There are actually two i2c busses, one internal to the board, and one between the ESP32 and the Linux machine, however, the busses are shorted together so that the Linux machine can directly talk to the sensors.
From what I can tell, the sensors seem to be working okay, except the LSM6DSM (tri-axis accelerometer/gyro) is acting... funny. I'm using it in continuous FIFO mode, at 108Hz, with no decimation. I'm configuring it as follows:
{0x12,0x44}, // CTRL3_C set to BDU + IF_INC
{0x08,0x09}, // FIFO_CTRL3 set to no decimation (accel+gyro)
{0x0a,0x2e}, // FIFO_CTRL5 set to continuous mode, 104 Hz (accel+gyro)
{0x10,0x40}, // CTRL1_XL set to 104Hz, +/- 2g, ODR/2
{0x11,0x42}, // CTRL2_G set to 104Hz, +/- 125 dps
{0x14,0x60}}; // CTRL5_C set to rounding for accel+gyro
Every 150ms, I run a function that does the following:
read FIFO_STATUS1/2 (0x3a/0x3b) to get the num_samples
for (i=0;i<num_samples;++i) {
read FIFO_STATUS3 (0x3c) to get the FIFO_PATTERN
read FIFO_DATAOUT_L/H(0x3e/0x3f) to get data
printf ("%d %d %d\n",i,FIFO_PATTERN,data);
}
What should be happening is that the the FIFO_PATTERN should be incrementing from 0 to 5 and then returning to 0. Pattern 5 should be Accel in Z direction (i.e. 1G, or ~16384).
This is what usually happens, but if you run the program long enough, you'll see FIFO_PATTERN skip to a different value (sometimes not even between 0 and 5). Skips are typically either jump by one in the pattern, or a completely random number (outside the 0-5 range). When it skips to a random number, it'll keep giving random numbers for maybe 20 samples, and then get back to 0-5. When it skips to a different value that is in 0-5, it returns to the increment by 1 pattern, but it is no longer synchronized with the data.
I've also seen data skipped. So for example, you should see 16384 every 6 samples, but sometimes it'll miss 1 and you'll see it 11 samples later. So both the data and pattern can get desynchronized. However, it is interesting to note that when the data skips, it is ALWAYS by a complete sample (16-bits), not 8-bits.
The behavior is repeatable but somewhat random (i.e. you may have to run the program for 20 seconds, or 5 minutes, before it happens, but it will happen). I had four boards built up, they all exhibit the same behavior. The LPS22 seems to be working okay, although I haven't tested it nearly as extensively. The sensor is giving about 560 uG's of noise, which is less than the quoted typical number of ~750 uG's at 108Hz, and I went to great pains to keep the power supplies clean.
Sending a software reset (0x01 to address 0x12) seems to fix it (temporarily). I also tried an experiment where I sent a reset, initialized everything and read for a few seconds, stopped, and then restarted many minutes later (repeatedly) for a few seconds. Every time, it worked fine. In other words, the problem appears to be occurring as a result of reading or somehow interacting with the LSM6DSM, it doesn't just get screwed up on its own.
I tried looking at the i2c bus on my scope (DS1054Z), there are occasional undershoots to about -1.1V on falling edge transitions of the data line, and some (+/-150mV) on cross-talk, but generally the signal is pretty clean on rising edges of the clock. When using the scope in decode mode, I am seeing exactly what I think I am sending (and receiving) on the scope. Although the scope produces a "?" (failure to acknowledge) after the last byte of each read -- which I think is expected behavior.
FWIW, I realize that the way I'm reading the FIFO out is unusual. I was initially reading the number of samples, the FIFO_PATTERN, and then reading out all the data in the buffer in one go, i.e.
Read 2 bytes at 0x3a to get num_samples
Read 1 byte 0x3c to get FIFO_PATTERN
Read num_samples * 2 bytes at 0x3e to get data
Which is obviously *WAY* more efficient... However, this exhibited the same problem, so I am now reading them individually to try to improve my ability to debug.