I have 20 microswitches like this:
How would you wire them to the RaspberryPi's GPIO, using multiplexing techniques?
PS: here is a related discussion about multiplexing but it's theoritic and doesn't discuss precise GPIO wiring, etc.
Raspberry Pi Stack Exchange is a question and answer site for users and developers of hardware and software for Raspberry Pi. It only takes a minute to sign up.Sign up to join this community
I have a bank of 8 LEDs where I need to be able to tell which one of them a photoresistor is positioned over, and I think this is a version of the same problem.1 To determine which LED is lit, I don't need to be able to control them all individually. Instead I use 5 lines -- actually transistors toggling the return to ground, since one GPIO directly is not enough for multiple LEDs. Four of them control two LEDs each, call those pairs A, B, C, D, and one of them controls the final return from a cross-section bank of 4 LEDs, the second one from each pair. This way, I can turn each pair on until the photoresistor triggers, then I just turn off the cross-section of four. If the pair is A and the photoresistor then goes off, I know the LED is A2. If it stays on, it must be A1.
To apply this to buttons you need a slightly different strategy, providing power to "columns" that can be toggled and then testing the return "rows" with inputs. Shown below, the GPIO output columns are labeled A and B and the GPIO input rows are labelled IN1 and IN2. For simplicity I've used four buttons, which multiplexed this way is a bit pointless, but if there were 9 buttons you would only need 3 outputs + 3 inputs = 6 GPIOs. The numbers do not have to be the same, so with 20 buttons you could use 5 outputs and 4 inputs -- or 4 outputs + one non-toggle 3.3V connection as an output line or, as in my LED/photoresistor scenario, one ground line without an input (to save a GPIO), a total of 8 GPIOs. I'll explain why you can leave one GPIO output out in more detail.
The inputs (IN1, IN2), are set as interrupts. Note they are pulled to ground through a resistor (this also limits the current from the GPIOs, and more importantly, the 3.3V rail if you use it as a source for one column). The outputs are both set high. When an input triggers, you then turn off all but one of the outputs and cycle through them (not necessary here since there are only 2).
Note you never have to toggle A -- this is why one of the inputs can just be the 3.3V rail, saving one gpio, so with a 5 x 4 grid you would only need 8 GPIOs. Again, alternately you could have one ground line without an input on it.
This only applies to the use of one button at a time. I do not think you can multiplex if you need to distinguish an arbitrary number; just get some bus based multiplexers or shift registers, they are cheap and simple anyway (along those lines, there are 8 channel I2C multiplexers than can be chained together and/or configured to use different address).
You need to implement a bounce time on the inputs. With buttons like that, it does not need to be more than 10-20 ms, but you must do it for both press down and release. Make sure you can do that consistently with just one button, or with a set of individually connected buttons, before you try this. Otherwise the bounce will create uncertainty for you ;)
I have a practical demo of how to implement bounce time here.
1. If you are are okay with allowing for a minimum hold time of say 50 milliseconds per GPIO output to toggle and test, so 200 ms with 20 buttons (which should be fine with human fingers). I think this is a highball estimate but it could end up requiring more.