From counts to g
Each axis arrives as two bytes, low byte first, holding a 12-bit number parked at the top of 16 bits. Shift it down four places and, at ±2 g, every count is one thousandth of a g. The range setting trades how far the chip can reach against how fine each step is.
Two bytes, one number
Each axis is two registers: the low byte at the lower address, then the high byte. Join them high-then-low and you have a 16-bit word, and because acceleration can point either way, it is signed: a word with its top bit set is negative.
The chip only measures to 12 bits, though, and it puts them at the top of the word, with the bottom four bits always zero. So the sketch shifts the word four places to the right, which leaves the 12-bit count, from −2048 to +2047. Move the slider and watch all three forms of the same reading:
At ±2 g the data sheet's sensitivity is 1 mg per count, so the count is the reading in thousandths of a g, and the sketches divide by 1000 and print g. Its worked example on page 19 rounds instead: it calls 0x40 0x00, a count of 1024, exactly 1.0 g. The two differ by 2.4 %, which is less than a level board's offset and changes nothing in this book.
The range is a trade
CTRL_REG4 picks one of four ranges. The count still runs from −2048 to +2047, so a wider range spreads the same counts over more g:
| Range | Each count | Largest reading |
|---|---|---|
| ±2 g | 1 mg | 2.047 g |
| ±4 g | 2 mg | 4.094 g |
| ±8 g | 4 mg | 8.188 g |
| ±16 g | 8 mg | 16.376 g |
Tilt only ever sees 1 g, so ±2 g and its fine steps are right for it, and that is what every sketch here uses. A tap on a desk can briefly reach several g, and past the range the count simply stops at its largest value, which the figure draws in red. Nothing tells you it clipped; the number just stops climbing.
A zero that is not zero
Lay the board level and X and Y should read 0. They will not, quite. The data sheet gives a mounted chip's zero-g offset as 90 mg typical and 120 mg at most, larger than before soldering, because soldering the package down stresses it. It also moves by about 0.5 mg for every degree of temperature.
That is small next to 1 g and large next to an angle: 90 mg is about 5° of tilt, which the next article shows. The fix is the one in the troubleshooting below: measure the offset once, level, and subtract it from every reading after.
When it does not work
The four-bit shift is missing. The 12 bits sit at the top of the 16-bit word, so without the shift every number is sixteen times too big: 1 g arrives as 16384 instead of 1024. Shift right by four before scaling.
The two bytes were joined as an unsigned number. The word is two's complement, so it has to become a signed 16-bit value before the shift: (int16_t)(hi << 8 | lo) >> 4 in Arduino, and subtracting 0x10000 when the top bit is set in MicroPython.
That is the edge of the ±2 g range: the count has stopped at its largest value and says nothing about how far past it the knock went. Set the range to ±4, ±8 or ±16 g in CTRL_REG4 and change the scale to 2, 4 or 8 mg a count.
No. The data sheet allows a mounted chip's zero to be up to 120 mg off, typically 90. Lay the board level, average a hundred readings of each axis, and subtract those averages from every later reading. Z's own offset is the average minus 1.
The first build: three readings from a still board, turned into two angles.
Tilt from gravity →Edit this page — content/books/3-axis-accelerometer/from-counts-to-g.mdx
Questions about this product
See what other owners have asked, and read their solutions.
3-Axis Accelerometer
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.