GY-291 ADXL345 Accelerometer

10/05/18

Categories: Electronics Tags: Arduino

~/contents

ADXL345 is a 3-axis MEM accelerometer accessible through SPI and I2C. It is sometimes referred to as a gravity or tilt sensor, but it is probably more useful to think of it as a motion sensor. The Sparkfun and Adafruit versions of this module appear to only be 3.3V tolerant. The commonly available GY-291 is 3 to 5V tolerant and has internal pullup resistors. I did have issues detecting freefall with this module, but it’s not something I’ve thoroughly tested.

I had difficulty confirming if the GY-291 pins are all 5V tolerant. There is a schematic floating around that suggests to me they are not, but I have no had issues (yet) powering it from an Arduino with 5V pins, and I have done so without putting CS high.

GND - GND
VCC - 3.3V to 5V
CS - (High if connected as I2C)
INT1 (Interrupt Support, connect to any GPIO)
INT2 (Interrupt Support, connect to any GPIO -- use INT1 when possible)
SDO / Z - GND
SDA / Y - SDA / Arduino Uno-Nano Analog 4
SCL / X - SCL / Arduino Uno-Nano Analog 5

In addition to detecting tilt via x, y, z axis this module can detect tap, double tap, free fall, and activity (and conversely, inactivity) motions via the interrupt pins, making it a very inexpensive and easy way to add motion support to a device. The applications are vast, from gesture support to having a toy go to sleep/low battery consumption if it’s not being played with. See my tilt toy project notes for more information.

There are a number of libraries available through the Arduino IDE Library Manager. The popular Adafruit ADXL345 library provides functionality for reading the sensor values (x,y,z) and does not provide functions for handling the interrupts. If you want to use the interrupts try the SparkFun library. Below is the code I use for testing.

#include <SparkFun_ADXL345.h>
ADXL345 accel = ADXL345();

void setup(){
  Serial.begin(9600);
  accel.powerOn();
  accel.setRangeSetting(4);
  accel.setActivityXYZ(1, 1, 1);
  accel.setActivityThreshold(30);
  accel.setInactivityXYZ(1, 1, 1);
  accel.setInactivityThreshold(75);
  accel.setTimeInactivity(30);

  // setting tap detection
  accel.setTapDetectionOnXYZ(0, 0, 1);
  accel.setTapThreshold(50);
  accel.setTapDuration(15);
  accel.setDoubleTapLatency(80);
  accel.setDoubleTapWindow(200);
  accel.InactivityINT(MOSI); // using ICSP pin as INT1
  accel.ActivityINT(MOSI);
  accel.doubleTapINT(MOSI);
}

void loop(){
  int x_diff,y_diff,z;
  accel.readAccel(&x_diff, &y_diff, &z);
  byte interrupts = accel.getInterruptSource();

  if(accel.triggered(interrupts, ADXL345_INACTIVITY)){
    Serial.println("*** INACTIVITY ***");
  }

  if(accel.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***");
  }

  if(accel.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
  }

  Serial.print("X: ");
  Serial.println(x_diff);
  Serial.print("Y: ");
  Serial.println(y_diff);
  Serial.print("Z: ");
  Serial.println(z);
  delay(1000);
}