I'm currently getting inconsistent data from the accelerometer of my Adafruit LSM9DS1. To be more precise I either get a value close to the correct gravity (eg. 9.496515) or some reading like it was in space/free fall (eg. -0.023928225).
This seems to happen on all three the axes (I tried rotating the LSM9DS1).
I get the same behavior with FIFO enabled or not and with the Gyro enabled or not.
This is a set of 32 consecutive samples that I read from the FIFO memory:
result = {float[32][]@5092}
0 = {float[3]@5100}
0 = -0.41754755
1 = 0.19501504
2 = 9.519247
1 = {float[3]@5112}
0 = -0.421735
1 = 0.19980069
2 = 9.51805
2 = {float[3]@5120}
0 = -0.4229314
1 = 0.20757735
2 = 9.510274
3 = {float[3]@5128}
0 = -0.4127619
1 = 0.2207379
2 = 9.502497
4 = {float[3]@5139}
0 = -0.39302114
1 = -0.06580262
2 = -0.0017946169
5 = {float[3]@5140}
0 = -0.06939186
1 = -0.045463633
2 = -0.020937197
6 = {float[3]@5141}
0 = -0.05742774
1 = -0.03469593
2 = -0.0317049
7 = {float[3]@5142}
0 = -0.053838514
1 = -0.039481573
2 = -0.041874394
8 = {float[3]@5143}
0 = -0.054436717
1 = -0.052642096
2 = -0.043669015
9 = {float[3]@5144}
0 = -0.059820566
1 = -0.068793654
2 = -0.03469593
10 = {float[3]@5145}
0 = -0.06819545
1 = 0.22731815
2 = -0.019142581
11 = {float[3]@5146}
0 = -0.38644087
1 = 0.2225325
2 = -0.00418744
12 = {float[3]@5147}
0 = -0.40079778
1 = 0.21535406
2 = 9.505488
13 = {float[3]@5148}
0 = -0.40977085
1 = 0.21355942
2 = 9.525827
14 = {float[3]@5149}
0 = -0.40917268
1 = 0.21296123
2 = 9.540783
15 = {float[3]@5150}
0 = -0.40558344
1 = 0.2207379
2 = 9.5455675
16 = {float[3]@5151}
0 = -0.39960137
1 = 0.22671993
2 = 9.544371
17 = {float[3]@5152}
0 = -0.39302114
1 = 0.22791636
2 = 9.534203
18 = {float[3]@5153}
0 = -0.3906283
1 = 0.21535406
2 = 9.517452
19 = {float[3]@5154}
0 = -0.38584265
1 = 0.19441684
2 = 9.496515
20 = {float[3]@5155}
0 = -0.384048
1 = 0.17347965
2 = -0.023928225
21 = {float[3]@5156}
0 = -0.38883367
1 = 0.15553348
2 = -0.042472597
22 = {float[3]@5157}
0 = -0.39541394
1 = -0.014356935
2 = -0.05802595
23 = {float[3]@5158}
0 = -0.40259242
1 = -0.026919257
2 = -0.06580262
24 = {float[3]@5159}
0 = -0.40977085
1 = -0.03589234
2 = -0.071186475
25 = {float[3]@5160}
0 = -0.4151547
1 = -0.040677987
2 = -0.062213387
26 = {float[3]@5161}
0 = -0.421735
1 = -0.03888337
2 = -0.04965107
27 = {float[3]@5162}
0 = -0.42831525
1 = -0.040677987
2 = -0.032303106
28 = {float[3]@5163}
0 = -0.4372883
1 = -0.04426722
2 = -0.014356935
29 = {float[3]@5164}
0 = -0.445065
1 = -0.04785645
2 = 9.496515
30 = {float[3]@5165}
0 = -0.44865423
1 = -0.04666004
2 = 9.503693
31 = {float[3]@5166}
0 = -0.44865423
1 = -0.04426722
2 = 9.506086
As you can see 15 times the Z axis shows the correct value and 17 shows -0.
This is how I'm initializing the sensors:
// soft reset & reboot accel/gyro
writeRegByte(SensorType.XG, REGISTER_CTRL_REG8, (byte) 0b00000101);
// soft reset & reboot magnetometer
writeRegByte(SensorType.MAG, REGISTER_CTRL_REG2_M, (byte) 0b00001100);
SystemClock.sleep(10);
byte idXg = readRegByte(SensorType.XG, REGISTER_WHO_AM_I_XG);
byte idMag = readRegByte(SensorType.MAG, REGISTER_WHO_AM_I_M);
if (idXg != XG_ID || idMag != MAG_ID) {
throw new IllegalStateException("Could not find LSM9DS1, check wiring!");
}
setFifoMemoryEnabled(false);
// enable gyro continuous
writeRegByte(SensorType.XG, REGISTER_CTRL_REG1_G, (byte) 0b11000000); // on XYZ
// Enable the accelerometer continuous
writeRegByte(SensorType.XG, REGISTER_CTRL_REG5_XL,
(byte) (CTRL_REG5_XL_ZEN_XL | CTRL_REG5_XL_YEN_XL | CTRL_REG5_XL_XEN_XL)); // enable X Y and Z axis
writeRegByte(SensorType.XG, REGISTER_CTRL_REG6_XL, (byte) 0b11000000); // 1 KHz out data rate, BW set by ODR, 408Hz anti-aliasing
writeRegByte(SensorType.XG, REGISTER_CTRL_REG7_XL, (byte) 0b10000000); // HR - High resolution mode
// enable mag continuous
writeRegByte(SensorType.MAG, REGISTER_CTRL_REG3_M, (byte) 0x00); // continuous mode
And this is how I'm reading the accelerometer data:
byte[] buffer = new byte[6];
int[] result = new int[3];
readRegBuffer(SensorType.XG, REGISTER_OUT_X_L_XL, buffer, buffer.length);
result[0] = (buffer[1] << 8) | buffer[0]; // Store x-axis values
result[1] = (buffer[3] << 8) | buffer[2]; // Store y-axis values
result[2] = (buffer[5] << 8) | buffer[4]; // Store z-axis values
return result;
I'm then converting the raw values with this formula (but this is a constant change so it should not matter):
rawAccelerometerData[i] * mAccelMgLsb / 1000f * mGravity;
I've also tried to disable the gyro and the magnetometer and left only the Z axis enabled and than tried to fetch the data using different output data rate but the result is the same.
The full code of my driver is available here.
I currently have only one LSM9DS1 so I have no clue if this is a defective product or an expected behavior and if this can be fixed with a different configuration.
PS
! as you might have guessed looking at the code I'm not really using an Arduino to access the LSM9DS1 but I still believe that this is still a good place to ask for help since I don't think my issue is platform related but is either some error in my code or a faulty sensor. And my code is just a port of this Arduino driver: https://github.com/adafruit/Adafruit_LSM9DS1.
-
This community will have no way to tell you if your hardware is defective, and since your code isn't for Arduino, it doesn't really fit in this group. The code sample you provided is nice, but can't be verified on Arduino.jose can u c– jose can u c2017年12月21日 13:56:56 +00:00Commented Dec 21, 2017 at 13:56
-
I understand this but at least I can have a confirmation that this doesn't happen on Arduino, right? Can someone with a LSM9DS1 tell me if he/she get always consistent data from the accelerometer using this Arduino driver? github.com/adafruit/Adafruit_LSM9DS1Roberto Leinardi– Roberto Leinardi2017年12月21日 14:22:50 +00:00Commented Dec 21, 2017 at 14:22
-
the comments in your code shows that you are enabling "everything" . try enabling only one direction of the accelerometer and disable the gyro .... also try reading the data at slower ratejsotola– jsotola2017年12月21日 17:59:02 +00:00Commented Dec 21, 2017 at 17:59
-
Hi @jsotola, thanks for the hint, I tried to disable everything but the accelerometer and there I enabled only the Z axes. I tried with several values of output data rate, from the min to the max, with high resolution enable and disabled but the result is always the same. I've updated the OP including this new info and a link to the full source code of the driver.Roberto Leinardi– Roberto Leinardi2017年12月21日 20:27:31 +00:00Commented Dec 21, 2017 at 20:27
1 Answer 1
The problem is how the accelerometer data is read, to be precise is in these lines:
result[0] = (buffer[1] << 8) | buffer[0]; // Store x-axis values
result[1] = (buffer[3] << 8) | buffer[2]; // Store y-axis values
result[2] = (buffer[5] << 8) | buffer[4]; // Store z-axis values
What I'm getting from the sensor is a 16bit in two’s complement spitted in 2 bytes, for example buffer[4]
and buffer[5]
where 4 is the low byte and 5 is the high.
In Java the &
and |
are defined to operate only on int
and long
values, so what happens is that the byte
is always promoted to signed int
:
buffer[5] = 00111100
buffer[4] = 11110110
(int)buffer[4] = 11111111111111111111111111110110 = FF FF FF F6
(buffer[5] << 8) | buffer[4] = FF FF FF F6
With the original code both bytes are handled has two’s complement when actually only the high byte is holding the sign.
Long story short, you have to keep the sign for the high byte (cast to int
) and threat the low as unsigned (autocast to int
using the &
and keeping only the original byte with 0xFF
):
result[0] = (((int) buffer[1]) << 8) | (buffer[0] & 0xFF); // Store x-axis values
result[1] = (((int) buffer[3]) << 8) | (buffer[2] & 0xFF); // Store y-axis values
result[2] = (((int) buffer[5]) << 8) | (buffer[4] & 0xFF); // Store z-axis values
Explore related questions
See similar questions with these tags.