I'm trying to understand the method to convert raw accelerometer's output to m/s^2 Suppose I'm using ADXL345:
Supposed that the value I got for Z axe is 36. I would do the following math to convert it to m/s^2:
val = (36 * 31.2) = 1123,2mg -> 1,123g
valms = val * 9.81m/s^2 = 1,123g * 9.81m/s^2 = 11,01663m/s^2
whereas in the Zephyr's code the formula is as follows:
static void adxl345_accel_convert(struct sensor_value *val, int16_t sample)
{
if (sample & BIT(9)) {
sample |= ADXL345_COMPLEMENT;
}
val->val1 = ((sample * SENSOR_G) / 32) / 1000000;
val->val2 = ((sample * SENSOR_G) / 32) % 1000000;
}
val->val1 -> is integral part
val->val2 -> is fractional part
SENSOR_G is 9806650LL micro m/s^2
Let's skip the fractional part for now.
I cannot understand why sample is multiplied by SENSOR_G and then divided by 32? Why 32? I suspect that maybe it's rounded scaling factor? But why is this divided by scaling factor? I cannot wrap my head around it.
Anyway both calculations provide roughly the same output. Perhaps the Zephyr's version is more accurate?
I believe your confusion stems from the fact that 32 * 32 == 1024
, and also that the calculations involve g
and mg
which differ by a factor of 1000.
It just so happens that multiplying by 32 and then dividing by 1000 is the approximate same as dividing by 32.
i.e. 1 / 32 == 32/1024
In your calculation you multiply by 31.2 then divide by 1000 to get a value measured in g
. (This is effectively the same as dividing by 32.) You then multiply by g
to get m/s^2
.
In the Zephyr code, they just combine the multiply by 31.2 and the divide by 1000 into a single divide by 32.
You only get this coincidence for 32/LSB because 32 happens to square to ~1000. For other resolutions, this wouldn't be the case, and it would probably be less confusing.