There are many explanations of pull-up or pull-down resistors that gloss a bit too much over the details, keeping you in doubt about how they really work, especially in conjunction with microcontrollers.

To improve our understanding, we will use a simplified schematic that models a microcontroller input-pin connected to a switch and a pull-up resistor. Then we calculate the voltages on the input-pin resulting from a closed or open switch.

Key to understanding how a pull-up resistor works, is to consider not only the external circuit connected to the input pin, but also the (simplified) internal circuit of the microcontroller that follows it.

In the following schematic (scaled up version of the one above), a circuit is shown where the input pin will be pulled high to $V_{CC}$ (typically $5\_{V}$ or $3.3\_{V}$) when the switch is open, and low to ground ($0\_{V}$) when the switch is closed. If there was no pull-up resistor the input pin would be floating.

The voltage on a floating pin is undefined, since the pin is unconnected, and any electromagnetic radiation/interference (EMI) from the environment could “randomly” change it. When the pin is connected properly however, any voltage driving the pin directly will override EMI (such as wires unintentionally picking up radio signals or radiation from close by circuit elements), that is usually much weaker.

In case of strong EMI, shielding might be necessary, the wires / traces on a circuit board might need to be shortened to be less likely to act as an antenna, or other measures need to be taken to avoid picking up unwanted signals. Digital circuits however are rather robust to noise.

In summary: when the switch is open the input pin would be floating, but since there is also a pull-up resistor to $V_{CC}$, the input pin’s voltage will be close to $V_{CC}$. So the microcontroller will read a 1 or a HIGH in this case. When the switch is closed however, the input pin is still connected to $V_{CC}$ through the pull-up resistor, but at the same time to $Gnd$ ($0\_{V}$). Yet it reads approximately $0\_{V}$.

### Key question

How is it possible, that the input pin is (approximately) at $0\_{V}$ when the switch is closed, and therefore is read as a 0 or LOW, instead of being at some intermediary voltage or close to $V_{CC}$?

Before deriving from the circuit above why this is the case, we need to justify that this model and the resistor values are realistic.

## Input pin impedance

A digital pin configured as input typically has a high impedance, the value of which cannot be determined accurately without considering the surrounding circuit or the expected frequency of the input signal.

The total input pin impedance is affected by the capacitance of the input pin (and the internal microcontroller circuitry attached to it), but also the external circuit leading to the input pin. The length of wires/circuit board traces and their arrangement can cause capacitive or inductive effects that alter the total impedance of the input pin.

Usually however, those effects are small enough that we can assume “rules of thumbs” for common low frequency signals (up to 10 MHz) fed into microcontrollers. Depending on the author, the impedance of a digital input pin is assumed to be between 100 kΩ and 1 MΩ, or even as high as 100 MΩ.

Therefore, we can model the input pin as a resistor to ground, with a high resistance that is constant across all possible signals (within the frequency range we usually want to consider), or at least has an impedance that remains within the range of 100 kΩ to 100 MΩ.

For a quick overview of further details, refer to this discussion about input pin impedance, which is pretty general and even discusses analog input pins, although it started as a question about the digital input pin impedance for an ATmega328P.

## Calculating the input pin voltages

Coming back to our initial problem, we will make the simplifying assumption that the input impedance can be modeled as a resistor with 100 MΩ (and repeat the same calculation with 100 kΩ, later). The pull-up resistor has a typical value of 10 kΩ. To get concrete values, we will also assume $V_{CC}$ to be $5\_{V}$.

### Opened switch

When the switch is open, we have a simple series circuit (marked in red in the following schematic), going from $V_{CC}$ to two resistors (10 kΩ and 100 MΩ) and ending in $Gnd$.

In a series circuit the total resistance, $R_{tot}$, is the sum of the resistances of the individual components ($R_{pu}$ for the pull-up resistor, and $R_{ip}$ for the input-pin), so:

$$R_{tot} = R_{pu} + R_{ip} = 10 \k{Ω} + 100 \M{Ω} = 100.010 \M{Ω}$$

To compute the total current of any circuit, we can apply Ohm’s law (*I = V / R*) when knowing the total resistance and the active components (here just one power source, $V_{CC}$). We get the total current, $I_{tot}$, as such:

$$I_{tot} = {V_{CC} \over R_{tot}}$$

Applying Kirchhoff’s Voltage Law to this series circuit (which forms a closed loop from $V_{CC}$ to ground), we know that the total voltage applied at ($V_{CC}$) must drop off at both resistors. So $V_{CC} = V_{pu} + V_{ip}$.

$$V_{pu} = I_{tot} \cdot R_{pu}$$

$$V_{ip} = I_{tot} \cdot R_{ip}$$

Assembling it all together, and simplifying …

$$V_{ip} = I_{tot} \cdot R_{ip} = {V_{CC} \over R_{tot}} \cdot R_{ip} = {V_{CC} \over {R_{pu} + R_{ip}}} \cdot R_{ip}$$

… we get the voltage divider formula:

$$V_{ip} = V_{CC} \cdot {R_{ip} \over {R_{pu} + R_{ip}}}$$

Putting in the specific values, the result for $R_{ip} = 100 \M{Ω}$ is:

$$V_{ip} = 5 \_{V} \cdot \frac{100 \M{Ω}}{10 \k{Ω} + 100 \M{Ω}} = 5 \_{V} \cdot \frac{100 \M{Ω}}{100.010 \M{Ω}} \approx 4.9995000 \_{V}$$

and for $R_{ip} = 100 \k{Ω}$ it is:

$$V_{ip} = 5 \_{V} \cdot \frac{100 \M{Ω}}{10 \k{Ω} + 100 \k{Ω}} = 5 \_{V} \cdot \frac{100 \k{Ω}}{110 \k{Ω}} \approx 4.5454545\_{V}$$

So $V_{ip}$ is (very) close to $5\_{V}$ or $V_{CC}$, and the microcontroller will reliably recognize it as HIGH or 1.

Looking at the voltage divider formula again, we can determine the conditions for $V_{ip}$ being as close as possible to $V_{CC}$. To guarantee this, $R_{ip} \over {R_{pu}+ R_{ip}}$ should be as close as possible to 1. This is always true if $R_{pu}$ is much lower than $R_{ip}$.

Knowing this, it makes sense that the pull-up resistor, $R_{pu}$, is typically not chosen too high, yet high enough, to keep the current through it low.

### Closed Switch

When the switch is closed, we have a parallel circuit (shown in red in the following schematic), made of the switch and the input pin resistor. This circuit is in series with the pull-up resistor.

To properly compute the current that flows through the switch to ground, we have to assume a certain resistance. Measuring the resistance of a closed switch whose terminals are connected to wires (through a breadboard), my multimeter read a couple Ω resistance. Depending on what switch and wires are used the resistance may vary, but should be pretty low. 10 Ω seems to be a good upper bound for a functional switch and good connections.

This gives us all the resistances in this circuit:

$$\begin{align}

R_{switch} &= 10 \_{Ω} \\

R_{pu} &= 10 \k{Ω} \\

R_{ip} &= 100 \M{Ω}

\end{align}$$

As mentioned above, the switch and input-pin form a parallel circuit, whose resistance we compute as such:

$$R_{parallel} = R_{switch} || R_{ip} = \frac{1}{\frac{1}{R_{switch}}+ \frac{1}{R_{ip}}} = \frac{1}{\frac{1}{10 \_{Ω}} + \frac{1}{100 \M{Ω}}} \approx 9.999999 \_{Ω}$$

The calculation shows $R_{switch}$ almost completely dominates the parallel circuit’s resistance, as long as $R_{switch}$ is much lower than $R_{ip}$.

If we join the parallel circuit and the pull-up resistor in a series circuit, we obtain the entire circuit shown in the schematic above. As usual in series circuits, the total resistance $R_{tot}$ is obtained by adding the components resistances. Applying Ohm’s law we get the total current in the entire circuit, $I_{tot}$:

$$\begin{align}

R_{tot} &= R_{pu} + R_{parallel} \approx 10 \k{Ω} + 9.999999 \_{Ω} = 10009.999999 \_{Ω} \\

I_{tot} &= \frac{V_{CC}}{R_{tot}} \approx 0.0005 \_{A}

\end{align}$$

Since the switch and input pin are in parallel, they have the same voltage $V_{parallel} = V_{ip} = V_{switch}$. This parallel circuit is also in series with the pull-up resistor, so considering Kirchhoff’s Voltage Law, $V_{CC} = V_{pu} + V_{parallel}$ or $V_{CC} = V_{pu} + V_{ip}$. We can now compute $V_{pu}$ using Ohm’s law and finally obtain $V_{ip}$:

$$\begin{align} V_{pu} &= I_{tot} \cdot R_{pu} \approx 4.9950 \_{V} \\

V_{ip} &= {V_{CC}} \,- {V_{pu}} \approx 0.0050 \_{V} \end{align}$$

$V_{ip}$ being close to $0\_{V}$ ($0.0050\_{V}$), the microcontroller will read it as 0 or LOW.

If we assume $R_{ip} = 100 \k{Ω}$ instead of $100 \M{Ω}$, then $V_{pu}$ remains almost unchanged ($V_{pu} \approx 4.9950$ as above, when rounded to 4 decimals), and thus all the other calculations and conclusions remain the same.

So, for a closed switch, the input pin impedance matters less than for an open switch. But in both cases a $10 \k{Ω}$ pull-up resistor is a good choice.

## Pull-up resistors in other circuits

We can understand pull-up resistors that act as inputs to other circuits, not just microcontroller pins, in a similar way. The key insight is that a pull-up resistor needs to have a much lower resistance than the resistance/impedance of the circuit to which it is an input. In this case, the equations above result in voltages close to $V_{CC}$ when the switch is opened, and $Gnd$ ($0\_{V}$) when the switch is closed.

## Further reading

For other factors to consider when choosing pull-up resistors, such as current, or the required switching speed/signal frequency, refer to SparkFun’s quiz and the discussion about input pin impedance on AVR Freaks already linked above.

You might also want to look at an introduction to pull-up resistors from the Seattle Robotics Society.

See also, network analysis of electrical circuits for an overview on how to compute voltages and currents in circuits, especially mesh analysis and nodal analysis.