LIS2DH12 HOWTO Convert Register value to mg value
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-03-22 9:20 AM
Hi,
I am using the LIS2DH12 to interrupt me on an inertial wake. I am running in Low Power mode with a scale of 4G. After verifying that the X axis produced the force that caused the interrupt I read the X_OUT_L and X_OUT_H registers to get the 2's complement value in the X_OUT register. I want to calculate the actual force in mg that caused the wake. Can someone verify that I am doing this correctly?
OUT_X register contains 0xFC00
I use these functions in my calculation
int16_t twos_complement_to_decimal(int num_bits, int16_t num) {
// Create a mask to isolate the sign bit (most significant bit)
int sign_bit_mask = 1 << (num_bits - 1);
// If the sign bit is set (number is negative)
if (num & sign_bit_mask) {
// Invert all bits, add 1, and negate to get the decimal value
return -((~num & ((1 << num_bits) - 1)) + 1);
} else {
// If the sign bit is not set (number is positive), return the number as is
return num;
}
}
float_t lis2dh12_from_fs4_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 32.0f;
}
Here is what I think I should be doing to calculate the mg value...
int16_t iVal = (int16_t)twos_complement_to_decimal(16, 0xF900);
float_t fVal = lis2dh12_from_fs4_lp_to_mg(iVal);
Thanks for your help..
- Labels:
-
Accelerometers
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-03-23 3:24 AM - edited ‎2025-03-23 3:26 AM
Hi,
please use </> for code, like this
int16_t twos_complement_to_decimal(int num_bits, int16_t num) {
// Create a mask to isolate the sign bit (most significant bit)
int sign_bit_mask = 1 << (num_bits - 1);
// If the sign bit is set (number is negative)
if (num & sign_bit_mask) {
// Invert all bits, add 1, and negate to get the decimal value
return -((~num & ((1 << num_bits) - 1)) + 1);
} else {
// If the sign bit is not set (number is positive), return the number as is
return num;
}
}
float_t lis2dh12_from_fs4_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 32.0f;
}
Thats easier to understand.
To Your question, as the X_OUT_L and X_OUT_H register are "left aligned" (whould be probably better to say MSB aligned). You get a 16Bit int value by simply combining the two register like this:
uint8_t HiReg, LowReg;
// get OUT_X_LO in LowReg and OUT_X_HI in HiReg
int16_t Acceleration = (int16_t)(((uint16_t)HiReg < | (uint16_t)LowReg) / 8;
After this You only have to reduce the value by dividing it with the right factor (in Your case, using the 4G range, by 8), and You have the Acceleration value in mg.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-03-31 6:18 AM
I was specifically asking about the function below which is supplied by ST. The answer is that you just combine the OUT_X_L and OUT_X_Y to get a 16 bit value and then just feed this value into the function below. ST provides one of these for each scale/power setting.
lis2dh12_from_fs4_lp_to_mg
I am listing these functions here for others to see..
////////////////////////////////////////////////////////////////////////////////
// These functions are used to convert the 16 bit values read from the OUT_X_L
// and OUT_X_H registers to a mg value.
// Example: let's say that I the OUT_X_L register holds 0x00 and the OUT_X_H
// register holds 0xF9. Also, let's say that we are operating in LP mode and
// the scale is set to 4G.
//
// We calculate the mg as follows:
// float_t fVal = lis2dh12_from_fs4_lp_to_mg(0xF900);
////////////////////////////////////////////////////////////////////////////////
float_t lis2dh12_from_fs2_hr_to_mg(int16_t lsb)
{
return ((float_t)lsb / 16.0f) * 1.0f;
}
float_t lis2dh12_from_fs4_hr_to_mg(int16_t lsb)
{
return ((float_t)lsb / 16.0f) * 2.0f;
}
float_t lis2dh12_from_fs8_hr_to_mg(int16_t lsb)
{
return ((float_t)lsb / 16.0f) * 4.0f;
}
float_t lis2dh12_from_fs16_hr_to_mg(int16_t lsb)
{
return ((float_t)lsb / 16.0f) * 12.0f;
}
float_t lis2dh12_from_lsb_hr_to_celsius(int16_t lsb)
{
return (((float_t)lsb / 64.0f) / 4.0f) + 25.0f;
}
float_t lis2dh12_from_fs2_nm_to_mg(int16_t lsb)
{
return ((float_t)lsb / 64.0f) * 4.0f;
}
float_t lis2dh12_from_fs4_nm_to_mg(int16_t lsb)
{
return ((float_t)lsb / 64.0f) * 8.0f;
}
float_t lis2dh12_from_fs8_nm_to_mg(int16_t lsb)
{
return ((float_t)lsb / 64.0f) * 16.0f;
}
float_t lis2dh12_from_fs16_nm_to_mg(int16_t lsb)
{
return ((float_t)lsb / 64.0f) * 48.0f;
}
float_t lis2dh12_from_lsb_nm_to_celsius(int16_t lsb)
{
return (((float_t)lsb / 64.0f) / 4.0f) + 25.0f;
}
float_t lis2dh12_from_fs2_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 16.0f;
}
float_t lis2dh12_from_fs4_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 32.0f;
}
float_t lis2dh12_from_fs8_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 64.0f;
}
float_t lis2dh12_from_fs16_lp_to_mg(int16_t lsb)
{
return ((float_t)lsb / 256.0f) * 192.0f;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-03-31 12:12 PM
Is this a contest on "how to write bad code"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-01 11:41 PM
gdm: If You have to add something useful, feel free to do so!
