Traffic Light Party Mode Question

Hiya, beginner arduino programmer here.

I recently bought an old industrial traffic light (thing is over a meter (4 feet) tall on a yard sale for €40 and now I want to make it into a mood light. I picked up an arduino Uno & started playing with it. Now I want to implement it into that light to make it more special.

What I want to do.
I want to make different modes that switch on the push of a button. I’d think that would be best if I use a Switch Case.
Mode 1: Only red on (makes the room look like a brothel, but hey it’s cosy)
Mode 2: Only orange on
Mode 3: Only green on
Mode 4: All lights on
Mode 5 : Traffic Light mode = Switch from green to orange for a short time, then red, then back to green…
Mode 6: Full party mode = have the light flicker randomly

I have managed to get up untill mode 4, but 5 is where i’m stuck at. I have done some research and
it seems my problem is because my button press doesn’t get registered whilst it is looping inside my 5th mode. I read something about debouncing the button but I don’t really understand it. If anyone could help me to fix this i’d be really grateful and will promise to make a guide to the project public so everyone can make his or her own party traffic light at home!

Right now i’m just making the circuit with regular LED’s to test out the code. I have a quad channel 220v relay on the way to controll my big LED’s that fit inside the traffic light.

Here is my code

int button = 2; // pin on board for button
int green = 10; 
int blue = 11; //blue LED at the moment, don't have orange
int red = 9;

int state = 0; // Current state count for button
int old = 0;   // Old state count button
int buttonPoll = 0;  // Button position


void setup() {
  // put your setup code here, to run once:
  pinMode(button, INPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(red, OUTPUT);

  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);
  digitalWrite(red, LOW);
  Serial.begin(9600);
}

void loop() {

  buttonPoll = digitalRead(button);
  if (buttonPoll == 1) {
    delay(50);
    buttonPoll = digitalRead(button);
    if (buttonPoll == 0) {
      state = old + 1;
    }
  }
  else {
    delay(100);
  }
  switch (state) {
    case 0:
      Serial.println("Case 0");
      digitalWrite(red, HIGH);
      digitalWrite(blue, LOW);
      digitalWrite(green, LOW);
      old = state;
      break;

    case 1:
      Serial.println("Case 1");
      digitalWrite(red, LOW);
      digitalWrite(blue, HIGH);
      digitalWrite(green, LOW);
      old = state;
      break;

    case 2:
      Serial.println("Case 2");
      digitalWrite(red, LOW);
      digitalWrite(blue, LOW);
      digitalWrite(green, HIGH);
      old = state;
      break;


    case 3:
      Serial.println("Case 3");
      digitalWrite(red, HIGH);
      digitalWrite(blue, HIGH);
      digitalWrite(green, HIGH);
      old = state;
      break;

    case 4:
      Serial.println("Case 4");
      digitalWrite(red, LOW);
      digitalWrite(blue, LOW);
      digitalWrite(green, HIGH);
      delay(3000);
      digitalWrite(red, LOW);
      digitalWrite(blue, HIGH);
      digitalWrite(green, LOW);
      delay(3000);
      digitalWrite(red, HIGH);
      digitalWrite(blue, LOW);
      digitalWrite(green, LOW);
      delay(3000);
      old = state;
      break;

    default:
      Serial.println("Default Case");
      digitalWrite(green, LOW);
      digitalWrite(red, LOW);
      digitalWrite(blue, LOW);
      old  = 0;
  }
}

Free digital Belgian waffles for the person that can educate me!

These:

delay(3000);

need to go. The code does nothing else 'til delay is done - as you have discovered. Look for the pinned thread 'doing several things at the same time' at the top of some topics.

You read the button press at the top of loop() but since your code spends 9 seconds inside the case statement the button reading code is not run until all three lights have been cycled through.

The solution is to keep leaving and re-entering loop() even as the lights are being cycled. The way to do that is to use the millis() function to determine how long each LED has been on.

I suggest that when you initially get to state 4 you turn on the green LED and begin timing. Each time through loop() while state is still 4 you check to see if the next light should go on. I sketched out some code to give you an idea, it compiles but is not tested. I also wrote some functions to turn on the LEDs by name to make it a bit more readable.

int button = 2; // pin on board for button
int green = 10;
int blue = 11; //blue LED at the moment, don't have orange
int red = 9;

int state = 0; // Current state count for button
int old = 0;   // Old state count button
int buttonPoll = 0;  // Button position

bool flashingLeds = false;  // true => flash each led in turn
unsigned long startFlash = 0UL;

void setup() {
  // put your setup code here, to run once:
  pinMode(button, INPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(red, OUTPUT);

  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);
  digitalWrite(red, LOW);
  Serial.begin(9600);
}

void loop() {

  buttonPoll = digitalRead(button);
  if (buttonPoll == 1) {
    delay(50);
    buttonPoll = digitalRead(button);
    if (buttonPoll == 0) {
      state = old + 1;
    }

  }
  else {
    delay(100);
  }
  switch (state) {
    case 0:
      Serial.println("Case 0");
      redLed();
      old = state;
      break;

    case 1:
      Serial.println("Case 1");
      blueLed();
      old = state;
      break;

    case 2:
      Serial.println("Case 2");
      greenLed();
      old = state;
      break;


    case 3:
      Serial.println("Case 3");
      allOn();
      old = state;
      break;

    case 4:
      Serial.println("Case 4");

      // if not already flashing
      if ( !flashingLeds )
      {
        flashingLeds = true;    // set flag
        startFlash = millis();  // record time
        greenLed();             // green is on

      } else {

        // already flashing, update
        updateFlash();

      } // else

      //      digitalWrite(red, LOW);
      //      digitalWrite(blue, LOW);
      //      digitalWrite(green, HIGH);
      //      delay(3000);
      //      digitalWrite(red, LOW);
      //      digitalWrite(blue, HIGH);
      //      digitalWrite(green, LOW);
      //      delay(3000);
      //      digitalWrite(red, HIGH);
      //      digitalWrite(blue, LOW);
      //      digitalWrite(green, LOW);
      //      delay(3000);
      old = state;
      break;

    default:

      // done flashing
      flashingLeds = false;

      Serial.println("Default Case");
      allOff();
      old  = 0;
  }


}

// set LEDs to passed values
void setLeds(byte val1, byte val2, byte val3)
{
  digitalWrite(red, val1);
  digitalWrite(green, val2);
  digitalWrite(blue, val3);
}

void redLed() {
  setLeds(HIGH, LOW, LOW);
}
void greenLed() {
  setLeds(LOW, HIGH, LOW);
}
void blueLed() {
  setLeds(LOW, LOW, HIGH);
}


// all LEDs on
void allOn()
{
  setLeds(HIGH, HIGH, HIGH);
}

// all LEDs off
void allOff() {
  setLeds(LOW, LOW, LOW);
}

// turn on next LED if it's time
void updateFlash()
{
  unsigned long now = millis();

  if ( now - startFlash > 9000 )
  {
    // after 9 seconds green turns on
    greenLed();
    startFlash = now; // start over

  } else if ( now - startFlash > 6000 ) {

    // after 6 seconds red turns on
    redLed();

  } else if ( now - startFlash > 3000 ) {

    // after 3 seconds blue turns on
    blueLed();

  }
}

Change a little the algorithm and you'll observe that it will start working as you want. Small correction you need. But the idea is just perfect because everybody will want this. If you'll try a little bit more you can get even the hire lighting for party)) Make a party from lights but it can cause some problems to you because it is illegal. Now the policeman can fire you even because of an incorrect pass. That's just awful and I don't know when all this will be finished. I hope that very soon.

dorothyburgess:
Change a little the algorithm and you'll observe that it will start working as you want. Small correction you need.

Why resurrect a dead conversation after 16 months to add so little?

Yoda we have here. Time meaningless is. :slight_smile: