cancel
Showing results for 
Search instead for 
Did you mean: 

LIS2DH12 HOWTO Convert Register value to mg value

DPatt.2
Associate II

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..

4 REPLIES 4
MHoll.2
Senior II

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.

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; }
View more

 

gbm
Principal

Is this a contest on "how to write bad code"?

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

gdm: If You have to add something useful, feel free to do so!