about
github β†—
bsky β†—
← posts

electrical engineering for frontend developers

2025 Nov 11
2m read
πŸ“ maine πŸ‡ΊπŸ‡Έ
in frontend development, if you want to press a button, you have an input available that the system has already interpreted. wiring a physical button lets us examine that interpretation.
say you're using a chip running at 3.3 volts and one pin is configured as digital input. the pin reads voltage relative to ground (the circuit's zero-volt reference) and then classifies it as HIGH or LOW. the exact voltage threshold depends on the chip.
connect that input to ground through a button, and pressing it yields LOW. releasing it disconnects the input from ground, but doesn't establish another voltage. the input is now floating and its reading can be affected by electrical noise. 'disconnected' doesn't reliably mean either state.
enter resistors. a pull-up resistor gives the input a defined voltage while the button is released:
3.3 V ──[10 kΞ©]──┬── input pin β”‚ button (open) β”‚ GND
with the button open, the resistor connects the input to 3.3 volts. the input draws very little current, so very little voltage drops across the resistor. the pin now reads HIGH.
pressing the button connects the input directly to ground, making it LOW. current now flows from the supply, through the resistor and button, to ground. the resistor limits that current; replacing it with a wire would create a short circuit.
we calculate the current using ohm's law:
current = voltage / resistance = 3.3 V / 10,000 Ξ© = 0.00033 A = 0.33 mA
this arrangement is called active-low: a low signal = button is pressed. the electrical level and the meaning we assign it are separate decisions.
we now have defined resting states, but the transition between them needs attention. a mechanical switch's contacts can bounce as they meet, briefly making and breaking the connection. one press may produce several transitions.
HIGH β†’ LOW β†’ HIGH β†’ LOW β†’ HIGH β†’ LOW …
counting every transition to LOW would count several presses.
one way to handle this is to wait until the observed input has stopped changing before accepting its new state. expressed in javascript:
let timer; let pressed = false; // button is released function onPinChange(level) { clearTimeout(timer); timer = setTimeout(() => { const nextPressed = level === 0; if (nextPressed === pressed) return; pressed = nextPressed; if (pressed) onPress() }, 20); }
you recognize this as a debounce. eventually onPress runs and we're back at the start.
#tech