cancel
Showing results for 
Search instead for 
Did you mean: 

LIS2DH12 Measure conversion

P M
Associate II
Posted on June 06, 2017 at 09:20

I am having some problems when I try to get data from my sensor. I can read registers and get some data but I don't know how I should do the covnersion to get a real value.

I am using an arduino and I found some libraries. Those libraries tend to use this format:

x = ((int8_t)sensorData[1])*256+sensorData[0];

y = ((int8_t)sensorData[3])*256+sensorData[2];

z = ((int8_t)sensorData[5])*256+sensorData[4];

Where position 0 of sensorData starts at OUT_X_L (28h) and goes up.

Is this right? I have read something about left justified of LSB and I think it should be like:

Is it the same?

Apart from that, they use a formula to get mg values from the x,y and z values:

x = (int32_t)x*1000/(1024*mgScaleVel); //transform data to millig, for 2g scale axis*1000/(1024*16),

y = (int32_t)y*1000/(1024*mgScaleVel); //for 4g scale axis*1000/(1024*8),

z = (int32_t)z*1000/(1024*mgScaleVel); //for 8g scale axis*1000/(1024*4)

What is this about? where does this formula appear? Is it correct? How should I parse the data?

#lis2dh12
10 REPLIES 10
P M
Associate II
Posted on June 06, 2017 at 09:21

I can't edit my post. I forgot to add this where I put: '...LSB and I think it should be like:'

x = (int16_t)x_h<<8;

x |= x_l;

y = (int16_t)y_h<<8;

y |= x_l;

z = (int16_t)z_h<<8;

z |= x_l;
Miroslav BATEK
ST Employee
Posted on June 06, 2017 at 11:14

There is many ways how to do it, but lets use typical approach.

1. You need to first make one number from 

High and Low bytes which you read from the sensor:

x_raw = ((int16_t)OUT_X_H<<8) + OUT_X_L;

2. Then you need to adjust the number according to the mode which you use (the data are left justified in the output registers):

- High-resolution mode (12-bit data output) x_raw = x_raw>>4;

- Normal mode (10-bit data output)

 x_raw = x_raw>>6;

- Low-power mode (8-bit data output) x_raw = x_raw>>8; (For this mode you can skip first and second step and use only the OUT_X_H)

3. Convert the raw data into g unit value using sensitivity for selected mode and full scale. The sensitivy value can be found in Table 4 in datasheet.

x = x_raw * sensitivity ... value will be in mg (milli g)

0690X00000607FCQAY.png
Posted on June 07, 2017 at 10:01

Thank you Miroslav, I see it now.

I have the interrupt 1 working right now. But I would want to change it a bit.

My problem is that I don't know how the board will be set on a surface (head, tail on a edge...) So I would want to modify axis so the first time I power it up, it will get that position as 0,0,0 and then interrupt fires when the threshold is passed over. 

Right now, I have the devel board on my table and depending on the position, interrupt fires all the time. Is it possible to modify this behaviour? How can I modify it?

Posted on June 07, 2017 at 11:05

For that case you can use high pass filter. You can enable high pass filter for output values and/or for interrupt generator.

Reading REFERENCE register in Normal mode you can set the ''0,0,0'' position and then evaluate only the differences.

0690X00000607FbQAI.png
Miroslav BATEK
ST Employee
Posted on June 07, 2017 at 14:46

If you want to see the output after the high-pass filter you have to set the bit FDS = '1'.

To reset the high-pass filter by reading reference register you have to set 

HPM[1:0] = '00', but I think in your case the normal mode 

HPM[1:0] = '10' is also possible to use.

Posted on June 07, 2017 at 13:49

Then, I should write on CTRL_REG2 a 0x81 

NORMAL MODE IN HPM[1:0]

FDS           0

HPCLICK  0

HP_IA2      0

HP_IA1      1

And then, read REFERENCE(0x26) register to set up 0,0,0, shouldn't I?

Is this correct? Because I tried and I still get x,y,z values as before.  Is this ok?

P M
Associate II
Posted on June 12, 2017 at 09:26

Ok, I think I got it. 

I have a problem about the interrupt getting fired. 

I am trying INT1. If I set INT1_CF to be 0010 1010. It is configured to fire interrupt when a Z,Y or X event goes HIGH. It is working.

But, I want to set Z,Y or X event to go HIGH or LOW. I don't mind sign, I just want to get accel in every direction. Well, I set 0011 1111 and it doesn't work. Interrupt never got fired then.

This is my current configuration: 

#define ACCL_CTRL_REG1 0x3F

#define ACCL_CTRL_REG2 0x01

#define ACCL_CTRL_REG3 0x40

#define ACCL_CTRL_REG4 0x80

#define ACCL_CTRL_REG5 0x00

#define ACCL_CTRL_REG6 0x00

//Int1 config

#define ACCL_INT1_CFG 0x2E

#define ACCL_INT1_THS 0x32

#define ACCL_INT1_DUR 0x02

#define ACCL_INT1_TIME 0x01

I want to try low power. but if I set 1Hz in CTRL_REG1, it is even worst. I guess it is because the 1Hz instead of 25Hz...

What should I do in this case? activate 6d? set to 0 every z,y,x event? I don't fully understand how 6d works....

Miroslav BATEK
ST Employee
Posted on June 12, 2017 at 10:10

The interrupt threshold is absolute value. If you set the threshold to for example 1g, the interrupt will be triggered for example by +1.2g or -1.2g.

The duration settings is linked with the ODR settings, basically it means number of ODR periods for which the acceleration must exceed the threshold to trigger the interrupt. So in your case for ODR = 25Hz the duration will be 1/25 * 2 = 0.08s, for ODR = 1Hz the duration is 1/1 * 2 = 2s which can be difficult to reach.

P M
Associate II
Posted on June 12, 2017 at 12:44

I see about threshold, what I do not see is that if I activate ZH and ZL, my interrupt never triggers. If I just set Zh or ZL, it triggers when it has to.

Also, In case of 1Hz, the lowest time of duration is 1 second, isn't it?