- Published on
Interrupt dan Tombol
- Authors
π Modul 5 β Interrupt dan Tombol
- π§ Prolog Modul: Posisi dan Peran Modul 5
- π§ Konteks Pengetahuan: Relasi Antar Modul
- π― Tujuan Modul (Learning Objectives)
- π§© Masalah yang Diselesaikan Modul Ini
- ποΈ Konsep Inti yang Diperkenalkan
- π οΈ Desain Teknis & Arsitektur
- π§ͺ Implementasi Bertahap (High-Level)
- π§Ύ Validasi dan Pengujian
- π Refleksi dan Keterkaitan ke Modul Lain
- π§ Navigasi Modul
- π Penutup Analitis
Baik. Berikut penulisan Prolog Modul 5 dengan gaya teknis, disiplin, dan langsung ke konteks, tanpa pengantar naratif tambahan.
π§ Prolog Modul: Posisi dan Peran Modul 5
Modul 5 menandai peralihan arsitektural dari firmware yang sinkron dan berbasis polling menuju firmware yang mampu menangani event asinkron secara deterministik. Setelah Modul 4 menetapkan struktur sistem melalui ComponentBase, modul ini memperkenalkan interrupt sebagai mekanisme utama untuk merespons kejadian eksternal.
Pada tahap ini, firmware telah tersusun rapi dan modular, namun masih bergantung pada eksekusi berurutan di dalam loop(). Pendekatan tersebut tidak memadai untuk input fisik yang membutuhkan respons cepat dan konsisten. Modul 5 melengkapi arsitektur dengan integrasi ISR (Interrupt Service Routine) yang dirancang aman, minimal, dan terpisah dari logika aplikasi.
Fokus modul ini adalah memastikan bahwa event asinkron dapat diproses tanpa merusak kontrak komponen, tanpa menambah kompleksitas di firmware.ino, dan tanpa mengorbankan stabilitas sistem. Dengan demikian, interrupt menjadi bagian yang terkontrol dalam arsitektur firmware modular, bukan pengecualian yang merusak desain.
π§ Konteks Pengetahuan: Relasi Antar Modul
π Prasyarat Konseptual
Modul 4 β ComponentBase Wajib paham:
- kontrak
begin()/update() - pengelolaan komponen via pointer base class
- kontrak
Modul 2 β LED Modular dengan Class LED digunakan sebagai target aksi event tombol (tidak ada desain LED baru di modul ini)
Tanpa dua modul ini, integrasi interrupt tidak valid secara arsitektur.
π Digunakan Kembali di Modul Selanjutnya
Konsep di Modul 5 dipakai langsung pada:
- Modul 6 β Sensor Modular
- Modul 7 β Actuator Modular
- Modul 8 β MQTT Integration
Yang dibawa ke depan:
- event β state
- sinkronisasi data
- pemisahan event dan aksi
π― Tujuan Modul (Learning Objectives)
Setelah Modul 5, pembaca harus bisa:
- Membedakan polling vs interrupt secara praktis
- Menjelaskan fungsi ISR dan batasannya
- Menggunakan
volatileuntuk data lintas ISR - Menggunakan
staticpada konteks ISR dengan benar - Mendesain handler tombol berbasis interrupt
- Menghubungkan event interrupt ke arsitektur
ComponentBase
Jika salah satu tidak tercapai β modul gagal.
π§© Masalah yang Diselesaikan Modul Ini
Masalah polling input fisik:
- Respons bergantung ke kecepatan
loop() loop()membengkak dan sulit dirawat- Tidak efisien untuk banyak input
- Mengganggu proses lain (sensor / komunikasi)
Solusi Modul 5:
- Input ditangani dengan interrupt
- ISR hanya mengubah flag
- Logika aplikasi tetap di
loop() - Firmware tetap non-blocking
ποΈ Konsep Inti yang Diperkenalkan
Konsep Utama
- Interrupt dan ISR
volatileuntuk data yang diubah ISRstaticuntuk state lokal ISR- Event flag
- Deferred processing (ISR β logic)
Konsep yang Tidak Dibahas
- Sensor kompleks
- Actuator selain LED
- MQTT
- RTOS / multitasking
Scope modul ini hanya event handling dasar.
π οΈ Desain Teknis & Arsitektur
Aturan desain wajib:
ISR:
- singkat
- tanpa logika bisnis
- tanpa
delay - tanpa alokasi memori
ISR hanya:
- set/reset flag (
volatile)
- set/reset flag (
Aksi:
- dilakukan di
loop()/update()
- dilakukan di
Peran class tombol:
- Mendaftarkan interrupt
- Menyediakan event (flag)
- Tidak mengendalikan actuator langsung
Hasil desain:
- Interrupt tidak merusak
ComponentBase - Modularitas tetap utuh
- Event terintegrasi ke sistem, bukan pengecualian
π§ͺ Implementasi Bertahap (High-Level)
Di bawah ini adalah implementasi rinci, detail, dan siap compile untuk ESP32/ESP8266 (Arduino IDE). Tidak ada teoriβhanya langkah dan artefak kode.
0) Struktur Folder (artefak yang harus ada)
firmware/
βββ ComponentBase.h
βββ LedController.h
βββ LedController.cpp
βββ ButtonHandler.h
βββ ButtonHandler.cpp
βββ firmware.ino
ComponentBase.hAnda pakai dari Modul 4 (kontrakbegin()/update()).
1. Identifikasi kebutuhan input berbasis event
Kebutuhan minimal yang harus dipenuhi:
- Tombol memicu event tanpa polling.
- ISR tidak menjalankan logic aplikasi.
- ISR hanya set flag.
- Pemrosesan event dilakukan di
update()(deferred processing). - Tidak boleh ada
delay()untuk respon tombol.
Artefak: akan diwujudkan sebagai ButtonHandler (komponen) + event flag.
2. Konfigurasi pin dan interrupt
Konvensi wiring (stabil dan umum)
- Gunakan INPUT_PULLUP (tombol ke GND).
- Event dianggap terjadi saat FALLING.
Parameter:
buttonPin= GPIO tombol- Interrupt attach:
attachInterrupt(digitalPinToInterrupt(pin), isr, FALLING)
3. Penulisan ISR minimal
ISR wajib:
- sangat singkat
- tidak ada
Serial - tidak ada
delay - tidak ada alokasi memori
- hanya set flag dan (opsional) timestamp
Kita buat macro atribut ISR agar kompatibel:
- ESP32:
IRAM_ATTR - ESP8266:
ICACHE_RAM_ATTR
4. Penggunaan volatile flag
Flag yang diubah ISR harus volatile agar compiler tidak mengoptimasi salah.
Kita pakai:
volatile bool _irqFlag;volatile uint32_t _irqUs;(timestamp microseconds saat interrupt)
5. Desain class ButtonHandler
ButtonHandler.h
#ifndef BUTTON_HANDLER_H
#define BUTTON_HANDLER_H
#include <Arduino.h>
#include "ComponentBase.h"
// ISR attribute compatibility
#if defined(ESP32)
#define ISR_ATTR IRAM_ATTR
#elif defined(ESP8266)
#define ISR_ATTR ICACHE_RAM_ATTR
#else
#define ISR_ATTR
#endif
class ButtonHandler : public ComponentBase {
public:
using Callback = void (*)();
ButtonHandler(uint8_t pin, Callback onPress, uint32_t debounceMs = 50);
void begin() override;
void update() override;
// ISR must be static
static void ISR_ATTR isrRouter();
private:
uint8_t _pin;
Callback _onPress;
uint32_t _debounceMs;
// ISR-shared state
static volatile bool _irqFlag;
static volatile uint32_t _irqUs;
// instance pointer for static ISR routing (single-button version)
static ButtonHandler* _instance;
// runtime state
uint32_t _lastHandledMs = 0;
void handleIrqDeferred();
};
#endif
ButtonHandler.cpp
#include "ButtonHandler.h"
// static members
volatile bool ButtonHandler::_irqFlag = false;
volatile uint32_t ButtonHandler::_irqUs = 0;
ButtonHandler* ButtonHandler::_instance = nullptr;
ButtonHandler::ButtonHandler(uint8_t pin, Callback onPress, uint32_t debounceMs)
: _pin(pin), _onPress(onPress), _debounceMs(debounceMs) {}
void ButtonHandler::begin() {
pinMode(_pin, INPUT_PULLUP);
// register instance for ISR routing (single instance)
_instance = this;
attachInterrupt(digitalPinToInterrupt(_pin), ButtonHandler::isrRouter, FALLING);
}
void ButtonHandler::update() {
handleIrqDeferred();
}
void ButtonHandler::handleIrqDeferred() {
// Fast check first (no lock)
if (!_irqFlag) return;
// Critical section to read+clear flag safely
noInterrupts();
bool flagged = _irqFlag;
_irqFlag = false;
interrupts();
if (!flagged) return;
// Debounce in main context (NOT in ISR)
uint32_t nowMs = millis();
if (nowMs - _lastHandledMs < _debounceMs) return;
_lastHandledMs = nowMs;
if (_onPress) _onPress();
}
void ButtonHandler::ISR_ATTR isrRouter() {
// Minimal ISR: set flag + timestamp
_irqUs = micros();
_irqFlag = true;
}
Catatan: versi ini single-button (1 instance) untuk menjaga modul tetap fokus. Multi-button akan dibahas saat arsitektur makin matang.
6. Integrasi event tombol dengan LED
Agar event tombol mengubah LED, kita buat LedController sebagai komponen yang:
begin()melakukan inisialisasi hardwareupdate()kosong (LED tidak perlu polling)- menyediakan
toggle()untuk dipanggil dari callback tombol
LedController.h(Modul 5)
#ifndef LED_CONTROLLER_H
#define LED_CONTROLLER_H
#include <Arduino.h>
#include "ComponentBase.h"
class LedController : public ComponentBase {
public:
LedController(uint8_t pin, bool initialState = false);
void begin() override;
void update() override;
void on();
void off();
void toggle();
bool isOn() const;
private:
uint8_t _pin;
bool _state;
};
#endif
LedController.cpp(Modul 5)
#include "LedController.h"
LedController::LedController(uint8_t pin, bool initialState)
: _pin(pin), _state(initialState) {}
void LedController::begin() {
pinMode(_pin, OUTPUT);
digitalWrite(_pin, _state ? HIGH : LOW);
}
void LedController::update() {
// LED tidak butuh loop/polling pada Modul 5
}
void LedController::on() {
_state = true;
digitalWrite(_pin, HIGH);
}
void LedController::off() {
_state = false;
digitalWrite(_pin, LOW);
}
void LedController::toggle() {
_state = !_state;
digitalWrite(_pin, _state ? HIGH : LOW);
}
bool LedController::isOn() const {
return _state;
}
7. Validasi non-blocking behavior
firmware.ino(FINAL, UTUH, SIAP COPAS)
#include <Arduino.h>
#include "ComponentBase.h"
#include "LedController.h"
#include "ButtonHandler.h"
// ====== Konfigurasi pin ======
static const uint8_t LED_PIN = 2; // sesuaikan board Anda
static const uint8_t BTN_PIN = 0; // contoh: GPIO0 (sesuaikan wiring)
// ====== Komponen ======
LedController led(LED_PIN, false);
// Callback harus fungsi bebas / static
void onButtonPressed() {
led.toggle();
}
ButtonHandler button(BTN_PIN, onButtonPressed, 50);
// ====== Registry komponen ======
ComponentBase* components[] = {
&led,
&button
};
const size_t COMPONENT_COUNT = sizeof(components) / sizeof(components[0]);
void setup() {
Serial.begin(115200);
delay(200);
for (size_t i = 0; i < COMPONENT_COUNT; i++) {
components[i]->begin();
}
Serial.println("Modul 5: Interrupt button -> LED toggle (non-blocking)");
}
void loop() {
// Tidak ada delay untuk tombol
for (size_t i = 0; i < COMPONENT_COUNT; i++) {
components[i]->update();
}
// Opsional: kerja lain bisa jalan di sini (sensor/MQTT) tanpa terganggu
}
β Checklist Validasi (WAJIB)
Tombol memicu LED
- Tekan tombol β LED toggle.
Respons cepat tanpa delay di loop
loop()tidak mengandungdelay().
ISR minimal
- Tidak ada
Serial, tidak adadelay, tidak ada logika toggle di ISR.
- Tidak ada
Stabil saat spam tombol
- Tekan cepat berulang β tidak hang/reset (debounce di
update()).
- Tekan cepat berulang β tidak hang/reset (debounce di
firmware.ino tidak mengandung logic hardware tombol/LED
- Tidak ada
digitalWrite, tidak adaattachInterruptdifirmware.ino.
- Tidak ada
π§Ύ Validasi dan Pengujian
Keberhasilan Modul 5 divalidasi melalui:
- Tombol fisik memicu perubahan state LED
- Respons cepat tanpa delay
- Firmware tetap stabil saat tombol ditekan berulang
- Tidak ada logika berat di dalam ISR
- Serial Monitor menunjukkan alur event yang benar
π Refleksi dan Keterkaitan ke Modul Lain
Kondisi firmware setelah Modul 5:
- Event eksternal (tombol) diproses secara asinkron melalui interrupt
- ISR dibatasi hanya untuk set flag
- Seluruh logika aplikasi tetap dijalankan di konteks normal (
update()) - Kontrak
ComponentBasetidak dilanggar firmware.inotetap berperan sebagai orchestrator, bukan tempat logika event
Implikasi langsung:
- Firmware aman terhadap event cepat dan berulang
- Tidak ada blocking behavior
- Sistem siap menangani banyak sumber event secara bersamaan
Konsep ini menjadi fondasi teknis wajib untuk:
- Modul 6 β Sensor Modular (data periodik + event)
- Modul 7 β Actuator Modular (aksi berbasis state dan event)
π§ Navigasi Modul
β¬ οΈ Modul sebelumnya β Modul 4: ComponentBase Menyediakan kontrak dan lifecycle komponen.
β‘οΈ Modul selanjutnya β Modul 6: Sensor Modular Memperluas arsitektur untuk menangani data sensor yang berjalan paralel dengan event.
π Penutup Analitis
Modul 5 menambahkan dimensi waktu dan event ke dalam firmware tanpa merusak struktur arsitektur. Setelah modul ini, firmware:
- tidak lagi bergantung pada polling,
- tidak bergantung pada delay,
- dan tidak terikat pada alur linier
loop().
Sistem kini mampu merespons dunia nyata secara asinkron dan terkontrol, yang merupakan prasyarat teknis untuk firmware IoT yang stabil dan dapat diskalakan.
Catatan Penyusunan Artikel ini disusun sebagai materi edukasi dan referensi umum berdasarkan berbagai sumber pustaka, praktik lapangan, serta bantuan alat penulisan. Pembaca disarankan untuk melakukan verifikasi lanjutan dan penyesuaian sesuai dengan kondisi serta kebutuhan masing-masing sistem.