11,653

33

5

I often run out of digital pins on my Arduino. Anything as complicated as, say, a video game controller, was near impossible with the amount of pins I had available. Multiplexing buttons works, but it requires lots of connections and soldering. So, I put together a solution!

## Step 1: Resistor Dividers in Five

In a circuit consisting of one resistor and a 9V battery, the resistor drops 9V across itself. So, the resistor's forward voltage is 9V. Two resistors of equal value would each drop half the voltage, 4.5V, each being half the total resistance in the circuit. If one resistor is 100 ohms, and a second resistor is 300 ohms, each will have a proportional forward voltage. In a 12V circuit, the 100 ohm resistor would drop 3V and the 300 ohm resistor would drop 9V. There's more to resistor dividers (such as potentiometers), but that is beyond the scope of this instructable. I suggest reading this for more info: https://www.sparkfun.com/tutorials/207

## Step 2: Schematics and Explanation

The first diagram above is the standard way to connect buttons. Each connects to its own digital pin, and each has its own pull-down resistor. In the second diagram, all of the buttons connect to the same analog pin.  They also connect to positive via a 1K ohm resistor, and negative through different value resistors. When button 1 is pressed, the voltage level at Analog 0 is equal to {R2 / (R1+R2)} * Vcc or {100 / (1000+100)} * 5 = 5/11 of a volt or 0.45V. Solving for the other two buttons with 330 and 470 ohm resistors, we get 1.24V for button 2 and about 1.6V for button 3. We could continue adding buttons with higher value resistors, such as 680 ohms, 1.5K ohms, 3.3K ohms, and so on.

Also useful is the fact that pressing two buttons simultaneously will produce a completely independent value. Based on the equation for parallel resistors, 1/R=1/R1 +1/R2 ... 1/Rx, we can determine that buttons one and two pressed together will produce an overall resistance of 1/100 +1/330 =1/R, so solving for R, the result is about 77 ohms. Plug that into the voltage divider formula with 77 ohms as R2, {77 / (1077)} * 5 = 0.35V, we get an entirely new voltage reading. Possible uses include being able to read diagonals on joysticks that use buttons, like this one: https://www.sparkfun.com/products/9182, without several if..then...else if statements on the Arduino.

## Step 3: Final Notes & Code

I recommend using the "switch...case" structure for the code. You can set up a case for each button/resistor combo, and I prefer it to using if-thens over and over again.
Read here on the arduino website: http://arduino.cc/en/Reference/SwitchCase
Example:

int buttonValue1 = 92; //convert 0.45V into analog reading
int buttonValue2 = 254; //convert 1.24V into analog reading
int buttonValue3 = 327; //convert 1.6V into analog reading
int value;
void setup ()
{
}

void loop() {
switch (value) {

case 92:
//button one was pressed
break;
case 254:
//button two was pressed
break;
case 327:
//button three was pressed
break;
case 72: //convert 0.35V into analog reading
//button one AND button two were pressed
default:
//no button pressed
break;

}
}

This can only be used for digital input devices such as phototransistors, switches, and the like.

146 15K
125 6.9K
1 304 22K
96 11K

## 5 Discussions

Great explanation. I'm a little confused by the last sentence. Can "switch case" only be used with digital inputs? I know the cases can look for a range of values. I don't think I've used it with analogue input, but I always thought you could. Maybe I missed something.

Switch case just compares integers. It's possible, I'll post some code.

Done. The formula to convert a voltage into analog reading is (V/Vcc) * 1023, but it's a better idea to actually check the values you get using the serial monitor because of resistor tolerances and other imperfections.

Ok, I see. I was still a little confused so I checked http://arduino.cc/en/Reference/AnalogRead. So analogRead() calls this function ((V/Vcc) * 1023) and assigns the reading an integer value from 0 to 1023.

Along the way I learned, as russ_hensel has pointed out that the Arduino can only read analog to digital about 10,000 times a second. Pshh.

You should probably put a bit more emphasis on the fact that you are not multiplexing digital signals directly but converting the digital input to an analog one. Analog input is a bit more complicated and much slower than digital. This is indeed a useful technique in some cases. Why not post a code snippet to go with it.