Multiple buttons, multiple actions

Hi,

I have a sketch with (for now) 2 buttons.
Each button must do an action. In this test case it will write a line on the serial monitor only.

When I upload the sketch and open the serial monitor, it will write:
Button 1 pressed!
Button 2 pressed!

But I did not touch a button.
I did something wrong, but I can’t see what.
The “Generic function to check if a button is pressed” I found online, maybe something is wrong with the check of the state of the buttons.

Can anybody help me.

Gr. Edwin.

#define BTN1_PIN 9
#define BTN2_PIN 8

// Generic function to check if a button is pressed
int buttonPressed(uint8_t button) {
  static uint16_t lastStates = 0;
  uint8_t state = digitalRead(button);
  if (state != ((lastStates >> button) & 1)) {
    lastStates ^= 1 << button;
    return state == HIGH;
  }
  return false;
}

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

void loop() {
  if(buttonPressed(BTN1_PIN)) {
    Serial.println("Button 1 pressed!");
  }
  if(buttonPressed(BTN2_PIN)) {
    Serial.println("Button 2 pressed!");
  }
  delay(100);
}

That function only works for one button because there is only one lastState variable. Each button requires its own lastState variable.

How could this be done?

The code above was explained on Checking for a button press in Arduino | by Rodrigo Sousa Coutinho | Arduino Playground | Medium

I can pres button 1 and 2 and the serial monitor is showing exactly which button I pressed.

Well now.

The code you illustrate is not the same as the website you indicate and we have no idea how you have wired your two buttons.

Nor are you explaining the problem clearly. In your first post you say it is giving output when no button is pressed and now you say "the serial monitor is showing exactly which button I pressed".

The information on that website is unfortunately, misleading. Rather like many "instructables". Well, I believe we here can give far better advice, but we need to know what you are actually doing. :roll_eyes:

Okay, I’ll try to explain what is happening.

My code is:

#define BTN1_PIN 9
#define BTN2_PIN 8

// Generic function to check if a button is pressed
int buttonPressed(uint8_t button) {
  static uint16_t lastStates = 0;
  uint8_t state = digitalRead(button);
  if (state != ((lastStates >> button) & 1)) {
    lastStates ^= 1 << button;
    return state == HIGH;
  }
  return false;
}

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

void loop() {
  if(buttonPressed(BTN1_PIN)) {
    Serial.println("Button 1 pressed!");
  }
  if(buttonPressed(BTN2_PIN)) {
    Serial.println("Button 2 pressed!");
  }
  delay(100);
}

After uploading this code the output in the Serial monitor, without pressing any buttons, is:
Button 1 pressed!
Button 2 pressed!

When I press button 1 the serial monitor output is:
Button 1 pressed!

When I press the second button, the output is:
Button 2 pressed!

What I don’t get is why the Serial Monitor is showing output after uploading the code, before I press any button.
I’ve added the wiring as attachement.

So, what I would like to have is the following.

I want to be able to have up to 20 buttons.
Each button has to do something different.

Lets say when I press button 1, I want to play song 001.mp3
When I press button 2, I want to play song 002.mp3.
etc.
etc.

The code for playing audio files is already working with DF player.
I only need to implement the code for the push buttons and I struggle with that.

I hope my question is clear. If not, please let me know.

sketch_pushbuttons.jpg

sketch_pushbuttons.jpg
OK, so you have appropriately connected the buttons from input pins to ground and used pinMode of INPUT_PULLUP, which means the inputs read HIGH until a button is pressed when they read LOW.

However your "buttonPressed" code is the same as in the article you cite which expects buttons to read HIGH when pressed, so as that is your default state on start-up - or indeed when buttons are not pressed, then it tells you the buttons - both - are pressed. Exactly what you would expect.

Similarly, what you are mistaking is that the code correctly identifies that you have pressed each button - but - not when it is pressed, rather when it is released - because that is when the pin again goes HIGH. :grinning:

To correct this, just change HIGH to LOW in "buttonPressed". :sunglasses:

Now ...

Grumpy_Mike:
That function only works for one button because there is only one lastState variable. Each button requires its own lastState variable.

Poor old Mike has missed the clever code! :roll_eyes:

OK, so I had to go through it very closely myself. :astonished:

There is indeed one "lastStates" variable but note it is plural, it is not "lastState". It contains as many button states as you care to define on an Arduino UNO/ Nano etc. :sunglasses:

Paul__B,

Thanks for you explanation.
I wasn't aware of the INPUT_PULLUP mode being default high.

After changing the code all is working fine now.