2019-05-21 06:24 PM
Hi, I'm using the LIS3DH to detect body movement, but I'm suspecting that the accelerometer is defective as the samples do not seem reasonable (for example, when testing a single axis and turning it all around, it won't go from 1 to -1 g).
I wrote a program to use the self test feature, and this is what I got from it, while leaving the LIS3DH resting horizontally with the Z axis pointing down:
OUTX_NOST 1: 0x7F80 2: 0x7F80 3: 0x7F80 4: 0x7F80 5: 0x7F80
OUTY_NOST 1: 0x7F80 2: 0x7F80 3: 0x7F80 4: 0x7F80 5: 0x7F80
OUTZ_NOST 1: 0x6240 2: 0x6100 3: 0x6300 4: 0x62C0 5: 0x6140
=========
OUTX_ST 1: 0xFFFF 2: 0xFFFF 3: 0xFFFF 4: 0xFFFF 5: 0xFFFF
OUTY_ST 1: 0xFFFF 2: 0xFFFF 3: 0xFFFF 4: 0xFFFF 5: 0xFFFF
OUTZ_ST 1: 0xFFFF 2: 0xFFFF 3: 0xFFFF 4: 0xFFFF 5: 0xFFFF
I didn't want to average the 5 samples within the program, so I sent all of them so I could analyze them. Of course, all the registers are set as the procedure states on the AN3308 document, on page 57.
I'm wondering what the samples from the ST mean. They are all FFFF; does this mean it's not working properly?
Please advice, thanks!
2019-05-22 03:46 AM
Hi Max, so the CTRL_REG1 is well configured, as I understand. Did you check the integrity of the I2C communication e.g. checking the WHO_AM_I (0Fh) reg (value read has to be 33h)? Have you the possibility to check another device? Did you get the FFFFh value only during self test or also with normal mode running? Regards
2019-05-22 06:42 AM
Thanks for your answer, Eleon.
The configuration of each register is exactly as the procedure states (50Hz, normal mode, etc). I'm using SPI and I know the comms are working, as I can read the WHO_AM_I register fine.
The 0xFFFF values are coming after enabling the self test. The values before it are different (they are stored in the ST and NOST registers respectively, as I show above). I've been testing the accelerometer for a while but failed to get "reasonable" measurements. I could never get to measure 1g on any axis, which is why I tried the self test to see if there is something wrong with it.
Unfortunately, I don't have another test board to try it out. I will most likely get a couple more just to be sure, but I still want to know if there results point to a defective unit, or if there might be something else going on.
Is there something you would recommend doing to be sure if it's broken or not?
2019-05-27 01:49 AM
Hi Max, for my understanding the flow was the following, right? You saw the sensor output never gave 1g on any axis (also the resultant on the 3 axis is never 1g), you tried the self test according to p.57 of the app note that went wrong and after that you re-check the sensor and it was broken, right? Or did it simply give the same results as before the self test)?
Just for checking, which ODR did you set in reg CTRL_REG1 (20h)? You have to format the data according to this table. Regards
2019-05-27 05:11 AM
I set the configuration registers as the procedure states. CTRL_REG1 is set to 47h, which sets an ODR of 50Hz. I also made sure to wait the stated time to allow for powering up and stabilization, in addition to discarding the first samples.
The tests I had previously done never gave reasonable results. Even when placing the accelerometer at rest and as flat as possible, I never got to measure anywhere close to 1g in any of the axes. As a matter of fact, when using it in the ±2g range, I always measured samples around the 25k mark (I mean the 16-bit integer from joining both the high and low bytes), which corresponds to more than 1g (~25/32 * 2g = 1,5g).
The self test by itself does not seem to have broken the accelerometer, as it continues to work the same way after doing it. I just don't know how to interpret the results, even though I do think there's definitely something wrong there. The results of the self test shouldn't be FFFFh, and even less on every axis, right? I don't have access to my program right now, but I will share the program with you, in case I were to be doing something wrong.
2019-05-27 09:27 PM
This is an extract of the program I'm running. I run the Self Test by calling the SelfTest procedure, than also uses the ReadNextSample function.
Let me know if you find anything wrong with it. I think it's pretty straightforward.
void SelfTest() {
int OUTX_NOST1, OUTY_NOST1, OUTZ_NOST1;
int OUTX_NOST2, OUTY_NOST2, OUTZ_NOST2;
int OUTX_NOST3, OUTY_NOST3, OUTZ_NOST3;
int OUTX_NOST4, OUTY_NOST4, OUTZ_NOST4;
int OUTX_NOST5, OUTY_NOST5, OUTZ_NOST5;
int OUTX_ST1, OUTY_ST1, OUTZ_ST1;
int OUTX_ST2, OUTY_ST2, OUTZ_ST2;
int OUTX_ST3, OUTY_ST3, OUTZ_ST3;
int OUTX_ST4, OUTY_ST4, OUTZ_ST4;
int OUTX_ST5, OUTY_ST5, OUTZ_ST5;
int TempX, TempY, TempZ;
char textoint[5];
// Configure LIS3DH
WriteRegister(CTRL_REG2, 0x00);
WriteRegister(CTRL_REG3, 0x00);
WriteRegister(CTRL_REG4, 0x80);
WriteRegister(CTRL_REG1, 0x47);
// Wait to stabilize
Delay_ms(90);
// Read and discard the first samples
while ((ReadRegister(STATUS_REG)&0x08) != 0x08) { }
ReadRegister(OUT_X_L);
ReadRegister(OUT_X_H);
ReadRegister(OUT_Y_L);
ReadRegister(OUT_Y_H);
ReadRegister(OUT_Z_L);
ReadRegister(OUT_Z_H);
// Read next 5 samples
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_NOST1 = TempX;
OUTY_NOST1 = TempY;
OUTZ_NOST1 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_NOST2 = TempX;
OUTY_NOST2 = TempY;
OUTZ_NOST2 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_NOST3 = TempX;
OUTY_NOST3 = TempY;
OUTZ_NOST3 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_NOST4 = TempX;
OUTY_NOST4 = TempY;
OUTZ_NOST4 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_NOST5 = TempX;
OUTY_NOST5 = TempY;
OUTZ_NOST5 = TempZ;
// =========================
// Activate Self Test mode
// =========================
WriteRegister(CTRL_REG4, 0x23);
// Wait to stabilize
Delay_ms(90);
// Read first sample and discard it
while ((ReadRegister(STATUS_REG)&0x08) != 0x08) { }
ReadRegister(OUT_X_L);
ReadRegister(OUT_X_H);
ReadRegister(OUT_Y_L);
ReadRegister(OUT_Y_H);
ReadRegister(OUT_Z_L);
ReadRegister(OUT_Z_H);
// Read next 5 samples
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_ST1 = TempX;
OUTY_ST1 = TempY;
OUTZ_ST1 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_ST2 = TempX;
OUTY_ST2 = TempY;
OUTZ_ST2 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_ST3 = TempX;
OUTY_ST3 = TempY;
OUTZ_ST3 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_ST4 = TempX;
OUTY_ST4 = TempY;
OUTZ_ST4 = TempZ;
ReadNextSample (&TempX, &TempY, &TempZ);
OUTX_ST5 = TempX;
OUTY_ST5 = TempY;
OUTZ_ST5 = TempZ;
// End Self Test
WriteRegister(CTRL_REG1, 0x20);
WriteRegister(CTRL_REG4, 0x23);
// Show values
UART1_Write_Text("OUTX_NOST 1: 0x");
IntToHex(OUTX_NOST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTX_NOST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTX_NOST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTX_NOST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTX_NOST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("OUTY_NOST 1: 0x");
IntToHex(OUTY_NOST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTY_NOST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTY_NOST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTY_NOST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTY_NOST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("OUTZ_NOST 1: 0x");
IntToHex(OUTZ_NOST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTZ_NOST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTZ_NOST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTZ_NOST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTZ_NOST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("=========");
UART1_Write(CR);
UART1_Write_Text("OUTX_ST 1: 0x");
IntToHex(OUTX_ST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTX_ST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTX_ST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTX_ST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTX_ST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("OUTY_ST 1: 0x");
IntToHex(OUTY_ST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTY_ST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTY_ST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTY_ST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTY_ST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("OUTZ_ST 1: 0x");
IntToHex(OUTZ_ST1, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 2: 0x");
IntToHex(OUTZ_ST2, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 3: 0x");
IntToHex(OUTZ_ST3, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 4: 0x");
IntToHex(OUTZ_ST4, textoint);
UART1_Write_Text(textoint);
UART1_Write_Text(" 5: 0x");
IntToHex(OUTZ_ST5, textoint);
UART1_Write_Text(textoint);
UART1_Write(CR);
UART1_Write_Text("=========");
UART1_Write(CR);
while (1) {
}
}
void ReadNextSample (int* X, int* Y, int* Z) {
char RegH, RegL;
unsigned int Temp;
while ((ReadRegister(STATUS_REG)&0x08) != 0x08) { }
RegH = ReadRegister(OUT_X_H);
RegL = ReadRegister(OUT_X_L);
Temp = RegH;
Temp = Temp << 8;
Temp = Temp | RegL;
*X = (int) Temp;
RegH = ReadRegister(OUT_Y_H);
RegL = ReadRegister(OUT_Y_L);
Temp = RegH;
Temp = Temp << 8;
Temp = Temp | RegL;
*Y = (int) Temp;
RegH = ReadRegister(OUT_Z_H);
RegL = ReadRegister(OUT_Z_L);
Temp = RegH;
Temp = Temp << 8;
Temp = Temp | RegL;
*Z = (int) Temp;
}