Electrical – Accelerometer gives wrong values for stationary axes

accelerometerimu

I have a BMI160 IMU which gives a good reading for the axis parallel to gravity (1G or -1G), but a changing value of about 2G or -2G for the axes that should show 0G. This is true for all axes, I've tried rotating the IMU.

I'm reading the IMU with an STM32F4 Discovery board via SPI. To my understanding, the IMU outputs data for the accelerometer in 2 bytes, with LSB being first. Inside these bytes, the bits are in MSB format. So a reading of 0111 0010 1111 1101 should be 64 882 in decimal (flipped to 1111 1101 0111 0010) and equate to about 19.23 m/s^2 or 1.96 G. I know the exact bits moving in the SPI data line, since I've read it with a logic analyzer to check.

BMI160 settings: power mode is "normal", and ACC_CONF register is "0x2B": no undersampling, normal filter mode (3dB cutoff frequency), and a data rate of 800 Hz. I've also tried 100 Hz and 1600 Hz. Baud rate for SPI is 156,250 Hz, I've tried higher too (for example 1,250,000 Hz).

I know the BMI160 works well, because I have a Bosch Application board and Development Desktop program, which output a nice running graph of good-looking data for all axes. I've also tried a different BMI160 and different STM32 board.

I suspect the problem is somewhere in how I either initialize the board, or how I read the SPI, but where exactly?

Datasheet for BMI160: https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMI160-DS000-07.pdf

Best Answer

You are getting a value of 0xFD72 which works out as -654 not 64,882. In 2g range mode that works out as -39.9mg. About what I would expect.

-- Additional information

As noted in comments below, this is a 2's compliment signed number. That is the standard way of representing signed numbers in a computer or electronic system.

Treat the most significant bit as indicating -32768 rather than +32768 and then add the other bits as normal e.g.

1000_0000 0000_0000 (0x8000) = -32768

1000_0000 0000_0001 (0x8001) = -32768 + 1 = -32767

1111_1111 1111_1111 (0xFFFF) = -32768 + 32767 = -1

You shouldn't need to do this conversion yourself, just tell the compiler that the value is a 16 bit signed value and it should understand it correctly (e.g. in c store it as an int16_t)

With 16 bits you can represent any value between -32768 and +32767. In 2g range mode the senor you are using outputs a value of g/16384 giving a range of +/- 2g

Also when dealing with binary numbers it is normal to use hexadecimal rather than writing the binary. It's quicker and far less error prone, since each character relates to 4 bits it's quick and easy to convert between binary and hex as needed.