Pushbutton. Why this code not working?

Probably this is simple for most of you, but I am still learning.

I tried not to use delay function in this code but nothing changes. the functions remains the same i.e. the button has to be pressed so that the status of output goes on-off-on-off. I need what's on to go off after a set time if the button is not pressed earlier.

thanx for your help!

int inPin2 = 2; // the number of the input pin
int outPin1 = 6; // the number of the output1 pin
int outPin2 = 7; // the number of the output2 pin
int state2 = LOW; // the current state of the output2 pin
int reading2; // the current reading from the input pin2
int previous2 = HIGH; // the previous reading from the input pin2
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount1 = 1; 

unsigned long endTime;

void setup()
{
pinMode(inPin2, INPUT);
pinMode(outPin1, OUTPUT);
pinMode(outPin2, OUTPUT);
}

void loop()
{
  {
  reading2 = digitalRead(inPin2);
if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) 
{
state2 = !state2; // Toggle the state
pressCount1++;
time = millis();
switch(pressCount1%4)
 {
      case 0:
digitalWrite(outPin1, HIGH);        // Turn on  pin1
endTime = millis() + 3000; //  seconds delay
if (millis() > endTime) {
digitalWrite(outPin1, LOW);
  }
        break;
      case 1:
digitalWrite(outPin1, LOW);       // Turn off  pin1
          break;
      case 2:
digitalWrite(outPin2, HIGH);        // Turn on  pin2
endTime = millis() + 3000; //  seconds delay
if (millis() > endTime) {
digitalWrite(outPin2, LOW);

        break;
      case 3:
digitalWrite(outPin2, LOW);       // Turn off  pin2
        break;
    }
  }
  previous2 = reading2;
  } 
  }
endTime = millis() + 3000; //  seconds delay
if (millis() > endTime) {
digitalWrite(outPin1, LOW);
  }

You just set endTime. How can you realistically expect millis() to immediately return a value that is more than 3 seconds later?

Your code is very hard to read. Please put each { on a separate line, and line it up with the statement that it goes with. Then, line the } that matches it up. Indent all code in between the { and the } a consistent amount.

It will be a lot easier to understand what is happening if you can quickly skip past code that is not to be executed, without having to hunt around to find what } closes a block.

It is also easier to debug code that uses functions, when appropriate.

endTime = millis() + 3000; //  seconds delay
if (millis() > endTime) {
digitalWrite(outPin2, LOW);

This is not a 3 second delay
this is

endTime = millis() + 3000; //  seconds delay
while (endTime > millis()) { } / do nothing 
digitalWrite(outPin2, LOW);

is a 3 second delay as is
delay(3000);
there is no advantage in using millis() if you are just going to hang about in a null loop until it has expired.

Thank you guys for your help!

thanx a lot Mike! the 3sec delay in your code works but the problem is that it still works the same as the delay command. meaning that during the 3sec, I can't do anything- I can't turn the outPin LOW. pressing the pushbutton during the 3sec does nothing. I have to wait till after 3sec pass.

Programming is not only a matter of learning some weird language but also to organize your ideas systematically.

  • At what place do you want to remember the current time?
  • At what place do you want to check how much time has ellapsed since then?

(Can't help further, because I am unable to read unindented code...)

I need what's on to go off after a set time if the button is not pressed earlier.

Can you explain what you want to do in simple pseudo-code? The way I read your explanation, you want something like this:

setup() {
  something = on
  countdown = millis() + COUNT_MAX
}

loop()  {

    if (button_press()) { 
          countdown = millis() + COUNT_MAX
    }

    if ( countdown <= millis() ) {
         countdown = millis() + COUNT_MAX
         something = !something
    }  

}

If that is what you want, compare each step of the pseudocode to your program and see where the code does something different.

As deSilva says, it is much easier to figure how to write your code when you know exactly what it is supposed to do at each step, and when you keep each step simple and clear.

but the problem is that it still works the same as the delay command.

Yes that's what I said.
However you have the opportunity to do something in your code if you wish.
That opportunity can be to do something either while you hang around in the loop or globally.
If you want to only do something if something hasn't happened for three seconds then you set an end time. Then in the main loop check if the three seconds has elapsed if so do something. If you want something to reset that delay then simply redefine the end time.

Look at the blink without delay example for the sort of structure you need.

Sorry guys for the confusion I made. I rewrote the code with more explanation about what it does. Please take a look.

As soon as the pushbutton is first pressed, time start counting. After 4 seconds, the lit LED should turn off. If the pushbutton is pressed again during those 4sec (before they pass), the lit LED should turn off, too.

The code now shows further details. Hope it's clear. Plz let me know if not.

/*
   Bushbutton

   Turns on and off an LED connected to digital pins 6 & 7 when pressing
   a pushbutton connected to pin 2. First press turns LED connected to
   pin 6 ON. Second press turns the same LED OFF. 3rd press turns LED
   connected to pin 7 ON. 4th press turns this LED OFF.
   Even if the second press does not take place to turn OFF LED connected
   to pin 6, this LED will turn OFF after set time (say 4000). This also 
   applies to LED connected to pin 7.

   *Note: delay function is not used. Otherwise, the first and 3rd presses
   to turning a Lit LED OFF will do nothing because they are interrupted by
   the delay function. (NOT SOLVED YET)
*/


int inPin2 = 2; // the number of the input pin
int outPin1 = 6; // the number of the output1 pin
int outPin2 = 7; // the number of the output2 pin
int state2 = HIGH; // the current state of the output2 pin
int reading2; // the current reading from the input pin2
int previous2 = HIGH; // the previous reading from the input pin2
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount1 = 1; 
unsigned long endTime;

void setup() {
      // initialize the pushbutton pin as an input:
   pinMode(inPin2, INPUT);
   // initialize the LED pins as an output:
   pinMode(outPin1, OUTPUT);
   pinMode(outPin2, OUTPUT);
}

void loop() {
  {
  reading2 = digitalRead(inPin2);
  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) 
  {
  state2 = !state2; // Toggle the state
  pressCount1++;
  time = millis();
  switch(pressCount1%4)
  {
      case 0:
  digitalWrite(outPin1, HIGH);        // If the button pressed, turn on  pin1
  endTime = millis() + 4000;      // 4 seconds delay. 
  while (endTime > millis()) { }  // do nothing
  digitalWrite(outPin1, LOW);     // Pin1 turns off after 4 seconds delay. that's
                                  // even if case 1 not start (button is not yet
                                  // pressed again)
        break;
      case 1:
  digitalWrite(outPin1, LOW);     // Turn off  pin1 before the set time (4 secnds)
                                  // pass. 
          break;
      case 2:
  digitalWrite(outPin2, HIGH);        // If the button pressed, turn on  pin1
  endTime = millis() + 4000;      // 4 seconds delay. 
  while (endTime > millis()) { }  // do nothing
  digitalWrite(outPin2, LOW);     // Pin2 turns off after 4 seconds delay. that's
                                  // even if case 3 not start (button is not yet
                                  // pressed again)
        break;
      case 3:
  digitalWrite(outPin2, LOW);      // Turn off  pin1 before the set time (4 secnds)
                                   // pass.
        break;
    }
  }
  previous2 = reading2;
  
  } 
  }

Hope it's clear.

Sorry it's not. What is not clear is what you actually want to do. Please see my previous post.

so, your loop pseudocode would be:

if ( buttonPushIsDetected ) {
   expire = millis() + interval;
   switch(clicks%4):
       case 0: led6 on
       case 1: led6 off
       case 2: led7 on
       case 3: led7 off
   clicks++
}

if ( millis() >= expire ) {
   switch off 6
   switch off 7
}

No need to mix the logic of the button, and the logic of the expiring time, that just confuses things.

Is this what you are trying to do?

/*
   Bushbutton

   Turns on and off an LED connected to digital pins 6 & 7 when pressing
   a pushbutton connected to pin 2. First press turns LED connected to
   pin 6 ON. Second press turns the same LED OFF. 3rd press turns LED
   connected to pin 7 ON. 4th press turns this LED OFF.
   Even if the second press does not take place to turn OFF LED connected
   to pin 6, this LED will turn OFF after set time (say 4000). This also
   applies to LED connected to pin 7.

   
*/


int inPin2 = 2; // the number of the input pin
int outPin1 = 6; // the number of the output1 pin
int outPin2 = 7; // the number of the output2 pin
int state2 = HIGH; // the current state of the output2 pin
int reading2; // the current reading from the input pin2
int previous2 = HIGH; // the previous reading from the input pin2
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount1 = 1;
unsigned long endTime, endTime2;

void setup() {
      // initialize the pushbutton pin as an input:
   pinMode(inPin2, INPUT);
   // initialize the LED pins as an output:
   pinMode(outPin1, OUTPUT);
   pinMode(outPin2, OUTPUT);
}

void loop() {
  if(endTime > millis() && digitalRead(outPin1) == LOW) digitalWrite(outPin1, LOW); // Pin1 turns off after 4 seconds delay.
  if(endTime2 > millis() && digitalRead(outPin2) == LOW) digitalWrite(outPin2, LOW); // Pin2 turns off after 4 seconds delay.
  {
  reading2 = digitalRead(inPin2);
  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce)
  {
  state2 = !state2; // Toggle the state
  pressCount1++;
  pressCount1 &= 0x3; // wrap round the counter
  time = millis();
  switch(pressCount1)
  {
      case 0:
  digitalWrite(outPin1, HIGH);        // If the button pressed, turn on  pin1
  endTime = millis() + 4000;      // 4 seconds delay.
  break;
      case 1:
  digitalWrite(outPin1, LOW);     // Turn off  pin1 before the set time (4 secnds)
          break;
      case 2:
  digitalWrite(outPin2, HIGH);        // If the button pressed, turn on  pin1
  endTime2 = millis() + 4000;      // 4 seconds delay.
        break;
      case 3:
  digitalWrite(outPin2, LOW);      // Turn off  pin1 before the set time (4 secnds)
                                   // pass.
        break;
    }
  }
  previous2 = reading2;
  
  }
  }

Thank you all for your help!

Finally, it works! this what solved my problem:

void loop() {
  if(digitalRead(inPin2) == LOW) expire =  millis() + interval;
  if ( millis() >= expire ) {
  digitalWrite(outPin1, LOW); // Pin 1 turns off after interval
  digitalWrite(outPin2, LOW); // Pin 2 turns off after interval
  }
  {
  reading2 = digitalRead(inPin2);
  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce)
  {
  state2 = !state2; // Toggle the state
  pressCount1++;
  pressCount1 &= 0x3; // wrap round the counter
  time = millis();
  switch(pressCount1)
  {

It's a combination of (jubal harshaw and Mike's) sketches. thx :slight_smile: