Pressing two buttons at once

I did a dead simple arduino + coding challenge which entails setting up 2 LED's and 2 corresponding buttons then code it to have the button turn the corresponding led on or off with each click. I noticed when I would click the button it would often do the correct action but the go through the loop again and change it back so I added a while loop to just hold the process until the button is released. Works pretty good but is there a better approach? I bet so. I could see other issues arising from holding the process completely. Also what Im more interested in is what would be the simplest way to make it work if you press both buttons at the same time?

// DEFINE ALL PINS
const int BUTTON_GREEN_PIN = 5;
const int BUTTON_RED_PIN = 6;
const int LED_GREEN_PIN = 7;
const int LED_RED_PIN = 8;

// DEFINE HIGH/LOW STATE VARIABLES
bool BUTTON_GREEN_STATE = LOW;
bool LED_GREEN_STATE = LOW;
bool BUTTON_RED_STATE = LOW;
bool LED_RED_STATE = LOW;

void setup() {
  pinMode(BUTTON_GREEN_PIN, INPUT);
  pinMode(LED_GREEN_PIN, OUTPUT);
  pinMode(BUTTON_RED_PIN, INPUT);
  pinMode(LED_RED_PIN, OUTPUT);
}

void loop() {
  if(digitalRead(BUTTON_GREEN_PIN)){                    // CHECK IF GREEN BUTTON IS PRESSED
    LED_GREEN_STATE = !LED_GREEN_STATE;                 // REVERSE THE CURRENT STATE OF THE LED VARIABLE
    digitalWrite(LED_GREEN_PIN, LED_GREEN_STATE);       // UPDATE THE LED STATUS ELECTRONICALLY

    while(digitalRead(BUTTON_GREEN_PIN)){}              // HOLD OPEN LOOP WHILE THE BUTTON IS PRESSED TO AVOID LOOP-REPEAT
    }

  if(digitalRead(BUTTON_RED_PIN)){                    // CHECK IF RED BUTTON IS PRESSED
    LED_RED_STATE = !LED_RED_STATE;                   // REVERSE THE CURRENT STATE OF THE LED VARIABLE
    digitalWrite(LED_RED_PIN, LED_RED_STATE);         // UPDATE THE LED STATUS ELECTRONICALLY

    while(digitalRead(BUTTON_RED_PIN)){}              // HOLD OPEN LOOP WHILE THE BUTTON IS PRESSED TO AVOID LOOP-REPEAT
    }

}

Yes

You need to detect when a button becomes pressed rather than when it is pressed

Look at the StateChangeDetection example in the IDE

3 Likes

You will probably also need to debounce your buttons. A short delay() is ok for this purpose, eg. 30~50ms

1 Like

You have several issues with only a single button.
First you have switch bounce, which you need to eliminate.

Then if you use a while loop you are tying up the system so it cant respond to another button press or release.

Now if you have two buttons you need to consider all the possible states. This tutorial may help

And finally you need to eliminate "blocking code" - so look at the "blink without delay" example

1 Like

Not necessarily. Each LED/button pair can have its own state variable, which will need to have only 2 states/values. There may be no need to combine all 4 LEDs and buttons into a single, more complex state machine with 4 states, because

Hi, @mattyp77

How have you got your buttons wired?
I looks like your buttons pull the input HIGH.
Do you have a pull down resistor, such as 10K, connected from the input to gnd to pull the input LOW when the button is open?

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

What model Arduino are you using?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

there was a very similar question some days ago.

The circuit shows a high active and a low active LED per output pin, but in general it is just a simple toggle:

if you need less outputs, adopt the pins in the two arrays.

look this over
... with button wired between pin and ground

// minimal prog to read button & toggle LED

const byte PinLed = LED_BUILTIN;
const byte PinBut = A1;
byte butState;

void loop ()
{
    byte but = digitalRead (PinBut);
    if (butState != but) {              // state change
        butState  = but;
        delay (20);                     // debounce

        if (LOW == but)                 // pressed
            digitalWrite (PinLed, ! digitalRead (PinLed));
    }
}

void setup() {
    Serial.begin(115200);

    pinMode (PinLed, OUTPUT);
    pinMode (PinBut, INPUT_PULLUP);    // enable pull-up resistor
    butState = digitalRead (PinBut);
}

Forgive me if I'm missing something but I wrote this code without any "debounce delays" and it works perfectly now just based on this principal alone.

  // CHECK IF BUTTON IS PRESSED THEN UPDATE BUTTON STATE
  if (digitalRead(BUTTON_PIN)){
    if (BUTTON_STATE == BUTTON_PREV_STATE) {BUTTON_STATE = !BUTTON_STATE;}
  }
  else {BUTTON_PREV_STATE = BUTTON_STATE;}

Hi, @mattyp77

Well then I'm confused. Exactly what help do you need?
Do you want the code to be faster, use less memory, use less RAM?

are you sure? an even # of bounces results in a toggle of the LED but an odd # of bounces sets it back to its original state

I understand the concept of button bounce but the main issues that I was having was the program looping and setting it back before I ever released the button. It seams to me as though these tiny little buttons that come with arduino kits are really optimized to minimize any button bounce. Anyway ya. The code I have now is working perfect no matter the duration I hold or tap the button. I can press both at the same time that works great. And its also controlled by a photo resistor Ill paste the whole thing here.

// DEFINE PINS-DEVICES
// green LED and associated components
const int LED_GREEN_PIN = 8;
bool LED_GREEN_STATE = LOW;
const int BUTTON_GREEN_PIN = 5;
bool BUTTON_GREEN_STATE = LOW;
bool BUTTON_GREEN_PREV_STATE = LOW;
const int PHOTOR_GREEN_PIN = A1;
int PHOTOR_GREEN_VALUE = 0;

// red LED and associated components
const int LED_RED_PIN = 9;
bool LED_RED_STATE = LOW;
const int BUTTON_RED_PIN = 6;
bool BUTTON_RED_STATE = LOW;
bool BUTTON_RED_PREV_STATE = LOW;
const int PHOTOR_RED_PIN = A0;
int PHOTOR_RED_VALUE = 0;

const int PHOTOR_LIGHT_THRESHOLD = 500;  // photoresistor light value at which LED is triggered on


void setup() {
  Serial.begin(9600);
  pinMode(LED_GREEN_PIN, OUTPUT);
  pinMode(BUTTON_GREEN_PIN, INPUT);
  pinMode(LED_RED_PIN, OUTPUT);
  pinMode(BUTTON_RED_PIN, INPUT);
}


void loop() {
  // CHECK IF BUTTON IS PRESSED THEN UPDATE BUTTON STATE
  if (digitalRead(BUTTON_GREEN_PIN)){
    if (BUTTON_GREEN_STATE == BUTTON_GREEN_PREV_STATE) {BUTTON_GREEN_STATE = !BUTTON_GREEN_STATE;}
  }
  else {BUTTON_GREEN_PREV_STATE = BUTTON_GREEN_STATE;}

  if (digitalRead(BUTTON_RED_PIN)){
    if(BUTTON_RED_STATE == BUTTON_RED_PREV_STATE) {BUTTON_RED_STATE = !BUTTON_RED_STATE;}
  }
  else {BUTTON_RED_PREV_STATE = BUTTON_RED_STATE;}

  // CHECK PHOTO-RESISTOR VALUES AND UPDATE VALUE
  PHOTOR_GREEN_VALUE = analogRead(PHOTOR_GREEN_PIN);
  PHOTOR_RED_VALUE = analogRead(PHOTOR_RED_PIN);
  // UPDATE LED STATUS BASED ON BUTTON STATUS AND/OR PHOTO-RESISTOR SENSOR LEVEL
  if (BUTTON_GREEN_STATE | PHOTOR_GREEN_VALUE < 500) {
    LED_GREEN_STATE = HIGH;
  } else {
    LED_GREEN_STATE = LOW;
  }
  if (BUTTON_RED_STATE | PHOTOR_RED_VALUE < 500) {
    LED_RED_STATE = HIGH;
  } else {
    LED_RED_STATE = LOW;
  }
  // DIRECT PROPER SIGNAL TO LED'S
  digitalWrite(LED_GREEN_PIN, LED_GREEN_STATE);
  digitalWrite(LED_RED_PIN, LED_RED_STATE);

}

they get worse with use.

My apologies. There definitely are times where I absolutely have it in me to solve the problems if I just think about it a little longer. However I just love getting advice from smart people in forums because even if I can figure it out on my own, surely most of the time there is a better way. Its from forums like this that I always learn cool little tricks . And like you mentioned I'm sure there's a faster, less memory intensive solution. That was one thing I was thinking when I wrote it is yes it seams to work perfect but its a lot of variables and if statements

I'm far from being a C++ expert but 4 variables, 2 ifs and 2 whiles doesn't seem lik a lot.
I would also be curiousto see if someone here could do better.

Im confused by why so many people do INPUT PULLUP. The purpose of that is just to invert the normal state right? Like if its a normally open momentary button, the input pullup would basically reverse that and make it act like a normally closed momentary button right? And if so how is that done? With an internal built in resistor something like that? And as for the added resistor. Your saying you can put on a resistor and it will act as a pull down? I do have a 10k resistor going from 1 leg of the button to the negative rail on the BB. I thought that was just to keep from burning things out like an LED requires one



.

If for no other reason, it removes the need to use an external resistor, that is good enough reason for me

1 Like

Until I came to the Arduino forum, I never heard of using a Pull-down resistor for a button input. In my opinion it's bad practice and should never be used since it requires connecting a voltage source directly to a I/O pin.
Why is that bad? Well, in your haste to finish your code you accidentally swapped a few pin numbers and now your button pin is connected to an output and you set it low. Poof, end of Arduino.

This can never happen with a pull-up. Plus as @UKHeliBob said, it saves a resistor in many cases. When microcontroller manufacturer's started including them it was touted as a big selling feature.

Hi, @mattyp77

Thanks... Tom.. :smiley: :+1: :coffee: :australia: