# How to interpret accelerometer output data?

I'm running my accelerometer through my Arduino mini and outputting my values using the following values

`````` // print the sensor values:
Serial.print(analogRead(xpin));
// print a tab between values:
Serial.print("\t");
Serial.print(analogRead(ypin));
// print a tab between values:
Serial.print("\t");
Serial.print(analogRead(zpin));
Serial.println();
// delay before next reading:
delay(100);
``````

Here's an example. The x,y,z values that are outputted are quite high even the arduino is not moving. I'm new to Arduino programming and would love some understanding on how to convert these x,y,z to an Acceleration value ie. Is the arduino moving or not?

• Can you edit the original question and include the model of accelerometer and a link to the datasheet. – KennetRunner Sep 30 '16 at 8:27
• I've edited. @KennetRunner – Ben Sep 30 '16 at 8:32
• It is possible that sensor is close to both values. For example, if x is at 9.9 sometimes it can be a bit more, so it will give you 10, while other times it will just give you 9. (this would be the same for y and z) – Foitn Sep 30 '16 at 8:54
• Quite high? Those are minuscule values. You have the raw ADC values there. They can range from 0 to 1023. 8 is just 0.78% of the maximum value. That's hardly "quite high" - that's almost non-existent. – Majenko Sep 30 '16 at 12:38
• Can you please specify the Model of Accelerometer? Each different model will send data differently and values will have to be interpreted differently. – Mero55 Oct 1 '16 at 15:20

## 2 Answers

The accelerometer will output a specific number of volts (or millivolts) per g. You need to find that information in the datasheet for your accelerometer.

Then you need to take the readings you make through `analogRead()` and convert them to a voltage. Then that voltage can be used, combined with the value you found above, to determine the g reading.

As has been noted by @Majenko, you are reading voltages with your `analogRead()` as a ratio of the A/D reference voltage specified for the Arduino you are using rather than true accelerations. For example, your first pass readings of x=9, y=8, z=8 were really saying x = Vref * 9 / 1023 volts. The datasheet for your accelerometer sensor will specify a calibration factor to be applied in terms of Volts/g.

Therefore, if you wish to read in terms of actual acceleration g. then you will need to first convert the value read from the A/D to volts and then convert the voltage to g by applying the datasheet sensitivity factor.

You can brute force this conversion calculation if you wish by using variables of type `float`. If you wish to avoid floating point arithmetic and use fixed point calculations, you can consider defining the result as being multiplied by 10 or 100. (Example: a reading of 1.0g might be reported as 10 if using 10x reporting or it might be reported as 100 if using 100x reporting.

Additionally, if you suspect some jitter in your measurements, you can read multiple times to average and smooth the readings. You can then divide the total of the readings to get an average.

Example Code for Single Axis Using Integer Variables (Untested)

``````#define AXIS_PIN A0

void setup() {
// Insert Setup Code Here

}

void loop()
{
int reading;

reading = 0;

// Read the sensor axis value 4 times
//  Use a short delay between reads if you might exceed
//    the read frequency of the sensor.
// Use millis() for non-blocking aspects if needed
for (int readLoop = 0; readLoop < 4; readLoop++)
{
reading += analogRead(AXIS_PIN);
delay(2);
}

// Map the reading to a voltage using a 100x multiplier
//  The raw reading has a range of (0 to 1023) * 4
//  The mapped reading has a range of (0 to 3300) * 4
//    (assuming a 3.3v reference voltage)
//    (Use 0 to 4 * 5000 if required by the choice of sensor and
//      Arduino used.)
reading = map(reading, 0, 4 * 1023, 0, 4 * 3300);

// Find the average by now dividing by 4
reading = reading >> 2;

Serial.print(F("Average axis reading (x100) is: "));
Serial.println(reading);

// Read the axis once per second
// Use millis() for non-blocking aspects, if needed
delay(1000);
}
``````

EDIT NOTE: I see you have now specified an Adafruit ADXL345 sensor. Be aware that this sensor references 3.3v (offset ratio-metric, ie +/- 1.65v) even though it runs off of a 5v power source. Depending on which Arduino you are using, you may have to adjust the map() function input above to account for the proper output. You can try something like `map(reading, 0, 4 * 1023, -2 * 3300, 2 * 3300);`.

ADDED EDIT: The above will output a converted voltage. If you would like to output directly in units of g (x100), then you can change the `map()` function to something like `map(reading, 0, 4 * 1023, -2 * 300, 2 * 300)` assuming the Adafruit ADXL345 (PRODUCT ID: 163) which reads to +/- 3g.