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

  • \$\begingroup\$ Please provide a datasheet to the BMI160. And maybe your code that processes the answer of the IMU. \$\endgroup\$ Aug 3, 2016 at 10:30
  • \$\begingroup\$ I omitted the code, as it's a Simulink model. Waijung blocks for the SPI: waijung.aimagin.com/index.htm?stm32f4_spimaster_setup.htm Datasheet is now edited in the main post. \$\endgroup\$
    – epe
    Aug 3, 2016 at 10:45

1 Answer 1


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.

  • \$\begingroup\$ Thanks, there is a serious hole in my knowledge here. Why -654? What about when the IMU outputs something like 1111 1111 0000 0000 (flipped to 0000 0000 1111 1111, 255 in my mind)? \$\endgroup\$
    – epe
    Aug 3, 2016 at 11:03
  • \$\begingroup\$ @epe the data is in 2's complement. The most significant bit a sign bit. When the MSb is 1, the "weight" of that place is negative. 0x8000 is -32768. 0xFFFF is -1. 0x0001 is 1. 0x7FFF is 32767. \$\endgroup\$
    – CHendrix
    Aug 3, 2016 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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