Notifications
Clear all

toggle between two LEDs with one push (momentary) button

18 Posts
6 Users
7 Likes
1,446 Views
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

Hello All,

I'm working on a project with what i thought was the simple goal of using a momentary push button to switch between two LEDs.  Once the button is pushed, the intention is to light one LED for about 2 seconds (the delay time isn't too important).  The next time the button is pushed, I'd like the other LED to light for same time.  It seemed simple in concept but I'm having trouble working it out.  I suspect I need to keep track of the last LED that was lit, and then flip to the other one on the next button push but I've taken several stabs at it now and can't seem to finish the code so that it works.  Of course I'm relatively new to Arduino and programming.  I removed some of my distracting bad code from the void loop section.  I wanted to give folks a "cleaner slate" to work with and help guide me through this small project.

Thank you for any help you can provide.

Best,

Tony

 

By the way, not sure the code button is working.  Going to paste below.  My apologies for being unable to post the code in a code block.

 

int LED1=6; // LED1 tied to pin 6
int LED2=7; // LED2 tied to pin 7
int buttonRead; // variable to hold value of button
int buttonPin=2; // button tied to pin 2
int dt=20; // delay next booton read - debounce
int delayoff=2000; // once button is pushed, keep LED lit delay
int laststate=1; // variable to keep last LED lit (1 or 2)

void setup() {
// put your setup code here, to run once:
pinMode(LED1, OUTPUT); // set LED1 pin to OUTPUT
pinMode(LED2, OUTPUT); // set LED2 pin to OUTPUT

pinMode(buttonPin,INPUT); // set buttonPin to INPUT
digitalWrite(buttonPin, HIGH); // set buttonPin HIGH for pull-up resistor
// -- button state will always be 1
// -- until button is pressed and then
// -- will read 0

Serial.begin(9600); // begin serial monitor for debug

}

void loop() {
// put your main code here, to run repeatedly:

buttonRead=digitalRead(buttonPin);
Serial.println(buttonRead);


if (buttonRead==0 && laststate==1) {
digitalWrite(LED1, HIGH);
delay(delayoff);
digitalWrite(LED1, LOW);
}

if (buttonRead=0 && laststate==2) {
digitalWrite(LED2, HIGH);
delay(delayoff);
digitalWrite(LED2, LOW);
}

delay(dt);

}

 


   
Quote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2037
 

   
ReplyQuote
Sid
 Sid
(@sid)
Member
Joined: 3 years ago
Posts: 111
 

Life is exploring and learning


   
ReplyQuote
Sid
 Sid
(@sid)
Member
Joined: 3 years ago
Posts: 111
 
Posted by: @tperry724

Hello All,

I'm working on a project with what i thought was the simple goal of using a momentary push button to switch between two LEDs.  Once the button is pushed, the intention is to light one LED for about 2 seconds (the delay time isn't too important).  The next time the button is pushed, I'd like the other LED to light for same time.  It seemed simple in concept but I'm having trouble working it out.  I suspect I need to keep track of the last LED that was lit, and then flip to the other one on the next button push but I've taken several stabs at it now and can't seem to finish the code so that it works.  Of course I'm relatively new to Arduino and programming.  I removed some of my distracting bad code from the void loop section.  I wanted to give folks a "cleaner slate" to work with and help guide me through this small project.

Thank you for any help you can provide.

Best,

Tony

Hello Tony, I know, I am too young here, but I would also add the results of what is currently happening - just to make it easier for others to understand the problem better.

Note: Please dont misinterpret my suggestion. I suggested the above so that we the readers would know exactly what/where the problem is 🙂

Life is exploring and learning


   
tperry724 reacted
ReplyQuote
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

@sid  Hello, I've tried the code and only one LED lights with the first button press.  The second button press did not result in the second LED coming on.  A third, and every subsequent, button press results in the no activity from either LED.  What I thought would be such a simple sketch seems quite troublesome.  


   
ReplyQuote
Sid
 Sid
(@sid)
Member
Joined: 3 years ago
Posts: 111
 

@tperry724

I do hope that the above fix as pointed out by @robobuilder works out good. In case those changes in the codes do not, it might be the right time to add up an image of your circuitry - maybe the breadboard version or otherwise.

Life is exploring and learning


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@tperry724

Posted by: @tperry724

I've tried the code and only one LED lights with the first button press.  The second button press did not result in the second LED coming on.  A third, and every subsequent, button press results in the no activity from either LED.  What I thought would be such a simple sketch seems quite troublesome.  

I'm a little surprised by that result, but stranger things have happened 🙂

I do see one other issue though, as the "laststate" variable is set to "2" before leaving the first if conditional statement, the next if conditional statement is also met.

As a beginner, a basic debugging technique is to add additional "Serial.println(...);" statements in strategic places within the code to validate what the variables are storing, then you can seek to rectify the logic.

Cheers.


   
tperry724 reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2037
 

@tperry724

I didn't spot the assignment statement,
if (buttonRead = 0 ...
instead of a comparison,
if (buttonRead == 0 ....

I can't test it just now but maybe this will work better?

 

 

void loop() {

  buttonRead=digitalRead(buttonPin);
  Serial.println(buttonRead);

  if (buttonRead==0 && laststate==1) {
    digitalWrite(LED1, HIGH);
    digitalWrite(LED2, LOW);
    laststate = 2;
  else
    digitalWrite(LED2, HIGH);
    digitalWrite(LED1, LOW);
    laststate = 1;
  }

  delay(dt);  // keep led on for some delay
  
  digitalWrite(LED1,LOW);  // turn off leds
  digitalWrite(LED2,LOW);

}

 

 


   
tperry724 reacted
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1112
 

@tperry724

I knocked up a small example code, got distracted and now as I come to post it I see @robotbuilder has provided a good example.  However as I did it, for what its worth here is my small snippet

 

int which_LED_pin = 6;

void loop() {
// put your main code here, to run repeatedly:

    buttonRead=digitalRead(buttonPin);
    if (buttonRead == LOW){
       digitalWrite(which_LED_pin, HIGH);
       delay(delayoff);
       digitalWrite(which_LED_pin, LOW);

    if(which_LED_pin == 6)
        { which_LED_pin = 7;}
    else
        { which_LED_pin = 6;}
}
delay(dt);
}

 

 

This post was modified 3 years ago by byron

   
tperry724 reacted
ReplyQuote
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

@robotbuilder  - Hi, I've received an error message when I went to upload the code.  He is the code and the error message.  

 

int LED1=6;        // LED1 tied to pin 11
int LED2=7; // LED2 tied to pin 10
int buttonRead; // variable to hold value of button
int buttonPin=2; // button tied to pin 2
int dt=20; // delay next button read - debounce
int delayoff=2000; // once button is pushed, keep LED lit delay
int laststate=1; // variable to keep last LED lit (1 or 2)

void setup() {
pinMode(LED1, OUTPUT); // set LED1 pin to OUTPUT
pinMode(LED2, OUTPUT); // set LED2 pin to OUTPUT

pinMode(buttonPin,INPUT); // set buttonPin to INPUT
digitalWrite(buttonPin, HIGH); // set buttonPin HIGH for pull-up resistor
Serial.begin(9600); // begin serial monitor for debug

}

void loop() {

buttonRead=digitalRead(buttonPin);
Serial.println(buttonRead);

if (buttonRead==0 && laststate==1) {
digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
laststate = 2;
}
else
digitalWrite(LED2, HIGH);
digitalWrite(LED1, LOW);
laststate = 1;
}

delay(dt); // keep led on for some delay

digitalWrite(LED1,LOW); // turn off leds
digitalWrite(LED2,LOW);

}

ERROR MESSAGE:

Button_Sketch_2-LEDS_flip_flop_2:35:8: error: expected constructor, destructor, or type conversion before '(' token
delay(dt); // keep led on for some delay
^
Button_Sketch_2-LEDS_flip_flop_2:37:15: error: expected constructor, destructor, or type conversion before '(' token
digitalWrite(LED1,LOW); // turn off leds
^
Button_Sketch_2-LEDS_flip_flop_2:38:15: error: expected constructor, destructor, or type conversion before '(' token
digitalWrite(LED2,LOW);
^
Button_Sketch_2-LEDS_flip_flop_2:40:1: error: expected declaration before '}' token
}
^
exit status 1
expected constructor, destructor, or type conversion before '(' token

 


   
ReplyQuote
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

@byron  Hi, I uploaded the code but I'm having trouble.  There were a couple variables that through me off.  If you have a moment to upload on your end and see what's going on, I'd appreciate it.  Thank you to both you and @robotbuilder for helping.  Best, Tony.  - UPDATE, I HAD A PIN PLACEMENT ISSUE.  THE CODE WORKS!

 

int which_LED_pin=6; // LED1 tied to pin 11
int LED2=7; // LED2 tied to pin 10
int buttonRead; // variable to hold value of button
int buttonPin=2; // button tied to pin 2
int dt=20; // delay next button read - debounce
int delayoff=2000; // once button is pushed, keep LED lit delay
int laststate=1; // variable to keep last LED lit (1 or 2)

void setup() {
pinMode(which_LED_pin, OUTPUT); // set LED1 pin to OUTPUT
pinMode(LED2, OUTPUT); // set LED2 pin to OUTPUT

pinMode(buttonPin,INPUT); // set buttonPin to INPUT
digitalWrite(buttonPin, HIGH); // set buttonPin HIGH for pull-up resistor
Serial.begin(9600); // begin serial monitor for debug

}

void loop() {

buttonRead=digitalRead(buttonPin);
Serial.println(buttonRead);

buttonRead=digitalRead(buttonPin);
if (buttonRead == LOW){
digitalWrite(which_LED_pin, HIGH);
delay(delayoff);
digitalWrite(which_LED_pin, LOW);

if(which_LED_pin == 6)
{ which_LED_pin = 7;}
else
{ which_LED_pin = 6;}
}
delay(dt);
}

 

 

 


   
ReplyQuote
hstaam
(@hstaam)
Mr.
Joined: 5 years ago
Posts: 61
 

The following worked for me.

int buttonpin=2;
int led1 = 7;
int led2=8;
int delaytime=2000;
int lastled;

void setup() {
pinMode(buttonpin,INPUT_PULLUP);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
lastled=led2;
Serial.begin(9600);
}

void loop() {
static int led=0;
if(lastled==led2)
{
led=led1;
}
else
{
led=led2;
}
if(digitalRead(buttonpin)==LOW)
{
runled(led);
}
}

void runled(int l)
{
Serial.print(l); Serial.print(", ");Serial.println(lastled);
digitalWrite(l,HIGH);
delay(delaytime);
digitalWrite(l,LOW);
lastled=l;
}

 

hj


   
tperry724 reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2037
 

   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@tperry724

It's easy to get discouraged when your new to programming, as it takes a little time to get up to speed, but it does become quite enjoyable when your knowledge increases, and you'll be looking for more and more projects to apply your new found skills to!

I'm posting this as a mini tutorial, as there are a number of examples provided now, and there appears to be a couple of similar posts with the same logical goal in mind.

Here is the first example, with an explanation below:

#define button 2

void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
 }

int duration = 200;
bool toggle = false;

void loop() {

  if(digitalRead(button) == LOW) {
    toggle = !toggle;

    if (toggle) {
      digitalWrite(LED1, HIGH);
      digitalWrite(LED1, LOW);
     }
  
    if (!toggle) {
      digitalWrite(LED2, HIGH);
      digitalWrite(LED2, LOW);
     }
   }

  delay(duration);
 }

Hopefully we can see, that the most difficult part of the code is understanding what the following ("!", known as the logical "NOT" operator) is doing, for example:

toggle = !toggle;

In short, it's job is to simply invert the result of the boolean variable it is applied to upon evaluation. So if the variable is false when it is evaluated, it is inverted and then reassigned back to itself as true, and vise versa, simple as that.

With this understanding, we can see that the toggle is initially declared and defined as false before the loop, but when the button is pressed, the conditional statement is entered and the variable is immediately inverted with the "NOT" operator ("!") to produce a true value, and then reassigns that true value back to itself.

The same principle applies to the if conditional statements that follow... if it's true, then evaluate it as if it were false, and if it's false, evaluate it as if it were true.

In essence, when the "NOT" operator (!) is applied to a boolean condition, it simply toggles (flips) the boolean result at each iteration of the loop from what it was previously.

Now that we understand how this operator works, we can start to look for refactoring opportunities to improve our code even further.

For example, our loop can now be refactored down to the following piece of code:

void loop() {

  if(digitalRead(button) == LOW) {
    toggle = !toggle;

    digitalWrite(LED1, toggle);
    digitalWrite(LED2, !toggle);
   }

  delay(duration);
 }

Anyhow, I hope this very small tutorial help's you and other readers, into the wonderful journey of programming 🙂

Good luck!


   
tperry724 reacted
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1112
 

@tperry724

Good to hear that you managed to incorporate my code snippet into you code and you got it all to work.  Looking at the code you presented I expect you can see that you could cut out some old variable declarations  no longer used and theres no need to repeat the 'buttonRead=digitalRead(buttonPin);' line more than once in the loop section.   The code that @robotbuilder presented is probably a better tutorial for you than my snippet as it builds on the original code you presented and thus probably a better building block for you to see where your original code was not working. 

As you intimated that this was just a cut down version of your project to get the button push and led toggle code working you may like to consider breaking some code out into separate functions along the lines that @hstaam suggested which may make all your other stuff more readable.  Also, depending on what the rest of your project does, often a button push is programmed to generate an interrupt so that the button push gets immediate attention from your program regardless of what else it may be doing at the time.  But thats another story and just something to bear in mind as your project progresses.  Have fun. 😀 


   
ReplyQuote
Page 1 / 2