Anu Electronics push-button press counter cover with an illustrative four-pin tactile switch and Arduino circuit, wiring and code title.

Arduino Push-Button Press Counter: Debounce, Circuit, Breadboard Wiring and Code

EDITOR REVIEW — INCOMPLETE PART VERIFICATION: The store identifies a normally-open 6×6×4.3 mm switch, but provides no manufacturer part number, contact rating or terminal drawing. Confirm the shipping part documentation and breadboard fit before publication. Code is reviewed and its logic simulated, but not compiled or physically tested. The cover is illustrative.

Build a press counter using the four-pin tactile push button and Arduino Uno R3. Each deliberate press adds one to the Serial Monitor count. Holding the button does not keep counting, and the onboard LED follows the accepted press state.

Level: beginner. What you will learn: contact pairs, active-low inputs, software debounce and counting transitions. Use a computer as the display; no cloud account or extra display is required.

Contents

  1. How it works
  2. Parts list
  3. Identify the contacts
  4. Circuit and wiring
  5. Assembly and setup
  6. Complete code
  7. Upload and test
  8. Troubleshooting
  9. FAQs

How it works

A normally-open button closes only while pressed. The Uno’s internal pull-up keeps D2 HIGH when released; pressing connects D2 to ground and reads LOW. The switch carries only the input pull-up current, not a motor or lamp load. No external pull-up resistor is needed.

Mechanical contacts can make several rapid transitions during one action. The sketch waits until the raw input stays unchanged for 30 ms, then accepts the new state. It increments only on the accepted released-to-pressed transition. Thirty milliseconds is a starting software setting, not a verified bounce specification for this unnamed switch. Very brief presses or releases can be deliberately ignored.

Parts list

Component / purchase link Required Specification / pack
Tactile push button 1 switch 6×6×4.3 mm, 4-pin, normally open; sold as a pack of 10.
Arduino Uno R3 1 Classic 5 V Uno; onboard LED used.
Solderless breadboard 1 840-point board; verify switch leg fit.
Male-to-male jumper wires 2 leads 20 cm; sold as a pack of 40.
USB A–B data cable 1 USB Type-B plug for the Uno R3.

You also need a computer with Arduino IDE and a continuity meter to check contact pairs before wiring. No external LED or LED resistor is used. A meter purchase link is omitted because no compatible store listing was verified.

Identify the four contacts before applying power

Four legs do not mean four independent switches. Many tactile switches have two internally connected pairs; pressing bridges the pairs. Because this store listing has no terminal drawing, identify yours electrically rather than guessing from its shape.

  1. Remove the switch from the circuit and disconnect all power.
  2. With the button released, find two legs that have continuity. Label this pair A on paper.
  3. Check that the other two legs form a second pair B.
  4. Between a leg of A and a leg of B, the meter should show open when released and continuity only when pressed.
  5. If the result differs, stop and obtain the exact part drawing. Never choose two permanently connected legs for D2 and ground.

Circuit and connections

Uno connection Switch connection
D2 One leg of verified pair A
GND One leg of verified pair B
USB Computer for power, programming and serial output

A and B are tutorial labels, not markings promised on the product. No wire connects the switch directly to 5V.

Electrical schematic

Normally-open switch from Uno D2 to ground with internal pull-up enabled.
Normally-open switch from Uno D2 to ground with internal pull-up enabled.

Visual breadboard wiring

Symbolic breadboard switch wiring; verify contact pairs and physical fit.
Symbolic breadboard switch wiring; verify contact pairs and physical fit.

The light horizontal strips show groups of five connected holes. Opposite sides of the centre gap are isolated. The illustrated switch joins the two A terminals internally and the two B terminals internally; pressing bridges A to B. Match this verified topology on your actual switch. Physical board positions are symbolic. Do not force legs into misaligned holes.

Assembly and IDE setup

  1. Unplug USB and complete the contact test above.
  2. Place the switch across the breadboard gap only if all four legs align without force. Check that A and B remain isolated while released.
  3. Connect D2 to a free hole on an A terminal strip and GND to a free hole on a B terminal strip. Leave the breadboard power rails unused.
  4. Install Arduino IDE from Arduino’s official software page. Select Arduino Uno under Arduino AVR Boards and select the connected port.
  5. Create a sketch named button_press_counter and paste the program. It uses the built-in Arduino core; no extra library is required.

Power check: this is a USB-powered logic input circuit. Never connect 5V directly to ground, never wire the button to mains, and do not use an unknown switch rating for a power load. Rewire only with USB unplugged. Do not configure D2 as an output in this circuit.

Complete program

Copy the complete sketch below into button_press_counter.ino. A hosted code download is pending; the complete source is included here.

// Anu Electronics: one count per debounced button press.
// Classic Uno R3: D2 -> normally-open switch -> GND.
const byte BUTTON_PIN = 2;
const unsigned long DEBOUNCE_MS = 30UL;
int previousRaw = HIGH;
int stableState = HIGH;
unsigned long changedAt = 0;
unsigned long pressCount = 0;
bool armed = false;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.begin(9600);
  previousRaw = digitalRead(BUTTON_PIN);
  stableState = previousRaw;
  changedAt = millis();
  Serial.println("Release button to start. Presses: 0");
}

void loop() {
  const unsigned long now = millis();
  const int raw = digitalRead(BUTTON_PIN);
  if (raw != previousRaw) {
    previousRaw = raw;
    changedAt = now;
  }
  // Unsigned subtraction also works across millis() rollover.
  if (now - changedAt < DEBOUNCE_MS) return;
  if (!armed) {
    // Require a stable release, even if held during reset.
    if (raw == HIGH) {
      armed = true;
      stableState = HIGH;
    }
    return;
  }
  if (raw == stableState) return;
  stableState = raw;
  digitalWrite(LED_BUILTIN, stableState == LOW ? HIGH : LOW);
  if (stableState == LOW) {
    ++pressCount;
    Serial.print("Presses: ");
    Serial.println(pressCount);
  }
}

Key code sections

INPUT_PULLUP supplies a defined released state. previousRaw tracks each raw transition and changedAt records its time. Only a stable input is copied into stableState. The unsigned elapsed-time calculation continues through the normal millis() wraparound.

armed requires a stable release after reset, so a button held while starting does not add a count. A long hold produces one accepted press. The built-in LED turns on for the accepted pressed state and off after a stable release. The counter lives in RAM, resets to zero after reset or power loss, and eventually wraps after the unsigned-long maximum; it is not persistent event storage.

Upload and test

  1. Click Verify and then Upload. Open Serial Monitor at 9600 baud.
  2. Release the button and wait briefly. Press and release it five times, allowing more than 30 ms for each state. Expect counts 1 through 5.
  3. Hold it down for two seconds. Expect only one additional count and the onboard LED to remain on.
  4. Release it: the LED turns off without increasing the count. Press again to add one.
  5. Hold the button while resetting the Uno. It should wait for release; the next press starts at 1.
Release button to start. Presses: 0
Presses: 1
Presses: 2

This is illustrative output, not a recorded hardware test.

Simulated button count: a held press counts once; not a hardware recording.
Simulated button count: a held press counts once; not a hardware recording.

Troubleshooting

Problem Check
Always pressed or never arms Remove power. Check whether both leads use the same permanently connected pair or the same breadboard strip.
Never counts Check D2, common GND, opposite contact pairs, breadboard insertion and the selected serial port.
Several counts per press Check loose wiring first. If contacts still bounce, increase DEBOUNCE_MS modestly and repeat the test; this makes short taps harder to detect.
Very fast taps are missed Both pressed and released states must last at least the debounce interval. This example is intended for deliberate human presses.
Count returns to zero Reset, power loss or opening Serial Monitor on some setups can restart the Uno.

Frequently asked questions

Why does a press read LOW?

The pull-up biases D2 high and the button takes it to ground when closed. LOW is the active state for this wiring.

Can I use only two of the four legs?

Yes, use one verified contact from each pair. The other two legs are duplicates for this common switch topology, but must still be placed so they cannot short unrelated strips.

Do I need an external resistor?

Not for this short-wire INPUT_PULLUP demonstration. Longer or noisy wiring can require a different input design, filtering and protection.

Can I count a motor or machine with this?

This is a manual learning project. Its debounce window and software polling can miss short pulses, and an unknown switch must not be assumed suitable for a power circuit.

Related learning and parts

For a different input method, try our TTP223 touch tutorial. Compare digital input with the resistor voltage-divider tutorial.

Start your build with the tactile push-button pack and the compatible controller, breadboard and wires in the parts table.

Sources and validation

Original text, diagrams and sketch informed by Arduino’s public-domain examples. Logic simulation is not a compiled Arduino test or a physical test. Exact switch manufacturer ratings and contact drawing remain unavailable; review is required before publishing. The cover illustrates the part type rather than an authenticated product photograph.