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:
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 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.
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 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.
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.
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:
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?
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.
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?
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).
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.