The problem: a pin connected to nothing
A digital input pin is a very sensitive voltmeter. It decides, many times a second, whether the voltage it sees is high or low. If it is connected to a clear source, the answer is easy. If it is connected to nothing at all, the pin is said to be floating, and its reading becomes unreliable.
A floating pin has extremely high input resistance. Stray electric fields from nearby wires, your hand, or other signals can nudge its voltage up or down. It might read high, then low, then flicker between the two. The result in a project is a button that seems to press itself, or a program that behaves differently every time you move a wire.
This often catches people with a push button. When the button is not pressed, the input connects to nothing, so it floats. The button only gives a defined value while it is held down.
The fix: give the pin a default
A pull-up or pull-down resistor connects the pin to a fixed voltage through a fairly large resistance, so that when nothing else is driving the pin, it settles at a predictable level.
- A pull-up resistor connects the pin to the positive supply. Default reading: high.
- A pull-down resistor connects the pin to ground. Default reading: low.
The resistor is “weak” on purpose. When a button or another circuit actively connects the pin to the opposite level, that stronger connection wins and the pin follows it.
A button with a pull-up
Picture a button between the pin and ground, plus a pull-up resistor from the pin to the supply.
- Button not pressed. The pin is connected to the supply through the resistor. Almost no current flows because the pin draws very little, so the pin sits at the supply voltage and reads high.
- Button pressed. The pin is connected directly to ground. Current flows from the supply through the resistor to ground, and the pin reads low.
Note that the logic is inverted: pressed reads low. Many makers find that confusing at first, but the code only needs to treat low as “pressed”.
A pull-down version flips the arrangement. The button connects the pin to the positive supply, the resistor holds the pin to ground otherwise, and pressed reads high.
Why not connect the pin straight to the supply or ground?
Because a button would then short out. With the pin tied directly to the supply, pressing a button that connects to ground would join the supply directly to ground, which is a short circuit. The resistor is what limits that current to a trivial amount.
In the pull-up case with a 3.3 V supply and a 10 kilohm resistor, the current while pressed is 3.3 divided by 10,000, or 0.00033 A, which is 0.33 mA. That is small enough to be harmless but still clearly forces the pin low.
Choosing a value
Values around 10 kilohms are a very common starting point for digital inputs, and that is a convention, not a rule. The trade-off:
- Smaller resistor (stronger pull). More resistant to noise and faster at recovering, but more current is wasted each time the input is pulled the other way, which matters on batteries.
- Larger resistor (weaker pull). Saves current but can leave the pin vulnerable to interference, and can make signal edges slower when other capacitance is present.
Some communication buses specify values in their documentation, and the right choice can depend on the length of the wires and the speed. In those cases the datasheet and the bus specification are the places to look, as covered under reading datasheets. Different resistor values affect the result in a way related to the broader question of resistor values for each job.
Internal pull-ups
Many microcontrollers include software-selectable pull-up resistors, and sometimes pull-downs, inside the chip. Enabling one in code means a button can be wired between the pin and ground with no external resistor at all.
This is handy, but check your board’s documentation:
- The internal resistor is typically larger and less precisely defined than an external one, so check the manual for its range.
- Not every pin or every chip offers it, and some offer only pull-ups or only pull-downs.
- Some pins have special behaviour at start-up, and they may need an external resistor to ensure a safe state while the chip boots.
If a pin has to be in a known state from the very instant power arrives, such as one that enables motor drivers, an external resistor is the sturdier choice. Otherwise the pin may float briefly before your code runs.
Other places these resistors appear
- Open-drain and open-collector outputs. Some outputs can only pull a line low and rely on a pull-up resistor to bring it high. Shared buses often work this way, so several devices can share a line without fighting.
- Enable and reset pins. A chip’s reset or enable pin often needs a pull-up so that it behaves predictably while a microcontroller is starting.
- Transistor bases and gates. A resistor to ground keeps a transistor firmly off when its control pin floats, a use that comes up when applying transistor switching to larger loads.
Debouncing is a separate issue
A pull resistor solves the floating problem but not contact bounce. When a mechanical switch closes, the contacts can make and break several times in a few milliseconds, producing a burst of readings. This is handled with a small delay in code, a capacitor, or dedicated hardware. It is a signal-quality matter distinct from the question of default state, and it shows up when thinking about analog digital signals at the boundary with the real world.
Troubleshooting checklist
- Does the pin have a defined path to the supply or ground in every state of the switch?
- Is there only one pull resistor on that line, not both a pull-up and a pull-down fighting each other?
- Are you reading the logic the right way round for a pull-up (pressed reads low)?
- Is the internal pull-up actually enabled in your code, and is it available on that pin?
- Is the ground shared between the button circuit and the board?
Taken together, these small resistors are among the cheapest ways to stop an otherwise puzzling class of faults.