2025-02-20 11:17 AM - edited 2025-02-20 11:59 AM
Hi,
I am using an LIS2DE12 in I2c mode. During setup, my code:
- wrote 0 to CTRL_REG4 (BDU=0, FS=00, ST=00, and SIM=0)
- wrote 0 to CTRL_REG2 (no high-pass filtering)
- wrote 0 to CTRL_REG5 (disable FIFO)
- wrote 0 to FIFO_CTRL_REG (selects Bypass mode)
- wrote 0b00111111 to CTRL_REG1 (sets ODR to 25Hz (40ms), LPen=1, X=1, Y=1, Z=1 which enables all 3 axes).
Then, approximately once every 100ms, my code does the following:
- It reads STATUS_REG and confirms that the 3 least significant bits are all 1.
- With one I2c transaction, it reads 5 bytes starting with register 0x29 (with the 0x80 bit set). This gives me the value from OUT_X_H in the first byte, OUT_Y_H in the third byte, and the value from OUT_Z_H in the fifth byte.
Will the values I get from OUT_X_H, OUT_Y_H, and OUT_Z_H always be coherent, i.e. from the same measurement?
OR is it possible that the chip could update some of these registers with a new measurement at the same time that my I2c transaction is reading them, such that one or two of the numbers I get are from one measurement (A) and the other number(s) I get are from a different measurement (B)?
If the answer is that they could be from different measurements, what strategy & algorithm should I use to guarantee that I always obtain a coherent vector from the latest measurement?
Thanks in advance.
2025-02-20 11:56 AM
Your current setup (BDU = 0) may result in mixed-data reads from different samples. Set BDU = 1 in CTRL_REG4 to prevent register updates during reading.
2025-02-20 03:09 PM
Normally BDU (block data update) would solve your problem. Unfortunately, for LIS2DE one has to set it to 0 when reading accelerometer data, and to 1 when reading temperature data.
When BDU is set to 0, it can happen that output registers are updated while readout is in progress; it can happen that then you read X relative to time t, and Y and Z relative to time t+Ts (where Ts is the sampling interval = 1/ODR, 40msec at 25Hz).
The output values are int8 and stored at 0x29 0x2B and 0x2D; values in 0x2A 0x2C should be ignored.
It seems your intent is to read fresh data, and this is why you have programmed an ODR = 25Hz, which is higher than the readout frequency of 10Hz. Unfortunately, looking at STATUS_REG can only tell you if there is data to be read and if the data has been 'overrun' meaning fresh data has overwritten stale data which have not been readout.
The solution is to readout twice and verify that X Y Z values do match both times.
Pseudo-code:
// X, Y, Z, X2, Y2, Z2 are all int8 variables
// get_value() takes the address of the register to be read, and a pointer to the variable where the value can be stored
while (1) {
get_value(0x29, &X); get_value(0x2B, &Y); get_value(0x2D, &Z);
get_value(0x29, &X2); get_value(0x2B, &Y2); get_value(0x2D, &Z2);
if ((X == X2) && (Y == Y2) && (Z == Z2)) break;
}
// at this point you can use X Y Z