0

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 Dec 21 '17 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_LSM9DS1 – Roberto Leinardi Dec 21 '17 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 rate – jsotola Dec 21 '17 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 Dec 21 '17 at 20:27
0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.