DEV Community

Cover image for How to Connect and Calibrate the ADXL345 with Arduino
Shilleh
Shilleh

Posted on

How to Connect and Calibrate the ADXL345 with Arduino

Welcome to this tutorial on the ADXL345 accelerometer sensor and how to interface it with an Arduino. The ADXL345 is a popular 3-axis accelerometer that measures acceleration in three directions: X, Y, and Z. This sensor is often used in various applications, such as robotics, gaming, and wearable technology.

In this tutorial, we will walk you through the provided Arduino code, which demonstrates how to set up and calibrate the ADXL345 sensor. Calibration is an essential step to ensure accurate measurements. We'll discuss the code's functions, explain the sensor's configuration, and guide you through the calibration process for accurate data collection.

By the end of this tutorial, you'll have a better understanding of how the ADXL345 sensor works and how to calibrate it to achieve reliable acceleration data. This knowledge will be valuable in your Arduino-based projects that involve motion and orientation sensing.

Let's get started by examining the code and understanding how it communicates with the ADXL345 sensor, configures it, and calibrates it for accurate measurements.

Before reading the remainder, be sure to subscribe and support the channel if you have not!

Subscribe:

Youtube

Support:

https://www.buymeacoffee.com/mmshilleh

Remember you can purchase an ADXL345 at our Shop!

https://shillehtek.com/collections/all

Step 1-) Physical Connection:

You should set up I2C connection with the device as follows:

Image description

We need four jumper wires. In this case I am using a two sided ADXL and an Arduino Nano, but in reality you can use any ADXL model or Arduino controller as long as you match the connections!

Step 2-) Code:

Run the following code on the device

#include <Wire.h>

int ADXL345 = 0x53; // The ADXL345 sensor I2C address
float X_out, Y_out, Z_out; // Outputs
int X_offset = 0, Y_offset = 0, Z_offset = 0; // Offset values

void setup() {
  Serial.begin(9600);
  Wire.begin();
  configureADXL345(); // Configure the sensor
  // Note: You should calibrate upon re-powering the sensor
  // Uncomment if you want to calibrate
  // calibrateADXL345(); // Calibrate the sensor
}

void calibrateADXL345() {
  // You should calibrate with the positive axis pointed upwards against gravity
  // You should calibrate each axis separately and change the offset constant, 
  // You need to run this code three times if you want to calibrate all three axes
  float numReadings = 500;
  // float xSum = 0;
  // float ySum = 0;
  float zSum = 0;
  Serial.print("Beginning Calibration");
  Serial.println();
  for (int i = 0; i < numReadings; i++) {
    Serial.print(i);
    Serial.println();
    Wire.beginTransmission(ADXL345);
    Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(ADXL345, 6, true);
    X_out = (Wire.read() | Wire.read() << 8);
    Y_out = (Wire.read() | Wire.read() << 8);
    Z_out = (Wire.read() | Wire.read() << 8);
    // xSum += X_out;
    // ySum += Y_out;
    zSum += Z_out;
  }
  //// 256 is the raw value for 1g, (we calibrate at 1g hence why we take the difference)

  // X_offset = (256 - xSum / numReadings) / 4;
  // Serial.print("X_offset= " );
  // Serial.print(X_offset);
  // Y_offset = (256 - ySum / numReadings) / 4;
  // Serial.print("Y_offset= " );
  // Serial.print(Y_offset);

  Z_offset = (256 - (zSum / numReadings)) / 4;
  Serial.print("Z_offset= " );
  Serial.print(Z_offset);
  Serial.println();
  delay(1000);
  // We need to add it to the offset channel respectively =
  // Once you write to the offset channel you do not need to do it again,
  // unless you unpower and power the device
  // Each offset address is different for X, Y, and Z

  // Wire.beginTransmission(ADXL345);
  // Wire.write(0x1E);
  // Wire.write(X_offset);
  // Wire.endTransmission();
  // Wire.beginTransmission(ADXL345);
  // Wire.write(0x1F);
  // Wire.write(Y_offset);
  // Wire.endTransmission();
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20);
  Wire.write(Z_offset);
  Wire.endTransmission();
}

void configureADXL345() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  Wire.write(8); // Enable measurement (D3 bit high)
  Wire.endTransmission();
  delay(10);
}

void loop() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true);
  X_out = (Wire.read() | Wire.read() << 8);
  X_out = X_out / 256;
  Y_out = (Wire.read() | Wire.read() << 8);
  Y_out = Y_out / 256;
  Z_out = (Wire.read() | Wire.read() << 8);
  Serial.print(Z_out);
  Z_out = Z_out / 256;

  Serial.print("Xa= ");
  Serial.print(X_out);
  Serial.print("   Ya= ");
  Serial.print(Y_out);
  Serial.print("   Za= ");
  Serial.println(Z_out);
  delay(500);
}
Enter fullscreen mode Exit fullscreen mode

The code provided includes the following sections:

Setup: In the setup() function, the code initializes serial communication for debugging, sets up I2C communication, configures the ADXL345 sensor, and calls the calibration function. You should only call the calibration function initially when re-powering, then uncomment it in practice. The sensor is able to remember the calibration value as long as it remains on. See video above for further details on how to use this code for calibration.

Calibration: The calibrateADXL345() function is responsible for calibrating the sensor. Calibration should be performed with the positive axis (e.g., X, Y, Z) pointed upwards against gravity; you need to do one at a time in this code (room for improvement on the code level for sure). For example, when calibrating the Z-axis, the code collects data from the Z-axis (vertical) acceleration and calculates an offset value (Z_offset) based on the difference between the raw sensor values and a known value (256 for 1g). This offset is later applied to correct measurements and is written back to the sensor's register. You will need to uncomment and comment accordingly to calibrate the X and the Y. When the sensor is calibrated it should be as steady as possible, ideally using a calibration block.

Configuration: The configureADXL345() function sets up the ADXL345 sensor by accessing the POWER_CTL register to enable measurements.

Loop: In the loop() function, the code continuously reads acceleration data from the ADXL345 sensor. It sends an I2C request to get the raw acceleration values for the X, Y, and Z axes, converts these values to meaningful data, and prints them to the Serial Monitor. This code allows you to interface with the ADXL345 accelerometer, configure it, and calibrate it for accurate measurements of acceleration in multiple directions. You can further utilize this data in your Arduino projects, such as detecting motion or controlling devices based on orientation.

Conclusion

Hope this high-level overview of the code makes sense, you do not need to calibrate if you do not want to; it is only meant for improvement of results! Hope you got it working and enjoyed the tutorial. Do not forget to subscribe to our Youtube channel above for more in depth guides on projects. Stay tuned!

Top comments (0)