If pin goes LOW, wait 2 seconds then go HIGH using millis() time with no delay

Hello all. I’ve been searching and reading everywhere for a solution to my simple issue. I just can’t wrap my head around on how to use the millis function with no delay to monitor a pin that if it goes LOW then wait 2 seconds and then have it go HIGH.

I’m successfully using “delay” with the following code however it’s pausing the loop for the required 2 seconds which is not desirable for my project.

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char ssid[] = "xxxxxxxx";
char pass[] = "xxxxxxx";

void setup() {
 Blynk.begin(auth, ssid, pass, IPAddress(192,168,x,xxx), 8080);

pinMode(PiROV, OUTPUT);
digitalWrite(PiROV, HIGH);
}
 
void loop() {
   if (digitalRead(PiROV) == LOW); 
    {
     delay (2000);
     digitalWrite(PiROV, HIGH);
    }

Below is some code from someone else but I can’t get the desired function. When I set the pin LOW it immediately goes HIGH within what looks like a fraction of a millisecond. All I want is for the code to watch for pin if LOW then go HIGH after 2 seconds using millis without delay. Thank you in advance for any help or suggestions.

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char ssid[] = "xxxxxxxx";
char pass[] = "xxxxxxx";

unsigned long startTime;
unsigned long interval = 2000;
const byte PiROV = D5;


void setup() {
  pinMode(PiROV, OUTPUT);
  digitalWrite(PiROV, HIGH);
  Blynk.begin(auth, ssid, pass, IPAddress(192,168,x,xxx), 8080);
}

void loop() {
  Blynk.run();
  
  if (millis() - startTime >= interval)
  {
    digitalWrite(PiROV, LOW);
  }
}

You're treating an output as an input??

I'm setting the pinmode to output and having it go HIGH on bootup. This controls a relay that is off while pin is HIGH. I control the pin though an Android app that sets the pin LOW when I press a button on my phone. Hopefully that makes sense.

Pseudo code for you

start of loop()
  if the pin becomes LOW (NB not is LOW)
    save start time from millis()
  end if

  if current time - start time >= 2 seconds
    set pin HIGH
  end if 

  //other code here if required
end of loop()

I just can't wrap my head around on how to use the millis function with no delay to monitor a pin that if it goes LOW then wait 2 seconds and then have it go HIGH.

If the pin is an input pin, then it makes sense to be monitoring it, to see when it goes low. You can't make an input pin go high, so your whole sentence does not make sense.

If you explain what you are REALLY trying to accomplish, then we can help you.

Perhaps you want to do something if a pin goes low, and is still low two seconds later. That would be easy, combining the state change detection example and the blink without delay example.

I just want to do this but with millis() with no delay

void setup() {
pinMode(D5, OUTPUT);
digitalWrite(D5, HIGH);
}
 
void loop() {
   if (digitalRead(D5) == LOW); 
    {
     delay (2000);
     digitalWrite(D5, HIGH);
    }
}

I just activate a relay connected to pin D5 which should turn off automatically after 2 seconds. Again I can do this with delay however I would like to do it with millis() with no delay.

I believe UKHeliBob has exactly the right idea but I'm not sure how put in code :slightly_frowning_face:

Please go easy on me, I'm still very new to arduino. Thank you for the help thus far.

Under what conditions would PiROV go low?

You set it as an output and set it high in setup. You then wait for it to go low. Is there unseen code that writes a low to it? Or is there an external agent that shorts the high-side transistor pin to ground?

Check this

const int PiROV = 5; //pin 5

boolean isButtonPressed = false;

unsigned long startTime;
unsigned long interval = 2000;

void setup() {

  pinMode(PiROV, OUTPUT);
  digitalWrite(PiROV, HIGH);
  
}

void loop() {

  //here put your code and change isButtonPressed to true when you receive from the Android app that the button is pressed

  if (isButtonPressed == true) {
   startTime = millis();
   digitalWrite(PiROV, LOW);
   isButtonPressed = false;
  }
  
  if (millis() - startTime >= interval && digitalRead(PiROV) == LOW) {
    digitalWrite(PiROV, HIGH);
  }
  
}

Blackfin I'm using an android app called Blynk which connects my NodeMCU and android phone together via a cloud server. In this app I can directly set any pin I want to HIGH or LOW with virtual buttons on the screen. However I'm trying to simulate a momentary 2 second button via code as I can't program this on the Blynk app. It works great with delay (first code I posted) however I want to use millis() with no delay.

I've been playing with danardos code but it's not working. I believe it's because the code is assuming it's a button that's being pressed when in fact the app it's just writing HIGH or LOW command to the NodeMCU.

Show the code where you receive HIGH and LOW

First image shows the description of how the Blynk virtual button works.
Second image shows the virtual button when is pressed which sends the signal to the NodeMCU via the cloud. I know the buttons work because I can engage my relays with no issues however one of the relays I need to automatically go LOW after 2 seconds after it gets triggered to go HIGH.

I was hoping code below would work but no luck.

const int PiROV = D5; //pin 5

unsigned long startTime;
unsigned long interval = 2000;

void setup() {
  
pinMode(PiROV, OUTPUT);
digitalWrite(PiROV, HIGH);

void loop() {

   if (digitalRead(PiROV) == LOW); 
  
     if (millis() - startTime >= interval)
         {
        digitalWrite(PiROV, HIGH);
         }
}

Here's some timing code which simulates the message from the phone with input from the serial monitor. Send 1 to get the two second time out.

const int PiROV = 5; 
boolean timing = false;
unsigned long startTime;
unsigned long interval = 2000;
char message;

void setup()
{
  Serial.begin(115200);
  pinMode(PiROV, OUTPUT);
  digitalWrite(PiROV, HIGH); //off
}

void loop()
{
  //receive message from phone setting PiROV LOW simulate with Serial input setting PiROV LOW
  //enter 1 from serial monitor
  if (Serial.available() > 0)
    message = Serial.read();
  if (message == '1')
    digitalWrite(PiROV, LOW);//turn on

  if (digitalRead(PiROV) == LOW and timing == false)
  {
    startTime = millis();
    timing = true;
  }

  if (millis() - startTime >= interval && timing == true)
  {
    digitalWrite(PiROV, HIGH);
    timing = false;
  }
}

You could be starting the timing from the receipt of the correct message and not the actual read of the output.

Connect the relay to another pin, when D5 changes state to LOW change the relay pin to LOW, something like that:

const int PiROV = D5;
const int RelayPin = D6;

boolean relayOn = false;

unsigned long startTime;
unsigned long interval = 2000;

void setup() {
  pinMode(PiROV, OUTPUT);
  digitalWrite(PiROV, HIGH);
  pinMode(RelayPin, OUTPUT);
  digitalWrite(RelayPin, HIGH);
}

void loop() {
  if (digitalRead(PiROV) == LOW) {
   startTime = millis();
   digitalWrite(RelayPin, LOW);
   relayOn = true;
  }
 
  if (millis() - startTime >= interval && relayOn == true) {
    digitalWrite(RelayPin, HIGH);
    relayOn = false;
  }
}

@malvar: your code doesn't call:

Blynk.run();

You need to put that in loop(). It may not be your only problem, but Blynk definitely won't work without it.

Blynk works fine. I just left it out to show the basic code for what I'm trying to accomplish.

malvar:
Blynk works fine. I just left it out to show the basic code for what I'm trying to accomplish.

And you don't think the fact that you're using Blynk is relevant information? You didn't even mention that fact until Reply #8. So, until then everyone was wondering how a pin you set as an OUTPUT would spontaneously change state. Good luck getting help when you don't supply crucial information.

I looked at Blynk doc and it is very simple to do that. Why you not use virtual pin in Blynk app? Change pin to Virtual V1, and use this code:

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "YourAuthToken";

char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";

const int PiROV = D5;

boolean relayOff = false;

unsigned long startTime;
unsigned long interval = 2000;

void setup() {
  Blynk.begin(auth, ssid, pass);

  pinMode(PiROV, OUTPUT);
  digitalWrite(PiROV, HIGH);
}

void loop() {
  Blynk.run();

  if (millis() - startTime >= interval && relayOff == true) {
    digitalWrite(PiROV, HIGH);
    relayOff = false;
  }
}

BLYNK_WRITE(V1) {
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable

  if (pinValue == 1) {
    startTime = millis();
    digitalWrite(PiROV, LOW);
    relayOff = true;
  }
}