Converting values from an Accelerometer to Gs

In this post I will show how to convert the raw values read from an accelerometer to ‘Gs’.

 

An accelerometer measures proper acceleration, which is the acceleration it experiences relative to freefall. This is most commonly called “G-Force” (G)

For example, an accelerometer at resting on a table would measure 1G ( 9.81 m/s2) straight upwards. By contrast, accelerometers in free fall and accelerating due to the gravity of Earth will measure zero.

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.

mg = milli-G’s (just like milliliters)
1mG = 0.001 G’s of acceleration, so 1000mG = 1G.
LSB = Least Significant bit, which is the last bit on the right.

BerryIMU Raspberry Pi Gyroscope Accelerometer

The LSM9DS0 outputs a 16 bit value for the accelerometer readings.

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.

LSM9DS1 BerryIMU

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)

 4,000 MilliGs / 65,535 = 0.061

Each time the LSB changes by one, the value changes by 0.061, which is the value highlighted in blue in the table above.

For FS ±8 g, the range would be -8 to +8, which is a total of 16,000 MilliGs.
 16,000 MilliGs / 65,535 = 0.244

Example when using ±2g sensitivity
In the table below, every time the raw values increments by one, the final calculated value(which is MilliG) increments by 0.061

RAW  	BINARY	LSB value for +/-2G	Calc MilliG
16	10000		0.061		0.976
17	10001		0.061		1.037
18	10010		0.061		1.098

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

Example when using ±8g sensitivity
In the table below, every time the raw values increments by one, the final calculated value(which is MilliG) increments by 0.244

RAW  	BINARY	LSB value for +/-2G	Calc MilliG
16	10000		0.244		3.904
17	10001		0.244		4.148
18	10010		0.244		4.392

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.

4,475
 X 0.224 = 1002.4 MilliGs or 1G

 

The Code

The two above examples are easy to implement in python;
±8g Sensitivity

writeACC(CTRL_REG2_XM, 0b00010000) #+/- 8G full scale
print("G Value for Z axis %f G" % ((ACCz * 0.224)/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 using the raw values from the accelerometer.

±2g Sensitivity

writeACC(CTRL_REG2_XM, 0b00000000) #+/- 2G full scale
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;

import smbus
import time
import math
from LSM9DS0 import *
import datetime
bus = smbus.SMBus(1)




def writeACC(register,value):
        bus.write_byte_data(ACC_ADDRESS , register, value)
        return -1




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)

	return acc_combined  if acc_combined < 32768 else acc_combined - 65536


def readACCy():
        acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_Y_L_A)
        acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_Y_H_A)
	acc_combined = (acc_l | acc_h <<8)

	return acc_combined  if acc_combined < 32768 else acc_combined - 65536


def readACCz():
        acc_l = bus.read_byte_data(ACC_ADDRESS, OUT_Z_L_A)
        acc_h = bus.read_byte_data(ACC_ADDRESS, OUT_Z_H_A)
	acc_combined = (acc_l | acc_h <<8)

	return acc_combined  if acc_combined < 32768 else acc_combined - 65536




	
#initialise the accelerometer
writeACC(CTRL_REG1_XM, 0b01100111) #z,y,x axis enabled, continuos update,  100Hz data rate
writeACC(CTRL_REG2_XM, 0b00010000) #+/- 8G full scale



while True:
	
	
	#Read the accelerometer,gyroscope and magnetometer values
	ACCx = readACCx()
	ACCy = readACCy()
	ACCz = readACCz()

	print("##### X = %f G  #####" % ((ACCx * 0.224)/1000)),
	print(" Y =   %fG  #####" % ((ACCy * 0.224)/1000)),
	print(" Z =  %fG  #####" % ((ACCz * 0.224)/1000))

	
	
	#slow program down a bit, makes the output more readable
	time.sleep(0.03)

The complete code is in our Git repository here
The code can be pulled down to your Raspberry Pi with;

pi@raspberrypi ~ $ git clone http://github.com/mwilliams03/BerryIMU.git

Raspberry Pi Digital Spirit Level

 

In this post we show how to create a Digital Spirit Level using a Raspberry Pi and python.

The code moves that bubbles on the display in relation to the angle read from the IMU.
Parts used in this project;

Any IMU or TFT can be used, however the code would need to be updated to accommodate the different devices. It is best to use a 480×320 TFT as the images are scaled to fit this resolution.

This guide assumes that some basic understanding of an IMU(Accelerometer and Gyroscope)  is already known. And you have one already working with your Raspberry Pi.

If you don’t, we do have some guides which covers this.

BerryIMU Raspberry Pi Gyroscope Accelerometer

 

We have used our existing python code to read the values from the IMU, however we have removed the code related to the magnetometer as it isn’t needed for this project.

Git repository here
The code can be pulled down to your Raspberry Pi with;

pi@raspberrypi ~ $ git clone http://github.com/mwilliams03/BerryIMU.git

 

Placement of IMU

The IMU can be attached anywhere, however it is best to place it in the same orientation as shown below. If you do change the orientation, you will need to update the code accordingly.

spiritLevel1-600

Continue reading Raspberry Pi Digital Spirit Level

BerryIMU Python Code Update – Kalman Filter and More

We have updated to the python code in our git repo.

It now includes;

  • The elusive Kalman filter.
  • Math needed when the IMU is upside down
  • Automatically calculate loop period.
  • A lot more comments.

What is a Kalman filter?  In a nutshell;
A Kalman filter is, it is an algorithm which uses a series of measurements observed over time, in this context an accelerometer and a gyroscope. These measurements will contain noise that will contribute to the error of the measurement. The Kalman filter will then try to estimate the state of the system, based on the current and previous states, that tend to be more precise that than the measurements alone.

A Kalman filter is more precise than a Complementary filter. This can be seen in the image below, which is the output of a complementary filter (CFangleX) and a Kalman filter (kalmanX) from the X axis plotted in a graph.

The red line (KalmanX) is better at filtering out noisep;

Python Kalman filter Raspberry Pi

 

The code can be found here in our Git repository here
And  can be pulled down to your Raspberry Pi with;

pi@raspberrypi ~ $ git clone https://github.com/mwilliams03/BerryIMU.git

BerryIMU Raspberry Pi Gyroscope Accelerometer

A summary of the code;


def kalmanFilterY ( accAngle, gyroRate, DT):
        y=0.0
        S=0.0

        global KFangleY
        global Q_angle
        global Q_gyro
        global y_bias
        global XP_00
        global XP_01
        global XP_10
        global XP_11
        global YP_00
        global YP_01
        global YP_10
        global YP_11

        KFangleY = KFangleY + DT * (gyroRate - y_bias)

        YP_00 = YP_00 + ( - DT * (YP_10 + YP_01) + Q_angle * DT )
        YP_01 = YP_01 + ( - DT * YP_11 )
        YP_10 = YP_10 + ( - DT * YP_11 )
        YP_11 = YP_11 + ( + Q_gyro * DT )

        y = accAngle - KFangleY
        S = YP_00 + R_angle
        K_0 = YP_00 / S
        K_1 = YP_10 / S

        KFangleY = KFangleY + ( K_0 * y )
        y_bias = y_bias + ( K_1 * y )

        YP_00 = YP_00 - ( K_0 * YP_00 )
        YP_01 = YP_01 - ( K_0 * YP_01 )
        YP_10 = YP_10 - ( K_1 * YP_00 )
        YP_11 = YP_11 - ( K_1 * YP_01 )

        return KFangleY

Raspberry Pi 3 + LED Cube + Spectrum Analyzer = Awesome Audio Visualizer!

To create an awesome audio visualizer, using a spectrum analyzer( C.A.V.A:  Console-based Audio Visualizer for ALSA ), all you need is a Raspberry Pi 3 and a RGB LED cube – VoxCube!

Raspberry Pi LED cube

C.A.V.A

CAVA was created by Karl Stavestrand and it is a  great tool to create an audio visualizer in the console.

C.A.V.A spectrum analyzer Raspberry Pi

Continue reading Raspberry Pi 3 + LED Cube + Spectrum Analyzer = Awesome Audio Visualizer!

How to Program an AVR/Arduino using the Raspberry Pi GPIO

In this tutorial I am going to show you how to program an AVR(ATmega328) and an Arduino UNO using the GPIO on the Raspberry Pi.

Adding an Arduino or an AVR to your projects will give you much greater flexibility.

 

Hook up the Raspberry Pi to the Arduino UNO or AVR.

 

The image below shows how to connect a Raspberry Pi 2 and an  Arduino UNO. click the image to make it larger

 

Raspberry Pi and Arduino

Continue reading How to Program an AVR/Arduino using the Raspberry Pi GPIO

Raspberry Pi controlling a LED cube with Python

The above LED cube [VoxCube] is being controlled via a Raspberry Pi, using python and the official Raspberry Pi display.

Buttons were setup using the Kivy. Kivy is a Python library which makes creating buttons and events with a touchscreen very easy.

Here is a very good guide on how to get Kivy setup on a Raspberry Pi.
Continue reading Raspberry Pi controlling a LED cube with Python

Blip, blop, bloop…