Executes a statement only if the condition is True for 5 seconds

[u][b]OBJECTIVE:[/b][/u]
​Hi. I'm stuck with a project for a long. Can anyone help me out? 

I'm trying to create an Arduino project with a gyroscope(mpu6050). The idea is that whenever the 
gyroscope axis gyX,gyY,gyZ returns an expected value of (0,-1,0) for "5" seconds, the leds should turn ON.
And i want this to happen inside a loop function. So whenever i keep the gyro on a flat surface/ a table 
without disturbing, the leds should turn ON. And whenever I interrupt the gyro, the leds should turn OFF.

Basically an if condition executes a statement when the condition is True for 5 seconds. 
This count should reset everytime I intruput the gyro.

[b][u]Problem:
[/u][/b]I used millis in this code. The leds turns ON right after the gyroscope values return the expected value. 

But what I want is the leds to turn ON only if the gyroscope return expected values for minimum of "5" seconds.
#include <Wire.h>
#include <GY6050.h>

unsigned long lasttime;
bool state;

GY6050 gyro(0x68);
int led1=2;
int led2=4;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  gyro.initialisation();
  lasttime = millis();
  state = true;
}

void loop() {
  if ((gyro.refresh('G', 'X')==0)&&(gyro.refresh('G', 'Y')==-1)&&(gyro.refresh('G', 'Z')==0)) {
    if(millis - lasttime > 1000)
    {
      lasttime = millis();
      state = !state;
    }
    digitalWrite(led1, state);
    digitalWrite(led2, state);
  }
  else {
    digitalWrite(led1,LOW);
    digitalWrite(led2,LOW);
  }
}

To check if some value is consistent for a period of time you need to think of the problem upside down - like this pseudo code

if (value too low) {
   lastTimeValueWasLow == millis();
}

if (millis() - lastTimeValueWasLow >= period) {
   // value has been higher throughout the period
   // do something
}

...R

OBJECTIVE:
Hi. I'm stuck with a project for a long. Can anyone help me out?

I'm trying to create an Arduino project with a gyroscope(mpu6050). The idea is that whenever the
gyroscope axis gyX,gyY,gyZ returns an expected value of (0,-1,0) for "5" seconds, the leds should
turn ON. And i want this to happen inside a loop function. So whenever i keep the gyro on a flat
surface/ a table without disturbing, the leds should turn ON. And whenever I interrupt the gyro,
the leds should turn OFF.

Basically an if condition executes a statement when the condition is True for 5 seconds.
This count should reset everytime I intruput the gyro. I've attched my code in this forum.

Problem:
I used millis in this code. The leds turns ON right after the gyroscope values return the expected value.

But what I want is the leds to turn ON only if the gyroscope return expected values for minimum of "5" seconds.

Gyro_Leds.ino (719 Bytes)

When the gyro becomes the required value (not is the right value) save the value of millis() as the start time and set a boolean to true. If the gyro is not the required value then set the boolean to false. Each time through loop(), if the boolean is true, subtract the start time from the current value of millis() and take action if the required period has elapsed

See the StateChangeDetection example in the IDE

Please post your code here rather than attaching it as it is quite small

Please follow the advice on posting code given in posting code

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

Duplicate topics merged

The OPs for the two topics have different usernames but the same IP address

I assume that they are the same person

@jerome747, @gabrielaron373 - what is going on here ?

Actually i have two arduino accounts. I accidenty uploaded the forum in the other account by thinking of uploading with this account. And now i got same forum from two different account :frowning:

The 2 accounts were created less than an hour apart. Why did you do that ?

You do not need 2 accounts. The jerome747 account has only 1 post and has been banned

No problem with the ban. Can you write an example of how to implement the code. I've tried implementing your fix but it did'nt work out. Here the led only glows so far (after setup).

#include <Wire.h>
#include <GY6050.h>
#include <TinyMPU6050.h>
GY6050 gyro(0x68);
MPU6050 mpu (Wire);

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 5000; 
const int led = 4; 
bool val;

void setup()
{
  pinMode(led, OUTPUT);
  mpu.Initialize();
  mpu.Calibrate(); //calibration takes 10-15seconds. 
}
void loop(){
  currentMillis = millis(); 

  if ((gyro.refresh('G', 'X')==0)&&(gyro.refresh('G', 'Y')==-1)&&(gyro.refresh('G', 'Z')==0)) { //stationary
  startMillis = millis();
  val=true;
  }
  if ((gyro.refresh('G', 'X')!=0)&&(gyro.refresh('G', 'Y')!=-1)&&(gyro.refresh('G', 'Z')!=0)) { //non-stationary
  val=false;
  }
  
  if (val=true && currentMillis - startMillis >=period) {
    digitalWrite(led,HIGH);
  }
  if (val=false) {
    digitalWrite(led,LOW);
  }
}

Comparisons must use == so this is wrong

if (val=false)

Also, you do not seem to have tried what I suggested in Reply #1

...R

As UKHeliBob said you need to check when the gyro BECOMES stationary not when it IS stationary. This is causing the startMillis to constantly reset and therefore never measured 5 seconds.

In order to do this you need to remember the last position. I have not tested this but hopefully you get the idea:

#include <Wire.h>
#include <GY6050.h>
#include <TinyMPU6050.h>
GY6050 gyro(0x68);
MPU6050 mpu (Wire);

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 5000;
const int led = 4;
int lastX, lastY, lastZ;

bool stationary = false;

void setup()
{
  pinMode(led, OUTPUT);
  mpu.Initialize();
  mpu.Calibrate(); //calibration takes 10-15seconds.
  lastX = gyro.refresh('G', 'X');
  lastY = gyro.refresh('G', 'Y');
  lastZ = gyro.refresh('G', 'Z');
}

void loop() {
  currentMillis = millis();
  
  int currX = gyro.refresh('G', 'X');
  int currY = gyro.refresh('G', 'Y');
  int currZ = gyro.refresh('G', 'Z');

  if (currX != lastX || currY != lastY || currZ != lastZ) {
    // Gyro position has changed
    if (currX == 0) && currY == -1) && currZ == 0)) { 
      // Transition from non-stationary to stationary
      startMillis = millis();
      stationary = true;
    }
    else {
      // Still moving
      stationary = false;
    }
    
    // Update last position
    lastX = currX;
    lastY = currY;
    lastZ = currZ;
  }

  if (stationary  && currentMillis - startMillis >= period) {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }
}

ToddL1962, It worked perfectly :slight_smile: Thank you so much.

Since I'm new to millis function, I couldn't manage to make it work by myself. However i learnt alot from you guys.
Thank You so much for helping. @Robin2 and** @UK HeliBob** and @ToddL1962. :slight_smile:

My millisDelay class (included SafeString library available from the library manager) provides an alternative, but equivalent solution to #1

#include <millisDelay.h>
millisDelay gyroscopeTimeout;
const unsigned long period = 5000; // 5000mS = 5sec

if (value too low) {
   gyroscopeTimeout.start(period);
}

if (gyroscopeTimeout.justFinished()) {
   // value has been higher throughout the period
   // do something
}

The advantage of millisDelay is that it provides other utility methods like, stop() and isRunning()
see the detailed tutorial How to code Timers and Delays in Arduino which also covers the logic behind the code in #1

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