blog · 2 August 2026
Pull-ups, pull-downs, and why your button lies without one
Wire a push button three ways in the simulator: floating, pulled up, and pulled down. The floating version misbehaves on purpose, and the fix is one resistor.
Ask a room of beginners what a button outputs when it is not pressed and most will say zero volts. The truthful answer is: whatever the wind decides. An unconnected input is not low, it is undefined, and de:volt now models that honestly instead of quietly reading zero. Today's build makes the problem visible, then fixes it both directions.
The broken version first
Open a guest session at sim.devoltapp.com and build the naive circuit:
- Breadboard (400), Bench PSU at 5 V.
- A Push Button straddling the centre gap. Note the pin pairing: on a real 4-pin tact button the two pins on each side are internally joined, and the simulator models exactly that, so read the legs before trusting them.
- Wire one side of the button to the PSU's red terminal. Wire the other side to nothing at all, and pretend that side is "the signal to my chip".
Run it and probe the open side with the multimeter (View → Multimeter). Pressed, it reads a solid 5 V. Released, the meter does not read a reassuring 0 V: the Inspector marks the floating value as a numerical artifact rather than a measurement, and the Diagnostics tab raises a floating-input warning that explains why: a real high-impedance input responds to leakage, bias currents, and nearby fields. In a physical classroom this is the circuit that works on the bench, then triggers randomly when someone's phone buzzes near it.
Pull-down: default low, press for high
Fix it with one part. Add a Resistor, set it to 10 kΩ, and connect it from the signal side of the button to the PSU's black (ground) terminal:
- Released: the resistor gently holds the signal at 0 V.
- Pressed: the button connects the signal to 5 V, and the 10 kΩ just wastes a harmless 0.5 mA while it does.
Probe both states with the meter. The readings are now boring, which is the entire point. The warning in Diagnostics goes away, because the input genuinely has a DC path now.
Pull-up: default high, press for low
Swap the arrangement: resistor from the signal to 5 V, button from the signal to ground. Released reads 5 V, pressed reads 0 V. The logic is inverted, and this inverted version is the one you will meet everywhere in practice, for a practical reason: chips and microcontrollers ship with built-in pull-up resistors, so the button only needs to short to ground.
de:volt models those built-in pulls for real. On an RP2040 MicroPython Board, Pin(14, Pin.IN, Pin.PULL_UP) places an actual resistor to the actual 3.3 V rail inside the simulation, and the same is true of INPUT_PULLUP on the Arduino boards. Before the July physics work those internal pulls were not modelled at all, and the most common beginner input circuit read near zero volts; now it reads high until pressed, like hardware. You can verify with the scope: the button node sits at 3.3 V, dips to 0 V during a press, and the trace shows clean edges rather than wishful thinking.
Choosing the value
10 kΩ is the classroom default for a reason: strong enough to hold the line against noise, weak enough that pressing the button wastes only half a milliamp. Go much larger (1 MΩ) and the input becomes slow and touchy; much smaller (100 Ω) and each press draws 50 mA for nothing. Try both extremes in the simulator and watch the meter; the 100 Ω version is also a nice preview of why current budgets matter, since de:volt's resistors accumulate stress when overdriven.
Where this shows up next
Every microcontroller input you wire from here on carries this decision. The micro:bit's edge pads, the RP2040's GPIO, the 74LS logic inputs in the Logic Gates course: all of them want to know what happens when nothing is driving them. The two-lesson version of this build, with objective checks and hints, is in the free intro course at learn.devoltapp.com, and the button parts themselves are documented at docs.devoltapp.com/parts/switches-and-buttons.