Overview

Push buttons are the most fundamental way to add interactivity to your projects. They allow users to control devices, trigger actions, and make selections. On the Vumbua Synapse Kit, the push button is pre-connected to Digital Pin D7 of the ATmega328P microcontroller.

In this lesson, you'll learn not only how to read button states, but also crucial concepts like pull-up resistors and debouncing that ensure reliable input in real-world applications.

Real-World Applications

Push buttons are used in countless applications:

  • Power switches on electronic devices
  • Game controller buttons
  • Elevator floor selection
  • Microwave oven controls
  • Industrial machine controls
  • Emergency stop buttons
  • Keyboard keys

Prerequisites

Before starting Lesson 2, make sure you have completed:

Completed Lessons
  • Lesson 1: Blinking LED
  • Understanding of setup() and loop()
  • Using pinMode() and digitalWrite()
  • Basic Serial Monitor usage
Hardware Requirements
  • Vumbua Synapse Kit with push button
  • USB Type-C cable
  • Computer with Arduino IDE installed
On Vumbua Synapse Kit

The push button is pre-connected to the Vumbua board on Digital Pin D7. It includes an internal pull-up resistor - you can start programming immediately without any wiring!

The button is located near the top-right corner of the board, labeled "BUTTON" or with a tactile switch icon.

Learning Objectives

By the end of this lesson, you will be able to:

  • Understand how push buttons work electrically
  • Configure digital pins as inputs with pinMode()
  • Read button states using digitalRead()
  • Understand and use internal pull-up resistors
  • Implement button debouncing techniques
  • Create interactive button-controlled LED projects
  • Use buttons to toggle between different states
  • Display button status on Serial Monitor
  • Understand the ATmega328P's digital I/O system

What is a Push Button?

Mechanical Operation

A push button is a simple switch that makes or breaks an electrical connection when pressed. Most buttons have four pins internally connected in pairs:

  • Two pins are always connected (common connection)
  • The other two pins connect when button is pressed
  • This is called a "push-to-make" or "normally open" switch
  • When released, the connection opens again
Electrical Characteristics

Buttons are characterized by:

  • Contact Resistance: Very low when closed (< 0.1Ω)
  • Bounce Time: Mechanical vibration when pressed (1-50ms)
  • Actuation Force: Pressure needed to press (varies by type)
  • Lifecycle: Number of presses before failure (50K-1M+)
Types of Buttons

Common types in electronics:

  • Tactile Switches: Small, clicky buttons (like on Vumbua)
  • Momentary Switches: Return to original state when released
  • Toggle Switches: Stay in position until switched again
  • Pushbutton Switches: Larger industrial buttons
  • Membrane Switches: Flat, flexible buttons
Button Internal Connections
BUTTON
1 2
Top Row
INTERNAL CONNECTION
BUTTON
3 4
Bottom Row

Pins 1-2 are always connected internally
Pins 3-4 are always connected internally
When pressed, all four pins connect together

Button Connections on Vumbua

The push button on the Vumbua Synapse Kit is connected as follows:

Button Pin 1
Connected to Digital Pin D7
D7 (Input)
Button Pin 2
Connected to GND through internal pull-up
GND via Resistor
Button Pin 3
Not used (floating)
NC
Button Pin 4
Not used (floating)
NC
Circuit Diagram - Vumbua Button Connection
ATmega328P
D7
Digital Pin
BUTTON
1 2
10KΩ
PULL-UP
Resistor
5V
Power Supply

Normal State (Button NOT pressed): D7 reads HIGH (5V) through pull-up resistor
Pressed State (Button pressed): D7 reads LOW (0V) connected to GND

Understanding Pull-up Resistors

Pull-up resistors are essential for reliable button reading:

The Floating Pin Problem

Without a pull-up resistor, when a button is not pressed, the microcontroller pin is "floating" - not connected to anything. This can cause:

  • Random HIGH/LOW readings due to electrical noise
  • Unreliable button detection
  • False triggers from static electricity
Pull-up Solution

A pull-up resistor connects the pin to 5V through a high resistance (10KΩ typical). This ensures:

  • Pin reads HIGH when button is NOT pressed
  • Pin reads LOW when button IS pressed (connects to GND)
  • Clear, unambiguous signal levels
  • Protection against electrical noise
Internal vs External Pull-ups

The ATmega328P has built-in pull-up resistors that can be enabled in software:

  • Internal Pull-up: ~20KΩ resistor inside microcontroller
  • External Pull-up: Physical resistor on circuit board
  • Vumbua Kit: Uses external 10KΩ pull-up for reliability
  • Enabling: pinMode(pin, INPUT_PULLUP);
Button State Electrical Connection Pin D7 Voltage digitalRead() Internal Logic
NOT Pressed Open circuit 5V (through pull-up) HIGH (1) Logic 1
PRESSED Connected to GND 0V LOW (0) Logic 0
Important: Active-LOW Logic

With pull-up resistors, buttons use active-LOW logic:

  • HIGH (1): Button NOT pressed (default state)
  • LOW (0): Button IS pressed (active state)

This is opposite to what beginners might expect, but it's the standard for reliable digital input. Always check for LOW to detect button presses!

Using digitalRead() Function

The digitalRead() function reads the state of a digital pin:

Function Syntax
int buttonState = digitalRead(pin);

Where pin is the digital pin number (D7 for Vumbua button).

Return Values

digitalRead() returns either:

  • HIGH: Voltage ≥ 3V (logic 1)
  • LOW: Voltage ≤ 2V (logic 0)

For buttons with pull-up resistors:

  • HIGH = Button NOT pressed
  • LOW = Button IS pressed
Setup Requirements

Before using digitalRead(), you must configure the pin:

// For external pull-up (like Vumbua)
pinMode(pin, INPUT);

// For internal pull-up (if no external resistor)
pinMode(pin, INPUT_PULLUP);

The Vumbua Synapse Kit uses an external 10KΩ pull-up, so use INPUT mode.

Basic Button Reading

Let's start with a simple program to read and display button states:

button_basic.ino
/*
  Vumbua Synapse Kit - Lesson 2: Basic Button Reading
  Read digital input from push button on pin D7
  Display button state on Serial Monitor
*/

const int buttonPin = 7;   // Push button connected to digital pin 7
int buttonState = 0;         // Variable to store button state

void setup() {
  // Initialize Serial communication at 9600 bps
  Serial.begin(9600);
  
  // Initialize button pin as input
  // Vumbua uses external pull-up resistor, so use INPUT mode
  pinMode(buttonPin, INPUT);
  
  Serial.println("Vumbua Synapse Kit - Button Reading Program");
  Serial.println("===========================================");
  Serial.println("Press the button to see state change from HIGH to LOW");
  Serial.println("Remember: LOW means button is PRESSED (active-low logic)");
  Serial.println();
}

void loop() {
  // Read the state of the button
  buttonState = digitalRead(buttonPin);
  
  // Display button state
  Serial.print("Button State: ");
  
  if (buttonState == HIGH) {
    Serial.print("HIGH");
    Serial.println(" (NOT pressed)");
  } else {
    Serial.print("LOW");
    Serial.println(" (PRESSED!)");
  }
  
  // Wait for 100 milliseconds before next reading
  // This prevents Serial Monitor from flooding too fast
  delay(100);
}

Testing the Program

1. Upload the Code

Upload to your Vumbua Synapse Kit. The button is already connected to pin D7 on the board.

2. Open Serial Monitor

Go to Tools → Serial Monitor or press Ctrl+Shift+M. Set the baud rate to 9600.

3. Press and Release the Button

Watch the Serial Monitor output:

  • When button is NOT pressed: Should show "HIGH (NOT pressed)"
  • When button is PRESSED: Should show "LOW (PRESSED!)"

Try pressing and holding for a few seconds to see the continuous readings.

Click Me!

Click the button above to simulate the physical button press on your Vumbua Kit.

Button Controlled LED

Now let's combine button input with LED output to create an interactive project:

button_led_control.ino
/*
  Vumbua Synapse Kit - Lesson 2: Button Controlled LED
  Control LED on pin 9 using push button on pin 7
  LED turns ON only when button is pressed
*/

const int buttonPin = 7;   // Button on digital pin 7
const int ledPin = 9;      // LED on digital pin 9
int buttonState = 0;        // Variable for button state

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Initialize button pin as input
  pinMode(buttonPin, INPUT);
  
  // Initialize LED pin as output
  pinMode(ledPin, OUTPUT);
  
  Serial.println("Button Controlled LED System");
  Serial.println("LED will turn ON when button is pressed");
}

void loop() {
  // Read the button state
  buttonState = digitalRead(buttonPin);
  
  // Check if button is pressed (active-low logic)
  if (buttonState == LOW) {
    // Button is pressed - turn LED ON
    digitalWrite(ledPin, HIGH);
    Serial.println("Button PRESSED - LED ON");
  } else {
    // Button is not pressed - turn LED OFF
    digitalWrite(ledPin, LOW);
    Serial.println("Button RELEASED - LED OFF");
  }
  
  // Small delay to make Serial Monitor readable
  delay(50);
}

Challenge: Toggle LED with Button Press

Modify the program so the LED toggles (changes state) each time you press the button:

button_led_toggle.ino
/*
  Vumbua Synapse Kit - Lesson 2: LED Toggle with Button
  Toggle LED state each time button is pressed
  Includes debouncing for reliable toggling
*/

const int buttonPin = 7;      // Button on pin 7
const int ledPin = 9;         // LED on pin 9

int buttonState;               // Current button reading
int lastButtonState = HIGH;  // Previous button reading
int ledState = LOW;          // Current LED state

// Variables for debouncing
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  // Set initial LED state
  digitalWrite(ledPin, ledState);
  
  Serial.println("LED Toggle System Ready");
  Serial.println("Press button to toggle LED");
}

void loop() {
  // Read the button state
  int reading = digitalRead(buttonPin);
  
  // Check if button state changed (due to noise or pressing)
  if (reading != lastButtonState) {
    // Reset the debouncing timer
    lastDebounceTime = millis();
  }
  
  // Check if enough time has passed since last change
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // If the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;
      
      // Only toggle the LED if the new button state is LOW (pressed)
      if (buttonState == LOW) {
        ledState = !ledState;  // Toggle LED state
        digitalWrite(ledPin, ledState);
        
        // Print status to Serial Monitor
        if (ledState == HIGH) {
          Serial.println("LED turned ON");
        } else {
          Serial.println("LED turned OFF");
        }
      }
    }
  }
  
  // Save the current reading as last state for next loop
  lastButtonState = reading;
}
Programming Tip: State Machines

The toggle program introduces the concept of a state machine - the LED has two states (ON/OFF) and the button causes transitions between them.

This pattern is fundamental to more complex programs where devices have multiple modes or states (like a traffic light controller).

Button Debouncing

Mechanical buttons have a physical phenomenon called "bouncing" that must be handled:

What is Button Bounce?

When a button is pressed or released, the metal contacts don't make perfect contact immediately. They physically vibrate (bounce) for a few milliseconds, causing multiple rapid ON-OFF transitions.

Without debouncing, a single button press might be detected as multiple presses!

Bounce Characteristics
  • Duration: Typically 1-50 milliseconds
  • Cause: Mechanical vibration of contacts
  • Effect: Multiple rapid state changes
  • Solution: Software or hardware debouncing
Debouncing Methods
  • Software Debouncing: Ignore changes for a few ms after detection
  • Hardware Debouncing: RC circuit (resistor + capacitor)
  • Debounce Library: Pre-written code for easy implementation
  • Vumbua Approach: Software debouncing (shown in toggle example)
Button Bounce Visualization
BOUNCE
Multiple rapid transitions
CLEAN
Single clean transition

Simple Debouncing Code

// Simple debouncing function
bool isButtonPressed() {
  static unsigned long lastPressTime = 0;
  const unsigned long debounceTime = 50; // milliseconds
  
  // Read current button state
  int currentState = digitalRead(buttonPin);
  
  // If button is pressed (LOW) and enough time has passed
  if (currentState == LOW && (millis() - lastPressTime) > debounceTime) {
    lastPressTime = millis();
    return true;
  }
  
  return false;
}
Vumbua Hardware Design

The Vumbua Synapse Kit includes both hardware and software considerations for reliable button input:

  • Hardware: 10KΩ pull-up resistor for stable signal
  • Hardware: Quality tactile switch with minimal bounce
  • Software: Debouncing code examples provided
  • Education: Understanding both approaches taught

ATmega328P Digital I/O System

Understanding how the microcontroller handles digital I/O helps you write better code:

Port Registers

The ATmega328P organizes digital pins into three 8-bit ports:

  • PORTB: Digital pins 8-13
  • PORTC: Analog pins A0-A5
  • PORTD: Digital pins 0-7 (D7 is here!)

Pin D7 is bit 7 of PORTD. Each port has three registers:

  • DDRx: Data Direction Register (input/output)
  • PORTx: Data Register (write outputs)
  • PINx: Pin Input Register (read inputs)
How digitalRead() Works Internally

When you call digitalRead(7):

  1. Arduino translates pin 7 to PORTD, bit 7
  2. Reads the PIN register for that port
  3. Extracts the specific bit (bit 7)
  4. Returns HIGH (1) or LOW (0) based on bit value
  5. This happens in about 50 nanoseconds!
Direct Port Manipulation (Advanced)

For maximum speed, you can manipulate ports directly:

// Set pin 7 as input (equivalent to pinMode(7, INPUT))
DDRD &= ~(1 << 7);

// Enable internal pull-up on pin 7
PORTD |= (1 << 7);

// Read pin 7 state (equivalent to digitalRead(7))
bool state = (PIND & (1 << 7)) != 0;

This is faster but less readable - use only when speed is critical!

Arduino Function Equivalent Register Operation For Pin D7 Speed
pinMode(7, INPUT) DDRD &= ~(1 << 7) Clear bit 7 of DDRD ~3.5μs
pinMode(7, OUTPUT) DDRD |= (1 << 7) Set bit 7 of DDRD ~3.5μs
digitalRead(7) (PIND & (1 << 7)) Read bit 7 of PIND ~4.5μs
digitalWrite(7, HIGH) PORTD |= (1 << 7) Set bit 7 of PORTD ~4.5μs

Advanced Applications

Project 1: Multi-Click Detector

Detect single, double, and triple clicks on the same button:

multi_click_detector.ino
/*
  Vumbua Synapse Kit - Multi-Click Detector
  Detect single, double, and triple button clicks
*/

const int buttonPin = 7;
const int ledPin = 9;

int clickCount = 0;
unsigned long lastClickTime = 0;
const unsigned long clickTimeout = 400; // Time between clicks in ms

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.println("Multi-Click Detector Ready");
  Serial.println("Try single, double, or triple clicks");
}

void loop() {
  int buttonState = digitalRead(buttonPin);
  
  if (buttonState == LOW) {
    // Button is pressed
    unsigned long currentTime = millis();
    
    // Check if this is a new click (not holding)
    if (currentTime - lastClickTime > 200) {
      clickCount++;
      lastClickTime = currentTime;
      
      // Visual feedback - blink LED
      digitalWrite(ledPin, HIGH);
      delay(50);
      digitalWrite(ledPin, LOW);
    }
    
    // Wait for button release
    while (digitalRead(buttonPin) == LOW) {
      // Wait for release
    }
    delay(10); // Debounce
  }
  
  // Check for click sequence timeout
  if (millis() - lastClickTime > clickTimeout && clickCount > 0) {
    // Timeout reached - process the clicks
    switch (clickCount) {
      case 1:
        Serial.println("Single click detected");
        blinkLED(1);
        break;
      case 2:
        Serial.println("Double click detected");
        blinkLED(2);
        break;
      case 3:
        Serial.println("Triple click detected");
        blinkLED(3);
        break;
      default:
        Serial.print("Multiple clicks detected: ");
        Serial.println(clickCount);
        blinkLED(clickCount);
    }
    
    clickCount = 0; // Reset counter
  }
}

void blinkLED(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(ledPin, HIGH);
    delay(200);
    digitalWrite(ledPin, LOW);
    delay(200);
  }
}

Project 2: Button Controlled LED Modes

Use button to cycle through different LED patterns:

led_mode_controller.ino
/*
  Vumbua Synapse Kit - LED Mode Controller
  Cycle through LED modes with button presses
*/

const int buttonPin = 7;
const int ledPin = 9;

int mode = 0;              // Current mode (0-3)
int lastButtonState = HIGH;
unsigned long lastModeChange = 0;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  Serial.println("LED Mode Controller");
  Serial.println("Press button to cycle through modes");
  Serial.println("Mode 0: LED Off");
  Serial.println("Mode 1: LED On");
  Serial.println("Mode 2: Blinking");
  Serial.println("Mode 3: Breathing (PWM)");
}

void loop() {
  // Check for button press to change mode
  int currentButtonState = digitalRead(buttonPin);
  
  if (currentButtonState == LOW && lastButtonState == HIGH) {
    // Button just pressed - debounce check
    if (millis() - lastModeChange > 300) {
      mode = (mode + 1) % 4; // Cycle through 0-3
      lastModeChange = millis();
      
      Serial.print("Mode changed to: ");
      Serial.println(mode);
    }
  }
  lastButtonState = currentButtonState;
  
  // Execute current mode
  switch (mode) {
    case 0: // LED Off
      digitalWrite(ledPin, LOW);
      break;
      
    case 1: // LED On
      digitalWrite(ledPin, HIGH);
      break;
      
    case 2: // Blinking
      digitalWrite(ledPin, HIGH);
      delay(250);
      digitalWrite(ledPin, LOW);
      delay(250);
      break;
      
    case 3: // Breathing (PWM)
      // Fade in
      for (int brightness = 0; brightness <= 255; brightness++) {
        analogWrite(ledPin, brightness);
        delay(5);
        if (checkButton()) return; // Check for mode change
      }
      // Fade out
      for (int brightness = 255; brightness >= 0; brightness--) {
        analogWrite(ledPin, brightness);
        delay(5);
        if (checkButton()) return; // Check for mode change
      }
      break;
  }
}

bool checkButton() {
  if (digitalRead(buttonPin) == LOW) {
    delay(50); // Debounce
    return true;
  }
  return false;
}

Troubleshooting Common Issues

Common Button Problems

  • Check: Button is properly connected to D7 on Vumbua
  • Verify: Using pinMode(7, INPUT) not OUTPUT
  • Test: Measure voltage at D7 pin with multimeter
  • Try: Different button if available (could be stuck)
  • Remember: Vumbua uses active-LOW logic (LOW = pressed)

  • Symptom: One button press triggers multiple actions
  • Cause: Button bouncing (mechanical vibration)
  • Solution: Implement debouncing (see examples above)
  • Debounce Time: Start with 50ms, adjust as needed
  • Alternative: Use hardware debouncing with capacitor

  • Check: LED is connected to correct pin (pin 9 in examples)
  • Verify: LED polarity (long leg to +, short to -)
  • Test: LED with simple blink program first
  • Confirm: Using digitalWrite(ledPin, HIGH/LOW) correctly
  • Remember: Check Serial Monitor for button state feedback

  • Cause: Floating input pin (no pull-up resistor)
  • Solution: Vumbua has external pull-up, ensure proper connection
  • Alternative: Enable internal pull-up: pinMode(7, INPUT_PULLUP)
  • Check: For loose connections or damaged button
  • Test: With different delay values in loop

Debugging Tips

1. Serial Monitor is Your Friend

Always print button states to Serial Monitor for debugging. This helps you see exactly what the microcontroller is reading.

void loop() {
  int state = digitalRead(7);
  Serial.print("Button state: ");
  Serial.println(state);
  delay(100);
}
2. Test with Known Good Code

Start with the simplest button reading program. If that works, gradually add complexity (debouncing, toggling, etc.).

3. Check Hardware First

80% of button issues are hardware-related:

  • Loose connections
  • Damaged button
  • Incorrect wiring
  • Power supply issues

Video Demonstration

Video Tutorial Coming Soon!

We're preparing a detailed video walkthrough for this lesson.

Subscribe to our YouTube channel to be notified when it's available.

Subscribe to OLSPACE

What's Next?

Congratulations! You've successfully mastered digital input with push buttons. Here's what you've accomplished:

  • ✓ Learned how push buttons work electrically and mechanically
  • ✓ Used digitalRead() to read button states from D7
  • ✓ Understood pull-up resistors and active-LOW logic
  • ✓ Implemented button debouncing techniques
  • ✓ Created button-controlled LED projects
  • ✓ Built toggle switches and mode selectors
  • ✓ Understood the ATmega328P's digital I/O system
  • ✓ Learned troubleshooting techniques for button issues

In the next lesson, you'll explore sound generation:

Lesson 3: Buzzer - Sound Generation

Learn to generate tones and melodies using the piezo buzzer on your Vumbua Synapse Kit. Create audible alerts, simple music, and sound effects that respond to button presses and other inputs.

Resources & Downloads