# 6 Buttons, 2 Wires, 1 Microcontroller

First off I should probably mention that I'm a beginner when it comes to electronics.

I am planning on adding some buttons to a controller but have limited space for wires. Only 2 of the wires I have will fit (3 with a little modification perhaps). I would like at least 6 buttons (2 groups of 3) to connect to the microcontroller using only these wires. There are plenty of digital and analogue pins available.

What are my best options? I've read about multiplexing and using an analog pin with resistors on the buttons to give each its own voltage but they both only allow one button to be pressed at a time. Ideally I want to be able to push at least two buttons at the same time (one from each group).

• You can resolve double button presses, if you select resistor values such that any pair of buttons produces a unique analog voltage. – Nick Alexeev Jul 24 '15 at 3:00
• Have you considered maybe using thinner wires, so you can put more of them in the limited space? QFN breakout, another QFN breakout, hand soldering BGA, laptop screen FPD-Link cables (a kind of LVDS cables), etc. – davidcary Jul 24 '15 at 14:31
• @davidcary I'd like to use what I already have and I have concerns about the durability of the wires as there are moving parts involved. Really just assessing the options. – James Coyle Jul 24 '15 at 15:44
• Can Vcc and GND be accessed separately, or are the two wires the only connections allowed to the controller? That is, must the controller be considered to be sealed in a box with only two wires coming out of it? – EM Fields Jul 25 '15 at 16:51

The standard technique used in old CD player wired remote controls and such uses a series string of resistors. The resistors are chosen to give approximately equal voltage drop change for each unique button press.

simulate this circuit – Schematic created using CircuitLab

Note that this connection scheme does not allow any illegal values to be fed to the A/D converter. If more than one button is pressed, the top button has priority and the remaining buttons are ignored.

Note that the resistor values shown are NOT optimal. Calculating those resistor values is left as an exercise for the student .

Original poster wants two independent sets of 3- buttons each. That is also fairly easy but the downside is that this now takes TWO lines from the microcontroller instead of only one line plus ground.

simulate this circuit

In use, set one of the I/O pins HI, then read the voltage on the other pin. Then reverse the two pins: set the other pin HI, read the voltage on the first pin.

You need to take the diode voltage drop into account when calculating the resistor values to achieve the desired voltages. The upside of this is that you are looking for only 3 (4) discrete voltage levels - that makes your threshold voltages have a LOT of leeway and still give you accurate button press detection.

Again - resistor values are NOT optimum. Ask for help if you need assistance in calculating them.

• Would something like this which uses three wires (two pins and ground) work: i.imgur.com/bxKdING.png ? Ideally I'd like to be able to press a button from both groups of 3 at the same time. How would I calculate the resistor values required? – James Coyle Jul 24 '15 at 11:41
• This wouldn't meet the requirement "I want to be able to push at least two buttons at the same time." – RJR Jul 25 '15 at 10:54
• Sorry - that was not obvious from your question as originally stated. Try the revised circuit that I'll add. – Dwayne Reid Jul 25 '15 at 15:45
• Why bother with the diode arrangement in the second circuit? It would use the same number of pins to just have two copies of the first circuit each with only 3 buttons. – Tom Carpenter Jul 25 '15 at 16:15
• The OP is asking to use only two conductors to the switch array, not 3. The circuit shown doesn't need a separate ground wire - only two wires are needed. – Dwayne Reid Jul 25 '15 at 16:36

There are a few ways.

The simplest is to use 7 resistors in series, with the first 6 doubling in value and the last the same as the 6th. So 1-2-4-8-16-32-32 for example. You then wire the button to short one resistor each - except for the 'top' one. You then have a unique value for each button combination that you can sample with an A/D convertor. Note that you only need two wires to the keypad (assuming you can solder the resistor across the keys/buttons). The 7th resistor can sit near the microcontroller.

You can also put all buttons in parallel, with a series resistor that doubles in value for every button. Create a voltage divider with the buttons and a resistor that gives you the best range of voltage for the resistor values you chose for the buttons. This give a worse 'dynamic range' and 'resolution' compared to the approach above though - but a bit more math just for understanding below:

With 6 buttons, this gives you (for example) 10,20,40,160,320 and 640 ohm in series with a 640ohm resistor. The binary sequence will mean that every combination will give a different value - not trivial but you should be able to create a lookup table with all 64 values.

Note that you need to use an analog input with enough resolution to resolve the highest and lowest value and the two closest matches.

Highest value is 640ohm, lowest is about 5 ohm. 1:100 or so, no issue.
Smallest difference will be 10//320 = 9.48ohm and 10//640 = 9.69ohm

So you'd need to be able to detect a difference of 0.3 ohm on a 640 ohm scale, or 1:2100 or so. This means you'd need at least a 12 bit A/D convertor and low noise.

If the resolution and dynamic range of you A/D isn't enough, you could try some tricks with diodes and alternating the voltage sign (positive / negative) using two digital outputs. You'd need three wires though to go to the buttons.
This would give you two sets of 3 buttons which means a much better resolution but you'd have to deal with a more complex software setup to deal with this scenario. Not impossible though. With 10, 20 and 40 ohm making up a voltage divider with a 40 ohm resistor, you'd get the following voltages for a 5V source (ignoring the diode drop here):

R1      R2      R3      V
1E+18   1E+18   1E+18   5.00
1E+18   1E+18   40      2.50
1E+18   20      1E+18   1.67
1E+18   20      40      1.25
10      1E+18   1E+18   1.00
10      1E+18   40      0.83
10      20      1E+18   0.71
10      20      40      0.63


That said, if you're going to use 3 wires anyway, a 3rd way would be to ChaliePlex the buttons. This is a bit more complex software-wise but the nice thing is that you don't need an analog input. Google 'Charlieplex 6 buttons' for more info.

With only two I/Os available to do the work, you can use one of them to broadside load the switch states into an external parallel-in serial-out shift register, like an HC165, then use the other I/O to alternately clock the acquired data through the register and read the data between clocks by switching the I/O from output to input and using a diode for steering.

Doing it that way will allow you to press any number of buttons at once and read them all with no interaction between them.

• Unfortunately, this technique needs at least 4 conductors and the original poster has only two lines available. Gnd, Vdd, clk/load, data. – Dwayne Reid Jul 25 '15 at 16:06

With only 2 wires available, you could dedicate one of the wires to GND and the other to a 1-wire bus carrying both power (when 1 bits are transmitted) and bidirectional data (0 and 1 bits).

Then you can load the switch states into a (few) 1-wire GPIO chip(s) and send the acquired data over that line to the microcontroller.

Each button requires a pull-up resistor, and a diode and a capacitor can supply local energy storage for all the buttons and 1-wire GPIO chips.

(This is very similar to the answer by EM Fields, except this answer only uses 2 wires, including the GND wire).