Chapter 4

Chapter 4: GPIO Input & Output Basics

Di chapter ini, kita akan belajar menggunakan GPIO sebagai INPUT (membaca button) dan OUTPUT (kontrol multiple LEDs). Mari kita buat traffic light sederhana dengan button!

GPIO sebagai INPUT

Hardware Setup: Push Button

                     ┌─── 3.3V
                     │
                     └─── Resistor 10kΩ (Pull-up)
                          │
ESP32 Pin 5  ────────────┤
                          │
                          └─── Push Button ─── GND

Cara Kerja:

  • Tidak ditekan: Pin 5 baca HIGH (3.3V dari pull-up resistor)
  • Ditekan: Pin 5 baca LOW (0V karena connect ke GND)

Code: Read Button State

#define BUTTON_PIN 5
#define LED_PIN 2

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // INPUT dengan internal pull-up
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

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

  if (buttonState == LOW) {  // Button ditekan
    digitalWrite(LED_PIN, HIGH);
    Serial.println("Button PRESSED - LED ON");
  } else {
    digitalWrite(LED_PIN, LOW);
    Serial.println("Button RELEASED - LED OFF");
  }

  delay(100);  // Debounce delay
}

Penjelasan:

INPUT_PULLUP:

  • ESP32 punya internal pull-up resistor (10-50kΩ)
  • Tidak perlu external resistor!
  • Pin default HIGH, jadi button press = LOW

digitalRead():

  • Membaca state pin (HIGH atau LOW)
  • Return value: HIGH (1) atau LOW (0)

Debouncing:

  • delay(100) mencegah multiple reads dari satu press
  • Button mechanical switch bisa “bounce” (flicker)

Button dengan Toggle

Sekarang kita buat button yang toggle (nyalakan/matikan setiap press):

#define BUTTON_PIN 5
#define LED_PIN 2

bool ledState = false;
bool lastButtonState = HIGH;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

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

  // Detect button press (HIGH → LOW transition)
  if (lastButtonState == HIGH && buttonState == LOW) {
    ledState = !ledState;  // Toggle LED state
    digitalWrite(LED_PIN, ledState);

    Serial.print("LED toggled: ");
    Serial.println(ledState ? "ON" : "OFF");

    delay(50);  // Debounce
  }

  lastButtonState = buttonState;
}

Penjelasan:

  • lastButtonState = State button sebelumnya
  • Hanya toggle saat transisi HIGH → LOW (button ditekan)
  • Mencegah multiple toggle dari satu press

Project: Traffic Light

Sekarang kita buat traffic light sederhana dengan 3 LED (Red, Yellow, Green) dan button untuk start cycle.

Hardware Setup:

Red LED    → GPIO 4  ──┬─── LED ─── 220Ω ─── GND
Yellow LED → GPIO 16 ──┤
Green LED  → GPIO 17 ──┘

Button     → GPIO 5  ─── Button ─── GND

Code:

// Pin definitions
#define RED_LED    4
#define YELLOW_LED 16
#define GREEN_LED  17
#define BUTTON_PIN 5

bool isRunning = false;

void setup() {
  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  Serial.begin(115200);
  Serial.println("Traffic Light Ready!");
}

void loop() {
  // Check button press
  if (digitalRead(BUTTON_PIN) == LOW) {
    isRunning = !isRunning;
    Serial.println(isRunning ? "Traffic Light START" : "Traffic Light STOP");
    delay(300);  // Debounce
  }

  if (isRunning) {
    trafficLightCycle();
  } else {
    // Turn off all LEDs
    digitalWrite(RED_LED, LOW);
    digitalWrite(YELLOW_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
  }
}

void trafficLightCycle() {
  // Red light (Stop)
  digitalWrite(RED_LED, HIGH);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  Serial.println("🔴 RED - STOP");
  delay(5000);  // 5 seconds

  // Yellow light (Ready)
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
  Serial.println("🟡 YELLOW - READY");
  delay(2000);  // 2 seconds

  // Green light (Go)
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  Serial.println("🟢 GREEN - GO");
  delay(5000);  // 5 seconds

  // Yellow light again before red
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
  Serial.println("🟡 YELLOW - SLOW DOWN");
  delay(2000);  // 2 seconds
}

Multiple Buttons: LED Controller

Sekarang kita tambahkan 3 buttons untuk kontrol masing-masing LED:

Hardware Setup:

Button 1 → GPIO 5  ─── Button ─── GND  (Control Red LED)
Button 2 → GPIO 18 ─── Button ─── GND  (Control Yellow LED)
Button 3 → GPIO 19 ─── Button ─── GND  (Control Green LED)

Code:

// LED pins
#define RED_LED    4
#define YELLOW_LED 16
#define GREEN_LED  17

// Button pins
#define BUTTON_RED    5
#define BUTTON_YELLOW 18
#define BUTTON_GREEN  19

// LED states
bool redState = false;
bool yellowState = false;
bool greenState = false;

void setup() {
  // Set LED pins as output
  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);

  // Set button pins as input with pull-up
  pinMode(BUTTON_RED, INPUT_PULLUP);
  pinMode(BUTTON_YELLOW, INPUT_PULLUP);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);

  Serial.begin(115200);
}

void loop() {
  // Check Red button
  if (digitalRead(BUTTON_RED) == LOW) {
    redState = !redState;
    digitalWrite(RED_LED, redState);
    Serial.println("Red LED: " + String(redState ? "ON" : "OFF"));
    delay(300);
  }

  // Check Yellow button
  if (digitalRead(BUTTON_YELLOW) == LOW) {
    yellowState = !yellowState;
    digitalWrite(YELLOW_LED, yellowState);
    Serial.println("Yellow LED: " + String(yellowState ? "ON" : "OFF"));
    delay(300);
  }

  // Check Green button
  if (digitalRead(BUTTON_GREEN) == LOW) {
    greenState = !greenState;
    digitalWrite(GREEN_LED, greenState);
    Serial.println("Green LED: " + String(greenState ? "ON" : "OFF"));
    delay(300);
  }
}

Advanced: Array untuk Multiple GPIOs

Jika punya banyak LED/button, pakai array untuk code lebih clean:

// Array of LED pins
int ledPins[] = {4, 16, 17, 18, 19, 21};
int numLeds = 6;

void setup() {
  // Initialize all LED pins
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
  }
}

void loop() {
  // Knight Rider effect
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(100);
    digitalWrite(ledPins[i], LOW);
  }

  // Reverse direction
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(100);
    digitalWrite(ledPins[i], LOW);
  }
}

Tips & Best Practices

1. Pull-up vs Pull-down

// Internal Pull-up (recommended)
pinMode(BUTTON_PIN, INPUT_PULLUP);  // Default HIGH, press = LOW

// Internal Pull-down (jika tersedia)
pinMode(BUTTON_PIN, INPUT_PULLDOWN);  // Default LOW, press = HIGH

// No pull (butuh external resistor)
pinMode(BUTTON_PIN, INPUT);  // Floating, tidak stabil!

2. Debouncing yang Lebih Baik

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void loop() {
  int reading = digitalRead(BUTTON_PIN);

  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
      // Do something
    }
  }

  lastButtonState = reading;
}

3. Non-blocking Code

Hindari delay() yang lama:

unsigned long previousMillis = 0;
const long interval = 1000;

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    // Do something every 1 second
  }

  // Code lain tetap jalan
}

Troubleshooting

Button Tidak Responsive

  • ❌ Lupa INPUT_PULLUP
  • ❌ Wiring salah
  • ❌ Button rusak

LED Flicker

  • ❌ Debounce delay terlalu kecil
  • ❌ Power supply tidak stabil

Multiple LED Redup

  • ❌ Power tidak cukup dari USB
  • ❌ Terlalu banyak LED parallel

Solusi: Pakai external power supply 5V

Challenge Projects! 🎯

Challenge 1: Dice Roll

Buat 6 LED yang menyala random saat button ditekan (simulasi dadu).

Challenge 2: Simon Says Game

Buat game memory dengan 4 LED dan 4 button. LED blink dalam urutan random, user harus ikuti urutannya.

Challenge 3: Password Lock

Buat sistem “password” dengan 4 button. User harus tekan button dalam urutan benar untuk nyalakan LED.

Kesimpulan

Sekarang Anda sudah bisa:

✅ Menggunakan GPIO sebagai INPUT dengan pull-up ✅ Read button state dengan digitalRead() ✅ Membuat toggle button ✅ Kontrol multiple LEDs ✅ Debouncing untuk button stability ✅ Membuat project traffic light ✅ Non-blocking code dengan millis()

Next Steps

Dari sini, Anda bisa explore:

  • PWM untuk kontrol brightness/motor speed
  • Analog Input untuk read sensor (temperature, light, potentiometer)
  • WiFi untuk IoT projects
  • Bluetooth untuk wireless control
  • I2C/SPI untuk sensor dan display modules

Selamat! Anda sudah menguasai fundamental ESP32! 🎉


Previous: ← Chapter 3 - Program Pertama

Tutorial Selesai! Lanjut explore ESP32 lebih dalam atau cek tutorial lainnya.