PinLab › Projects › Button turns on LED
#02 Beginner ⏱ 20 min

ESP32: Button turns on LED

The first digital input. Press a button → the LED lights. You learn what a pull-up resistor is and why the pin reads "1" when nothing is pressed.

Open it interactively in 3D →

What you learn

INPUT_PULLUP and why it is neededdigitalRead and inverted logicPlacing a button across the grooveTwo GND rails

You need

How it works

The button sits across the groove of the breadboard. Inside, the two legs on the same side are permanently joined; pressing joins both sides too. By wiring diagonally opposite legs (25 top, 27 bottom) we are sure to pass through the switching contact.

The problem with an input: if the pin is connected to nothing, it "floats" and reads a random 0 or 1. A pull-up resistor (built into the ESP32, ~45 kΩ) gently pulls the pin to 3.3 V → a stable HIGH. The button connects it to GND and "beats" the resistor → LOW. That is why the logic is inverted: if (digitalRead(BTN) == LOW) = pressed.

Wiring

FromToWhy
ESP32 · D4 (GPIO 4)Button, leg in column 25 (top)The pin is an input with the internal pull-up on: without a press it reads HIGH (1).
Button, diagonal leg (column 27, bottom)− railWhen you press, the button connects GPIO 4 directly to GND → the pin reads LOW (0).
ESP32 · D2LED → 220 Ω → − railSame as in project 1 — the output we control.
ESP32 · GND (both pins)− rails top and bottomThe top and bottom rails are not joined — so we use both GND pins.

Step by step

  1. LED (anode 19c, cathode 20c) and resistor 20a → − rail, as in project 1.
  2. The button: place it so it straddles rows e and f (across the groove), legs in columns 25 and 27.
  3. Wire D4 → 25a (top half).
  4. Short wire 27j → bottom − rail.
  5. GND → top − rail, GND (second pin) → bottom − rail.
  6. Upload the code. The LED lights while you hold the button. Open the Serial Monitor (115200) and watch the values.

Code (Arduino IDE)

// Project 2: Button turns on LED (with internal pull-up)
const int LED_PIN = 2;
const int BTN_PIN = 4;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP);  // internal resistor to 3.3 V
  Serial.begin(115200);
}

void loop() {
  int state = digitalRead(BTN_PIN); // 1 = released, 0 = pressed

  if (state == LOW) {
    digitalWrite(LED_PIN, HIGH);
    Serial.println("Pressed!");
  } else {
    digitalWrite(LED_PIN, LOW);
  }
  delay(20); // a little "settling" (debounce)
}

Typical problems

The button "works" without pressing? Your legs are on the same pair — move one leg to another column.
Flicker in the Serial Monitor on press = bouncing. Fix: delay(20–50) or a check with millis().
GPIO 34–39 will not work for this — no pull-up on them.

Open it interactively in 3D →

More projects (7 more) with a free sign-in in the course. Projects →