A push button is the simplest input there is, yet buttons cause plenty of beginner bugs: presses that happen by themselves, or one press counted three times. Both have standard fixes, and both are in this sketch.
On the Uno you don’t need a resistor at all. Wire one leg to D2 and the diagonal leg to GND, then turn on the chip’s internal pull-up with pinMode(2, INPUT_PULLUP). The pin now reads HIGH at rest and LOW while pressed.
The sketch debounces with millis() instead of delay(), so the rest of your code keeps running. Each clean press toggles the Uno’s on-board L LED and is counted on the Serial Monitor.
Wiring
| Arduino Uno R3 | Push button (6 mm tactile switch) | Wire | Notes |
|---|---|---|---|
| D2 | 1 | yellow | With INPUT_PULLUP the pin rests HIGH and reads LOW when pressed. |
| GND | 2 | black | On a 4-leg button use diagonally opposite legs — legs on the same long side are always joined. |
No supply — passive switch part, 5 V board. Wire the button between a GPIO and GND and use the internal pull-up. Never connect a button between a GPIO and 5 V on a 3.3 V board.
Board quirks
INPUT_PULLUPturns on a resistor of about 20–50 kΩ inside the ATmega328P, so the button needs only two wires and no external resistor. The logic is inverted: pressed =LOW.- A plain
INPUTwith nothing pulling it floats and reads random HIGH/LOW — touching the wire changes it. This is the most common “my button presses by itself” problem. - Contacts bounce for a few milliseconds, so one press can look like five. The sketch only accepts a change once the pin has been steady for 30 ms, and it never blocks with
delay(). - D2 is also an interrupt pin, but don’t use
attachInterrupt()for a hand-pressed button — bounce fires it many times. Polling with debounce is simpler and reliable.
Code
// Push button on an Arduino Uno R3 with the internal pull-up and debouncing.
// One leg → D2, the diagonal leg → GND. Not pressed = HIGH, pressed = LOW.
// Each press toggles the on-board "L" LED (D13) and is counted.
const uint8_t BUTTON_PIN = 2;
const unsigned long DEBOUNCE_MS = 30;
bool ledOn = false;
bool stableState = HIGH;
bool lastReading = HIGH;
unsigned long lastChange = 0;
unsigned int presses = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP); // no external resistor needed
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
Serial.println(F("Press the button on D2"));
}
void loop() {
bool reading = digitalRead(BUTTON_PIN);
if (reading != lastReading) lastChange = millis(); // contacts bouncing - restart the timer
lastReading = reading;
if (millis() - lastChange > DEBOUNCE_MS && reading != stableState) {
stableState = reading;
if (stableState == LOW) { // a clean press
presses++;
ledOn = !ledOn;
digitalWrite(LED_BUILTIN, ledOn);
Serial.print(F("Press #"));
Serial.print(presses);
Serial.println(ledOn ? F(" - LED on") : F(" - LED off"));
}
}
}// Push button on an Arduino Uno R3 with the internal pull-up and debouncing.
// One leg → D2, the diagonal leg → GND. Not pressed = HIGH, pressed = LOW.
// Each press toggles the on-board "L" LED (D13) and is counted.
const uint8_t BUTTON_PIN = 2;
const unsigned long DEBOUNCE_MS = 30;
bool ledOn = false;
bool stableState = HIGH;
bool lastReading = HIGH;
unsigned long lastChange = 0;
unsigned int presses = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP); // no external resistor needed
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
Serial.println(F("Press the button on D2"));
}
void loop() {
bool reading = digitalRead(BUTTON_PIN);
if (reading != lastReading) lastChange = millis(); // contacts bouncing - restart the timer
lastReading = reading;
if (millis() - lastChange > DEBOUNCE_MS && reading != stableState) {
stableState = reading;
if (stableState == LOW) { // a clean press
presses++;
ledOn = !ledOn;
digitalWrite(LED_BUILTIN, ledOn);
Serial.print(F("Press #"));
Serial.print(presses);
Serial.println(ledOn ? F(" - LED on") : F(" - LED off"));
}
}
}Expected serial output
Press the button on D2
Press #1 - LED on
Press #2 - LED off
Press #3 - LED onPress the button on D2 Press #1 - LED on Press #2 - LED off Press #3 - LED on
Common errors
The LED toggles on its own or the count jumps
The pin floats: INPUT_PULLUP missing, or the button is wired to 5V instead of GND.
Nothing happens when pressed
Both wires on legs that are already joined inside the button. Move one wire to the diagonally opposite leg.
One press counts twice
Raise DEBOUNCE_MS to 50 for worn or cheap buttons.