🌍 How to connect the ADXL345 digital accelerometer to Arduino

Let's connect to the Arduino a digital accelerometer module based on the ADXL345 chip with control via serial I2C and SPI interfaces.
03

Let’s connect to the Arduino a digital accelerometer module based on the ADXL345 chip with control via serial I2C and SPI interfaces.

We will need:

  • Arduino UNO or another compatible card;
  • GY-291 module or equivalent with an ADXL345 digital accelerometer;
  • connecting wires;
  • breadboard;

An accelerometer is a device that allows you to measure dynamic and static acceleration in three axes X, Y, and Z. Thanks to static acceleration, you can determine the position in space (accelerometer as a rotation sensor), and thanks to the dynamic (movement or shake) the acceleration direction.

The digital accelerometer ADXL345 is a 3-axis high-resolution accelerometer (13 bits) in axes with a limit of up to ± 16g. The module has low power consumption and small size. Information exchange with the module is carried out via serial interfaces I2C or SPI (3- or 4-wire).

There are many modules for Arduino with an accelerometer ADXL345. A module might look like this:

The module shown is called GY-291. The module has the following conclusions:

Module Description  Arduino pin
SPI I2C
GND Ground GND GND
VCC Power supply +3,3V +3,3V
CS Select SPI Slave Interface 10
INT1 Interrupt 1 output (*)
INT2 Interrupt 2 output (*)
SDO Data from the slave 12
SDA Data from the SPI Interface Wizard
I2C interface data bus
11 A4
SCL Clocking bus 13 A5

 

 Depending on the selected interface – SPI or I2C – the connection of the module will be appropriate, as shown in the table. But in both cases, very simple.

Consider the structure of the registers chip ADXL345:

 

 In addition, we are interested in the register of power management, since He is responsible for the operation mode of the device:

As you can see, the D3 (Measure) bit switches the accelerometer to the measurement mode.

Work with digital accelerometer ADXL345
SPI interface

The ADXL345 accelerometer supports 3- and 4-wire SPI interface options. We will consider the only a 4-wire connection. In addition, the accelerometer works in mode 3 of the SPI interface (remember, we have already discussed: CPOL = 1, CPHA = 1). A diagram showing the exchange with an ADXL345 accelerometer over a 4-wire SPI interface:

Here the MB bit is a sign that we are going to read many bytes at a time (if the bit is set to 1). For testing SPI devices and quick mastering of the exchange procedure with them, I usually use a debugging board with the FT2232H microcircuit. This chip supports many modes, including I2C and SPI. Controlling the operation of the FT2232H chip – using the SPI via FTDI program, which I have already spoken about several times.

We connect the accelerometer to the debug board and read the register DEVID, which stores the constant value of the accelerometer ADXL345. The id value should be 0xE5.

Before reading, do not forget to write down the command 0x80, which will indicate to the accelerometer that we are going to read, starting with the register at 0x0 :

It can be seen that the register contains the number 0xE5, which is the value of the accelerometer identifier ADXL345, according to the technical description (datasheet). Here is how it looks in the timeline:

 The device answers, everything is fine. Now we need to transfer the accelerometer to the measurement mode. To do this, write the number 0x08 into the POWER_CTL register (register address 0x2D) (set the Measure bit to HIGH). After that, you can start reading registers from 0x32 to 0x37, in which data on accelerations are stored in three axes. Do this with Arduino. Let’s write this sketch:

 

#include 

const byte READ = 0x80;
const byte MB = 0x40; 
const int CS = 10;

void setup() {
  Serial.begin(115200);
  SPI.begin(); 
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setDataMode(SPI_MODE3);
    
  byte id[1];
  readRegister(0x00, 1, id);
  Serial.print("ID = ");
  Serial.println(id[0], HEX);
  
  writeRegister(0x2D, 0x08); 
}

void loop() {
  byte buff[6];
  readRegister(0x32, 6, buff);
  
  int x = ((int)buff[1] << 8) | buff[0];
  int y = ((int)buff[3] << 8) | buff[2];
  int z = ((int)buff[5] << 8) | buff[4];

  Serial.print(x);
  Serial.print("t");
  Serial.print(y);
  Serial.print("t");
  Serial.println(z);

  delay(10);
}

void writeRegister(byte reg, byte value) {
  digitalWrite(CS, LOW);
  SPI.transfer(reg); 
  SPI.transfer(value); 
  digitalWrite(CS, HIGH);
}

void readRegister(byte reg, int bytesToRead, byte *outBuff) {
  digitalWrite(CS, LOW);
  reg = reg | READ; 
  if (bytesToRead > 1) {
     reg = reg | MB; 
  }
  SPI.transfer(reg);
  for (int i=0; i< bytesToRead; i++) {
    outBuff[i] = SPI.transfer(0x00);
  }
  digitalWrite(CS, HIGH);
}

 Here is the timing diagram of the work of this sketch:

 

 It is clear why the first byte of the transmission from the Arduino when reading the values ​​of the accelerations along the axes is the number 0xF2? This is the address of the first register with which we start reading (0x32), combined by OR with 0x80 – READ read marker – and with 0x40 – MB multibyte transfer marker:
0x32 OR 0x80 OR 0x40 = 0011_0010 OR 1000_0000 OR 0100_0000 = 1110_1101 = 0xF2
What do the read values ​​mean? This issue is discussed in the last section of the article. In addition, there are a number of libraries for Arduino, which simplify setting and reading data from the accelerometer, allowing you not to think about such low-level things as registers, bits, and bytes. Links to libraries are also provided at the end of the article.

Work with digital accelerometer ADXL345
I2C interface

The timing diagram of information exchange with the ADXL345 via the I2C interface looks like this:

Let’s rewrite the sketch for the Arduino, which will do the same thing, only with the exchange via the I2C interface:

#include 

const int adxl345 = 0x53;

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

  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x00));
  Wire.endTransmission();

  Wire.requestFrom(adxl345, 1);
  while (Wire.available()) {
    byte c = Wire.read();
    Serial.print("ID = ");
    Serial.println(c, HEX);
  }

  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x2D));
  Wire.write(byte(0x08));
  Wire.endTransmission();
}

void loop() {
  Wire.beginTransmission(adxl345);
  Wire.write(byte(0x32));
  Wire.endTransmission();

  int i = 0;
  byte xyz[6];
  Wire.requestFrom(adxl345, 6);
  while (Wire.available()) {
    byte c = Wire.read();
    xyz[i] = c;
    i++;
  }

  int x = word(xyz[1], xyz[0]);
  int y = word(xyz[3], xyz[2]);
  int z = word(xyz[5], xyz[4]);
  
  Serial.print(x);
  Serial.print("t");
  Serial.print(y);
  Serial.print("t");
  Serial.println(z);

  delay(100);
}

The read diagram of the DEVID register of the digital accelerometer ADXL345, when exchanged via the I2C serial interface, will be in this case:

 As you can see, the ADXL345 returns us the expected value of 0xE5. And this is how a chart of reading registers will look, in which data are stored along the XYZ axes:

 

 It’s still easier than working with the SPI interface.

Debriefing
digital accelerometer ADXL345

Look at the photo below. Three axes are drawn on the module board: X, Y, and Z. They show the direction of the accelerometer axes. The directions of the axes are due to the location of the ADXL345 chip on the board. In this case, the X-axis of the accelerometer is directed horizontally to the right, the Z axis is directed horizontally towards us, and the Y-axis is directed vertically upwards.

 

 And this is what our sketch brings to the Arduino IDE serial port monitor (you need to clarify that this output is observed in the rest mode – the accelerometer is still lying on the table in a position like in the above photo)

 

 The three columns represent the static acceleration value measured by the accelerometer along the X, Y, and Z axes, respectively. In the middle column, the Y-axis readings are larger than in the other two. These values are given in conditional samples, as recorded in the accelerometer registers. The ADXL345 accelerometer has several measurement ranges. Let’s look at the summary table of the ranges and resolutions of the accelerometer sensor:

The default range is from −16g to + 16g (span 32g). According to the table, 13 bits of accuracy or 213 = 8192 counts fall on this acceleration range. Thus, acceleration 32g / 8192 = 0.00390625g = 0.00390625 × 9.81 ≈ 0.038 m / s2 is accounted for 1 sample. With this in mind, it turns out that in this output of the sketch, the acceleration is:

Axis Acceleration, m/s2
X 0,76
Y 10,4
Z −0,12

 

 Well, it is quite logical. The Y axis is directed vertically, i.e. along with the force of gravity vector, and the value of the acceleration is approximately equal to the constant g. Accelerations along the X and Z axes, which lie in the same horizontal plane, are approximately the same and are around 0. Because of the curvature of the table on which the sensor stands, the values ​​are slightly different. If I leveled the accelerometer level, then his readings would be more accurate. In the ideal case, the acceleration should be 9.8 m / s2 along the Y-axis, and 0 along the X and Z axes.

In addition, the ADXL345 sensor has the ability to fine-tune and calibrate. In this example, we did not do this, but used an accelerometer with factory settings as is. Lack of calibration may also introduce some distortion in the sensor readings. I recommend using special Arduino libraries that simplify interaction with the ADXL345 accelerometer, in particular, allow fine-tuning.

 

 

 

 

 

Share on facebook
Facebook
Share on google
Google+
Share on twitter
Twitter
Share on linkedin
LinkedIn
Share on pinterest
Pinterest