LIS2DH12 accelerometer movement detection when the device is in any orientation

I have a LIS2DH12 accelerometer and the INT1 (interrupt 1) pin is wired to the ESP32 (or any arduino, I don't think it matters) pin 27. ESP32's two I2C pins are connected to LIS2DH12.

Imagine this device being inside a ball. ESP32 (or arduino) will go into deep sleep after 10 minutes of startup. Then with a slightest movement in any direction, I want the interrupt to trigger waking up the ESP32/arduino/microcontroller.

I am not an electrical engineer and not great at reading datasheets - I am copy/pasting code in an attempt to make it work. I have the following code that works great if the LIS2DH12 starting state is flat to the ground. With a slight movement on either x,y or z axis, the interrupt is triggered. However, if the device/ball starts out at a 45 degree angle on x-axis, moving it slightly on any axis does not fire the interrupt. It seems like LIS2DH12 compares it's internal values assuming a base that the device will start out always flat as far as physical orientation.

Question: Not sure if this is a hardware limitation or something can be done in code? If something is possible in code, please suggest changes to below.

#include <Wire.h>

#define LIS2DH12_ADDR 0x19 // I2C address of the LIS2DH12 accelerometer
#define INT_PIN 27          // Pin connected to INT1 of LIS2DH12

volatile bool motionDetectedFlag = false;

void setup() {
  Wire.begin();             // Initialize I2C communication
  Serial.begin(115200);     // Initialize serial communication

  // Configure LIS2DH12
  Wire.beginTransmission(LIS2DH12_ADDR);
  Wire.write(0x20);         // CTRL_REG1 register
  Wire.write(0x97);         // Set normal mode, enable all axes, enable INT1
  Wire.endTransmission();

  pinMode(INT_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(INT_PIN), motionDetectedISR, CHANGE); // Attach interrupt to INT1 pin
}

void loop() {
  if (motionDetectedFlag) {

    Serial.print(millis());
    Serial.println(" Motion detected!");
    motionDetectedFlag = false; // Reset flag
    // Do something when motion is detected
  }
  delay(1000); // Adjust delay as needed
}

void motionDetectedISR() {
  motionDetectedFlag = true;
}

I was able to also get a sparkfun example working which has the exact same issue

#include <Wire.h>
#include "SparkFun_LIS2DH12.h"

SPARKFUN_LIS2DH12 accel;

int accelInterruptPin = 27;

void setup()
{
  Serial.begin(115200);
  delay(500);
  Serial.println("SparkFun Accel Example");

  Wire.begin();

  if (!accel.begin())
  {
    Serial.println("Accelerometer not detected. Check address jumper and wiring. Freezing...");
    while (1);
  }

  pinMode(accelInterruptPin, INPUT_PULLUP);

  accel.setDataRate(LIS2DH12_POWER_DOWN); //Stop measurements

  // Set INT_POLARITY to Active Low
  accel.setIntPolarity(LOW);

  // Set INT1 interrupt
  accel.setInt1IA1(true);

  // Set INT1 threshold and duration for any movement detection
  accel.setInt1Threshold(6); // Set threshold to the smallest value for any movement
  accel.setInt1Duration(9);  // Set a duration to filter out noise

  // Clear the interrupt
  while (accel.getInt1()) delay(10); // Reading int will clear it

  // Set data rate and enable interrupts
  accel.setDataRate(LIS2DH12_ODR_400Hz); 
  accel.setInt1(true); // Enable interrupts on INT1 pin

  Serial.println("Begin Interrupt Scanning");
  Serial.println("Detecting any movement...");
}

void loop()
{
  // Poll for the interrupt via I2C just for testing purposes 
  if (accel.getInt1() == true) // Reading int will clear it
  {
    Serial.print(millis());
    Serial.println(" Movement Detected!");
  }

  delay(100);
}

ChatGPT generates this code and I can't find the LIS2DH12.h library anywhere to test it

#include <Wire.h>
#include <LIS2DH12.h>

#define INTERRUPT_PIN 2 // Pin connected to the interrupt output of LIS2DH12
#define MOTION_THRESHOLD 1000 // Adjust threshold according to your requirements
#define DEEP_SLEEP_DURATION_US 60000000 // 60 seconds

LIS2DH12 lis; // Initialize LIS2DH12 object

void setup() {
  Serial.begin(115200);
  
  // Initialize LIS2DH12
  if (!lis.begin()) {
    Serial.println("Failed to initialize LIS2DH12!");
    while (1);
  }

  // Set up interrupt pin
  pinMode(INTERRUPT_PIN, INPUT);

  // Enable motion detection interrupt
  lis.enableFreeFallDetection(LIS2DH12::FFD_INT1, MOTION_THRESHOLD, LIS2DH12::FREE_FALL_DURATION_1);

  // Attach interrupt handler
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), motionDetected, RISING);

  // Configure ESP32 for deep sleep
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_2, HIGH); // GPIO_NUM_2 is equivalent to INTERRUPT_PIN

  Serial.println("Setup complete, going to sleep...");
}

void loop() {
  // Put ESP32 into deep sleep mode
  esp_deep_sleep_start();
}

void motionDetected() {
  Serial.println("Motion detected!");
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.