Check if condition is still met 0.5 second after initially met

Hello everyone!

I have been looking for a code to satisfy my request however nothing has come up so I’m going to make a post about it.

I am in need of code that will check if a condition is still met 0.5 seconds after it has initially been met, and for it to only check once. Then if it is met, follow through with the code.

Here’s an example

if(buttonStateM == 0 && buttonStateL == 0 && buttonStateR == 0) {
 (wait 0.5 seconds);
 check if (buttonStateM == 0 && buttonStateL == 0 && buttonStateR == 0) is still true
then turn led1 on
}
else led1 off

Take a look at BlinkWithoutDelay:

File | Examples | Digital | BlinkWithoutDelay

It’s all in there. Basically you need a state machine with two states (at a minimum):

CheckingForNoButtonsPressed
ConfirmingNoButtonsPressed

(Don’t use those actual names, of course! :grinning: - they are to illustrate what the states are for.)

capture a timestamp and set a state when a button press is detected and clear the state when the button is released

if (butLst != but)  {
    if (On == but)  {
         msecPending = millis();
         butState = Pending;
    }
    else
        butState = NotPendig;
}

while the state is pending, check if the timeout is exceeded and some action including clearing the state

msec = millis();
if (Pending == butState && (msec - msecPending) > Timeout)  {
    butState = NotPending;
    takesomeAction();
}

Perfect thank you both so much!

Hello Steve,

I am trying to work the blinkwithoutdelay code into the code mentioned above, could you provide a bit more detail how its done if possible?

I am rather new to coding and have only really done if statements and serial prints, when it comes to variables and millis, I am at a loss.

Thanks

if (Pending == butState && (msec - msecPending) > Timeout)

the Blink without Delay concept is implemented the code above by repeatedly comparing the difference between the current time and the timestamp of some previous event is compared to a Timeout instead of using a delay()

Ooops, @gcjr beat me to it! :grinning:

Anyway, what @gcjr says is exactly right, of course. Instead of putting a delay() between the two tests, you should use two states. You might call one state AWAITING_INPUT and the other state might be AWAITING_CONFIRMATION.

  //PSEUDOCODE
  if (state == AWAITING_INPUT && input is active)
  {
    timestamp = millis() + 500
    state = AWAITING_CONFIRMATION
  }
  else if (state == AWAITING_CONFIRMATION && millis() >= timestamp)  //don't do this in real code
  {
    if (input is active)
    {
      do the important thing
    }
    else  //input wasn't still active after 500ms, so abort
    {
      state = AWAITING_INPUT
    }
  }

Put that into a boolean function which you call repeatedly from loop(), and make that function return true (“do the important thing”) when the requirements are met, else return false.

Where I’ve said “don’t do this is real code” it’s because the test will fail if millis() rolls over. I’ve shown it this way because it’s easy to understand. @gcjr has shown the correct way to do it: compare intervals, not timestamps.

I haven’t attempted to show you how to do this using your example code at the top, because I’m hoping you will understand the basic principle, rather than having someone write the code for you. :grinning:

Perfect, thank you both for further explaining! I will give the code a try and report back.

The millisDelay class in my tutorial How to write Timers and Delays in Arduino
makes it easy to do things like this.

the code would look like

millisDelay timer;
unsigned long TIMER_MS = 500;

if (buttonStateM == 0 && buttonStateL == 0 && buttonStateR == 0) {
  if (!timer.running()) {
     timer.start(TIMER_MS);
  }
} else { 
   // condition not true any more stop timer
  timer.stop();
}
if (timer.justFinished() ) {
   // condition true for 500ms
  // do some thing
}

After trying your code for a bit, I am running into a problem.

I am receiving an error message

expression cannot be used as a function
if (!timer.running()) {
^
exit status 1
‘bool millisDelay::running’ is private within this context

Thanks

opps, try timer.isRunning() instead
Check the millisDelay.h file for all the methods

Perfect, the code compiled and is working!