code is running right through the millis function

Hi All, My sketch monitors two buttons on pullups. When the both go low, D9 goes high. When one of the buttons goes high, I am trying to wait for three seconds the turn D9 low. The problem is its turning the output low right away. I can see it counting three seconds on the monitor, but thats after it’s already off. It’s not waiting thee three seconds. Thanks, Randy

#include <EEPROM.h>               //Save even when powered off
#include <avr/sleep.h>            // Might use sleep

unsigned long previousMillis = 0;// Store last time off was checked

const long interval = 3000;      // Short button press check
const int switchonPin = 2;       // Pin number of ON input
const int delayswitchPin = 3;    // Pin number of delay on switch
const int ssronPin = 10;         // Pin number of the SSR ON output pin
const int led1Pin = 7;           // Status LED

int switchonState = 0;          // Innitialize the switch state to 0
int delayswitchState = 0;       // Innitialize the delay ON switch state to 0
int ssronState = LOW;           // Innitialize the SSR state to 0
int led1State = LOW;            // Innitialize LED to low state

void setup() {

  pinMode(switchonPin, INPUT_PULLUP);   // Plasma signal through contactor
  pinMode(delayswitchPin, INPUT_PULLUP);// Rocker switch to select delay, or no delay
  pinMode(ssronPin, OUTPUT);            // Output to SSR +
  pinMode(led1Pin, OUTPUT);             // Display LED

  Serial.begin(9600);                   // Set up for analog read in
}

void loop() { // Monitors signal switch and push button

  switchonState = digitalRead(switchonPin);      // Signal
  delayswitchState = digitalRead(delayswitchPin);// Delay switch

  if (switchonState == LOW) {// Signal ON
    Serial.print("Signal is Active");
    digitalWrite(ssronPin, HIGH);                      // Turn SSR ON
    Serial.println("SSR is ON");
  }

  if (switchonState == HIGH && delayswitchState == HIGH) { // If signal is OFF and delay switch is OFF
    quickOFF();                                            // Turn off SSR right away
  }

  else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    delayOFF();                                        // Turn of SSR after delay
  }
}
void quickOFF() { // Turns SSR OFF immediately
  Serial.println("Quick OFF");
  digitalWrite(ssronPin, LOW);         // Turn SSR OFF
}

void delayOFF() { // Turns SSR OFF after delay
  Serial.println("Waiting to turn OFF");
  unsigned long currentMillis = millis();  // Time stamp this moment

  if (currentMillis - previousMillis >= interval) { // Test for three seconds
    previousMillis = currentMillis;                  // Rest timer
    Serial.print("counting");
    Serial.print("OFF");
    digitalWrite(ssronPin, LOW);         // Turn SSR OFF
  }
}

You haven't shown the code for quickOFF() or delayOFF()...

Stupid mistake. Thanks, I edited the original post. Randy

When it runs delayOFF(), previousMillis is 0 from its initialisation. So unless it runs delayOFF() in the first 3000ms, current-previous will be > 3000 and the SSR goes off.

edit: you said it needs 2 pins low to turn on, looks like you only use 1. Also you talk of pin 9 but use 10?

To achieve your three second time out you will have to modify the conditional statement calling delayOff() by adding a control variable to start the delay timing and saving a startTime when first called. Then delayOff() uses the startTime for the interval measurement and resets the control variable when done.

#include <EEPROM.h>               //Save even when powered off
#include <avr/sleep.h>            // Might use sleep

//control variables for delayOff()
unsigned long startTime;
boolean timingStarted = false;

const long interval = 3000;      // Short button press check
const int switchonPin = 2;       // Pin number of ON input
const int delayswitchPin = 3;    // Pin number of delay on switch
const int ssronPin = 10;         // Pin number of the SSR ON output pin
const int led1Pin = 7;           // Status LED

int switchonState = 0;          // Innitialize the switch state to 0
int delayswitchState = 0;       // Innitialize the delay ON switch state to 0
int ssronState = LOW;           // Innitialize the SSR state to 0
int led1State = LOW;            // Innitialize LED to low state

void setup() {

  pinMode(switchonPin, INPUT_PULLUP);   // Plasma signal through contactor
  pinMode(delayswitchPin, INPUT_PULLUP);// Rocker switch to select delay, or no delay
  pinMode(ssronPin, OUTPUT);            // Output to SSR +
  pinMode(led1Pin, OUTPUT);             // Display LED

  Serial.begin(9600);                   // Set up for analog read in
}

void loop() { // Monitors signal switch and push button

  switchonState = digitalRead(switchonPin);      // Signal
  delayswitchState = digitalRead(delayswitchPin);// Delay switch

  if (switchonState == LOW) {// Signal ON
    Serial.print("Signal is Active");
    digitalWrite(ssronPin, HIGH);                      // Turn SSR ON
    Serial.println("SSR is ON");
  }

  if (switchonState == HIGH && delayswitchState == HIGH) { // If signal is OFF and delay switch is OFF
    quickOFF();                                            // Turn off SSR right away
  }

  else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if(timingStarted == false)
    {
    timingStarted = true;
    startTime = millis();
    }
    delayOFF();                                        // Turn of SSR after delay
  }
}

void quickOFF() { // Turns SSR OFF immediately
  Serial.println("Quick OFF");
  digitalWrite(ssronPin, LOW);         // Turn SSR OFF
}

void delayOFF() { // Turns SSR OFF after delay
  Serial.println("Waiting to turn OFF");
  unsigned long currentMillis = millis();  // Time stamp this moment

  if (timingStarted == true && currentMillis - startTime >= interval) { // Test for three seconds
    timingStarted = false;//reset timer
    Serial.print("counting");
    Serial.print("OFF");
    digitalWrite(ssronPin, LOW);         // Turn SSR OFF
  }
}

Thank you for your replies.

Ardy_guy, Sorry, while I was describing my problem I glance at my uno. Guess I should have had my glasses on.

cattledog, it works the first time through, but when switchState goes low again then high it goes right through to turn the ssroff without timing.

I found by mistake if I put the delayOFF right under startTime = millis(); and end with three brackets, I get "waiting to turn off every time, but it never finishes and stays stuck there. This one sure has me stumped.

I tried using currentMillis = startTime right after it turns the ssr LOW thinking maybey that would force it to reset each time through, but it didn't work.

Thanks again, Randy

As you wrote it

   quickOFF();                                            // Turn off SSR right away
  }

  else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if(timingStarted == false)
    {
    timingStarted = true;
    startTime = millis();
    }
    delayOFF();                                        // Turn of SSR after delay
  }
}
void delayOFF() { // Turns SSR OFF after delay
  Serial.println("Waiting to turn OFF");
  unsigned long currentMillis = millis();  // Time stamp this moment

  if (timingStarted == true && currentMillis - startTime >= interval) { // Test for three seconds
    timingStarted = false;//reset timer
    Serial.print("counting");
    Serial.print("OFF");
    digitalWrite(ssronPin, LOW);         // Turn SSR OFF
  }
}

By mistake as I copied it without using "copy"

   quickOFF();                                            // Turn off SSR right away
  }

  else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if(timingStarted == false)
    {
    timingStarted = true;
    startTime = millis();
    delayOFF(); // Turn of SSR after delay
    }                                       
  }
}
void delayOFF() { // Turns SSR OFF after delay
  Serial.println("Waiting to turn OFF");
  unsigned long currentMillis = millis();  // Time stamp this moment

  if (timingStarted == true && currentMillis - startTime >= interval) { // Test for three seconds
    timingStarted = false;//reset timer
    Serial.print("counting");
    Serial.print("OFF");
    digitalWrite(ssronPin, LOW);         // Turn SSR OFF
  }
}

By mistake as I copied it without using "copy"

I found by mistake if I put the delayOFF right under startTime = millis(); and end with three brackets, I get "waiting to turn off every time, but it never finishes and stays stuck there. This one sure has me stumped.

Me too. delayOff() should only have run one time given the boolean control variable.
delayOff() needs to be called every pass through loop for the timeout to work.

cattledog, it works the first time through, but when switchState goes low again then high it goes right through to turn the ssroff without timing.

else if (switchonState == HIGH && delayswitchState == LOW)

I have not really looked at the logic for getting back into this state. Can you use some serial print debugging statements around the switch states, let me know you see, and see if you can focus on if we are entering the conditional and the downstream logic is faulty, or if you don't reenter the conditional.

The if and else if statements watch two inputs. The delaySwitch just says to go through quickOFF or to go through delayOFF. The switchON tells it if when to actually turn off. Both of them are working.

With delaySwitch OFF(HIGH because of pullups), I get “quick off” in the monitor until the switchON state goes low again(because of pullups) and that’s exactly how I want it.

Like this:

 else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if(timingStarted == false)
    {
    timingStarted = true;
    startTime = millis();
    }
    delayOFF();                                        // Turn of SSR after delay
  }
}

With delaySwitch ON(LOW going through grounded switch), I get the three second delay on first time and “waiting to turn off” in the monitor. After that I get three seconds of scrolling “waiting to turn off”, then “counting”, then “off”, as I would expect it to stay in that loop until switchonState goes low again, but when I take switchon low(to turn on the ssr) after the first time I see it go all the way through the void delayOFF() without counting as it did the original way.

Like this:

else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if(timingStarted == false)
    {
    timingStarted = true;
    startTime = millis();
    delayOFF(); // Turn of SSR after delay
    }                                       
  }
}

(Just moving the delayOFF() to the other side of the bracket) The if and else if work as intended, and I get “Waiting to turn off” every time, but it never times out and writes the ssr pin LOW. So it is stopping right at the if timing statement, but it doesn’t go any further.

I haven’t had time to really try anything else as I’m at work. I sure hope that helps. Thanks so much for your help, Randy

I suggest you let your if statement set a new variable - delayActive =true and currentmillis=millis().
At the end of main loop you can call delayOFF if delayActive is true.

If timing in delayOFF turn off your led SSR or whatever you also set delayActive = false.

I moved the reset of the timing control to when the signal is on, and changed some of the print out for clarity. I think it does what you want now. The delay is active each time the signal stops and the delay switch is set.

#include <EEPROM.h>               //Save even when powered off
#include <avr/sleep.h>            // Might use sleep

//control variables for delayOff()
unsigned long startTime;
boolean timingStarted = false;

const long interval = 3000;      // Short button press check
const int switchonPin = 2;  // Pin number of ON input
const int delayswitchPin = 3;    // Pin number of delay on switch
const int ssronPin = 10;         // Pin number of the SSR ON output pin
const int led1Pin = 7;           // Status LED

int switchonState = 0;          // Innitialize the switch state to 0
int delayswitchState = 0;       // Innitialize the delay ON switch state to 0
int ssronState = LOW;           // Innitialize the SSR state to 0
int led1State = LOW;            // Innitialize LED to low state

void setup() {

  pinMode(switchonPin, INPUT_PULLUP);   // Plasma signal through contactor
  pinMode(delayswitchPin, INPUT_PULLUP);// Rocker switch to select delay, or no delay
  pinMode(ssronPin, OUTPUT);            // Output to SSR +
  pinMode(led1Pin, OUTPUT);             // Display LED

  Serial.begin(9600);                   // Set up for analog read in
}

void loop() { // Monitors signal switch and push button

  switchonState = digitalRead(switchonPin);      // Signal
  delayswitchState = digitalRead(delayswitchPin);// Delay switch

  if (switchonState == LOW) {// Signal ON
    Serial.print("Signal is Active");
    digitalWrite(ssronPin, HIGH);                      // Turn SSR ON
    Serial.println("SSR is ON");
    timingStarted = false;
  }

  if (switchonState == HIGH && delayswitchState == HIGH) { // If signal is OFF and delay switch is OFF
    quickOFF();                                            // Turn off SSR right away
  }

  else if (switchonState == HIGH && delayswitchState == LOW) {// If signal is off and delay switch is ON
    if (timingStarted == false)
    {
      timingStarted = true;
      Serial.println("delayOFF timingStarted = true");
      startTime = millis();
    }
    delayOFF();                                        // Turn of SSR after delay
  }
 
}
void quickOFF() { // Turns SSR OFF immediately
  Serial.println("Quick OFF");
  digitalWrite(ssronPin, LOW);         // Turn SSR OFF
}

void delayOFF() { // Turns SSR OFF after delay
  //Serial.println("Waiting to turn OFF");
  unsigned long currentMillis = millis();  // Time stamp this moment

  if (timingStarted == true && currentMillis - startTime >= interval) { // Test for three seconds
   // timingStarted = false;//reset timer
    Serial.print("delayOFF timing finished");
    Serial.println("       OFF");
    digitalWrite(ssronPin, LOW);         // Turn SSR OFF
  }
}

Thanks cattledog, I never would have thought to move it there, thinking of it as part of the off routine. I will try it as soon as I get home. Thanks so much for the time you spent helping me. Randy

Edit: It works GREAT!! Thanks again, Randy