I am asking about the technique were switches and resistors in series are used on the analog pin, so it creates a voltage divider when one of the switches is pressed, it a well known technique it is described here with 5 buttons on one analog pin


Obviously we assume the circuit is set up correctly e.g. the voltage reference is stable-but such things aren't the main point of this question. My question is about an obvious generalisation of that circuit for more inputs - and where the resistors are all replaced by, a single type of resistor, a fixed resistance value (e.g. 4k ohm) with a known error on the resistance (e.g. 5%). We use the 4k resistors to make up larger values 4k,8k,12k,16k,20k Ohms and make the 100k Ohm resistor out of twenty five 4k ohm resistors. My question using only 4k ohm resistors (connected in series in the voltage divider) within a 5% error of their value -what is the most switches we can theoretically connect for reliable working on one analog pin?-I'll have a guess at 20 switches.

The second question is given X ohm resistors (connected in series in the voltage divider) within a E% error of their value -what is the most switches, M, we can theoretically connect for reliable working on one analog pin? So there will be a formula for this-so what is it?

  • Looks like a school assignment ...
    – user31481
    Feb 3, 2018 at 23:49
  • As some point even with perfect resistors you will run into noise, impact of dirty contacts, etc... It's not clear that what precision resistors will gain you over loose tolerance ones would leave enough margin for these concerns, though the situation might be better than pushing the limits of these concerns on top of only approximate resistances. Feb 4, 2018 at 0:23
  • @LookAlterno Its not a school assignment Feb 4, 2018 at 2:10
  • @LookAlterno I just wan't to know a formula,or a proof, for the most number of inputs I can use reliably,as that means I can replicate the circuit reliably,on the arduino with certain resistors as that would be the cheapest way for me to do the input of my circuit. Feb 4, 2018 at 2:10

3 Answers 3


My question using only 4k ohm resistors (connected in series in the voltage divider)

The circuit you are describing (a collection of identical resistors connected in series) is quite different from the one discussed in the link you provide. I assume you have in mind something analogous to a digital pot, i.e. a chain of N resistors between GND and Vcc, with N switches connecting the Arduino analog input to N taps along the chain: N−1 taps in between consecutive resistors and one extra tap at GND¹.


simulate this circuit – Schematic created using CircuitLab

The push buttons could actually be the multiple contacts of a rotary switch. If using real push buttons, it would be tricky to know whether a button is being pushed or if you are just reading noise, though it can be known by toggling the pin between output and input and using its stray capacitance.

In this case, the worst case error happens when all the resistors on one side of the tap are 5% too high, while all those at the other side are 5% too low. It can be easily shown that the minimum possible voltage at tap k is

V(k) = k(1−e)/(k(1−e) + (N−k)(1+e))×Vcc

where e = 0.05 is the 5% tolerance of the resistors. The maximum possible voltage, V+(k), is given by the same formula after replacing e by −e.

The graph below shows the expected voltage at each tap for a chain of 20 resistors, with the error bars showing the possible voltage ranges. The blue curves are the analytical expressions of V(k) and V+(k).

enter image description here

As can be seen on the graph, the largest error bars are the ones closer to the central tap. Thus, the buttons can be discriminated accurately if the two taps closest to the center have non overlapping error bars. This criterion could be translated into an exact formula, but the formula would be quite complex and depend on the parity of N. I propose to do instead some approximations, starting with a first order Taylor expansion on the error. This expansion gives the length of the error bars as

V+(k) − V(k) ≈ 4/N2 k (N−k) e × Vcc

This error is maximal when k = N/2 (we will forget the parity issue):

V+(N/2) − V(N/2k) ≈ e × Vcc

Then we say that the taps can be discriminated if this error is smaller than the expected voltage difference between consecutive taps, namely Vcc/N. Then the criterion is now simply

N ≤ 1/e

which is exactly what your intuition told you.

¹ The extra tap could be at Vcc rather than GND. It would be unwise, however, to tap both GND and Vcc, as a user pressing both buttons simultaneously would then short the power supply.

Edit to answer the questions in comments.

Yes, you could use the expressions of V+ and V to set the thresholds for discriminating the buttons. For example, you could set the threshold between k and k+1 halfway between V+(k) and V(k+1), i.e.

threshold(k, k+1) = (V+(k) + V(k+1)) / 2

However, if you try to compute that, you will see that it is extremely close the average between the expected voltages. Then, you could use that average as your threshold, which is given by a very simple formula:

threshold(k, k+1) = (k+½)/N×Vcc

Then, the pin number is just the integer closest to Vin/Vcc×N. Assuming N = 20, this can be written as:

const float VCC = 5.0
float voltage = analogRead(PIN) * VCC / 1024;
int button_number = round(voltage / VCC * 20);

This can be optimized to use only integer arithmetics:

int button_number = (analogRead(PIN) * 5 + 128) >> 8;

Note that 20 buttons is kind of borderline. Your system could fail if the errors due to resistor inaccuracies and those intrinsic to the ADC (offset, gain error...) add up the wrong way. If you are building only one device, then the safest fix would be to take note of the value analogRead() returns for each button, and set the thresholds halfway between consecutive values.

You could also measure the resistances of all your resistors, and arrange them in a way that minimizes the errors. For example, if you number the resistors from 0 to 19 in order of increasing resistance, I would build the chain by arranging them in the following order:

0 19 2 17 4 15 6 13 8 11 9 10 7 12 5 14 3 16 1 18

Then you could most likely use the simple formula above to get the button number at a minimal computing cost.

  • Yes-you are correct -that is the circuit I had in mind. Feb 8, 2018 at 23:07
  • Im asking this question because I have a lot of cheap resistors with the same value and wanted to know what the most inputs I can get from 1 pin. Feb 8, 2018 at 23:08
  • So If I chose N=20 resistors, then I could directly use the analytical expressions of V−(k) and V+(k) to set the bounds voltage tap k will produce in my arduino sketch?- -is that correct? Feb 8, 2018 at 23:08
  • And we dont use tap 20 in practice because V−(20)=V−(20) i.e. there are no lower and upper bounds Feb 8, 2018 at 23:08
  • This is the sort of answer I had in mind when I wrote this Meta post.
    – Nick Gammon
    Feb 13, 2018 at 7:22

The same the same technique is used routinely for 4x4 keypads. You don't really need very precise resistor as long as the final divider produce final voltage that are differente enough.

For each button/key you need to reserve some voltage range for it. You can expected some random fluctuation every time you read the analog input, so you need some safety margin.

I think you can use up to 32 button/key using this technique. That's give you 150 mV of distance between each button (or +/- 32 for the corresponding analog value.

  • I would like an answer with a mathematical formula,that is more enlightening for me and will give me a better understanding. Feb 4, 2018 at 2:10
  • And a formula would prove it can be replicated because its like a proof of reliability Feb 4, 2018 at 2:10
  • A possible error in your answer is -because you are not being precise it may mean that the circuit can't be reliably replicated (because it may just depend on those specific resistors used.) Feb 4, 2018 at 2:11

You're just making a voltage resistor divider, with Vin at the top of the string of resistors, Vout at the selected resistor junction, and Gnd at the bottom. Using 5V as Vin, then

Vout = Vin x (sum of resistance below the junction)/(sum of the entire string).

For example, 10 1K resistors, and the junction is between resistors 5 and 6 (resistor 1, R1, connected to Vin, resistor 10, R10, to Gnd).

Vout = 5V * 5,000/(10,000) = 2.5V

Arduino will return a reading of ~ 2.5V/5V * 1024 = 512 (~4.88mV per step)

Connect between R7 and R8

Vout = 5V * 3,000/(10,000) = 1.5V

analogRead = ~1.5/5 * 1024 = 307

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.