I try to use a BMI055 Acclerometer and the output is driving me crazy.

I have set it to 2G sensitivity at 1000Hz, that means I have an output between 0 and 4096 (12bit).
The output is said to be two complemented, so I expect 2048 to be 0G

The sensor is set up to be as flat as possible using gauges.

Now I am asking it in a loop for it's FIFO data (1 frame bypass fifo) which returns me 6 bytes .
According to datasheet: LSB X MSB X LSB Y MSB Y LSB Z MSB Z

LSB X needs to be right shifted 4 times and ORd with MSB X which is left shifted 4 times.
So I receive a 12 bit numer.

Just analyzing the X values shows that MSB X is jumping between 0 and 255 !


temp[0]=(result[1]<<4) | ((result[0])>>4);

This shows LSB MSB 12BIT-unsigned

Data X:  1       0       0 
Data X:  85      255     4085 
Data X:  201     255     4092 
Data X:  201     255     4092 
Data X:  221     255     4093 
Data X:  157     0       9 
Data X:  49      0       3 
Data X:  181     255     4091 
Data X:  229     255     4094 
Data X:  17      0       1 
Data X:  161     255     4090 
Data X:  117     255     4087 
Data X:  221     255     4093 
Data X:  5       0       0 
Data X:  209     255     4093 

It should return me 2048 as X is at 0G.
4096 would be 2G force.
0 would be -2G force.

When putting X on -1G and +1G the values seem to be correct (1000 and 3000).
Just the center 0G is at 0/4000 depending on minor vibrations instead of the expected 2046-2049

It is 4 in the morning, I guess I oversee something very critical. Enlightment please

  • 2
    \$\begingroup\$ I didn't look at the data sheet but if those values are signed all the readings are reasonably close to zero and your 3000 reading would be around -1000. \$\endgroup\$
    – PeterJ
    May 8, 2014 at 2:05
  • \$\begingroup\$ Hmm so it seems the 8 bit numbers are actaully signed on each own ?? Even though they are just a subset of a larger number (12 bit) ? I would have expected that the 12 bit number in signed state is stored in 8 bit + 4 bit. Just trying to make sense out of the math which would have been so simple before. \$\endgroup\$
    – John
    May 8, 2014 at 2:23
  • \$\begingroup\$ Not sure but if it is signed you could use your unsigned number and something like if (x >= 2048) x = x - 4096. \$\endgroup\$
    – PeterJ
    May 8, 2014 at 2:37
  • \$\begingroup\$ hmm maybe, I am still unsure how to treat the registers I receive. Datasheet says that MSB is two complement. LSB is not two complemented (i guess?) Does it mean that example values like lsb 10 msb 255 = -10 ? 10 1 would then be 26 ? \$\endgroup\$
    – John
    May 8, 2014 at 4:34
  • 1
    \$\begingroup\$ Right, the LSB should not be interpreted by itself as a two's complement value. Your first example actually has a value of -6 (your second one is right); if you don't understand why, I'd suggest brushing up on how two's complement works. \$\endgroup\$
    – kwc
    May 8, 2014 at 9:34

2 Answers 2


I think you are getting messed up by necessity for the sign of the number to be extended to the left. My reading of the datasheet is that the MSB and LSB registers give you a set of 12 bits, which, as a 12-bit number is to be considered to be in two's complement format.

So, you should first combine the values together, then if necessary, perform any fix to ensure it's a legit two's complement number given the size of the data type you've put it in. Then scale it if needed.

I'd suggest: first choose a target data size that's big enough to hold the result. Let's say you are using C on an MCU, and you can choose signed short, and it is 16 bits. (None of these are a given, BTW).

Let's also assume that MSB and LSB are 8-bit numbers. Now:

signed short result = (MSB << 8) | (LSB & 0xF0)

This should give you a number that's already in two's complement format, as signed short expects to be. This will give you a range of numbers that's 16 times the raw 12 bit number, but properly ranges around zero.

You might then want to scale it by dividing by 16. You might think to perform that division using scaledresult = (result >> 4) but if so you will need to check whether right shift performs sign extension. That is, sets scaledresult[15..12] to 1 if result[15] was 1.

  • \$\begingroup\$ I actually had that done already but was obsessed in keeping my number 12 bit and as efficient code as possible. Also I thought LSB is actaully not in two complement. It was maybe just a bit late for me yesterday :) I now implemented it exactly as you suggested and will likely even keep the 16 bit as my gyro also gives 16 bit results. \$\endgroup\$
    – John
    May 8, 2014 at 15:07
  • \$\begingroup\$ It's one of those cases where the format of the data handed to you by the registers is the format needing least effort to become useful in your program... so long as you know what the intent was -- in this case the target data type. \$\endgroup\$
    – gwideman
    May 8, 2014 at 17:43

There are ready-to-use APIs for the the accelerometer part in the BMI055. Please refer to:

Bosch Sensortec BMA2x2 sensor driver


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.