Using a push button to select between 2 loops

I have a traffic light and I would like to have 2 modes. 1 mode for a fast sequence of nonsense lighting (I am not good enough for anything random yet) and the other mode for a standard U.S. traffic sequence.

I placed a marker between the 2 parts that I would like to loop via a push button.

This is my first Arduino project other than the simple blinking leds. I know this may be simple for you guys and hopefully I can learn by your examples.

traffic_jam.ino (2.09 KB)

Hey, and welcome to the forum! For everyone’s convenience post your code in code </> tags on the forum. At a quick glance I see that your code has a lot of delays, which is frowned upon. Before you move on, try to read and understand the Blink without Delay example and apply it to what you have at the moment.

(Perhaps an Array or some type of For Loop would be needed instead in this case)

Once you have that down, work on setting up your button(s). Do you want to use one or two to toggle between the two modes? If you want one, do something like this:

boolean modeState;

to set up a true/false statement with boolean.

In void setup, declare your button as an input, using INPUT_PULLUP.

 pinMode(button, INPUT_PULLUP);

Then in your loop:

int buttonState = digitalRead(button);

if (buttonState == LOW) { // if the button is pressed... (since we are using INPUT_PULLUP, 'pressed' is LOW)

  modeState = !modeState; // switch the state of the variable

}

Then:

if (modeState == false) {

  // pattern 1

}

else { // (if modeState == true)

  // pattern 2

}

Hope this made sense and helped you out a little.

That is basically indeed simple :wink:

void loop()
{
  if(digitalRead(yourPin) == HIGH)
  {
    // your code for the one mode here
  }
  else
  {
    // your code for the other mode here
  }
}

There are a few things to consider
1)
buttons bounce; with your code that is not an issue because you have massive delays
2)
floating inputs will cause erratic behaviour
3)
it depends on how your button or switch is wired if it's HIGH when you place it in the one position or press it or LOW
4)
you have to keep the button pressed

For (2), you can prevent this using a pullup or pulldown resistor. Without additional components, pullup is the easiest. Wire the button or switch between the Arduino pin and ground and use pinMode(yourPin, INPUT_PULLUP) as described by chummer1010.

int greenled = 8; //Led's and pins
int yellowled = 9;
int redled = 10;

const byte modeSwitch = 2;

void setup()
{
  pinMode(greenled, OUTPUT); //Pinmodes of the leds
  pinMode(yellowled, OUTPUT);
  pinMode(redled, OUTPUT);

  pinMode(modeSwitch, INPUT_PULLUP);
}

Note the use of byte; if you change your led pins as well to byte, you save some bytes. Also note the use of the 'const' keyword. If you ever accidentally try to change the pin number, the compiler will complain.

In the next step, I suggest that you use functions for the two modes. Your loop() is far too long.

void modeOne()
{
  // your code for mode 1 here
  ...
  ...
}

void modeTwo()
{
  // your code for mode 2 here
  ...
  ...
}

and in loop()

void loop()
{
  // if button not pressed or switch in position 1
  if(digitalRead(modeSwitch) == HIGH)
  {
    modeOne();
  }
  // if button pressed or switch in position 2
  else
  {
    modeTwo();
  }
}

For (4), if you use a button and want to toggle between the two modes (so not keepin it pressed), you need to remember the state (as described by chummer1010). Also have a look at the StateChangeDetection example and the Debounce example that comes with the IDE.

For (1), I mentioned the massive delay (so debounce is not needed). Your first mode takes nearly 8 seconds (if I counted correctly :wink: ). This means that if you're in that first mode (and using above code) you will have to press the button for nearly 8 seconds (max) before the code will detect it. If you use a switch with two positions, you can flip it but the effect will still only be seen after those 8 seconds.

You will be better of to split the code for a mode into pieces using something like a state machine. For mode 1, there are 20 different states. E.g the first state is where the green led is on for 500ms, the second state is where the green led is off and the yellow one is on for 500ms and so on

void modeOne()
{
//1  
  digitalWrite(greenled, HIGH);
  delay(500);
//2
  digitalWrite(greenled, LOW);
  digitalWrite(yellowled, HIGH);
  delay(500);

  ...
  ...

//20
  digitalWrite(greenled, LOW);
}

Now you can use a variable to keep track of what the code is doing / has to do. I call it currentState.

int greenled = 8; //Led's and pins
int yellowled = 9;
int redled = 10;

const byte modeSwitch = 2;

// variable for state machine; initial state 1
int currentState = 1;

void setup()
{
  ...
  ...
}

void loop()
{
  ...
  ...
}

void modeOne()
{
  ...
  ...
}

void modeTwo()
{
  ...
  ...
}

And we will use that variable in modeOne in a switch / case

void modeOne()
{
  switch (currentState)
  {
    //1
    case 1:
      digitalWrite(greenled, HIGH);
      delay(500);
      // goto next state
      currentState++;
      break;
    //2
    case 2:
      digitalWrite(greenled, LOW);
      digitalWrite(yellowled, HIGH);
      delay(500);
      // goto next state
      currentState++;
      break;

do other cases here
...
...

    //20
    case 20:
      digitalWrite(greenled, LOW);
      // you might want to add a delay here
      ...
      // reset currentState to 1 so we start all over
      currentState = 1;
      break;
  }
}

Using this approach, you only have to wait a maximum of 500ms before the button or switch is checked again. Each time that a step (state) is finished, the currentState variable will be incremented and the next time that you call modeOne it will execute the next step. Problem with a button is that you have to keep it pressed to stay in mode 2. So have a look at the statechange example; with a minimum of 250ms delay, debouncing is probably still not required.

You can do the same for the second mode in the function modeTwo.

To solve the problem that you have to keep the button pressed to stay in mode 2, you can implement the below in loop(). This implements a 'toggle' where you have to press and release the button to switch between the two modes.

void loop()
{
  // variable to remember the last state of the button
  static byte lastState = HIGH;
  // variable to remember selected mode
  static byte selectedMode = 1;

  // read the button  
  byte currState = digitalRead(modeSwitch);
  // if it changed
  if (currState != lastState)
  {
    // button was released if last state was LOW
    if (lastState == LOW)
    {
      // change selected mode
      if (selectedMode == 1)
        selectedMode = 2;
      else
        selectedMode = 1;

      // reset currentState so we start from the beginning
      currentState = 1;
    }

    // remember last state
    lastState = currState;
  }

  if (selectedMode == 1)
  {
    modeOne();
  }
  else
  {
    modeTwo();
  }
}

Note the use of the 'static' keyword; a 'static' acts like a global variable (those that yoy declare outside any function) so the last value is remembered but only has local scope and hence can only be used inside the function where it is declared (loop() in this case).

Note1:
The one thing you might need to consider is to add a third mode so the traffic light does not suddenly changes from green to red but goes via orange.

Note2
This is not a perfect implementation (meaning things can be implemented in a better way); you also should eventually get rid of the use of delay and use millis() based timing (have a look at the BlinkWithoutDelay example that comes with the IDE).

Hi there
your code might be very helpful for my application.
I’m new in c++ so please understand my point.
I’m looking for a simple code witch will control 2 loops.
loop 1- is a led fade in and out when you apply logic 1 on input 8
loop 2- is a blink program every lads say 500ms when you apply logic 0 on input 8
Please give me some guaid in witch dyrection I should go
if you happy to help me with this sketch I will be very thank full

pccustom:
Hi there
your code might be very helpful for my application.
I’m new in c++ so please understand my point.
I’m looking for a simple code witch will control 2 loops.
loop 1- is a led fade in and out when you apply logic 1 on input 8
loop 2- is a blink program every lads say 500ms when you apply logic 0 on input 8
Please give me some guaid in witch dyrection I should go
if you happy to help me with this sketch I will be very thank full

You should start your own thread.

Have a look at Demonstration code for several things at the same time.

WOW! I wish I knew what you guys knew and then it would not seem like jibberish to me.

This is for an actual traffic light that a lady bought for an attention getter for her store. She said she wished that it would work and then me and my big mouth says "all you need is an arduino and some relays" So I got a traffic light pattern to work and she says "can you put a switch in it and make the lights dance or do the standard sequence.

Another foot in my mouth. "Sure" it can't be that hard, right?...

I really appreciate your help and I will try and figure out what you are talking about. I really don't know a thing about programming. Still trying to learn the basics.

oh, and I could not figure out how to post the code on the post until I read the 1st response. Thanks.

No problem,

I'm sure those posts were quite a mouthful but if you take it slow I'm sure you'll understand! Good luck, and if you need anything, just ask :slight_smile:

chummer1010:
I'm sure those posts were quite a mouthful but if you take it slow I'm sure you'll understand! Good luck, and if you need anything, just ask :slight_smile:

I don't see the problem as OP said

jehatcher:
then me and my big mouth says "all you need is an arduino and some relays"

:grinning: :grinning: :grinning:

Right you are!

What I should have said was. “I bet someone other than me could do it!”

Don’t get me wrong. I will learn this, but it will take time. Until then I am sitting in my office looking at this gigantic traffic light. :slight_smile:

I will try some of what you guys told me when I get back from work.

O.k. guys. I think I got it. It works pretty well anyway and I took the advice and got rid of all the delays.

/*
*Do what you like with this code as long as you set
*it free and allow others to do the same. i.e.
-------------------------------------------------
*This work is licensed under the Creative Commons 
*Attribution-ShareAlike 3.0 Unported License. 
*To view a copy of this license, visit
*http://creativecommons.org/licenses/by-sa/3.0/ 
*or send a letter to Creative Commons, 444 Castro Street, 
*Suite 900, Mountain View, California, 94041, USA.
----------------------------------------
*A set of Traffic Lights.
*A switch will set the defined delay of each sequence.
*First option with switch=high will begin a standard sequence.
*Second option with switch=low will begin a faster sequence. You can change the sequences and *delays as you wish.
*I am in the US so it will be a US set of traffic lights.
*Should be easy to customize to any configuration in the world!

*/

int red = 10;   //first of all associate a pin with the red light, in this case 10
int amber = 9; // associate pin 9 with the amber light
int green = 8; //and finally the green light with pin 8

int maindelay = 1500; //The timings of the lights are based around this number.
/*
*The maindelay is an arbitary delay time, 
*smaller is faster, larger is slower. 
*I use it so the proportions stay the same. 
*i.e. the wait is 4 times longer than the change
*/

void setup() {
  pinMode(red,OUTPUT);   //set the red pin as an output
  pinMode(amber,OUTPUT); //set the amber pin as an output
  pinMode(green,OUTPUT); //set the green pin as an output

  digitalWrite(red,HIGH); //Switch the red light on so we have something to start with
}

void loop()

{
  if(digitalRead(3) == HIGH)
  {
    // code for a basic US traffic light sequence
  
  digitalWrite(green,HIGH); //Green on, go
  digitalWrite(red,LOW);    //Red off as green is on
  digitalWrite(amber,LOW);  //amber off, it's finished with
  delay(maindelay*3);       //give traffic time to pass
  digitalWrite(amber,HIGH); //amber on, stop if safe to do so
  digitalWrite(green,LOW);   //green off, it's finished with
  delay(maindelay);          //wait
  digitalWrite(amber,LOW);   //amber off
  digitalWrite(red,HIGH);    //red on, stop
  delay(maindelay*3);        //Time for whatever the traffic has been stopped for to happen.
  
  /*And we are back where we started. 
   *That's the end of this sequence. 
   *The light is back at red and the 
   *sequence can begin again.
   */
    
  }
  else
  {
    
     // alternate code for fast sequence
  
  digitalWrite(green,HIGH); //Green on, go
  digitalWrite(red,LOW);    //Red off as green is on
  digitalWrite(amber,LOW);  //amber off, it's finished with
  delay(maindelay);       //give traffic time to pass
  digitalWrite(amber,HIGH); //amber on, stop if safe to do so
  digitalWrite(green,LOW);   //green off, it's finished with
  delay(maindelay);          //wait
  digitalWrite(amber,LOW);   //amber off
  digitalWrite(red,HIGH);    //red on, stop
  delay(maindelay);        //Time for whatever the traffic has been stopped for to happen.
  
  
  /*And we are back where we started. 
   *That's the end of this sequence. 
   *The light is back at red and the 
   *sequence can begin again.
   */
 
 }
  
  
}

Are you using a switch or a push button? I may be mistaken but with a push button wouldn't one 'loop' only be activated while the button is pressed? Also there are still a lot of delays in there.

A switch.

I'm still happy with the results because that bit of code is all that it will be using until the unit stops working, but how would you fix the delays?

I would help you and put something together, but my IDE is acting up and I can't get anything to compile. I'm writing something now but there is no way for me to test it

Hello, i'm using 3 push buttons to program three modes of operation and I want if one of the 3 push buttons is activated the other two automatically go OFF. Can anyone help please...

Thanks

bangura10:
if one of the 3 push buttons is activated the other two automatically go OFF

Like the way radio buttons work?

dougp:
Like the way radio buttons work?

And I thought you were talking about something like https://ak.picdn.net/shutterstock/videos/1053081491/thumb/4.jpg?ip=x160; not my image so not embedded in post.