Accelerometers can detect the magnitude and direction of acceleration. Many smartphones use accelerometers to detect when the phone is picked up or tapped. They can also be used to detect when a device is falling. Most laptops have internal accelerometers that switch off the hard drive before it hits the floor.

In this article, we will use an Arduino to get raw sensor data from an accelerometer and convert it into an acceleration value in g’s.

## Introduction to the ADXL345 Accelerometer

The accelerometer we will use in this tutorial is the ADXL345 accelerometer from Adafruit:

The directional arrows indicate the direction of each sensor axis (x, y, and z) in relation to the physical board. The z axis extends up and down, perpendicular to the x and y axes.

The ADXL345 can communicate with the Arduino over SPI and I2C. In this article we will use I2C, but SPI is an option if you want to use it.

• Vin – Connects to a 5 volt power source.
• 3V3 – The ADXL345 can be powered with 3.3 volts or 5 volts. This pin is where the 3.3 volt power source would connect.
• GND – Connects to ground.
• CS – Chip select pin for SPI communication.
• INT1 – Hardware interrupt pin 1.
• INT2 – Hardware interrupt pin 2.
• SDO – Serial data output pin. Doubles as the MISO pin for SPI communication.
• SDA – SDA pin for I2C communication. Doubles as the MOSI pin for SPI communication.
• SCL – SCL pin for I2C communication. Doubles as the SCLK pin for SPI.

## How the ADXL345 Accelerometer Works

Acceleration is the rate of increase or decrease of velocity:

If you drive in a car and step on the gas, the car has a positive acceleration. If you step on the brakes, the car has a negative acceleration. This is known as dynamic acceleration.

Static acceleration is caused by forces like gravity. Accelerometers measure both static acceleration and dynamic acceleration.

Two common units of acceleration are meters per second squared (m/s2) and g’s. One g is defined as the rate of acceleration of gravity, which is 9.8 m/s2.

The ADXL345 outputs separate acceleration measurements for each axis, x, y, and z:

The ADXL345 measures acceleration by detecting changes in capacitance. Along each axis there is a tiny plate suspended between two micro-springs that can move back and forth:

The mobile plate and the fixed plate are charged, so an electric field is formed between them:

When the accelerometer is at rest, the electric field between the plates is constant. When the sensor accelerates, the mobile plate moves, and the distance between the plates changes.

Capacitance is a function of the distance between two charged plates, so when the distance between the plates changes, the electric field between the plates also changes. The sensor measures this change in capacitance and calculates an acceleration value.

## How to Connect the ADXL345 Accelerometer to the Arduino

Let’s connect the accelerometer to the Arduino and take a look at the raw values it provides. We will connect the accelerometer with I2C, so the wiring is pretty simple.

These are the parts needed:

Connect the accelerometer to the Arduino like this:

## How to Program the ADXL345 Accelerometer

To program the ADXL345 accelerometer we will use the Sparkfun ADXL345 library. Download and install the library here.

Once you get the library installed, upload the code below to the Arduino. The sketch will output the raw accelerometer readings to the serial monitor:

``````#include <SparkFun_ADXL345.h>

int range = 2; // Range: 2g, 4g, 8g, 16g

void setup() {
Serial.begin(9600);

}

void loop() {
int x, y, z;

Serial.print("X: ");
Serial.print(x);

Serial.print("    Y: ");
Serial.print(y);

Serial.print("    Z: ");
Serial.println(z);

delay(250);
}``````

## Explanation of the Code

The first thing we do is include the Sparkfun ADXL345 library. Next we create an object called `adxl`, which is a member of the `ADXL345` class. We set the `adxl` object equal to the function `ADXL345()`. The `ADXL345()` function configures the communication mode that the sensor will use to talk to the Arduino. When there are no arguments passed to the function, as in this case, the sensor will use I2C to communicate with the Arduino. To use SPI, use `ADXL345(10)` instead.

Next we declare a variable called `range`, which will store the sensitivity range we want the ADXL345 to have. It can be either 2, 4, 8, or 16 g’s.

In the `setup()` section we initialize the serial monitor. Then we initialize the ADXL345 with the `powerOn()` function. This function is called through the `adxl` object we created earlier. Next, we call the `setRangeSetting()` function to set the sensitivity range of the sensor. We pass it the `range` variable, which stores the range setting we defined when we declared it.

In the `loop()` section, the first thing we do is declare variables to hold the sensor readings. The ADXL345 outputs separate acceleration measurements for each axis, so we need a unique variable for each axis. Therefore we declare three int variables – `x`, `y`, and `z`.

Next, we get the sensor readings from the accelerometer with the `readAccel()` function. The arguments of the `readAccel()` function are the variables that will hold the sensor readings from each axis. The sensor’s x axis measurement will be stored in the variable that is placed in the first parameter. The y axis measurements will be stored in the variable in the second parameter, and the z axis measurements will be stored in the variable placed in the third parameter.

Next we have a series of `Serial.print()` functions to print the values stored in the `x`, `y`, and `z` variables to the serial monitor. Then we delay for 250 milliseconds to slow down the output a bit.

Once you connect the ADXL345 to your Arduino and upload the code, open up the serial monitor. You should see values like this being printed out:

Notice how the X and Y values are close to zero, but the Z axis has a value around 230. The sensor was resting flat on a table when this screenshot was taken, so it wasn’t moving. But it was accelerating. The higher Z axis reading is caused by acceleration from gravity. Try moving the sensor around and see what happens to the values of the x, y, and z axes.

The raw values output by the accelerometer are not the typical Arduino ADC values between 0 and 1023. The numbers you see in the serial monitor are in “two’s complement” format. Two’s complement is a way to represent signed (positive and negative) numbers in binary.

We can convert the accelerometer’s two’s complement values to g’s with some conversion factors from the ADXL345 datasheet.

## How to Convert Two’s Complement Values to G’s

In the specifications table on page 4 of the ADXL345 datasheet there is a section called sensitivity. This section has the scale factors for each sensitivity range::

To get the acceleration readings in g’s, we need to multiply the sensor’s two’s complement output by one of these scale factors. Each sensitivity range has a different scale factor, indicated by the red box in the image above.

## ADXL345 Accelerometer Output in G’s

Now let’s look at a sketch that will output the accelerometer readings in g’s. This sketch will actually output the sensor readings in milli g’s, but if you want the output in g’s, just divide the milli g’s reading by 1,000.

``````#include <SparkFun_ADXL345.h>

int range = 2; // Range: 2g, 4g, 8g, 16g

void setup() {
Serial.begin(9600);

}

void loop() {

int x, y, z;

switch (range) {
case 2:
x = x * 3.9;
y = y * 3.9;
z = z * 3.9;
break;
case 4:
x = x * 7.8;
y = y * 7.8;
z = z * 7.8;
break;
case 8:
x = x * 15.6;
y = y * 15.6;
z = z * 15.6;
break;
case 16:
x = x * 31.2;
y = y * 31.2;
z = z * 31.2;
break;
default:
Serial.println("Please specify a range of 2, 4, 8, or 16 g");
}

Serial.print("X: ");
Serial.print(x);

Serial.print("    Y: ");
Serial.print(y);

Serial.print("    Z: ");
Serial.println(z);

delay(250);
}``````

## Explanation of the Code

The top of the sketch and the `setup()` section are identical to the raw data sketch explained earlier.

In the `loop()` section, we declare `x`, `y`, and `z` variables to store the sensor readings from each axis. Then we get readings for each axis with the `readAccel()` function.

Next we convert the raw sensor readings to g’s by multiplying the raw sensor readings by the scale factor. The scale factor is different depending on which range setting we choose. This is a perfect application for a `switch case` statement. So we use a `switch` statement with the `range` variable as the condition. Each `case` statement will define what happens when the range is set to 2, 4, 8, or 16 g’s. When the `range` variable is equal to 2, the code in the first `case` statement will be executed. The scale factor for 2 g sensitivity is 3.9, so we multiply the output from each axis by 3.9. Then we have a `break` command so that the program exits the `case` statement.

Then we have `case` statements for all the other possible values of the `range` variable. When the range is set to 4 g’s, the scale factor is 7.8, so we multiply each axis output by 7.8. When the range is set to 8 g’s, the scale factor is 15.6, so we multiply all three axis variables by 15.6. And when the range is set to 16 g’s, the scale factor is 31.2, so we have to multiply everything by 31.2.

Then we have a `default` statement at the end of the `switch case` statement. The `default` statement will only be executed if the `range` variable was set equal to something different than 2, 4, 8, or 16. The code inside the `default` statement will print a line on the serial monitor that says: “Please specify a range of 2, 4, 8, or 16 g’s”.

Now we print the `x`, `y`, and `z` variables to the serial monitor with a series of `Serial.print()` functions. Finally we use a delay of 250 milliseconds to slow down the output to make it easier to read on the serial monitor.

After uploading the sketch, open up the serial monitor and you should see the acceleration readings being output in milli g’s:

Notice that the Z axis values are around 910 milli g’s. That is pretty close to one g, which is the acceleration due to gravity.