Timing the Force of Gravity on an Axis

Hello all, I am using an Arduino Pro Mini with an LIS3DH Accelerometer. I’m currently tracking the force of gravity on each axis and I want to time how long the force of gravity is on each axis. Then if the time exceeds a certain threshold, I want to print a line. An example, would be if the force of gravity was on the z-axis for over 5 minutes then it would print a line of text. However, if the force of gravity shifted to a different axis then the timer would restart and begin to time gravity on that axis. Essentially, if the Accelerometer is being moved then the timer will continue to restart and no line of text will print. Not until the Accelerometer is in place in one orientation for a set period of time, will the line of text then print. Any ideas of how I can set a timer or timers that will achieve this goal? I’m having trouble having the timer time the different axis and restart. Thank you! Below is my code:

// Basic demo for accelerometer readings from Adafruit LIS3DH

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>

// Used for software SPI
#define LIS3DH_CLK 13
#define LIS3DH_MISO 12
#define LIS3DH_MOSI 11
// Used for hardware & software SPI
#define LIS3DH_CS 10

// software SPI
Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS, LIS3DH_MOSI, LIS3DH_MISO, LIS3DH_CLK);
// hardware SPI
//Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS);
// I2C
//Adafruit_LIS3DH lis = Adafruit_LIS3DH();

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

long previousMillis = 0; 
long interval = 5000; 
unsigned long currentMillisx = 0;
unsigned long currentMillisy = 0;
unsigned long currentMillisz = 0;  


void setup(void) {
#ifndef ESP8266
  while (!Serial);     // will pause Zero, Leonardo, etc until serial console opens
#endif

  Serial.begin(9600);
  //Serial.println("LIS3DH test!");
  
  if (! lis.begin(0x18)) {   // change this to 0x19 for alternative i2c address
    Serial.println("Couldnt start");
    while (1);
  }
  //Serial.println("LIS3DH found!");
  
  lis.setRange(LIS3DH_RANGE_4_G);   // 2, 4, 8 or 16 G!
  
  //Serial.print("Range = "); Serial.print(2 << lis.getRange());  
  //Serial.println("G");
}

void loop() {
  unsigned long currentMillis = millis();
  lis.read();      // get X Y and Z data at once
  // Then print out the raw data
  //Serial.print("X:  "); Serial.print(lis.x); 
  //Serial.print("  \tY:  "); Serial.print(lis.y); 
  //Serial.print("  \tZ:  "); Serial.print(lis.z); 

  /* Or....get a new sensor event, normalized */ 
  sensors_event_t event; 
  lis.getEvent(&event);
  
  /* Display the results (acceleration is measured in m/s^2) */
  Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
  Serial.print(" \tY: "); Serial.print(event.acceleration.y); 
  Serial.print(" \tZ: "); Serial.print(event.acceleration.z); 
  Serial.println(" m/s^2 ");

  Serial.println();

  if (abs(event.acceleration.x)>8 && abs(event.acceleration.y)<8 && abs(event.acceleration.z)<8)
  {
    if (currentMillis-currentMillisx > interval)
    {
       currentMillisx = currentMillis;
      Serial.println("Sedentary Body Detected");
    }
  }
   if (abs(event.acceleration.y)>8 && abs(event.acceleration.x)<8 && abs(event.acceleration.z)<8)
  {
    if (currentMillis-currentMillisy > interval)
    {
      currentMillisy=currentMillis;
      Serial.println("Sedentary Body Detected");
    }
  }
   if (abs(event.acceleration.z)>8 && abs(event.acceleration.y)<8 && abs(event.acceleration.x)<8)
  {
    if (currentMillis-currentMillisz > interval)
    {
      currentMillisz = currentMillis;
      Serial.println("Sedentary Body Detected");
    }
  }
  if (abs(event.acceleration.x)<1 && abs(event.acceleration.y)<1 && abs(event.acceleration.z)<1)
  {
    Serial.print("Fall Detected");
    delay(2000);
  }
  
 
  delay(200); 
}

Any ideas of how I can set a timer or timers that will achieve this goal?

How would YOU do it with nothing more than a piece of paper, a pen or pencil, and a watch? That's really all the Arduino has/uses. No timers are needed.

You read an axis, and determine that the value means that it is moving. So, you record the current time as lastXMoveDetected or lastYMoveDetected or lastZMoveDetected, depending on which axis you sensed motion on.

Periodically, you determine if now minus last(X,Y,Z)MoveDetected exceeds some threshold, and, if it does, send a message. The only function needed is millis(). A few if statements, and you're done.

archeresque:
and I want to time how long the force of gravity is on each axis

You don't even need a clock for that. The answer is "continuous" - certainly for the last x billion years.

...R

Figure out which axis is most aligned with the gravity vector:

  float accelerations[3];
  accelerations[0] =  abs(event.acceleration.x);
  accelerations[1] = abs(event.acceleration.y);
  accelerations[2] = abs(event.acceleration.z);

  float max = 0;
  int index = 0;
  for (int i = 0; i < 3 ; i++) {
    if (accelertions[i] > max) {
      index = i;
      max = accelerations[i];
    }
  }

Then, if the axis is different from the previous axis, start the timer:

  static int maxAxis = -1;
  static unsigned long timerStart = 0;

  if (maxAxis != index) { // Axis of maximum gravity has changed
    timerStart = millis();
    maxAxis = index;
  }

And when the timer expires, display you line of text:

  if (millis() - timerStart > 5UL * 60UL * 1000UL) {
    Serial.println("A line of text");
    startTime = millis();  // Don't display again for at least another five minutes
  }

johnwasser:
Figure out which axis is most aligned with the gravity vector:

  float accelerations[3];

accelerations[0] =  abs(event.acceleration.x);
  accelerations[1] = abs(event.acceleration.y);
  accelerations[2] = abs(event.acceleration.z);

float max = 0;
  int index = 0;
  for (int i = 0; i < 3 ; i++) {
    if (accelertions[i] > max) {
      index = i;
      max = accelerations[i];
    }
  }




Then, if the axis is different from the previous axis, start the timer:


static int maxAxis = -1;
  static unsigned long timerStart = 0;

if (maxAxis != index) { // Axis of maximum gravity has changed
    timerStart = millis();
    maxAxis = index;
  }




And when the timer expires, display you line of text:


if (millis() - timerStart > 5UL * 60UL * 1000UL) {
    Serial.println(“A line of text”);
    startTime = millis();  // Don’t display again for at least another five minutes
  }

Thanks, this is exactly what I need! I think there’s a typo in the variable startTime which should be timerStart but I tested this right now and it works very well!