How can I do something after X seconds? (Solved)

So I'm sure this question has been asked countless times, but I don't know how to ask that magical question. I need to find out how to make something happen "after" X seconds. I have tried virtually every combination except the right one. LOL

I need to make sure that a switch is closed before firing the actual function.

So like, if contact made, start timer, time 5 seconds, and if contact made still true, then fire, else do nothing.

So here is some code.

#define CONTACT_SENSOR 2

unsigned long elapsedTime = 0;       
unsigned long onTime;     

boolean contact_reading;


void setup()
{

  //This function runs once every time the Arduino is powered up.
  
  Serial.begin(115200);   // Set your Serial Monitor baud rate to this to see
                          // output from this sketch on your computer when 
                          // plugged in via USB.
  Serial.println(F("I'm Alive.")); //prints to the computer via Serial 
                                     //Monitor (when plugged in via USB)
  
  pinMode(StatLED, OUTPUT);
    
  pinMode(CONTACT_SENSOR, INPUT_PULLUP);
  contact_reading = digitalRead(CONTACT_SENSOR);
}


void loop()
{
  
   if (digitalRead(CONTACT_SENSOR) != contact_reading) {
    contact_reading = !contact_reading;
      onTime = millis();      
               
            if(!contact_reading){
                if(onTime >= 5000){
                 Serial.println(F("High 1"));
              message = String("High Level #1");
               digitalWrite(StatLED, HIGH);
            
                 sendTextMessage();
              digitalWrite(StatLED, LOW);
                        onTime = 0;
                    }
        } else
           {
             Serial.println(F("Low 1"));
        digitalWrite(StatLED, LOW);
              message = String("Low Level #1");
              //sendTextMessage();
    }
  }
}

I have tried different millis configuration and get not the result I need.

Thank you.
Any help would be great.

You need to keep firmly in mind, that millis() is a free running counter. The only time its value is close to zero is when the sketch begins to run, and when it later overflows. So although I haven't fully analyzed your code, this raises a red flag:

        onTime = 0;

Especially since it gets overwritten by setting it to millis() at the beginning of loop().
millis() will only be close to zero about every 50 days. So when you compare onTime to it, after it has been set to zero:

      if (onTime >= 5000) {

It can only be false at the beginning of the sketch, or for 5 seconds every 50 days, when millis() reaches its maximum count.

It can only be false at the beginning of the sketch, or for 5 seconds every 50 days, when millis() reaches its maximum count.

Oh OK that makes sense. So, how could I make it work? I have seen ways to do something for X amount of times, or the ino. sketch Blink without delay, but none of those seem to work for me.

By the way thanks for the quick reply.

“Problems worthy of attack,
prove their worth by hitting back”.
-Piet Hein

  1. Define the problem
  2. Break it down into definite actions
  3. Write code for each of those actions

You want to take action, X seconds after what ?

michinyon:
You want to take action, X seconds after what ?

Of the switch! I have a float switch and I want it to send me a message as the switch goes HIGH but, because it's water sometimes that switch will make contact for a brief moment. I don't want that, I want to be able to have a few seconds to make sure that the switch is in fact made contact. So, if the switch is made and then not don't worry about telling me. In a nut shell!

Take note of the time (millis()) when you first detect the switch closed. Then periodically (like once each time through the loop function) take note of the current value of millis(). If you subtract the two you get the time between. When that time is more than 5000 ms, then it's been 5 seconds closed and you can take your action.

It won't be exactly like blink without delay, but it will use exactly the same concept. Have a look at that example and see if you can understand how and why it works.

Ok, so what I have now is.

int ledState = LOW;            
long previousMillis = 0; 
long interval = 5000;
void loop()
{
  
 unsigned long currentMillis = millis(); 

  if (digitalRead(CONTACT_SENSOR) != contact_reading) {
    contact_reading = !contact_reading;
                  
            if(!contact_reading){
       if(currentMillis - previousMillis > interval) {
        previousMillis = currentMillis;   
              if (ledState == LOW)
     		 ledState = HIGH;
		//Serial.println(F("High 1"));
             // message = String("High Level #1");
		//sendTextMessage();
   		 else
     		ledState = LOW;
	digitalWrite(StatLED, ledState);
						
             }
        } else
           {
             Serial.println(F("Low 1"));
        digitalWrite(StatLED, LOW);
              message = String("Low Level #1");
              //sendTextMessage();
    }
  }
}

Delta_G thank you for your reply

So I run it and I have to switch it twice to turn on the LED after five seconds. Not, what I'm wanting. I did look at Blink without delay and thought if I use the LED to command my actions then that should work. But, I'm getting wrong results.

Yeah, once you start the transition, you never go into the if clause.

You need something like this:

void loop()
{
  if (digitalRead(CONTACT_SENSOR) != contact_reading) 
  {
    contact_reading = !contact_reading;
    // reset the timer every transition
    previousMillis = millis(); 
  }
           
  if (!contact_reading)
  {
     if (millis() - previousMillis > interval) 
     {
          previousMillis = millis();   
          if (ledState == LOW) 
          {
              ledState = HIGH;
             //Serial.println(F("High 1"));
             // message = String("High Level #1");
             //sendTextMessage();
          } 
          else
          {
              ledState = LOW;
          }
          digitalWrite(StatLED, ledState);            
        }
    }
  }
  else 
  {
          Serial.println(F("Low 1"));
          digitalWrite(StatLED, LOW);
          message = String("Low Level #1");
          //sendTextMessage();
  }
}
1 Like

arduinodlb you are amazing, this is what I was aiming for. Thank you all for your support in helping me get through this.

1 Like