Converting Values From An Accelerometer To G
Converting Values From An Accelerometer To G
com
BerryIMU
In this post I will show how to convert the raw values read from an accelerometer to 'Gs'.
The code for this guide can be found under the python-BerryIMU-measure-G directory.
The accelerometer used by the BerryIMU is a MEMS sensors(LSM9DS0), which outputs the raw readings
as mg/LSB.
Most MEMS accelerometers use this output format.
If you look at the characteristics of the LSM9DS0 in the datasheet, you can see the sensitivity levels for the
accelerometer highlighted in red below and the corresponding values for the LSB, which are highlighted in
blue. You can download the datasheet here;
The raw values from the accelerometer are multiplied by the sensitive level to get the value in G.
Let's use FS ±2 g as an example sensitivity level. As the range is -2 to +2, this would be a total of 4g. Or
4,000 Milli-Gs.
The output is 16 bits. 16 bits equals 65,535. This means we can get 65,535 different readings for the
range between -2 and +2. (or -2,000 MilliGs and +2,000 MilliGs)
Each time the LSB changes by one, the value changes by 0.061, which is the value highlighted in blue in the
table above.
The above values of 16,17 and 18 above a very low and only used for illustration.
If your accelerometer is horizontal and resting and at rest when using a sensitive level of ±2g, the raw value
for Z should hover around 16,500.
16,500 X 0.061 = 1006 MilliGs or 1G
If you accelerometer is horizontal and at rest, when using a sensitive level of ±8g, the raw value for Z should
hover around 4,475.
The Code
The two above examples are easy to implement in python;
±8g Sensitivity
The first line above is used to initialise the accelerometer with a sensitivity level of ±2g.
The second line prints the calculated value as G using the raw values from the accelerometer.
±2g Sensitivity
1 writeACC(CTRL_REG2_XM, 0b00000000) #+/- 2G full scale
2 print("G Value for Z axis %f G" % ((ACCz * 0.061)/1000))
The first line above is used to initialise the accelerometer with a sensitivity level of ±2g.
The second line prints the calculated value as G uses using raw values from the accelerometer.
Below is a snippet from the main program;
1 import smbus
2 import time
3 import math
4 from LSM9DS0 import *
5 import datetime
6 bus = smbus.SMBus(1)
7
8
9 def writeACC(register,value):
10 bus.write_byte_data(ACC_ADDRESS , register, value)
11 return -1
12
13
14 def readACCx():
15 acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_X_L_A)
16 acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_X_H_A)
17 acc_combined = (acc_l | acc_h <<8)
18 return acc_combined if acc_combined < 32768 else acc_combined - 655
19
20 def readACCy():
21 acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_Y_L_A)
22 acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_Y_H_A)
23 acc_combined = (acc_l | acc_h <<8)
24 return acc_combined if acc_combined < 32768 else acc_combined - 655
25
26 def readACCz():
27 acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_Z_L_A)
28 acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_Z_H_A)
29 acc_combined = (acc_l | acc_h <<8)
30 return acc_combined if acc_combined < 32768 else acc_combined - 655
31
32
33
34 #initialise the accelerometer
35 writeACC(CTRL_REG1_XM, 0b01100111) #z,y,x axis enabled, continuos update
36 writeACC(CTRL_REG2_XM, 0b00011000) #+/- 8G full scale
37
38 while True:
39
40
41 #Read the accelerometer,gyroscope and magnetometer values
42 ACCx = readACCx()
43 ACCy = readACCy()
44 ACCz = readACCz()
45 print("##### X = %f G #####" % ((ACCx * 0.244)/1000)),
46 print(" Y = %fG #####" % ((ACCy * 0.244)/1000)),
47 print(" Z = %fG #####" % ((ACCz * 0.244)/1000))
48
49
50 #slow program down a bit, makes the output more readable
51 time.sleep(0.03)
BERRYIMU
nuketard
JANUARY 8, 2017 AT 1:43 AM
What filter would be appropriate for the accelerometer data? It doesn't drift much, and at most is
slightly offset(from mounting) which can easy be corrected with calibration. But the signal is quite
noisy. I was thinking of using a low pass filter or a median filter. Are there more suitable alternatives or
a worked example?
Mark Williams
JANUARY 8, 2017 AT 11:44 AM
//Low Pass
float kLowPassFilterFactor = 0.1;
float kHighPassFilterFactor = 0.1;
oldXMagRawValue = *mag_raw;
oldYMagRawValue = *(mag_raw+1);
oldZMagRawValue = *(mag_raw+2);
//Median
#define MEDIANTABLESIZE 3
medianTable2 = medianTable1;
*mag_raw = medianTable2.x[(int)MEDIANTABLESIZE/2];
*(mag_raw+1) = medianTable2.y[(int)MEDIANTABLESIZE/2];
*(mag_raw+2) = medianTable2.z[(int)MEDIANTABLESIZE/2];
izaq09
FEBRUARY 21, 2017 AT 1:24 AM
Hi,
Thank you very much for your guide. It has provided me a lot of help.
For ±16 g, 32,000 MilliGs / 65,535 = 0.488, which is not same as the linear acceleration sensitivity
(0.732) in the datasheet. In this case, which one should we use? The one obtained through calculation
or the sensitivity in datasheet?
In fact, I had found something similar in your guide in interfacing gyroscope and accelerometer. In that
case, you are using sensitivity.
https://ozzmaker.com/berryimu/
Thank you.
Regards,
Izaq
Mark Williams
FEBRUARY 21, 2017 AT 12:51 PM
N
MARCH 12, 2017 AT 6:30 AM
Hey Mark,
How come for ±16 g, it's 16,000 MilliG, when for ±8 g, it's 16,000 MilliG...?
Thanks.
N
Mark Williams
MARCH 12, 2017 AT 9:52 PM
My comment above was incorrect. I got confused my my own math
Rory
MAY 5, 2018 AT 3:49 AM
Mark Williams
MAY 5, 2018 AT 11:54 AM
Yes and No
I spoke to ST who make the LSM9DS1, they told me that not all 16 bits are used for ±16 G.
I asked how many are used and they told me they couldn't give me this information as it is
proprietary.
Noel
MAY 16, 2018 AT 10:36 AM
Another way to explain the 0.732 is that the widest range is not ±16 g, but ±24 g !!!
Yifan Jia
MAY 24, 2017 AT 7:23 PM
May I ask the fastest frequency of getting the data, I found the sample code can provide data around
100Hz sampling rate, may I increase it to 1000Hz?
Thanks
Mark Williams
MAY 24, 2017 AT 8:53 PM
The output data rate is configured using the first 4 bits in the register below;
writeACC(CTRL_REG1_XM, 0b01100111) #z,y,x axis enabled, continuos update,
100Hz data rate
0110 = 100Hz
Yifan
MAY 26, 2017 AT 6:22 PM
Eric Olson
JULY 4, 2017 AT 8:24 AM
In the example code (python-berryIMU-measure-G) the value .224 is used for the 8G scale. This value
should be .244 per the table included in this article. Couldn't figure out why I wasn't reading 1G at level
with no motion so double-checked code.
That said, great job. You've made the process of deploying one of these units as a vibration sensor in a
large scale environment exceptionally easy. Saved me at least fifty hours with your efforts and this
product. Thank you very much!
Mark Williams
JULY 4, 2017 AT 4:45 PM
RSC
JULY 7, 2017 AT 2:22 PM
Vishal
SEPTEMBER 27, 2017 AT 9:06 PM
hi, Will u plz help me how to convert X,Y,Z axis raw data of LIS3DH to acceleration and how to detect
sudden acceleration and harsh breaking (deacceleration) in car.
Will
FEBRUARY 24, 2018 AT 9:02 PM
Why are you using "G" and "g" in the beginning? Are they not the same?
Payel
FEBRUARY 25, 2018 AT 7:10 AM
can you please explain why we are shifting value 8 bits left and then adding it.Below lines
def readACCx():
acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_X_L_A)
acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_X_H_A)
acc_combined = (acc_l | acc_h <<8)
PeterP
FEBRUARY 25, 2018 AT 10:19 AM
you need to shift to get the 16 bit value from two 8 bit values.
Each axis is represented as two bytes by the IMU. You read the high and low bytes from one axis. E.g
X for the accelerometer. And then combine them. shifting and OR is needed to combine them
X_Low = 212 or 11010100 in binary
X_High = 25 or 00011001 in binary
JAMES
APRIL 11, 2018 AT 1:21 AM
+-2g - z = 16500
+-8g - z = 4475
Which is similar to what I have at resting. For x/y, I'm getting the below:
+-2g - x = 65100
+-8g - x = 65420
+-2g - y = 524
+-8g - y = 128
Mark Williams
APRIL 11, 2018 AT 2:28 PM
if the IMU is flat.. you should only be getting large values on Z. you may get some small values on X
and Y, this would be because the IMU isn't absolutely horizontal.
Your X vales look incorrect. Are you using unmodified code from the git repo?
Aaron
NOVEMBER 13, 2018 AT 11:15 AM
Thank you sir, your work and time spent on this guide and the IMU/gps boards is appreciated. I have
learned a lot. There is enough information here to get started, that is extremely valuable to using some-
thing! Seems like people always forget that... anyway, thanks!
Rocket Man
FEBRUARY 18, 2019 AT 12:03 PM
Is the Max G's of Acceleration a known quantity of what this sensor can detect? I'm trying to use it to
collect data in my high powered rocket going supersonic, and I will probably need something that can
sense an acceleration of up to 20 G's of force
Mark Williams
FEBRUARY 18, 2019 AT 5:17 PM
Ravindra kumar
FEBRUARY 28, 2019 AT 6:37 PM
Ahmed
APRIL 13, 2019 AT 12:30 AM
Madhavi Gupta
MAY 13, 2019 AT 7:04 PM
Hi,
I am using ADXL335 accelerometer, I am getting the values but after some time, the sensor gives maxi-
mum value even if it is not moving. For eg,
1678 1987 4056
...(likewise 8-9 readings)
4058 290 1679
this happens after every 10-12 readings
Can you tell me why is this happening?
Markel Robregado
MAY 30, 2019 AT 3:27 AM
Hi, I am using LSM303AGR 2G normal mode 10 bit. So each bit will be 4000mg/ 2^10 = 3.90625 is this
right?
Ben in Seattle
FEBRUARY 25, 2020 AT 4:55 PM
How common is it for accelerometer manufacturers to pull tricks like ST did for the ±16G range where
they list the LSB as .732 when it should be .488?
The calculation would be simple to understand and wouldn't require a datasheet if we could just scale
the range the normal way: multiply by the max possible output (e.g., 4G) and divide by max possible in-
put (e.g., 32768, for 𝑛=16 bits).
What is with the LSB malarkey? Is it to deal with the fact that two's complement binary numbers have
one less negative number than positive? If so, the difference seems so minimal (<.0015%), that there is
more error from the datasheet rounding to three places of precision.
Also, I agree with Noel that the range should have simply read ±24G since 24 ÷ 32768 =
.000732421875. I suspect errata.
armin
JUNE 22, 2020 AT 11:55 PM
Hey there,
Bosley
AUGUST 18, 2021 AT 4:25 PM
Hi!
I’m looking to purchase this GPS/IMU for a project and I have a minor question. For the python exam-
ples listed here I see that they work for the BerryGPS v1-3. Will these also work for the v4? Or is there
an updated version of these example scripts for the current iteration of the GPS/IMU?
Thanks!
Mark Williams
AUGUST 18, 2021 AT 8:34 PM
The python code works for BerryIMUv3 and BerryGPS-IMUv4. These two devices use the same
IMU.
Eoin
MARCH 16, 2022 AT 1:51 AM
Just wondering if I have a value of 4000 raw data from accelerometer how I convert to m/s^2 please.
Selim Sagir
JUNE 30, 2022 AT 6:23 PM
Hi,
Great explanation, thanks.
The point I wonder, is there any way to calculate resting values such as, 16500 for the ±2g. My sensor
also gives the same value, but I don’t understand the logic behind it.
Thanks!
This site uses Akismet to reduce spam. Learn how your comment data is processed.