To connect a standard 4-pin tactile button to an Arduino, wire one switch terminal to a digital GPIO (like D2) and the diagonally opposite terminal to GND. You do not need an external resistor for most bench setups; simply enable the microcontroller's internal pull-up resistor in your code using INPUT_PULLUP. When the button is unpressed, the pin reads HIGH (5V); when pressed, it reads LOW (0V).

This guide walks through the exact physical terminals, traces the electrical path node-by-node, and shows you how to verify the circuit with a multimeter before you write a single line of code.

The Physical Button: Terminals, Symbols, and Specs

The most common switch in maker kits is the 6x6x5mm through-hole tactile push button. While it has four pins, it is internally wired as a simple SPST-NO (Single Pole, Single Throw, Normally Open) switch.

On the schematic symbol, an SPST-NO switch is drawn as a break in the wire line with a hinged actuator above it. The actuator represents the physical plastic plunger. When you press the plunger, the metal dome inside collapses, bridging the gap and allowing current to flow.

Physically, the four pins are arranged in a rectangle. Pins 1 and 2 are internally shorted together, and Pins 3 and 4 are internally shorted together. The switch mechanism bridges the 1-2 pair to the 3-4 pair only when pressed. To guarantee you are wiring across the actual switch mechanism and not just a dead short, always wire to diagonally opposite pins (e.g., Pin 1 and Pin 4).

Bench Tip: Never wire a tactile switch directly to a motor, relay coil, or solenoid. These switches are rated for logic-level currents. Switching an inductive load will cause an arc that pits the contacts, permanently welding the micro-dome shut.

Below is the engineering data for a standard Omron B3F-series tactile switch and the associated pull-up resistor values you need to know for circuit design.

Tactile Switch Specifications & Pull-Up Resistor Data
Parameter Typical Value Engineering Note
Contact Configuration SPST-NO Single Pole, Single Throw, Normally Open
Max Contact Rating 50mA @ 12VDC Logic signals only; use a MOSFET for loads >20mA
Contact Resistance < 100mΩ Measured across closed terminals (Pin 1 to Pin 4)
Mechanical Bounce 1ms - 5ms Metal leaf vibration; requires software debouncing
Internal Pull-Up (AVR) 20kΩ - 50kΩ Silicon resistor inside ATmega328P; enabled via code
External Pull-Up 4.7kΩ - 10kΩ Required for wire runs >12 inches or noisy environments

For deeper reference on microcontroller pin configurations, consult the official Arduino digital pins documentation, and for switch mechanical tolerances, review the Omron B3F tactile switch datasheet.

Node-by-Node Wiring Trace: Source to GPIO

We will trace the INPUT_PULLUP circuit. This is the modern standard for Arduino wiring because it eliminates the need for a breadboard resistor, reducing component count and points of failure.

In this configuration, the microcontroller provides the voltage source internally, and the physical button acts as a switchable path to ground. Here is the exact textual trace of the electrical path:

  1. Node 1 (Internal Source): Inside the ATmega328P silicon, the 5V VCC rail connects to a ~30kΩ internal silicon resistor.
  2. Node 2 (GPIO Junction): The other end of that internal resistor connects to the physical Arduino Digital Pin 2 (D2). Because of the resistor, D2 is 'pulled up' to 5V when nothing else is connected.
  3. Node 3 (Breadboard Junction): A jumper wire carries this 5V-pulled signal from Arduino D2 to Breadboard Row 10.
  4. Node 4 (Switch Terminal A): Button Pin 1 is inserted into Breadboard Row 10, receiving the 5V logic HIGH signal.
  5. Node 5 (The Air Gap): Inside the button, the metal dome sits above the contact pad. The circuit is open. No current flows. The GPIO reads 5V (HIGH).
  6. Node 6 (Switch Terminal B): When you press the button, the dome collapses, connecting Pin 1 to Pin 4. Pin 4 is inserted into Breadboard Row 12.
  7. Node 7 (Ground Path): A second jumper wire connects Breadboard Row 12 to the Arduino GND pin.

Polarity and Ground Path Callout: Tactile switches are non-polarized; current can flow in either direction. However, the circuit logic relies on the ground path. When the switch closes, current flows from the internal 5V source, through the 30kΩ resistor, through the switch, and sinks into the Arduino's ground plane. The GPIO pin reads the voltage at the junction. Because the switch has near-zero resistance (<100mΩ) compared to the pull-up resistor (30,000Ω), almost all the voltage drops across the internal resistor, leaving the GPIO pin at ~0.0V (LOW).

Terminal and Pin Mapping Table
Arduino Pin Breadboard Node Button Pin Function in Circuit
D2 Row 10 Pin 1 (Terminal A) Digital Input (Reads HIGH when open, LOW when closed)
GND Row 12 Pin 4 (Terminal B) Circuit Ground / LOW voltage sink
N/A Row 10 Pin 2 Internally shorted to Pin 1 (Leave unconnected)
N/A Row 12 Pin 3 Internally shorted to Pin 4 (Leave unconnected)

Verifying the Circuit and Handling Bounce

Before uploading code, verify your physical wiring with a multimeter. This saves hours of debugging 'ghost' button presses caused by floating pins or miswired switch legs.

Step 1: Continuity Test (Power Off)

Disconnect the Arduino from USB. Set your multimeter to Continuity mode (the diode/sound wave icon). Place the probes on your chosen button pins (e.g., Pin 1 and Pin 4).
Expected Result: Silence when unpressed. A solid beep when the plunger is fully depressed. If it beeps constantly, you are probing two pins on the same side of the switch (the internal short). Move one probe to the opposite side.

Step 2: Voltage Test (Power On)

Plug the Arduino into USB. Set the multimeter to DC Voltage (20V range). Place the black probe on the Arduino GND pin and the red probe on the breadboard row connected to D2.
Expected Result:
• Unpressed: 4.8V to 5.1V (The internal pull-up is working).
• Pressed: 0.0V to 0.05V (The ground path is solid).
Failure mode: If the unpressed voltage reads something random like 1.4V or 2.7V, your GPIO pin is floating. You either forgot to set INPUT_PULLUP in the code, or your microcontroller pin is damaged.

Step 3: Debouncing in Code

When the metal dome inside the button makes contact, it physically bounces like a trampoline for 1 to 5 milliseconds before settling. To a microcontroller running at 16MHz, this looks like 50 rapid button presses. You must debounce the signal in software.

Here is a complete, copy-pasteable sketch using a non-blocking millis() timer to debounce the signal. This avoids the delay() function, keeping your main loop free to run motors or read sensors.

// Pin mapping
const int BUTTON_PIN = 2;

// Debounce variables
bool lastButtonState = HIGH;
bool currentButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 50ms is safe for most tactile switches

void setup() {
  Serial.begin(115200);
  // Enable the internal 20k-50k pull-up resistor
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  // Read the raw physical state (LOW means pressed due to pull-up)
  bool reading = digitalRead(BUTTON_PIN);

  // If the switch changed state (due to noise or a real press), reset the timer
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  // If the reading has been stable longer than the debounceDelay, accept it
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != currentButtonState) {
      currentButtonState = reading;
      
      // Trigger action only on the exact moment of the press (LOW)
      if (currentButtonState == LOW) {
        Serial.println("Button Pressed (Debounced)");
      }
    }
  }

  // Save the raw reading for the next loop iteration
  lastButtonState = reading;
}
Edge Case - Long Wire Runs: If your button is mounted more than 12 inches away from the Arduino on a breadboard or panel, the wire acts as an antenna and will pick up electromagnetic interference (EMI) from nearby AC mains or switching power supplies. In this scenario, the internal 30kΩ pull-up is too weak to hold the line HIGH against the noise. Solder a physical 4.7kΩ external pull-up resistor between the button's D2 terminal and the 5V rail to stiffen the logic level.