How to Change LED with Button?

891 views Asked by At

i wanted to change LEDs with only one button. First click on the Button - Red Led turns on, Second - Red turns off and green turns on, third - Green turns off and yellow turns on, fourth - starts again with Red...

First i tried to turn on Red with one click and then turn off...

int red = 8;
int button = 13;
int buttonstate = 0;
bool redOn = false;


void setup(){
  pinMode(red,OUTPUT);
  pinMode(button,INPUT);
}

void loop(){
  
 buttonstate = digitalRead(button);
    

if (buttonstate == 1){
  if (redOn == false){
    digitalWrite(red,HIGH); 
    redOn = true;
        }
  else{
    digitalWrite(red,LOW);
    redOn = false;
    }
}
}

That works. Then I tried to add the other two LEDs..

int red = 8;
int yellow = 3;
int green = 6;
int button = 13;
int buttonstate = 0;
bool redOn = false;
bool yellowOn = false;
bool greenOn = false;


void setup(){
  pinMode(red,OUTPUT);
  pinMode(yellow,OUTPUT);
  pinMode(green,OUTPUT);
  pinMode(button,INPUT);
}

void loop(){
  
 buttonstate = digitalRead(button);
    

if (buttonstate == 1){
  if (redOn == false){
    digitalWrite(red,HIGH); 
    redOn = true;
        }
  else if (redOn == true && greenOn == false && yellowOn == false) {
    digitalWrite(red,LOW);
    redOn = false;
    digitalWrite(green,HIGH);
    greenOn = true;
    }
  else if (redOn == false && greenOn == true && yellowOn == false) {
    digitalWrite(green,LOW);
    greenOn = false;
    digitalWrite(yellow,HIGH);
    yellowOn = true;
    }
   else if (redOn == false && greenOn == false && yellowOn == true) {
    digitalWrite(yellow,LOW);
    yellowOn = false;
    }
  
  else{
      redOn = false;
      greenOn = false;
      yellowOn = false;
}
}
}

That doesn't work. Has someone an idea how to realize this?

2

There are 2 answers

1
Aconcagua On

You should at first detect if the button changed before running into the light switching stuff:

int buttonState = 0;
void loop()
{
    int bs = digitalRead(button);
    if(bs != buttonState)
    {
        // the button state changed!
        buttonState = bs;

        if(bs == 1)
        {
            // ... AND has been pressed
            // (if you want to switch on releasing, compare against 0)
            // -> switch now your LED outputs appropriately
        }
    }
}

From your code I'm not fully sure how the desired LED lighting pattern should look like, though, so skipping this part (until you provide a precise description).

Edit according to your comment:

There are several ways to achieve this blink pattern; with your boolean variables you could do like this (only considering the booleans, signals need to be set accordingly):

if(redOn)
{
    redOn = false;
    greenOn = true;
}
else if(greenOn)
{
    greenOn = false;
    yellowOn = true;
}
else if(yellowOn)
{
    yellowOn = false;
}
else
{
    redOn = true;
}

Above code would leave a dark phase after yellow being on; if you don't want one, you can simply have:

else if(greenOn)
{
    // ...
}
else
{
    yellowOn = false; // actually don't need the variable, just set the GPIO
    redOn = true;
}

Another variant is having a counter:

unsigned int ledState = 0;
void loop()
{
    if(buttonDetected) // see above
    {
        digitalWrite(red,    ledState == 0 ? HIGH : LOW);
        digitalWrite(green,  ledState == 1 ? HIGH : LOW);
        digitalWrite(yellow, ledState == 2 ? HIGH : LOW);
        ledState = (ledState + 1) % 3; // or 4, if you want a dark phase added!
    }
}
0
Mrabcom On

There are two things to put into consideration:

First, the processor of the Arduino is way faster than the human, meaning if you press the button even for short time, your code will get it as many rapid times. You solve that by either adding a small delay at the end of the loop() function like:

delay(1000)

Or by setting a variable that contains the previous state of the button and act according to change of state (from 0 to 1)

The second thing is that you are starting to check the red light alone first:

if (redOn == false){
    digitalWrite(red,HIGH); 
    redOn = true;
        }

This if statement will be valid when the green light is on as you are setting redOn to false there

else if (redOn == true && greenOn == false && yellowOn == false) {
    digitalWrite(red,LOW);
    **redOn = false;**
    digitalWrite(green,HIGH);
    greenOn = true;
    }

So, after you turn off the red light and turn on the green and you press the button, the red light will turn on and the green light will stay on since you will be executing the first if statement where you do nothing to the green and yellow lights:

if (redOn == false){
    digitalWrite(red,HIGH); 
    redOn = true;
        }

In addition, you will never reach the state where the yellow light turns on. So you can modify the first if statement to be more specific like the other if statements by replacing

if (redOn == false){
    digitalWrite(red,HIGH); 
    redOn = true;
        }

With

if (!greenOn && !yellowOn){
    digitalWrite(red,HIGH); 
    redOn = true;
        }

Remove the last else since you don't want them to turn off all at once again

else{
      redOn = false;
      greenOn = false;
      yellowOn = false;
}

Side Note: When using boolean variables in if statement you don't have to use the '==' comparator, just use the boolean variables

Use:

if(redOn)

Instead of:

if(redOn == true)

And use:

if(!redOn)

Instead of:

if(redOn == false)

I hope that my answer is helpful :)

Best Regards.