Stoplight Button

I've made a 6 LED stoplight on Arduino, but I can't seem to find out how to make a usable road button that would make the light turn green after. Is there a way to make an IF statement that delays for like a second and then restarts the void loop back to turning the green LED, or is there a better way other than that?

Any help would be much appreciated, thanks.

Here's the code so far.

/* LED Stoplight
* If red LED is on delay for 5 seconds then turn off
* If the red LED is on the opposite green light is on
* Green light delays for a 4 seconds and turns yellow for 1 second
* after 1 second turn red
* Monday, November 2nd 2015 by Repleh
*/

//variable table 
int pin_green1 = 13; //green LED1 is connected to pin 13
int pin_yellow1 = 12; //yellow LED1 is connected to PIN 12
int pin_red1 = 11; //red LED1 is connected to PIN 11
int pin_green2 = 9; //green LED2 is connected to PIN 9
int pin_yellow2 = 5; //yellow LED2 is connected to PIN 5
int pin_red2 = 4; //red LED2 is connected to PIN 4
int delay_red = 5000; // delay red is 5 seconds
int delay_green = 4000; //delay green is 4 seconds
int delay_yellow = 1000; //delay yellow is 1 second


//the setup() method runs when the sketch starts
void setup () {
  pinMode(pin_green1, OUTPUT); // sets digital pin 13 as output
  pinMode(pin_yellow1, OUTPUT); // Starts digital pin 12 as output:
  pinMode(pin_red1, OUTPUT); // Starts digital pin 11 as output:
  pinMode(pin_green2, OUTPUT);  // Starts digital pin 9 as output:
  pinMode(pin_yellow2, OUTPUT); // Starts digital pin 5 as output:
  pinMode(pin_red2, OUTPUT); // Starts digital pin 4 as output:

}
  //the script loops when the sketch starts
  void loop (){
  digitalWrite(pin_green1, HIGH); // turns green LED1 on
  digitalWrite(pin_red2, HIGH); //turns red led2 on 
  delay (delay_green); //delay 4 seconds
  digitalWrite(pin_green1, LOW); //turns green led1 off
  digitalWrite(pin_yellow1, HIGH); //turns yellow led1 on
  delay (delay_yellow);
  digitalWrite(pin_red2, LOW);
  digitalWrite (pin_yellow1, LOW);
  }

}

Stoplight => Traffic light (are you Dutch? ;) )

When you want to use a button you better stop using delay ;)

"//green LED1 is connected to pin 13" Comment like that is quite useless. We can see you use pin 13, but what does this pin do? "//Pin of Green light side 1" Would be a better comment.

And what does the button needs to do?

You'll need to learn to 'debounce' the button press, too, or when it's pressed it will rapidly cycle through the LED states. There's a guide to doing that here:- Debounce

Or just don't reinvent the wheel and use a library like Bounce2 ;)

septillion: Or just don't reinvent the wheel and use a library like Bounce2 ;)

You're right, it's easier that way, but learning to do it the hard way initially is a good learning exercise.

I'm all in favor of learning about that. But for now, to get this project started it's better to start with learning about non-blocking etc. That looks like enough work for the TS now :D

The button is supposed to delay half a second, and then turn the stoplight green when pressed. Only when the red LED is on though. Like the button mentioned in this article: http://www.geekinsydney.com/6245/point-pressing-buttons-traffic-lights/

Thanks everyone for the tips, I'm going to try this out tomorrow.

I am fascinated by the fact that, as soon a button is mentioned, everyone trots out various debounce suggestions without asking whether there is a bounce problem.

The simple way to have a "delay" is to use millis() as illustrated in Several Things at a Time. And it includes a simple debounce solution if that is needed.

You can have a variable that records whether the light should be red or green. And at the end of the time period that variable can be changed. Then the function that causes the LEDs to light will use the value of that variable to decide which colour is appropriate.

...R Planning and Implementing a Program

Robin2: I am fascinated by the fact that, as soon a button is mentioned, everyone trots out various debounce suggestions without asking whether there is a bounce problem.

How could there be a bounce problem when the code shown didn't have the button presses yet. Looking ahead though, you don't have to be blind to foresee that there*could* be a bounce issue. "trots out" is a bit rough.

And it includes a simple debounce solution if that is needed.

What's this, you're "trotting out" a potential debounce solution![/quote]

OldSteve: What's this, you're "trotting out" a potential debounce solution!

I just thought I should get my retaliation in first.

More significantly Several Things at a Time handles debouncing without a library.

...R

Robin2: I just thought I should get my retaliation in first.

Fair enough. But I had to mention it. We all made debounce suggestions. :)

More significantly Several Things at a Time handles debouncing without a library. ...R[/quote] I personally don't use a library either. I just do whatever the situation calls for. Sometimes, just a simple 50mS to 100mS delay. (Not often though - usually just in on/off situations, whre blocking is unimportant.)

OldSteve: Fair enough. But I had to mention it. We all made debounce suggestions. :)

As you all had done so I didn't want to be left out :)

...R

Repleh:
The button is supposed to delay half a second, and then turn the stoplight green when pressed. Only when the red LED is on though. Like the button mentioned in this article.

Sounds suspiciously like my old pedestrian light code:

// Pedestrian crossing lights - Paul B.

const int led13Pin =  13;    // LED pin number
const int PgrnPin =  2;      // Pedestrian
const int PredPin =  3;
const int RgrnPin =  5;      // Road
const int RyelPin =  6;
const int RredPin =  7;
const int button1 =  10;     // Button to ground

int led13State = LOW;        // initialise the LED
int PgrnState = LOW;
int PredState = LOW;
int RgrnState = LOW;
int RyelState = LOW;
int RredState = LOW;
char bstate1 = 0;
boolean press = false;

unsigned long count1 = 0;   // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long count4 = 0;
unsigned long count5 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check 
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

void setout(unsigned long *marker) {
  *marker = millis();             // initialise
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}


void setleds() {
  digitalWrite(led13Pin, led13State);
  digitalWrite(PredPin, PredState);
  digitalWrite(PgrnPin, PgrnState);
  digitalWrite(RredPin, RredState);
  digitalWrite(RyelPin, RyelState);
  digitalWrite(RgrnPin, RgrnState);
}

boolean ispress() { // One-directional read of button - sets but does not clear!
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    press = true;
  } 
  return(press);
}

void setup() {
  Serial.begin(9600);
  pinMode(led13Pin, OUTPUT);      
  pinMode(PgrnPin, OUTPUT);      
  pinMode(PredPin, OUTPUT);      
  pinMode(RgrnPin, OUTPUT);      
  pinMode(RyelPin, OUTPUT);      
  pinMode(RredPin, OUTPUT);      
  pinMode(button1, INPUT);      
  digitalWrite(button1,HIGH);        // internal pullup all versions
  press = false;
  Serial.println("Starting ...");
}

void loop() {
  // All red phase
  RredState = HIGH;
  RyelState = LOW; 
  RgrnState = LOW; 
  PredState = HIGH;
  PgrnState = LOW; 
  setleds();
  Serial.println("Red phase");
  setout(&count3);  
  while (!timeout(&count3, 3000UL )) {
    ispress();  // Check on the button
  }

  // Road Green
  RredState = LOW;
  RyelState = LOW; 
  RgrnState = HIGH; 
  PredState = HIGH;
  PgrnState = LOW; 
  setleds();
  Serial.println("Road green");
  setout(&count3);  
  while (!timeout(&count3, 8000UL )) { // Reasonable time on green
    ispress();  // Check on the button
  }
  Serial.println("Green stale, wait on button");

  while ( press == false )  // Now wait for the button 
  {
    if (timeout(&count2, 300UL )) {
      if (led13State == LOW) {
        led13State = HIGH;
      }
      else {
        led13State = LOW; 
      } 
      digitalWrite(led13Pin, led13State);
    }
    ispress();   
  }
  led13State = LOW; 
  digitalWrite(led13Pin, led13State);

  Serial.println("Button sensed");
  setout(&count3);  
  while (!timeout(&count3, 4000UL )) { // Do not respond immediately!
  }

  // Road Yellow
  RredState = LOW;
  RyelState = HIGH; 
  RgrnState = LOW; 
  PredState = HIGH;
  PgrnState = LOW; 
  setleds();
  Serial.println("Road yellow");
  setout(&count3);  
  while (!timeout(&count3, 5000UL )) {
  }

  // Road Red
  RredState = HIGH;
  RyelState = LOW; 
  RgrnState = LOW; 
  PredState = HIGH;
  PgrnState = LOW; 
  setleds();
  Serial.println("Road red");
  setout(&count3);  
  while (!timeout(&count3, 3000UL )) {
  }

  // Walk Green
  RredState = HIGH;
  RyelState = LOW; 
  RgrnState = LOW; 
  PredState = LOW;
  PgrnState = HIGH; 
  setleds();
  press = false;  
  Serial.println("Walk");
  setout(&count3);  
  while (!timeout(&count3, 6000UL )) {
  }

  // Flash Don't Walk
  RredState = HIGH;
  RyelState = LOW; 
  RgrnState = LOW; 
  PgrnState = LOW; 
  Serial.println("Flash Don't Walk");
  setout(&count3);  
  while (!timeout(&count3, 7000UL )) {
    if (timeout(&count2, 500UL )) {
      if (PredState == LOW) {
        PredState = HIGH;
      }
      else {
        PredState = LOW; 
      } 
      setleds();
    }
    ispress();  // Check on the button
  }

}

void oldloop() {
  // Toggle LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    if (led13State == LOW) {
      led13State = HIGH;
    }
    else {
      led13State = LOW; 
    } 
    digitalWrite(led13Pin, led13State);
  } 

  // Act if the latter time (ms) has now passed on this particular counter,
  if (timeout(&count2, 300UL )) {
    if (PgrnState == LOW) {
      PgrnState = HIGH;
    }
    else {
      PgrnState = LOW; 
    } 
    digitalWrite(PgrnPin, PgrnState);
  } 

  if (timeout(&count3, 600UL )) {
    if (PredState == LOW) {
      PredState = HIGH;
    }
    else {
      PredState = LOW; 
    } 
    digitalWrite(PredPin, PredState);
  } 

  if (timeout(&count4, 400UL )) {
    if (RgrnState == LOW) {
      RgrnState = HIGH;
    }
    else {
      RgrnState = LOW; 
    } 
    digitalWrite(RgrnPin, RgrnState);
  } 

  if (timeout(&count5, 800UL )) {
    if (RredState == LOW) {
      RredState = HIGH;
    }
    else {
      RredState = LOW; 
    } 
    digitalWrite(RredPin, RredState);
  } 
}

debounce uses the same concepts as blinkwithoutdelay
so it is needed, regardless how it is used.