Could use some help with a small project

Hello,

I'm fairly new to all of this and hope this is the right place, but I've been trying to design something that would basically simulate a traffic light.
The Green LED is supposed to come on for 20 seconds, then the Yellow LED for 5 seconds, and the Red LED for 30 seconds, and then keep repeating.
There is also a switch that, when active, will make the Yellow LED flash on and off by itself until the switch is turned off and it will go back to the Green -> Yellow -> Red sequence.
I got this to work using delays, but doing that I can only wait until the end of the loop to switch to the blinking yellow light. I want to be able to switch between the two immediately when I press the button.
The code I've been using for this is below.

int switchPin = 2;
int val;

void setup(){
  pinMode(switchPin,INPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
}

void loop(){
  val = digitalRead(switchPin);
  
  if (val == LOW) {
    digitalWrite(5, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    delay(20000);
    
    digitalWrite(5, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(3, LOW);
    delay(5000);
    
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, HIGH);
    delay(30000);
  }
  
  if (val == HIGH) {
    digitalWrite(5, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(3, LOW);
    delay(1000);
    
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    delay(1000);
  }
}

Thank you.

Look at the example sketch "Blink without delay" and "Debounce" in the Examples folder that installed with the Arduino IDE.

if you want to keep it simple, check out interrupts. It's like a mailman:
Normally, without interrupts:
You need to check the mail (button pressed) a lot...
With an interrupt:
Doorbell rings. You get mail.
See how useful they can be? :slight_smile:

So is Blink_Without_Delay. In the IDE, press File-->Examples-->Digital-->Blink Without Delay
Then clicky on it.

If you want to keep it simple, I recommend that you don't use interrupts unless/until absolutely necessary - they introduce lots of design issues and make your code much more complex. They are certainly not needed here. What you need is a finite state machine to deal with the lamp outputs, and non-blocking code similar to the blink without delay example to handle the timed actions in states where they are relevant. A very simple way to implement a finite state machine which works well in situations like this is to use a variable to hold the current state and a switch / case statement to implement the behaviour relevant to the current state. This is the sort of thing I mean:

switch(state)
{
    case GREEN:
        if(millis() - startTime > GREEN_DURATION)
        {
            greenOff();
            amberOn();
            state = AMBER;
            startTime = millis();
        }
        break;
    
    case AMBER:
        if(millis() - startTime > AMBER_DURATION)
        {
            amberOff();
            redOn();
            state = RED;
            startTime = millis();
        }
        break
            
    case RED:
        if(millis() - startTime > RED_DURATION)
        {
            redOff();
            greenOn();
            state = GREEN;
            startTime = millis();
        }
        break;
    
    case AMBER_FLASHING:
        if(millis() - startTime > FLASH_DURATION)
        {
            startTime += FLASH_DURATION;
            invertAmber();
            redOff();
            greenOff();
        }
        break;
}