Delay controlled relay sketch issues

Hello all,

As I am a newbie in programming, i need help in solving some issues on my sketch.
The application acts as follows:
While input pin 2 is HIGH, output pin 12 is HIGH too. when pin 2 goes LOW, a countdown of 30 mins (1800000 millis) starts and when this period expires, pin 12 goes low until pin 2 goes high again etc.
This works fine so far.
THE ISSUE: If pin 2 goes HIGH again while countdown is working, pin 12 goes HIGH and if pin 2 goes LOW, the countdown resumes and dont start counting 30 mins from the beginning.
In other words, I want the sketch to start the countdown from the beginning if pin 2 goes HIGH and then LOW again during a previous countdown operation.
My code is the below:

unsigned long interval=1800000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.

int BUTstate; // Current reading from BUTTON pin
int lastBUTstate = LOW; // Previous reading from BUTTON pin

int OFF = 0;
long lastDebounce = 0; // Last time output was changed
long Delay = 00; // Debounce Time

void setup() {
pinMode(2, INPUT);
pinMode(12, OUTPUT);

void loop()
int reading = digitalRead(2); // read button state

if (reading != lastBUTstate) // if change in button state
lastDebounce = millis();

if ((millis() - lastDebounce) > Delay) // verify reading is not noise
BUTstate = reading;

if (BUTstate == HIGH) // if button goes HIGH and is not noise
OFF = 1;

if (OFF==1 && BUTstate==LOW)
while ((unsigned long)(millis() - previousMillis) < interval);
OFF = 0;

lastBUTstate = reading;
previousMillis = millis();


sketch_ONDELAYOFF.ino (1.03 KB)

For next time, please use code tag.

Next up a big tip, but pin numbers in a variable. Makes it much clearer what it does;

const byte InputPin = 2;
const byte OutputPin = 12;

And the trouble is with the messy part (do while). You don't need to loop, just start the countdown (save the time, write the output) once based on state change detection, not based on the state. Because comment and code don't agree here

if (BUTstate == HIGH)  // if button goes HIGH and is not noise

Correct is

if (BUTstate == HIGH)  // if button _IS_ HIGH

And let the looping be done by the loop().

And a tip for easy, grab a library like Bounce2 to do the state change detection and debouncing.

Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

From what I gather you want;
If input is LOW, output is LOW
When input goes HIGH, output goes HIGH.
When input goes LOW, output stays HIGH for countdown of 30minutes, then goes LOW.

THE ISSUE: If pin 2 goes HIGH again while countdown is working, pin 12 goes HIGH and if pin 2 goes LOW, the countdown resumes and dont start counting 30 mins from the beginning.

In this case if you are counting down when input goes HIGH again, isn't your output already HIGH. because you are counting down?

What do you want to have happen if input goes HIGH and then LOW again, if the countdown is counting and output still HIGH?

Tom... :slight_smile:

Thank you all for your attention and comments.
I apologise for the wrong way i posted my code....

The case study to deal with is:
At start, output (pin 12) is low.
while input (pin 2) is high, pin 12 is high too.
when input goes low, a count down of 30 mins begins and output remains high until this period expires. then it goes low......
If input goes high again within these 30 mins, I need output to stay high as long as input is high and the count down to reset and start counting from the beginning when input goes low again etc etc........

Please advise the simplest you can, as this is my first step in programming......

Timing using millis() is fundamentally quite simple

Save the value of millis() as the start time when the start action occurs. In your case this will be when the input is LOW or when the input becomes HIGH. At the same time as saving the value of millis() set the output to HIGH and set a boolean to true.

Each time through loop(), if the boolean is true (timing started) check whether the required period has elapsed. If not keep going round loop() until it has. Once the required period has elapsed change state of the output and change state of the boolean to false.

One of several things may occur
1 - The input is kept LOW for longer that the period. No matter, because each time through loop() the start time will be reset and the output will remain HIGH

2 - The input becomes HIGH. The timing period will start and the output will be set HIGH

3 - the input goes LOW during the timing period. This is the same as 1 above

You debouncing code for the button is wrong, you should do something like:

byte state = digitalRead(buttonPin);
if ((state != buttonState) && (millis() - buttonChange >= buttonDebounce))
  buttonState = state;
  buttonChange = millis();
//Do buttonState related stuff here

Do you have a pulldown resistor from pin 2 to GND to make sure the pin does not "float" when the button is not pressed and cause "ghost" HIGHs?

Yeah, he should use "INPUT_PULLUP" for the button pin and remember that state==LOW means button is pushed.