Resistor on analog input - can I calculate the result?

Hi all

I'm quite new to electronics, and am right now trying to understand the theory behind this application, where a matrix keypad is using only one analog input pin by having a series of resistors to make different resistances with which the voltage measured on the analog input pin differs:

According to the example, the different button presses will result in resistances between 1,220 ohm and 4,660 ohm. What I'm really interested in is, how I can calculate which voltages the Arduino will read, when i supply 5 volt to the circuit without any other loads than the resistors themselves.
I believe it is pretty basic stuff, but i can't really get my mind around it.

I hope the question is clear enough :slight_smile:

Thanks!

Oh, and the whole example can be seen here: Matrix Keypad - reducing the pins from 8 digital to 1 analog on Arduino [How to] - YouTube
Also where I took the picture from.

kasperbruun:
What I'm really interested in is, how I can calculate which voltages the Arduino will read, when i supply 5 volt to the circuit without any other loads than the resistors themselves.

It seems you are forgetting the 10k resistor to ground.
The matrix resistor and the 10k resistor to ground make a voltage divider.
Don't calculate in voltage. Calculate in ratio.
Ratio of the button resistor and fixed 10k resistor is the same as the A/D ratio (1024 values).
Leo..

Just imagine a potentiometer with 16 stops. That's all there is to it.

Thank you guys! It makes sense now. :slight_smile:

kasperbruun:
Hi all

I'm quite new to electronics, and am right now trying to understand the theory behind this application, where a matrix keypad is using only one analog input pin by having a series of resistors to make different resistances with which the voltage measured on the analog input pin differs:

According to the example, the different button presses will result in resistances between 1,220 ohm and 4,660 ohm. What I'm really interested in is, how I can calculate which voltages the Arduino will read, when i supply 5 volt to the circuit without any other loads than the resistors themselves.
I believe it is pretty basic stuff, but i can't really get my mind around it.

I hope the question is clear enough :slight_smile:

Thanks!

Oh, and the whole example can be seen here: https://www.youtube.com/watch?v=kVw6kPSJJfw
Also where I took the picture from.

Hello there,

That circuit is not very well optimized and can do better with some change of resistor values. The idea is to get the widest range in ADC counts for each button press.

To start with, the 10k would be better at around 4600 Ohms.
Second, the 220 ohm resistors do not add up to 1k when there are four in series so 250 ohms would be better.

The results are as follows and the columns are in order of:
Total resistance, voltage, voltage deviation, count, count deviation, total count.

With 220 ohms and 10k we get this set:

1000 4.545455 0.454545 930 0 0
1220 4.456328 0.089127 912 18 18
1440 4.370629 0.085699 895 17 35
1660 4.288165 0.082465 878 17 52
2000 4.166667 0.121498 853 25 77
2220 4.091653 0.075014 837 16 93
2440 4.019293 0.072360 823 14 107
2660 3.949447 0.069846 808 15 122
3000 3.846154 0.103293 787 21 143
3220 3.782148 0.064006 774 13 156
3440 3.720238 0.061910 761 13 169
3660 3.660322 0.059916 749 12 181
4000 3.571429 0.088894 731 18 199
4220 3.516174 0.055254 720 11 210
4440 3.462604 0.053571 709 11 221
4660 3.410641 0.051963 698 11 232

and with 250 ohms and 4600 ohm we get this set:
1000 4.107143 0.892857 841 0 0
1250 3.931624 0.175519 805 36 36
1500 3.770492 0.161132 772 33 69
1750 3.622047 0.148445 741 31 100
2000 3.484848 0.137199 713 28 128
2250 3.357664 0.127184 687 26 154
2500 3.239437 0.118228 663 24 178
2750 3.129252 0.110185 640 23 201
3000 3.026316 0.102936 619 21 222
3250 2.929936 0.096379 600 19 241
3500 2.839506 0.090430 581 19 260
3750 2.754491 0.085015 564 17 277
4000 2.674419 0.080072 547 17 294
4250 2.598870 0.075549 532 15 309
4500 2.527473 0.071398 517 15 324
4750 2.459893 0.067579 503 14 338

As you can see the deviations are greater with 250 ohms and 4600 ohms instead of 220 and 10k. That means the ADC can detect the different button states better.
Note the 4600 ohm value is approximate and can probably be 4500 to 4700.
The 250 ohm resistors can be 240.

I see you are converting to voltage.
Don't understand why.
Voltage is always different, and depends on the supply.
Work with the A/D value. That is always the same.
Leo..

Wawa:
I see you are converting to voltage.
Don't understand why.
Voltage is always different, and depends on the supply.
Work with the A/D value. That is always the same.
Leo..

Hi there Leo,

Actually the voltage is there just to show the deviation as an example. If you read the header for what those columns are, you'll see there is also the ADC count, which is valid for those resistor values shown regardless of operating Vcc voltage. That's because the counts are ratiometric with the supply voltage Vcc. That means at 5v they will be the same, and at 4v the same, and at 3v the same, etc. Only the voltages themselves will change.
Also, the process of maximizing the deviation is also not specific to the operating voltage although the actual voltage deviations are. That means that no matter what the voltage supply Vcc is, the max deviation will always show up with a given set of resistor values and that set will be the same for any Vcc voltage like 5, 4, or 3v. The deviation in count will also stay the same.

The idea is to get the maximum deviation in the count for the minimum deviation, but it's related to the maximum deviation in voltage for the minimum voltage deviation so once we find one we find the other. The min deviation count is the last count deviation in each set.

To calculate a voltage with a supply other than 5v simply multiply any of those voltages shown by Vcc/5, so at 3v multiply them by 3/5 to see the actual voltage with Vcc=3v. The counts and count deviations all will stay the same however (with a 10 bit ADC of course).

+1
It seems you understand how it works.
I think spacing a 16-button keypad shouldn't be that hard.
Did once a 101 step pot (0-100%) without overlap/reading problems.
Leo..

Wawa:
+1
It seems you understand how it works.
I think spacing a 16-button keypad shouldn't be that hard.
Did once a 101 step pot (0-100%) without overlap/reading problems.
Leo..

Hi Leo,

Oh that's interesting too. Just one question, how did you know the counts were in prefect sync with the pot resistance?
If you got away with 100 steps or more then yes 16 should not present much of a problem. Just one other thing, did you use the center of the pot to feed the ADC? That would mean (if you did it that way) the top resistor would vary as well as the bottom resistor (10k in this example) so that should give a better result. The problem with the keypad setup is that as we get more and more resistance in series with that bottom resistor (10k) the count deviation gets smaller and smaller, but with 100 counts i guess that means you could easily detect a deviation of 10 counts (like 10,20,30, etc, up to 1000 or so). I guess that is reasonable too as 10 counts is sort of a lot for a 10 bit ADC. Now 1 count difference might be harder to get to be reliable.
I've used pots too for adjustment settings in circuits where the ADC reads the pot that the user sets. One such setting was for an 'on' time setting of a battery charger. As the pot was changed, the time increased. Seemed to work ok although for that i did not need perfect linearity or anything like that because if the time was not long enough the user just turns the pot up a little more :slight_smile:

Yes, I admit I used the pot as a voltage divider, not as variable resistor with fixed pull up.
Just wanted to say that because a resistor divider is ratiometric, A/D value is independent of supply (Aref).
Because of that, steps can be very close.
Spacing just has to be enough to take the bad/varying contact resistance of those silver/painted keypads.

Example code I wrote for that 0-100% pot with some hyteresis is attached (not related to this post).
Leo..

// converts the position of a 10k lin(B) pot to 0-100%
// pot connected to A0, 5volt and ground

int rawValue;
int oldValue;
byte potPercentage;
byte oldPercentage;

void setup() {
  Serial.begin(115200); // set serial monitor to this baud rate, or change the value
}

void loop() {
  // read input twice
  rawValue = analogRead(A0);
  rawValue = analogRead(A0); // double read
  // ignore bad hop-on region of a pot by removing 8 values at both extremes
  rawValue = constrain(rawValue, 8, 1015);
  // add some deadband
  if (rawValue < (oldValue - 4) || rawValue > (oldValue + 4)) {
    oldValue = rawValue;
    // convert to percentage
    potPercentage = map(oldValue, 8, 1008, 0, 100);
    // Only print if %value changes
    if (oldPercentage != potPercentage) {
      Serial.print("Pot percentage is: ");
      Serial.print(potPercentage);
      Serial.println(" %");
      oldPercentage = potPercentage;
    }
  }
}

Hi again,

Oh yeah you reminded me of my older TV set where the buttons do functions that are not assigned to them. I assume that is because the switches are old and have more resistance than they used to and so are triggering the internal uC chip to see the wrong function voltage and therefore execute the wrong function code. Pretty nutty when that happens: press the volume button, the channel changes :slight_smile: