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!");
}