Dividing delay by 2 for every button press

I'm having problems checking if the button is being pressed and dividing the delay timer properly.

Essentially, in the beginning, the Green LED should be on followed by a delay timer of 20 seconds. I need to be constantly checking the value of the delay timer. and check if a button is being pressed every 0.5 seconds, in which if so, the remaining time should be cut in half. For example, if the remaining time is 8 seconds, if the button is pressed, it should be 4 seconds now. Once the timer is finished, it should turn on the Red LED next for 10 seconds.

Circuit

And my code:

#define RedLED 13 // pin 13 on the board
#define GreenLED 11 // pin 11 on the board
#define Btn A3 // pin A4 on the board

void setup(void) {
	pinMode(Btn, INPUT);
  	pinMode(RedLED, OUTPUT);
    pinMode(GreenLED, OUTPUT);
}

void loop(void) {
 	changeToGreen(); 	
  	changeToRed();
}

void changeToGreen(void) {
 	digitalWrite(RedLED, LOW);
  	digitalWrite(GreenLED, HIGH);
  
    int btnState = 0;
  	btnState = digitalRead(Btn);
  	int timeLeft = 20000;
  
  	while (timeLeft > 0) { 
      	delay(500);
      
    	if (btnState == 1) { 	
      		timeLeft = timeLeft / 2;
          	//delay(timeLeft);
      	}
      	delay(timeLeft);
  	}
}

void changeToRed(void) {	
  	digitalWrite(GreenLED, LOW);
  	digitalWrite(RedLED, HIGH);
  	delay(10000);
}

Any help is appreciated, Thanks.

No matter how you change your code around this line, this line causes the program to hang out here and do nothing else until this delay completes.

So, step one is to study the blink without delay example and rewrite your code accordingly.

Then we can tackle your question.

Alright, thank you. Will look into that.

I see a few issues:

  1. As @Perehama stated your program will be only as responsive as your longest delay() call.
  2. How is your button wired? Your code implies you have a pull-down resistor. I recommend you wire your button like this and use INPUT_PULLUP:
    7305ae937d35a325d6127ab8206d6868d33f6570_2_690x217
    To detect a button press look at the following tutorial:
    StateChangeDetection
  3. btnState never changes in the following while loop so it may be stuck there forever.
  	while (timeLeft > 0) { 
      	delay(500);
      
    	if (btnState == 1) { 	
      		timeLeft = timeLeft / 2;
          	//delay(timeLeft);
      	}
      	delay(timeLeft);
  	}

Hello 49lone82
Take a view here to gain your knowledge about coding timing tasks.

Have a nice day and enjoy coding in C++.
Дайте миру шанс!

consider

#define RedLED   13 // pin 13 on the board
#define GreenLED 11 // pin 11 on the board
#define Btn A3 // pin A4 on the board

byte butState;
enum { ST_RED, ST_GREEN };
int  state = ST_GREEN;

unsigned long period = 20 * 1000;
unsigned long msecLst;

enum { Off = HIGH, On = LOW };

void
greenOn (void)
{
    period = 20 * 1000;
    state  = ST_GREEN;
    digitalWrite (GreenLED, On);
    digitalWrite (RedLED,   Off);
}

void
redOn (void)
{
    period = 10 * 1000;
    state  = ST_RED;
    digitalWrite (RedLED,    On);
    digitalWrite (GreenLED, Off);
}

void loop(void) {
    unsigned long msec = millis ();

    if ( (msec - msecLst) > period)  {
        msecLst = msec;

        switch (state)  {
        case ST_RED:
            greenOn ();
            break;
        case ST_GREEN:
            redOn ();
            break;
        }
    }

    byte but = digitalRead (Btn);
    if (butState != but)  {
        butState = but;

        if (LOW == but && ST_GREEN == state)
            period /= 2;
    }
}

// -----------------------------------------------------------------------------
void setup(void) {
	pinMode(Btn, INPUT_PULLUP);
	butState = digitalRead (Btn);

   	pinMode(RedLED,   OUTPUT);
    pinMode(GreenLED, OUTPUT);

    greenOn ();
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.