Analog INPUT_PULLUP and 6 buttons

Could somebody please explain me how this exactly works. I have connected 6 buttons and 6 2.2k ohm resistor. In code I have made analog pin 5 to be INPUT_PULLUP and when the right most buttons is pressed analog reading is 74 plus/minus 2, and then going to the left analog values for each button is 126 plus/minus 2, 173 plus/minus 2, 215 plus/minus 2, 254 plus/minus 2 and 287 plus/minus 2. I managed to connect all this by checking out google search for multiple buttons. I would like to know what is the math behind all this, why exactly these numbers am I getting for analog read when one of the buttons is pressed?

Code to se the analogRead values:

int a=0;
 
void setup()
{
  Serial.begin(9600);
  pinMode(A5, INPUT_PULLUP);
}
 
void loop()
{
  a = analogRead(5);
  Serial.println(a);
}

Two things are at play: 1. The analog port reads a voltage from the pin and returns 0-1023 proportional to the voltage powering the Arduino. 2. The analog pin is set up to measure the voltage divider (look this up) that depends on which switch is pressed. The voltage divider divides the nominal 5V according to a ratio defined by Ohms law.

Each switch creates a different divider resistance, producing a different voltage, which reads a different value on the analog read, allowing you to determine which switch has been pressed.

If it was me, I would not turn on the Pull-Up resistor in software but use an external sensitivity resistor instead.
In electronics it is best to draw a circuit out to see things better.

logitech: Could somebody please explain me how this exactly works. ... I would like to know what is the math behind all this, why exactly these numbers am I getting for analog read when one of the buttons is pressed?

Take "exactly" out of your sentence and the sentence has the same meaning. Unless you really want to get down to the atoms.

It's because you have a voltage divider which changes depending on what button is being pressed. Example of an "exact" resource: http://en.wikipedia.org/wiki/Voltage_divider

Use the schematic LarryD posted. R5 and the rest of the resistors create a voltage divider. Pull-up resistors vary from pin to pin and chip to chip, so let's just call it 30kohm. Even though yours probably won't be that value.

R6..R11 in series together creates a resistance of 13.2kohm. Using the R1 and R2 notation from the Wikipedia Article: So when no button is pressed the divider is R1 = 30k and R2 = 13.2k. Vout is the voltage on A5 and Vin is 5V (VCC for the Arduino board)

Vout = (R2 / (R1 + R2)) * Vin Vout = (13.2k / (30k + 13.2k)) * 5 = 1.53volts

Since the A/D 1023 steps, this means each step is worth: Steps: 5 volts / 1023 steps = 4.9mV

1.53V / 4.9mV = 312 steps

When S1 is closed in LarryD's schematic, R7..R11 get bypassed. So now your divider becomes R1=30k and R2 = R6 = 2.2K.

Vout = (2.2K / (30K + 2.2K)) * 5 = 0.342 volts. 0.342mV / 4.9mV = 70 Steps

When S1 is closed in LarryD's schematic, R8..R11 get bypassed while R6 and R7 are now in series. So R1=30K and R2=4.4k. Vout = (4.4k / (30K + 2.2K)) * 5 = 0.639 volts 0.639mV / 4.9mV = 130 steps

And So on.

logitech: a = analogRead(5);

Start the habit now that whenever you access an analog pin use the "Ax" designator. This reading your code easier and makes the code portable across different Arduino boards.

Thank you James C4S very much for your detailed explanation. That is what I meant with "exactly" .

Since I don't know a lot about circuit schematics, is LarryDs schematic the same as I made it when using INPUT_PULLUP in the code? Are your numbers "good" only if analog pin is used only as INPUT and not as INPUT_PULLUP? That is what would the schematics be when using INPUT_PULLUP in code?

logitech: is LarryDs schematic the same as I made it when using INPUT_PULLUP in the code?

Yes

logitech: Are your numbers "good" only if analog pin is used only as INPUT and not as INPUT_PULLUP?

The math relies on "R5" being there. So if you use the internal pull-up with INPUT_PULLUP then that is R5. If you only use the pin as "INPUT", then there is not "R5".

logitech: That is what would the schematics be when using INPUT_PULLUP in code?

The only difference between INPUT and INPUT_PULLUP is that INPUT_PULLUP turns on the internal pull-up resistor. It would be the same as using INPUT and adding an external resistor from the A5 pin to 5V.

Thank you very much once again for your explanation. :)

And I have just tried instead of using A5 as INPUT_PULLUP, use it only as INPUT and i have placed 100k ohm resistor as pull up. It works but readings are oscillating much more then before. They go plus/minus 7/8. Do you maybe know why is that?

Adjust Pot to 2.2K

logitech:
Do you maybe know why is that?

I already showed you how to do the math.

It’s normal for analog readings to vary. That’s the nature of analog to digital conversions. There are ways of cleaning it up. In an application like this, just using some >= and <= ranges instead of absolutes is probably the simplest.

just want to note, a resistor with gold 4th band has a tolerance of 5%. http://en.wikipedia.org/wiki/Electronic_color_code

The input pullups aren't actually linear(*), aren't accurate (between 20k and 50k is all you can assume), so if you want a voltage divider to produce consistent values don't use INPUT_PULLUP, use an external pull-up resistor.

INPUT_PULLUP is meant for digital inputs, not analog.

(*) They likely aren't actually resistors on-chip, but depletion-mode MOSFETs with a gate geometry chosen to provide roughly the right channel resistance.