Skip to content

Arduino - Connecting Switch

Arduino: Interfacing with a Pushbutton Switch

Section titled “Arduino: Interfacing with a Pushbutton Switch”

Pushbuttons or switches are fundamental components for user input in electronic projects. They temporarily connect two points in a circuit when pressed. This tutorial demonstrates how to read a switch’s state to control an LED. We will explore two methods: the traditional approach with an external pull-down resistor and the modern, recommended approach using the Arduino’s internal pull-up resistor.

When a digital input pin is not connected to anything, its state is ‘floating’. It can randomly read HIGH or LOW, leading to unpredictable behavior. To solve this, we use resistors to ‘pull’ the pin to a known state (either HIGH or LOW) when the switch is not active.

Method 1: The Pull-Down Resistor (Classic Approach)

Section titled “Method 1: The Pull-Down Resistor (Classic Approach)”

A pull-down resistor connects the input pin to Ground (GND). When the switch is open, the pin is pulled to LOW. When the switch is pressed, it connects the pin to a higher voltage (e.g., 5V), making the pin read HIGH. This requires an extra component in your circuit.

Section titled “Method 2: The Internal Pull-Up Resistor (Modern & Recommended)”

Most microcontrollers, including the one on the Arduino, have built-in, software-configurable pull-up resistors. A pull-up resistor connects the input pin to the supply voltage (VCC, 5V). This means the pin’s default state is HIGH. When you press the button, it connects the pin to Ground, pulling it LOW. This method is superior as it simplifies wiring and reduces component count.

Key Takeaway: We will use the internal pull-up resistor method for our main example as it represents modern best practice. The logic is inverted: LOW means the button is pressed, and HIGH means it is released.

  • 1 × Arduino UNO R3 or compatible board
  • 1 × Breadboard
  • 1 × Pushbutton switch
  • 1 × LED (any color)
  • 1 × 220Ω or 330Ω resistor (for the LED)
  • Jumper wires

Follow this simplified circuit. Note the absence of an external resistor for the button.

Arduino Pin D2 --- [Switch Terminal 1]
Arduino GND --- [Switch Terminal 2]
Arduino Pin D13 --- [Resistor] --- [LED Anode (+)]
Arduino GND --- [LED Cathode (-)]
// Connections explained:
// 1. Button: One leg to Digital Pin 2, the other leg to GND.
// 2. LED: The longer leg (anode) to a 220Ω resistor. The other end of the resistor to Pin 13.
// The shorter leg of the LED (cathode) to GND.

Arduino Code: Modern Approach with INPUT_PULLUP

Section titled “Arduino Code: Modern Approach with INPUT_PULLUP”

This code enables the internal pull-up resistor and checks for a LOW signal to detect a button press.

/**
* @file modern_switch_control.ino
* @brief Demonstrates controlling an LED with a pushbutton using the internal pull-up resistor.
* @author Modernized Tutorial
*/
// Use 'constexpr' for true compile-time constants. It's modern C++ practice.
constexpr int BUTTON_PIN = 2;
constexpr int LED_PIN = 13;
void setup() {
// Initialize Serial communication for debugging.
Serial.begin(9600);
// Configure the LED pin as an output.
pinMode(LED_PIN, OUTPUT);
// Configure the button pin as an input with the internal pull-up resistor enabled.
// The pin will be HIGH when the button is not pressed, and LOW when pressed.
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Read the state of the button.
int buttonState = digitalRead(BUTTON_PIN);
// The logic is inverted due to INPUT_PULLUP.
// LOW means the button is pressed.
if (buttonState == LOW) {
digitalWrite(LED_PIN, HIGH); // Turn the LED on.
Serial.println("Button Pressed - LED ON");
} else {
digitalWrite(LED_PIN, LOW); // Turn the LED off.
}
// A small delay to prevent spamming the Serial Monitor, but this is not for debouncing.
delay(10);
}

Physical switches don’t close cleanly. They ‘bounce’ between open and closed for a few milliseconds, which the fast microcontroller can read as multiple presses. This is called bouncing. For simple tasks like turning on an LED it’s not an issue, but for counting presses or toggling a state, it’s critical to handle.

The best way to debounce is with a non-blocking timer using millis(). This allows your loop() to remain responsive. The code below toggles an LED state only after the button signal has been stable for a short period.

// --- Add these variables to your global scope ---
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if bouncing is an issue
int ledState = LOW;
int lastButtonState = HIGH; // Pull-up means default state is HIGH
// --- Replace your loop() function with this ---
void loop() {
int reading = digitalRead(BUTTON_PIN);
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
int buttonState = reading;
if (buttonState == LOW) { // Button is pressed
digitalWrite(LED_PIN, HIGH); // Turn LED on
} else { // Button is released
digitalWrite(LED_PIN, LOW); // Turn LED off
}
}
lastButtonState = reading;
}
  • Always use INPUT_PULLUP for pushbuttons and switches when possible. It simplifies your hardware and is more reliable.
  • Remember the inverted logic: When using INPUT_PULLUP, a LOW reading means the button is active/pressed.
  • Always consider debouncing for any application more complex than a simple status light, especially for counting or toggling states.
  • Use non-blocking debouncing with millis() to keep your code responsive and scalable.