Embedded Systems

ESP32 Beginner Course #3: Push Button Input and INPUT_PULLUP Explained

Read a push button with ESP32 GPIO4, understand floating inputs, pull-up and pull-down resistors, and control an LED using digitalRead.

ESP32GPIOInputPull-up ResistorButton

Introduction

So far, the ESP32 has been sending signals. In this lesson, we reverse the direction and teach the ESP32 to receive information from the outside world using a push button.

Digital inputs are used everywhere in embedded systems: buttons, switches, sensors, door contacts, limit switches, and many industrial signals all rely on the same basic idea.

Output vs input

When a GPIO pin is configured as an output, the ESP32 drives the pin HIGH or LOW.

When a GPIO pin is configured as an input, the ESP32 observes the voltage on that pin and reads it as HIGH or LOW.

In this project:

  • GPIO2 controls an LED
  • GPIO4 reads a button

The floating input problem

A digital input must have a defined voltage. If nothing is connected to the input, the pin can float. A floating input may randomly read HIGH or LOW because it is affected by electrical noise, nearby signals, and tiny leakage currents.

This is why button inputs need pull-up or pull-down resistors.

The interactive lab Pull-up and Pull-down Resistors shows how the input voltage changes when the button is pressed and released.

Pull-up vs pull-down

A pull-up resistor connects the input to 3.3V through a resistor. When the button is not pressed, the pin reads HIGH. When the button connects the pin to ground, the pin reads LOW.

A pull-down resistor connects the input to ground through a resistor. When the button is not pressed, the pin reads LOW. When the button connects the pin to 3.3V, the pin reads HIGH.

Both methods work. The important point is that the pin always has a defined default state.

Using the ESP32 internal pull-up

The ESP32 includes internal pull-up resistors that can be enabled in software. That means we do not need to add an external resistor for this beginner button circuit.

We enable it with:

pinMode(buttonPin, INPUT_PULLUP);

With INPUT_PULLUP, the button logic is inverted:

  • Released button reads HIGH
  • Pressed button reads LOW

This is normal and expected.

Hardware required

  • ESP32 DevKit
  • Push button
  • LED
  • 220 ohm resistor
  • Breadboard
  • Jumper wires

Wiring

LED wiring:

GPIO2
  |
 LED
  |
220 ohm
  |
 GND

Button wiring:

GPIO4 ---- Push Button ---- GND

No external pull-up resistor is required because the ESP32 internal pull-up is enabled in code.

Source code

const int ledPin = 2;
const int buttonPin = 4;

void setup()
{
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
    int buttonState = digitalRead(buttonPin);

    if (buttonState == LOW)
    {
        digitalWrite(ledPin, HIGH);
    }
    else
    {
        digitalWrite(ledPin, LOW);
    }
}

Code explanation

The LED pin is configured as an output:

pinMode(ledPin, OUTPUT);

The button pin is configured as an input with the internal pull-up resistor enabled:

pinMode(buttonPin, INPUT_PULLUP);

Then the code reads the button:

int buttonState = digitalRead(buttonPin);

Because we use INPUT_PULLUP, a pressed button connects GPIO4 to ground, so the input becomes LOW. That is why the condition checks for LOW:

if (buttonState == LOW)

When the button is pressed, the LED turns on. When the button is released, the LED turns off.

Common mistakes

If the button does not behave correctly, check:

  • Button legs are placed across the breadboard gap
  • One side of the button goes to GPIO4
  • The other side goes to GND
  • Code uses INPUT_PULLUP, not plain INPUT
  • Logic checks for LOW when pressed
  • ESP32 ground is connected to the circuit ground

Real engineering use cases

Digital inputs are used for:

  • User buttons
  • Limit switches
  • Door sensors
  • Motion detector outputs
  • Emergency stop loops
  • Mode selection switches
  • Machine state feedback

Once you understand this button circuit, you can read many other digital devices.

Engineering challenge

Modify the project so the LED toggles every time the button is pressed instead of only staying on while the button is held down. This introduces the idea of state, edge detection, and eventually debouncing.

Next lesson

In the next lesson, we will use PWM to control LED brightness instead of simply turning it fully on or fully off.