Electronics basicsExplained

Pull-Up and Pull-Down Resistors, Explained Properly

Nearly every beginner project involves a button, and nearly every button tutorial says "add a pull-up resistor" without explaining what it's pulling, or from where. It's a simple idea once someone draws it properly.

The problem: a floating input

A digital input pin asks one question: is the voltage here high, or low?

Now picture a button wired between a pin and ground. Press it, and the pin is firmly connected to ground — that's a clear low. Release it, and the pin is connected to… nothing at all.

An unconnected input pin is called floating, and floating does not mean zero. The pin is extremely sensitive, and with nothing driving it, it picks up stray electrical noise from the air, nearby wires, even your hand moving near the board. It'll read high, then low, then high again, essentially at random.

The analogy: a door with no latch and no spring. Push it and it opens — that's a definite state. Let go and it doesn't return anywhere; it just drifts with any draught in the room. A pull-up or pull-down resistor is the spring that returns the door to a known position when nobody's touching it.

This is why a button project that "works but randomly triggers on its own" is almost never a code problem.

The fix

Connect the pin, through a resistor, to a known voltage. Now when the button isn't pressed, the pin has somewhere definite to sit.

Pull-up resistor

Resistor between the pin and the positive supply (3.3V or 5V). The pin sits high when idle. Press a button wired to ground, and the pin is dragged low.

Note that this inverts what you might expect in code: not pressed = HIGH, pressed = LOW. Perfectly normal, and it catches people out constantly.

Pull-down resistor

Resistor between the pin and ground. The pin sits low when idle. Press a button wired to the positive supply, and the pin goes high.

This matches intuition better — pressed = HIGH — but pull-ups are more common in practice, partly because most microcontrollers include them internally.

Why the resistor at all? Why not wire straight to 3.3V?

Good question, and the answer is the whole point of the component.

Without the resistor, pressing the button would connect your positive supply directly to ground — a dead short. Something would get hot and something would break.

The resistor is what lets both things be true at once: enough current flows to hold the pin at a definite voltage, but when the button closes, the current through that path is limited to something harmless. It's a compromise component, and it's doing more work than it looks like.

What value?

10kΩ is the standard answer for a button, and it's right the overwhelming majority of the time.

The reasoning behind it:

10k sits comfortably in the middle. Faster signals sometimes want lower values — I2C buses commonly use something in the 1k–4.7k range — because a stronger pull-up lets the line rise faster.

The good news: your board probably has them built in

Both Arduino and Raspberry Pi have internal pull-up resistors you can switch on in software. For a simple button, that means no external resistor at all.

Arduino:

pinMode(2, INPUT_PULLUP);   // internal pull-up on
// button wired between pin 2 and GND
// reads HIGH when released, LOW when pressed

Raspberry Pi (using gpiozero, which handles the pull-up for you):

from gpiozero import Button

button = Button(17)   # pull-up enabled by default
button.wait_for_press()
print("pressed")

Wire the button between the pin and ground, enable the internal pull-up, and you're done. This is why so many tutorials get away without mentioning resistors at all — and also why the ones that do mention them feel confusing.

When you still need a physical resistor

One more thing: bouncing

Even with a perfect pull-up, a mechanical button doesn't switch cleanly. The metal contacts physically bounce on contact, and the pin sees several rapid transitions in the few milliseconds after a press. Your code, being much faster than your finger, reads all of them — so one press registers as three.

That's a separate problem from floating, and it's solved separately: either a short delay in software after the first change, or a small capacitor across the switch to smooth the transitions. Libraries like gpiozero handle it for you by default.

The summary