Any ideas to make my accelerometer ignore shaking or jolting?

Hello everyone!

The goal of my project is to illuminate LEDs anytime the accelerometer achieves an orientation that is not somewhat flat. I have achieved this but my accelerometer seems to be too sensitive. What I mean by that is when the accelerometer is shaken or tapped, even if the actual orientaion remains flat, The LEDs trigger. I want to program it to ignore the minor taps or jolts.

I am using a working version of this abbreviated code.

loop(){

if ((Zval < 620))  

//LED flashing sequence

else {

//LED off

Could I write code that would run many Zval checks during my loop?

Currently when the accelerometer returns to a level orientation, the LED flashing sequence finishes the written loop before it deactivates to the else command. Would running these continual checks allow me to interrupt and stop the LEDs immediately?

Is there coding that can say..

verify that Zval is <620 for a continuous 50 milliseconds before running the loop
then interrupt the loop and run else if the Zval ever achieves >620

Do you think that would work?

My code.

int Xval;

int Yval;

int Zval;

int led1 = 11;

int led2 = 10;

int led3 = 9;

int led4 = 3;

int accPin = A3;

int accPin2 = A2;

int accpin3 = A4;

void setup(){

Serial.begin(9600);

pinMode(led1, OUTPUT);

pinMode(led2, OUTPUT);

pinMode(led3, OUTPUT);

pinMode(led4, OUTPUT);

delay(1000);

Xval = analogRead(accPin);
Yval = analogRead(accPin2);
Zval = analogRead(accpin3);

}

void loop(){

Xval = analogRead(accPin);

Yval = analogRead(accPin2);

Zval = analogRead(accpin3);

if ((Zval < 620)) 

{ 
digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(50);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(50);

digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(50);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(50);
digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(50);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(50);

digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(50);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(50);

digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(50);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(50);

digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(150);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(150);

digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(150);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(150);


digitalWrite(led2, HIGH);

digitalWrite(led3, HIGH);

digitalWrite(led1, HIGH);

digitalWrite(led4, HIGH);

delay(150);

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);

delay(150);





} 

else {

digitalWrite(led1, LOW);

digitalWrite(led4, LOW);

digitalWrite(led3, LOW);

digitalWrite(led2, LOW);
}
}

Thank you for any help!

JfromUT:
I want to program it to ignore the minor taps or jolts.

A simple way to do this is with a "running mean" - you store the last few readings and only react when the average goes outside your chosen limits. The neatest way to do that is with a "circular buffer". It slows down the response a bit but that's the trade-off you have to make. You'll need to learn about arrays.

Could I write code that would run many Zval checks during my loop?

Your flashing sequence is what's known as blocking code. It just runs from start to finish, no matter what happens. delay() is at the heart of the problem - it makes simple sketches easy to write but when you come to extend them it often means you have to re-write rather than adding a few lines.

To solve this one you need to learn about timing things with millis() instead of delay - look at the blink without delay example.

And there's some really good example code & discussion in this thread about doing several things at the same time.

Basically you want to filter out short duration changes, leaving only the longer timescale trends.

This is low-pass filtering, and there are many ways to do it.

The easiest is a simple one-pole digital filter, aka exponential smoothing.

#define TIME_CONSTANT 2.0  // seconds
#define DELAY 10   // recheck every 10ms
#define ALPHA (DELAY / 1000.0 / TIME_CONSTANT)

unsigned long last_time = 0 ;

float averaged_value ;

void loop ()
{
  if (millis() - last_time >= DELAY)   // sample at regular interval - essential for consistent results
  {
    last_time += DELAY ;
    averaged_value = smooth (analogRead (...)) ;
  }
}

float smooth (float input)  // exponential smoothing
{
  static float output = 0.0 ;    // persistent state private to this function
  output += ALPHA * (input - output) ;  // correct by a small fraction of the current error
  return output ;
}

Thank you both for the replies! I've had time to work with your suggestions.

I think I am too inexperienced to understand how to modify the suggestions to accommodate my code. Would you mind giving me some tips?

@GypsumFantastic -I ran the "blinking without using delay". It worked flawlessly. I just don't understand what to add and take away to make it work with Zval <620 rather than just the continuous time. I don't know how to create a unique flashing pattern rather than one continuous blink. Also from what I found, I believe that arrays may be too complicated to understand at my skill level.
Do you think the low pass filtering idea is a better way to go?

@MarkT -Your suggestion seems quite simple! I've tried to incorporate it into my code but I don't know how to properly use it. Would you please dumb it down further for me? I don't know how to incorporate my Zval <620 perimeter. could I still use my (delay) flashing pattern with this code or would I need to write something similar to the "blink without delay" code.

Thanks for any help!