Reading multiple button states using one pin and digital pins to supply power

Hi all.
I am trying to read the values of button presses using just one digital input pin. My approach is to power the buttons using digital pins as output and only turn on one output pin at a time, cutting the power to the button so as to not read from it when its off. This works well when I press one button at a time and I receive the expected output. However, when I hold down both buttons what I'm expecting to read is:

Slot: 0
start buttonState: 1
Power Pin 2 forward is high
End buttonState: 0
Slot: 1
start buttonState: 1
Power Pin 13 forward is high
End buttonState: 0

but instead what I receive is:

Slot: 0
start buttonState: 0
End buttonState: 0
Slot: 1
start buttonState: 0
End buttonState: 0

Also, this is not always consistent. Sometimes while holding both one will still read as high but not both. I understand I'm using an unorthodox method so I suspect they may be what is causing problems for me. I have seen other methods of using just one pin for multiple buttons so I am aware I have other options, I'm just curious if this method is even feasible. I've provided a circuit diagram (I'm using 10k resistors for pull-down) and my code below. Any help is very appreciated!

const int powerPins[2] = { 2, 13 };
int buttonPin = 4;


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

  pinMode(buttonPin, INPUT);

  for (int i = 0; i < 2; i++) {
    pinMode(powerPins[i], OUTPUT);
  }

  digitalWrite(powerPins[0], HIGH); //turn first slot on 
  digitalWrite(powerPins[1], LOW); //turn others off
}

void loop() {



  for (int i = 0; i < 2; i++) {

    Serial.println("Slot: " + String(i));
    Serial.println("start buttonState: " + String(digitalRead(buttonPin))); //for troubleshooting



    if (digitalRead(buttonPin) == HIGH ) {
      Serial.print("Power Pin ");
      Serial.print(powerPins[i]);
      Serial.println(" forward is high");
    }


    digitalWrite(powerPins[(i + 1) % 2], HIGH); // turn the neighbouring pin on
    digitalWrite(powerPins[i], LOW); //turn off current power pin so we dont read this button



    Serial.println("End buttonState: " + String(digitalRead(buttonPin)));
  }
  delay(1000);
}

If you press both buttons with one power pin set HIGH and one power pin set LOW you'll fry your Arduino.

What's the point? If it's academic then you can work this out by adding some diodes I think.

But if you've got an output pin per button available, why not just use them as inputs to read the button?

1 Like

This is just a simplified scenario. Its for a school project and i need more than the alloted pins so im trying to save on using pins. As for frying the arduino I have tried and ran this program and the arduino seems to be working fine.

How is this saving pins? This uses 3 pins to read 2 buttons. The normal way only takes 2 pins to read 2 buttons. How is using 3 pins saving pins over using 2 pins.

It may not be immediate, but you've created a dead short. It will kill the pins. That's something I know for certain.

1 Like

So, if you need many switches, maybe a key matrix would be a good solution ?

Or, use an analog input with an R2R ladder arrangement !

1 Like

Because i have other hardware connected to the arduino using pins that is not shown in this scenario I also need 12 buttons total .

OK, And if you use a pin to power each one then that will be 13 pins to read 12 buttons. The normal way would be 12 pins to read 12 buttons.

13 is still more than 12.

Im not sure if im misunderstanding you? I have other hardware taking up pins so i only have four pins to work with and i have 12 buttons

Yes. I understand that.

And you are proposing this as a way to save pins. But to use the method you are proposing with 12 buttons will require 13 pins. So if you can't spare 12, then where will you get 13?

Go ahead and draw it out. You have a common input pin and then you need a power pin for each button. The number of pins you are using will always be one larger than the number of buttons you have.

I understand now, sorry for the miscommunication on my part. I have a different setup for my project which is 4 slots with 3 strips of copper tape laid on one side and 1 strip of copper tape on the other side. The three strips are my inputs(3x4=12) and the one strip on the other side is the power pin so i only need 4 power pins. I then have blocks with copper tape on the bottom so when i place it into a slot depending on the block it turns a pin high. It works for the most part expect when i put in two blocks that are the same. I just used this scenario as an example to simplify it

Sorry, this point got dropped. To avoid this, you never set more than one of those power pins as OUTPUT at a time. Only one is OUTPUT, set all the rest as INPUT. Instead of setting them HIGH and LOW, you need to be switching between INPUT and OUTPUT so you don't fry anything.

Right, because you short out the Arduino. I am surprised it works at all after that.

You should be switching those pins from INPUT to OUTPUT, now LOW to HIGH. If you connect two output pins and one is LOW and one is HIGH you will have a bad day.

like this?


const int powerPins[2] = { 3, 5 };
int buttonPin = 2;
int buttonState = 0;





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

  pinMode(buttonPin, INPUT);





  pinMode(powerPins[0], OUTPUT);
  pinMode(powerPins[1], INPUT);
}

void loop() {



  for (int i = 0; i < 2; i++) {

    Serial.println("Slot: " + String(i));
    Serial.println("start buttonState: " + String(digitalRead(buttonPin)));



    if (digitalRead(buttonPin) == HIGH ) {
      Serial.print("Power Pin ");
      Serial.print(powerPins[i]);
      Serial.println(" forward is high");
    }


    pinMode(powerPins[(i + 1) % 2], OUTPUT);
    digitalWrite(powerPins[(i + 1) % 2], HIGH);
    pinMode(powerPins[i], INPUT);



    Serial.println("End buttonState: " + String(digitalRead(buttonPin))); 
  }
  delay(1000);
}

Edit* : I just tried this and it works. I am so thankful this was bugging me for 3 days!!!! thank you for replying so promptly i am so happy!

Rearrange this. Change to INPUT first and then set the new one as OUTPUT. You want to avoid ever having two as OUTPUT at the same time, even for an instant.

1 Like

Will do! Thank you again so much, I am so relieved.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.