if statement with time delay

Hi all, I am relatively new to Arduino but learning!

Basically, I am trying to create an if statement that will execute (preferably once) when a condition has existed for 5 continuous seconds. More specifically, using an ultrasonic sensors, I want code to run if an object is within 50cm for more than 5 seconds. I seem able to one (or the other) but not both conditions concurrently.

In the code below, it seems that “currentTime” is assuming the uptime of the Arduino. I need the timer reset to zero when the “(cm <50)” condition starts. Ideally, I only want the if statement to run once, because eventually, I will be pushing a notification to Blynk - and I don’t want a notification every 5 seconds.

Thanks in advance!

const int trigP = 2;  //GPIO-2 of nodemcu
const int echoP = 0;  //GPIO-0 of nodemcu
long duration, cm;

unsigned long previousTime = 0;
 
void setup() {
  Serial.begin (9600);
  pinMode(trigP, OUTPUT);
  pinMode(echoP, INPUT);
}
 
void loop() {
  digitalWrite(trigP, LOW);
  delayMicroseconds(5);
  digitalWrite(trigP, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigP, LOW);
 
  pinMode(echoP, INPUT);
  duration = pulseIn(echoP, HIGH);
  cm = (duration/2) / 29.1;  
  
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

unsigned long currentTime = millis();

  if ((cm <50) && (currentTime - previousTime >= 5000))
  {
     Serial.println("TOO CLOSE - FOR TOO LONG");
     previousTime = currentTime;
  }
  delay(250);
}

I would suggest spending some time and investigate the Millis() function. What your code is doing is stopping program execution every time it encounters a delay until it has timed out, this is called blocking. It will not process the next step until the delay is satisfied. That is not the case with the Millis() function.

Please be more specific in your functional description.
Describing exactly how you want your project to behave can suggest obvious solutions, and eliminate unexpected behaviours.

Do you want your Blynk notification whenever a new condition of (<50cm for >5 seconds) occurs?
Set a trigger which is set when the condition (<50cm for >5 seconds) occurs…
Is there a minimum time that it should be (>50cm) before the trigger point is reset?
Reset that trigger when (>50cm for >n seconds) occurs.

Link that trigger to your Blynk notification.

If you want to combine ‘if’ statements you can use … if { (condition 1) && (condition 2) … && (condition n) }

then do this.

else do that.

To detect if something exists for 5 seconds do it like this pseudo code (probably seems upside down at first reading)

if (condition is false) {
   lastTimeConditionWasFalse = millis();
}

if (millis() - lastTimeConditionWasFalse >= 5000) {
  // condition has been true for 5 seconds
  // do something
}

...R

Robin2:
To detect if something exists for 5 seconds do it like this pseudo code (probably seems upside down at first reading)

if (condition is false) {

lastTimeConditionWasFalse = millis();
}

if (millis() - lastTimeConditionWasFalse >= 5000) {
 // condition has been true for 5 seconds
 // do something
}




...R

Thank you. This makes sense, but can you please expand on “condition is false”?
I assume the condition in my case is cm<50, so how do I translate this is into cm<50 is false?

that would be

if (cm >= 50) // greater or equal 50

Try this code which uses my millisDelay class (part of the SafeString library). See the tutorial How to code Timers and Delays in Arduino

#include <millisDelay.h>
// included in the SafeString library available from the Arduino Library manager
// see the tutorial https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
const int trigP = 2;  //GPIO-2 of nodemcu
const int echoP = 0;  //GPIO-0 of nodemcu
long duration, cm;

unsigned long TIMEOUT_MS = 5000;
millisDelay closeTimeout;

void setup() {
  Serial.begin (9600);
  pinMode(trigP, OUTPUT);
  pinMode(echoP, INPUT);
}
 
void loop() {
  digitalWrite(trigP, LOW);
  delayMicroseconds(5);
  digitalWrite(trigP, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigP, LOW);
 
  pinMode(echoP, INPUT);
  duration = pulseIn(echoP, HIGH);
  cm = (duration/2) / 29.1;  
  
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  if (cm < 50) {
     if (!closeTimeout.isRunning()) { // first time <50
        closeTimeout.start(TIMEOUT_MS);
     }
  } else { // >= 50
    closeTimeout.stop(); // moved outside 50cm
  }

  if (closeTimeout.justFinished()) {
    // have been inside 50 for 5sec
     Serial.println("TOO CLOSE - FOR TOO LONG");
  }
}

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