cancel
Showing results for 
Search instead for 
Did you mean: 

Reading data from LIS2DUXS12 on X-NUCLEO-IKS4A1

suiunbek
Associate II

I am using NUCLEO-U083RC with X-NUCLEO-IKS4A1. I read the data from LIS2DUXS12 which is on X-NUCLEO-IKS4A1. The accelerometer data is in 8 registers. OUT_X_L, OUT_X_H, OUT_Y_L, OUT_Y_H, OUT_Z_L, OUT_Z_H.

I am trying to understand the instructions in the document AN5909 page 23. The example shows:

Get the raw data from the sensor:

OUT_X_L: 61h
OUT_X_H: FDh
OUT_Y_L: 73h
OUT_Y_H: 00h
OUT_Z_L: F0h
OUT_Z_H: 42h

Do the register concatenation (useful data on 14 bits, last 2 bits must be ignored):

(OUT_X_H << 8) + (OUT_X_L & 11111100b) = FD60h [-672 in two’s complement]
(OUT_Y_H << 8) + (OUT_Y_L & 11111100b) = 0070h [+112 in two’s complement]
(OUT_Z_H << 8) + (OUT_Z_L & 11111100b) = 42F0h [+17136 in two’s complement]

Apply the sensitivity and obtain the value in mg (0.061 mg/LSB at full scale ±2 g):

X: -672 * 0.061 = -41 mg
Y: +112 * 0.061 = +7 mg
Z: +17136 * 0.061 = +1045 mg

I have the following question: why is the two's compliment for FD60h calculated to be -672? Isn't it positive 672?

In my code I read the registers for Z axis:

uint16_t OUT_Z_L = 0x2C;

uint16_t OUT_Z_H = 0x2D;

uint8_t accz_l, accz_h;

status = BSP_I2C1_ReadReg(LIS2DUXS12_ADDR, OUT_Z_L, &accz_l, 1);

status = BSP_I2C1_ReadReg(LIS2DUXS12_ADDR, OUT_Z_H, &accz_h, 1);

Then I concatenate values:

uint16_t Z = (accz_h << 8) + (accz_l & 0b11111100);

And finally compute two's compliment and apply the sensitivity multiplier:

z = (~Z + 1) * 0.488;

I get a strange value:

My accz_l is B0h, accz_h is 07h. Therefore for Z I get 07B0h. The value for z is -960.383972

The NUCLEO board is in the positive position. Should I have approximately 1000 mg?

1 ACCEPTED SOLUTION

Accepted Solutions
Federica Bossi
ST Employee

Hi @suiunbek ,

You should not use (~Z + 1) for two’s complement conversion.
After reading the registers, do:

 
uint16_t Z_raw = (accz_h << 8) | (accz_l & 0xFC);
int16_t Z_14bit = Z_raw >> 2;
if (Z_14bit & 0x2000) Z_14bit -= 0x4000; // handle sign for 14 bits
float z_mg = Z_14bit * 0.061f; // for ±2g

This will give you the correct signed value.
Your current method inverts the bits incorrectly and gives wrong results.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

View solution in original post

1 REPLY 1
Federica Bossi
ST Employee

Hi @suiunbek ,

You should not use (~Z + 1) for two’s complement conversion.
After reading the registers, do:

 
uint16_t Z_raw = (accz_h << 8) | (accz_l & 0xFC);
int16_t Z_14bit = Z_raw >> 2;
if (Z_14bit & 0x2000) Z_14bit -= 0x4000; // handle sign for 14 bits
float z_mg = Z_14bit * 0.061f; // for ±2g

This will give you the correct signed value.
Your current method inverts the bits incorrectly and gives wrong results.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.