ESP32 & ESP8266

Panduan GPIO ESP32: Input, Output, PWM & Interrupt

Pelajari cara mengontrol pin GPIO ESP32 dari nol — dari menyalakan LED sampai mendeteksi tombol dan menghasilkan sinyal PWM untuk proyek dunia nyata

1. Apa Itu GPIO?

GPIO singkatan dari General-Purpose Input/Output, yaitu pin-pin pada mikrokontroler yang bisa dikonfigurasi secara fleksibel sebagai input (menerima sinyal dari luar) atau output (mengirim sinyal ke komponen eksternal). GPIO adalah jantung dari hampir semua proyek embedded — dari menyalakan LED sederhana sampai mengendalikan robot kompleks.

ESP32 memiliki hingga 34 pin GPIO yang dilabeli dari GPIO 0 sampai GPIO 39. Namun, tidak semua pin bisa digunakan secara bebas. Beberapa pin sudah dialokasikan untuk fungsi internal seperti flash memory, ADC internal, atau bootstrapping. Kita akan membahas detailnya di bagian pin mapping.

💡 Tips

Setiap pin GPIO ESP32 beroperasi pada level tegangan 3.3V. Jangan pernah memberikan tegangan 5V langsung ke pin GPIO — bisa merusak chip! Gunakan voltage divider atau level shifter jika perlu berkomunikasi dengan perangkat 5V.

Konsep Dasar GPIO
📥
Input Mode
Membaca sinyal dari tombol, sensor, saklar
📤
Output Mode
Menyalakan LED, relay, buzzer, motor
PWM Output
Sinyal pulsa untuk kecerahan/servo
🔔
Interrupt
Deteksi perubahan tanpa polling

2. Pin Mapping & Kapabilitas ESP32

Memahami pin mapping adalah langkah pertama sebelum mulai coding. Berikut tabel ringkasan pin GPIO ESP32 beserta kapabilitas dan batasannya:

Pin GPIO Fungsi Catatan
GPIO 0Input/OutputBootstrapping — harus LOW saat boot
GPIO 1TX0 (UART)Digunakan untuk serial output
GPIO 2Input/OutputLED bawaan pada beberapa board
GPIO 3RX0 (UART)Digunakan untuk serial input
GPIO 4–15Input/OutputGeneral purpose, aman digunakan
GPIO 6–11Flash SPI❌ JANGAN DIGUNAKAN — terhubung ke flash internal
GPIO 12Input/OutputBootstrapping — harus LOW saat boot
GPIO 13–19Input/OutputGeneral purpose, aman digunakan
GPIO 20–23Input/OutputGeneral purpose, aman digunakan
GPIO 25–26Input/Output + DACDAC1 dan DAC2
GPIO 27Input/OutputGeneral purpose
GPIO 32–33Input Only + ADCADC1_CH4 & ADC1_CH5
GPIO 34–39Input Only⚠️ Tidak bisa dikonfigurasi sebagai output
⚠️ Peringatan

GPIO 6–11 terhubung ke modul flash SPI internal. Menggunakan pin ini dapat menyebabkan crash atau brick pada ESP32. GPIO 34–39 hanya bisa sebagai input — tidak memiliki driver output internal. Selalu cek datasheet sebelum memilih pin!

3. Mode Output: Menyalakan LED

Mode OUTPUT digunakan ketika ESP32 perlu mengontrol komponen eksternal. Cara paling sederhana untuk memahami output adalah dengan menyalakan dan mematikan LED.

Konfigurasi Pin sebagai Output

Di Arduino framework, kita menggunakan fungsi pinMode() untuk mengatur arah pin, dan digitalWrite() untuk mengatur level HIGH (3.3V) atau LOW (0V):

// === Program Blink LED pada ESP32 ===
// Hubungkan LED ke GPIO 2 dengan resistor 220Ω

#define LED_PIN 2    // GPIO 2 (LED bawaan pada banyak board ESP32)

void setup() {
  pinMode(LED_PIN, OUTPUT);    // Atur GPIO 2 sebagai OUTPUT
}

void loop() {
  digitalWrite(LED_PIN, HIGH); // Nyalakan LED (3.3V)
  delay(1000);                 // Tunggu 1 detik
  digitalWrite(LED_PIN, LOW);  // Matikan LED (0V)
  delay(1000);                 // Tunggu 1 detik
}

Cara Kerja

  1. pinMode(LED_PIN, OUTPUT) — Mengkonfigurasi GPIO 2 sebagai output. Setelah ini, pin bisa mengeluarkan tegangan HIGH atau LOW.
  2. digitalWrite(LED_PIN, HIGH) — Mengatur pin ke 3.3V, LED menyala.
  3. digitalWrite(LED_PIN, LOW) — Mengatur pin ke 0V, LED mati.
  4. delay(1000) — Menunda eksekusi selama 1000 milidetik (1 detik).
💡 Tips — Resistor LED

Selalu gunakan resistor pembatas arus (220Ω–330Ω) secara seri dengan LED. Tanpa resistor, arus berlebih bisa merusak LED dan pin GPIO ESP32. Rumus: R = (Vsupply - VLED) / ILED

4. Mode Input: Membaca Tombol

Mode INPUT digunakan untuk membaca status dari komponen eksternal seperti tombol (push button), saklar (switch), atau sensor digital. Saat pin dikonfigurasi sebagai input, ESP32 akan membaca apakah pin tersebut dalam keadaan HIGH (3.3V) atau LOW (0V).

Skema Dasar Tombol

// === Membaca Tombol Push Button ===
// Tombol terhubung ke GPIO 4, LED ke GPIO 2

#define BUTTON_PIN 4
#define LED_PIN    2

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

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

  if (tombolState == LOW) {
    // Tombol ditekan (terhubung ke GND karena pull-up)
    digitalWrite(LED_PIN, HIGH);
    Serial.println("Tombol DITEKAN - LED ON");
  } else {
    // Tombol tidak ditekan
    digitalWrite(LED_PIN, LOW);
    Serial.println("Tombol dilepas - LED OFF");
  }

  delay(50);  // Debounce sederhana
}

Perhatikan penggunaan INPUT_PULLUP di atas — ini mengaktifkan resistor pull-up internal ESP32 sehingga pin secara default berada di HIGH saat tombol tidak ditekan. Saat tombol ditekan, pin terhubung ke GND dan pembacaan menjadi LOW. Ini akan dijelaskan lebih detail di bagian berikutnya.

5. Pull-Up & Pull-Down Resistor

Saat membaca tombol atau sensor digital, kita perlu memastikan pin GPIO selalu berada dalam keadaan yang terdefinisi (HIGH atau LOW), bahkan saat tombol tidak ditekan. Tanpa pull-up atau pull-down resistor, pin bisa mengambang (floating) dan menghasilkan pembacaan yang tidak stabil.

Apa Itu Pull-Up Resistor?

Pull-up resistor menghubungkan pin ke tegangan VCC (3.3V) secara default. Saat tombol tidak ditekan, pin terbaca HIGH. Saat tombol ditekan (terhubung ke GND), pin terbaca LOW.

Skema Pull-Up Resistor
🔋
3.3V (VCC)
Sumber tegangan
↓ R (10kΩ)
📍
Pin GPIO
Membaca HIGH default
↓ Tombol
⬇️
GND
LOW saat tombol ditekan

Apa Itu Pull-Down Resistor?

Kebalikan dari pull-up, pull-down resistor menghubungkan pin ke GND secara default. Saat tombol tidak ditekan, pin terbaca LOW. Saat tombol ditekan (terhubung ke VCC), pin terbaca HIGH.

Pull-Up Internal vs Eksternal

ESP32 memiliki resistor pull-up dan pull-down internal (sekitar 45kΩ) yang bisa diaktifkan melalui software. Ini sangat nyaman karena tidak perlu menambahkan resistor fisik:

// Mengaktifkan pull-up internal
pinMode(pin, INPUT_PULLUP);

// Mengaktifkan pull-down internal
pinMode(pin, INPUT_PULLDOWN);

// Input biasa (tanpa pull-up/pull-down, perlu resistor eksternal)
pinMode(pin, INPUT);
📋 Perbandingan Mode Input
Mode Resistor Default State Kapan Digunakan
INPUTTidak adaFloatingSudah ada resistor eksternal
INPUT_PULLUP~45kΩ ke VCCHIGHTombol aktif LOW (ke GND)
INPUT_PULLDOWN~45kΩ ke GNDLOWTombol aktif HIGH (ke VCC)

6. Interrupt: Deteksi Perubahan Tanpa Polling

Dalam program biasa, kita terus-menerus membaca pin GPIO di dalam loop() (disebut polling). Ini sederhana tapi boros CPU. Interrupt memungkinkan ESP32 bereaksi terhadap perubahan pada pin GPIO secara instan tanpa harus mengecek pin terus-menerus.

Kapan Menggunakan Interrupt?

Macam-Macam Trigger Interrupt

Trigger Keterangan
RISINGSaat sinyal berubah dari LOW ke HIGH
FALLINGSaat sinyal berubah dari HIGH ke LOW
CHANGESaat sinyal berubah apapun (LOW→HIGH atau HIGH→LOW)
LOWSelama sinyal dalam keadaan LOW
HIGHSelama sinyal dalam keadaan HIGH

Contoh: Interrupt pada Tombol

// === Interrupt untuk mendeteksi tombol ===
#define BUTTON_PIN 4
#define LED_PIN    2

volatile bool tombolPressed = false;  // volatile karena diubah di ISR

// ISR (Interrupt Service Routine) - harus sesingkat mungkin
void IRAM_ATTR onButtonPress() {
  tombolPressed = true;  // Hanya set flag, jangan Serial.print di sini!
}

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

  // Pasang interrupt pada FALLING edge (saat tombol ditekan)
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN),
                  onButtonPress,
                  FALLING);

  Serial.println("Interrupt siap. Tekan tombol!");
}

void loop() {
  if (tombolPressed) {
    tombolPressed = false;  // Reset flag
    digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle LED
    Serial.println("Tombol ditekan! LED ditoggle.");
  }

  // Program lain bisa jalan di sini tanpa terganggu polling
  delay(10);
}
⚠️ Aturan ISR

ISR (Interrupt Service Routine) harus sesingkat mungkin. Jangan gunakan Serial.print(), delay(), atau operasi berat lainnya di dalam ISR. Cukup set flag boolean dan proses di loop(). Gunakan keyword volatile untuk variabel yang diakses dari ISR. Gunakan IRAM_ATTR agar ISR ditempatkan di RAM untuk akses cepat.

7. PWM: Mengatur Kecerahan & Kecepatan Motor

PWM (Pulse Width Modulation) adalah teknik untuk meniru sinyal analog menggunakan sinyal digital. Dengan mengatur lebar pulsa (duty cycle), kita bisa mengontrol kecerahan LED, kecepatan motor, posisi servo, dan banyak lagi.

ESP32 memiliki peripheral LEDC (LED Control) yang sangat fleksibel dengan 16 channel PWM (0–15), frekuensi dan resolusi yang bisa diatur.

Cara Kerja PWM

Ilustrasi Duty Cycle PWM
◻️◻️◻️◻️◻️
25% Duty Cycle
LED redup / Motor lambat
◼️◼️◻️◻️◻️
50% Duty Cycle
LED setengah terang
◼️◼️◼️◼️◻️
75% Duty Cycle
LED terang
◼️◼️◼️◼️◼️
100% Duty Cycle
LED penuh / MAX

Kode PWM Sederhana

// === Mengatur Kecerahan LED dengan PWM ===
#define LED_PIN 2
#define PWM_CHANNEL 0
#define PWM_FREQ 5000     // Frekuensi 5 kHz
#define PWM_RESOLUTION 8  // Resolusi 8-bit (0-255)

void setup() {
  // Konfigurasi channel PWM
  ledcSetup(PWM_CHANNEL, PWM_FREQ, PWM_RESOLUTION);

  // Hubungkan channel PWM ke pin GPIO
  ledcAttachPin(LED_PIN, PWM_CHANNEL);
}

void loop() {
  // Nyalakan LED secara bertahap (fade in)
  for (int duty = 0; duty <= 255; duty++) {
    ledcWrite(PWM_CHANNEL, duty);
    delay(10);
  }

  // Matikan LED secara bertahap (fade out)
  for (int duty = 255; duty >= 0; duty--) {
    ledcWrite(PWM_CHANNEL, duty);
    delay(10);
  }
}

Parameter PWM ESP32

Parameter Nilai Keterangan
Channel0 – 1516 channel tersedia, bisa dipetakan ke pin manapun
Frekuensi1 Hz – 40 MHzServo: 50Hz, LED: 1-5kHz, Motor: 20kHz+
Resolusi1 – 16 bit8-bit = 0-255, 10-bit = 0-1023, 16-bit = 0-65535

8. Proyek: Lampu Lalu Lintas Otomatis

Sekarang kita gabungkan semua materi di atas ke dalam satu proyek nyata: simulasi lampu lalu linta dengan 3 LED (merah, kuning, hijau), tombol untuk mode manual, dan buzzer untuk pejalan kaki.

Skema Rangkaian

Komponen Pin GPIO Keterangan
LED MerahGPIO 25Dengan resistor 220Ω
LED KuningGPIO 26Dengan resistor 220Ω
LED HijauGPIO 27Dengan resistor 220Ω
Tombol Pejalan KakiGPIO 4INPUT_PULLUP (aktif LOW)
BuzzerGPIO 32PWM output untuk nada

Kode Program Lengkap

// ============================================
// PROYEK: Lampu Lalu Lintas Otomatis ESP32
// Fitur:
//   - 3 LED (merah, kuning, hijau) siklus otomatis
//   - Tombol pejalan kaki dengan interrupt
//   - Buzzer berbunyi saat hijau (pejalan kaki boleh jalan)
//   - Kode bersih dan terstruktur
// ============================================

// === PIN DEFINITIONS ===
#define LED_MERAH   25
#define LED_KUNING  26
#define LED_HIJAU   27
#define BTN_PEJALAN 4
#define BUZZER_PIN  32

// === PWM UNTUK BUZZER ===
#define BUZZER_CHANNEL 0
#define BUZZER_FREQ    1000  // 1 kHz
#define BUZZER_RES     8

// === DURASI DALAM MILIDETIK ===
#define WAKTU_HIJAU    5000   // 5 detik hijau
#define WAKTU_KUNING   2000   // 2 detik kuning
#define WAKTU_MERAH    5000   // 5 detik merah
#define WAKTU_BUZZER   500    // 0.5 detik buzzer

// === GLOBAL VARIABLES ===
volatile bool mintaPejalanKaki = false;
unsigned long lastDebounce = 0;

// === ISR: Tombol Pejalan Kaki ===
void IRAM_ATTR onPejalanPress() {
  unsigned long now = millis();
  if (now - lastDebounce > 300) {  // Debounce 300ms
    mintaPejalanKaki = true;
    lastDebounce = now;
  }
}

// === FUNGSI HELPER ===
void setLampu(bool merah, bool kuning, bool hijau) {
  digitalWrite(LED_MERAH, merah ? HIGH : LOW);
  digitalWrite(LED_KUNING, kuning ? HIGH : LOW);
  digitalWrite(LED_HIJAU, hijau ? HIGH : LOW);
}

void bunyibuzzer(int durasi, int freq) {
  ledcWriteTone(BUZZER_CHANNEL, freq);
  delay(durasi);
  ledcWriteTone(BUZZER_CHANNEL, 0);  // Matikan buzzer
}

void prosesPejalanKaki() {
  // Kedipkan LED merah dan bunyikan buzzer
  for (int i = 0; i < 3; i++) {
    setLampu(true, false, false);
    bunyibuzzer(WAKTU_BUZZER, 1500);
    setLampu(false, false, false);
    delay(300);
  }
  mintaPejalanKaki = false;  // Reset flag
}

void setup() {
  Serial.begin(115200);

  // Setup LED sebagai output
  pinMode(LED_MERAH, OUTPUT);
  pinMode(LED_KUNING, OUTPUT);
  pinMode(LED_HIJAU, OUTPUT);

  // Setup tombol dengan pull-up internal
  pinMode(BTN_PEJALAN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BTN_PEJALAN),
                  onPejalanPress, FALLING);

  // Setup buzzer PWM
  ledcSetup(BUZZER_CHANNEL, BUZZER_FREQ, BUZZER_RES);
  ledcAttachPin(BUZZER_PIN, BUZZER_CHANNEL);

  Serial.println("=== Sistem Lampu Lalu Lintas Aktif ===");
  Serial.println("Tekan tombol untuk mode pejalan kaki.");
}

void loop() {
  // FASE 1: HIJAU (kendaraan jalan)
  Serial.println("🟢 HIJAU - Kendaraan jalan");
  setLampu(false, false, true);
  unsigned long startHijau = millis();
  while (millis() - startHijau < WAKTU_HIJAU) {
    if (mintaPejalanKaki) {
      Serial.println("🚶 Pejalan kaki menekan tombol!");
      prosesPejalanKaki();
      break;  // Langsung ke fase kuning
    }
    delay(10);
  }

  // FASE 2: KUNING (bersiap berhenti)
  Serial.println("🟡 KUNING - Bersiap berhenti");
  setLampu(false, true, false);
  delay(WAKTU_KUNING);

  // FASE 3: MERAH (kendaraan berhenti)
  Serial.println("🔴 MERAH - Kendaraan berhenti");
  setLampu(true, false, false);
  delay(WAKTU_MERAH);
}
📋 Penjelasan Kode

Program ini menggunakan interrupt pada tombol pejalan kaki agar responsif kapan saja. Fungsi IRAM_ATTR memastikan ISR ada di RAM. Flag volatile bool menandakan tombol ditekan, kemudian diproses di loop(). PWM digunakan untuk menghasilkan nada buzzer. Siklus lampu berjalan otomatis dan bisa diinterupsi oleh tombol.

9. Tips & Peringatan Penting

Tips / Peringatan Penjelasan
⚠️ Jangan pakai GPIO 6-11 Pin ini terhubung ke flash SPI internal. Menggunakannya bisa crash atau brick ESP32.
⚠️ GPIO 34-39 input only Tidak bisa dikonfigurasi sebagai output, tidak punya pull-up/pull-down internal.
💡 Gunakan LEDC untuk PWM Jangan gunakan analogWrite() — ESP32 tidak mendukungnya. Gunakan fungsi ledcSetup() dan ledcWrite().
💡 Debounce tombol Tombol fisik menghasilkan noise saat ditekan. Selalu gunakan debounce (software atau hardware) untuk pembacaan yang stabil.
⚠️ Arus maksimum GPIO Setiap pin GPIO ESP32 maksimum mendorong 12mA (rekomendasi 6mA). Untuk mengendalikan motor atau LED strip, gunakan transistor atau MOSFET.
💡 Serial Monitor Gunakan Serial.begin(115200) untuk debug. Ini sangat membantu saat troubleshooting masalah GPIO.

10. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang GPIO ESP32:

Pertanyaan 1: Berapa jumlah pin GPIO yang dimiliki ESP32?

a) 20 pin
b) 34 pin
c) 40 pin
d) 26 pin

Pertanyaan 2: Pin GPIO mana yang TIDAK BOLEH digunakan karena terhubung ke flash internal?

a) GPIO 0–5
b) GPIO 6–11
c) GPIO 32–33
d) GPIO 34–39

Pertanyaan 3: Apa fungsi keyword volatile pada variabel yang diakses dari ISR?

a) Menghapus variabel dari memori
b) Mencegah compiler mengoptimasi akses ke variabel tersebut
c) Mengatur ulang variabel ke nol otomatis
d) Mengubah tipe data variabel menjadi integer

Pertanyaan 4: Fungsi apa yang digunakan untuk mengatur PWM pada ESP32 dengan Arduino framework?

a) analogWrite()
b) pwmWrite()
c) ledcWrite()
d) digitalWrite()

Pertanyaan 5: Saat menggunakan INPUT_PULLUP, apa state default dari pin saat tombol tidak ditekan?

a) LOW (0V)
b) HIGH (3.3V)
c) Floating (tidak tentu)
d) 1.65V (setengah tegangan)
← Sebelumnya Panduan Lengkap ESP32 Selanjutnya → Artikel Lainnya