Multiple buttons per pin

I have a project that has 4 buttons and I only have 3 pins available. I know there are various ways to put more than one button on a pin (e.g. resistor networks and analog reads) but I really just needed to free up one pin.

It occurred to me that I could do this easily by combing three of the four buttons into only two pins by using two diodes. The fourth button would have its own pin. For the other three I would end up with a truth table like this:

buttons      pins
(input)      (output)

B1 B2  B3    P1 P2

1   1   1    1  1
1   1   0    1  0
1   0   1    0  1
0   1   1    0  0

Of course this would work for 7 buttons on 3 pins or 15 buttons on 4 pins but it would involve an increasingly ridiculous number of diodes. There must be an IC that does what I want. It seems sort of like a multiplexor but it isn't quite that.

Is there any IC that performs this type of encoding?

This is called diode matrix, it's not multiplexing. Problem with it is you can't detect multiple button presses at the same time. Also you cannot distinguish button press B3 with buttons b1 and b2 being pressed at the same time.

But you CAN multiplex them :wink: Just use one of the pin's as an output. And yeay, there are some chips for it. Some led display drivers can do this. Or keyboard scan chips. I don't know a number right now but you can Google.

Are you using an Uno Arduino?
Are these input pins?
If you have a free analog pin you can use it as a digital pin.
A0-D14 etc.

septillion:
This is called diode matrix, it's not multiplexing. Problem with it is you can't detect multiple button presses at the same time. Also you cannot distinguish button press B3 with buttons b1 and b2 being pressed at the same time.

But you CAN multiplex them :wink: Just use one of the pin's as an output. And yeay, there are some chips for it. Some led display drivers can do this. Or keyboard scan chips. I don't know a number right now but you can Google.

The rule for this particular project is only one button can be pressed at a time.

I searched for "diode matrix" and couldn't really find an IC that does this. Maybe I need to spend more than 5 minutes on google; usually by the time I get to page 5 of the results I figure I'm not specifying the search correctly or the information isn't there.

What should be the output values for the missing input values?

Use a shift-in register, 74HC165.

digitalWrite (latchPin, LOW);
digitalWrite (latchPin,  HIGH);
incomingByte = shiftIn (dataPin, clockPin,MSBFIRST);

Pull all inputs high with 10K resistor, button press connects an input pin to Gnd.
Then scan it every 50mS (blink without delay is your friend here), if result is !=0xFF then one or more buttons are pressed, take some action.

Need more buttons, can daisy chain more shift registers.

LarryD:
Are you using an Uno Arduino?
Are these input pins?
If you have a free analog pin you can use it as a digital pin.
A0-D14 etc.

Thank you, but I know that an "analog" pin is also a digital pin.
It's not an Uno; the particular processor isn't that important.

robtillaart:
What should be the output values for the missing input values?

I don't care since multiple button presses are "not allowed" in the design. But for completeness the other inputs could produce (1, 1) outputs I suppose.

Maybe a picture will help?
This is what I'm doing to save one pin:

CrossRoads:
Use a shift-in register, 74HC165.
SN74HC165N Texas Instruments | Integrated Circuits (ICs) | DigiKey

digitalWrite (latchPin, LOW);

digitalWrite (latchPin,  HIGH);
incomingByte = shiftIn (dataPin, clockPin,MSBFIRST);



Pull all inputs high with 10K resistor, button press connects an input pin to Gnd.
Then scan it every 50mS (blink without delay is your friend here), if result is !=0xFF then one or more buttons are pressed, take some action.

In addition to an input pin for reading the shift register do you also need two output pins, one to latch and one to clock the register? Is that right?

This is the circuit I'm thinking of for your application:

Obviously pressing any 2 buttons will be the same as pressing SW2. You will also need to modify your debouncing code to wait and check both lines after the bouncing has stopped.

There's no IC for this but you might look into using BAT54S diodes - they combine two diodes into one package with 3 pins.

"the particular processor isn't that important."

I couldn't tell if this was an Arduino application or just a general electronics question.

LarryD:
I couldn't tell if this was an Arduino application or just a general electronics question.

I understand. In this case I'm using one of the Atmel processors but not an Arduino per se.

MorganS:
This is the circuit I'm thinking of for your application...

Morgan, what are the advantages of your design over mine?

In addition to an input pin for reading the shift register do you also need two output pins, one to latch and one to clock the register? Is that right?

Yes. You said you had 3 pins available.

You might also look into a priority encoder.

Very handy if you have a bunch of discretes and you need to know which one is active.

Thanks, that's exactly what I was expecting to find, I just didn't know what it was called. Although I think CrossRoads' shift register idea scales better (and handles multiple presses too).

Yeah, shift registers are easier to find too. I'm just throwing things out there :slight_smile:

If you google diode matrix you find a lot. But no, not a chip. That's because that would just be ALOT of pins for just some diodes... And yeay, a diode is cheap...

A shift register is an option. You indeed need 3 wires to connect it to your uC. The shiftIn function is available to read it.

But multiplexing buttons is called keyscanning. The chap Adafruit uses to drive a lot of there led displays use a HT16K33 and can be used to do keyscanning as well. If you Google you can find more keyscan IC's. But you can do keyscanning without a IC as well. Look at this. For four buttons it's not that great but when you scale it is.

But you can also use a variation on it. Connect 2 buttons to Vcc and 2 to GND. Connect 1 Vcc-button and 1 GND-button to 1 io pin. The other two to the second io pin. And you connect two resistors between the third io port and the first two. This will act as a pull down (because the Arduino has no internal pull down network.) For more buttons a resistor array is the way to go. Now when you make the third io HIGH (or enable the internal pull ups) the first two io lines are high unless the GND-button is pressed. And when you make the third io line LOW the first two read low unless the vcc-button is pressed. It scales well ( ([number of io] - 1) / 2 = [number of buttons] ), only uses resistors (or resistor arrays) and you can detect multi touch.

So it seems I have been Charlieplexing.

Good information, thank you. Thanks all of you guys.