[sdiy] Reading two buttons with a single IO pin
Tom Wiltshire
tom at electricdruid.net
Fri Feb 20 22:16:54 CET 2015
Hi All,
I've been considering the question of how to read two buttons with a single microcontroller IO pin. There are various ways to do this. One I've seen is to charge a capacitor via some resistors with switches around them. You then measure how fast the capacitor charges and you can work out which buttons are pressed. There are other techniques. Another way is to read an ADC value from some kind of potential divider, and by checking where the voltage falls, determine which switches are pressed. All the versions of this I saw used a *lot* of conditional statements ( if ((x>y) && (x<z)) { do summut } type of thing ).
It seemed to me it should be possible to arrange the incoming voltages so that the bits of the ADC reflected the switch states directly.
E.g. Do it a simpler way: Just read an ADC value, reduce the ADC value to the top two bits (00, 01, 10, 11) and arrange the resistor values such that the bits reflected the switch states. This was what I had in mind:
http://www.electricdruid.net/images/TwoButtonsV2.png
Having messed about with calculations and experiments for a while, I determined that this arrangement isn't possible. The 00 case is easy, since both switches are open and R3 acts as a pulldown, so we get 0V and read 00. The R1 and R2 values that give good stable ADC readings for the 01 and 10 cases are easy enough to determine, but unfortunately, they don't give the right value when used in parallel. Since the "ideal" value would be in the middle of the range, I did some experiments to see if I could make it work by pushing the R and R2 values closer to the limits, further from the ideal values. It turns out you can't.
Finally, I had a brainwave. What if I inverted the state of one of the switch bits? Let's say I invert S2, so that instead of reading 1 for pressed, it reads 1 for not-pressed. In this case, my required ADC sequence would be 10, 11, 00, 01. Given that for code it doesn't much matter whether a switch reads 1 pressed or 1 unpressed, this isn't a big deal. It turns out that this *is* possible to arrange:
http://www.electricdruid.net/images/TwoButtonsV3.png
I produced this with a PHP script, so I can enter a R4 value, and the code derives the other necessary values, finds the nearest actual resistor values, and checks what potential divider ratios they give to make sure they're in range. The given values are therefore a demonstration, and could be adjusted to taste.
I was quite pleased with this, since it'll allow me to double the number of switches for only a couple of resistors per switch.
Presumably I'm not the first person in seven billion to have come up with this idea, but I thought I'd share it, since I haven't been able to find it somewhere else.
HTH,
Tom
More information about the Synth-diy
mailing list