# Case Study 1 Modul 5 (Software Timer & Hardware Interrupt) : Sinkronisasi ISR & Task dengan Queue dan Software Timer
## <span style="color:purple;">(SCREENSHOOT TIAP LANGKAH)</span>
```text
Nama: Ryan Adidaru
NPM: 2306266994
Group 22 :
1. Muhammad Raihan Mustofa
2. Ryan Adidaru
3. Muhammad Rafli
```
## Tujuan Praktikum
Setelah menyelesaikan praktikum ini, praktikan diharapkan mampu:
- Mengimplementasikan beberapa task FreeRTOS dengan `xTaskCreate()`.
- Menggunakan Hardware Interrupt (GPIO) untuk menangani event eksternal secara asinkron.
- Memahami dan mengimplementasikan FreeRTOS Queue sebagai mekanisme transfer data yang aman (thread-safe) antara ISR dan Task.
- Mengimplementasikan FreeRTOS Software Timer untuk tugas periodik di latar belakang.
- Mempraktikkan arsitektur producer-consumer yang event-driven dalam sistem RTOS.
### Konsep Sistem
Kita akan membangun sebuah "System Status Monitor". Sebuah Hardware Interrupt dari tombol akan bertindak sebagai producer yang mengirimkan "perintah" melalui sebuah Queue. Sebuah Task consumer akan menunggu perintah ini, dan setelah menerimanya, akan melakukan pekerjaan utama (membaca sensor DHT). Secara bersamaan, sebuah Software Timer akan menjalankan tugas latar belakang non-kritikal, yaitu mengedipkan LED sebagai indikator "heartbeat" bahwa sistem masih hidup.
## Kebutuhan
### Hardware
- 1 buah ESP32
- 1 buah sensor DHT11
- 1 buah LED (warna apa saja)
- 1 buah Push Button
- 1 buah Resistor 220 Ohm (untuk LED)
- Kabel Jumper secukupnya
- Breadboard
### Software
- Laptop dengan Arduino IDE
## Langkah - Langkah Praktikum
### Instruksi Umum
1. Buat Rangkaian: Hubungkan semua komponen ke ESP32 sesuai skema berikut:
- VCC/VIN DHT11 → 3V3 ESP32
- GND DHT11 → GND ESP32
- DATA DHT11 → GPIO 4 ESP32
- LED Anoda (+) → Resistor 220 Ohm → GPIO 2 ESP32
- Push Button → satu kaki ke GPIO 5, kaki lainnya ke GND ESP32
2. Buat Project Baru: Buka Arduino IDE dan buat sketch baru.
3. Setup Awal: Salin kerangka dasar di bawah ini ke sketch kalian. Ini berisi semua include dan definisi pin yang diperlukan.
```ino
#include <Arduino.h>
#include "DHT.h" // Pastikan library DHT terinstall
// --- Konfigurasi Pin Hardware ---
#define DHT_PIN 4
#define LED_PIN 2
#define BUTTON_PIN 5
#define DHT_TYPE DHT11
// Inisialisasi Sensor
DHT dht(DHT_PIN, DHT_TYPE);
// ... (Kerangka fungsi akan ditambahkan di bagian selanjutnya)
```
### Implementasi Arsitektur RTOS <span style="color:red;">(Total 50 Poin)</span>
```ino=
#include <Arduino.h>
#include "DHT22.h"
// --- Konfigurasi Pin Hardware ---
#define DHT_PIN 4
#define LED_PIN 2
#define BUTTON_PIN 5
#define DHT_TYPE DHT22
DHT22 dht(DHT_PIN);
// TODO 1: Deklarasikan Handle untuk RTOS Objects.
// Beri nama yang deskriptif, contoh: 'sensorCommandQueue' dan 'heartbeatTimer'.
QueueHandle_t sensorCommandQueue;
TimerHandle_t heartbeatTimer;
// ===== Interrupt Service Routine (ISR) =====
void IRAM_ATTR buttonISR() {
// TODO 2: Kirim sebuah pesan/data sederhana ke queue untuk memberi sinyal pada Task.
// Gunakan versi fungsi yang tepat untuk ISR.
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint8_t buttonPressed = 1;
xQueueSendFromISR(sensorCommandQueue, &buttonPressed, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// ===== Software Timer Callback =====
void heartbeatCallback(TimerHandle_t xTimer) {
// TODO 3: Buat logika untuk toggle kondisi LED.
static bool ledState = false;
ledState = !ledState;
digitalWrite(LED_PIN, ledState);
}
// ===== Task Utama =====
void sensorReaderTask(void *parameter) {
for (;;) { // Infinite loop untuk task
// TODO 4: Tunggu hingga ada data yang masuk ke queue dari ISR.
// Task harus dalam kondisi 'Blocked' saat menunggu untuk menghemat pemakaian CPU.
uint8_t receivedData;
if (xQueueReceive(sensorCommandQueue, &receivedData, portMAX_DELAY) == pdTRUE) {
// Setelah menerima sinyal dari queue, jalankan kode di bawah:
Serial.println("Perintah diterima! Membaca sensor...");
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Gagal membaca dari sensor DHT!");
} else {
Serial.printf("Suhu: %.2f °C, Kelembaban: %.2f %%\n", temperature, humidity);
}
}
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
// dht.begin();
Serial.println("--- Sistem Status Monitor RTOS ---");
Serial.println("Tekan tombol untuk memulai pembacaan sensor.");
// TODO 5: Inisialisasi semua komponen RTOS.
// Bagian ini adalah 'otak' dari konfigurasi sistem kalian, di mana semua komponen RTOS dihidupkan.
// 1. Buat Queue untuk menampung data dari ISR.
sensorCommandQueue = xQueueCreate(10, sizeof(uint8_t));
// 2. Buat Software Timer untuk 'heartbeat' LED.
heartbeatTimer = xTimerCreate("HeartbeatTimer", pdMS_TO_TICKS(1000), pdTRUE, (void*)0, heartbeatCallback);
// 3. Buat Task utama untuk membaca sensor.
xTaskCreate(sensorReaderTask, "SensorReader", 2048, NULL, 1, NULL);
// 4. Pasang ISR ke pin tombol.
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);
// 5. Start software timer yang telah dibuat.
if (heartbeatTimer != NULL) {
xTimerStart(heartbeatTimer, 0);
}
}
void loop() {
// Biarkan kosong, semua pekerjaan ditangani oleh RTOS.
vTaskDelay(portMAX_DELAY);
}
```
### Pengujian dan Analisis
#### 1. Demonstrasi Fungsional <span style="color:red;">(20 Poin)</span>
Setelah meng-upload kode yang telah kalian lengkapi ke board ESP32:
- <span style="color:red;">(10 Poin)</span> Ambil screenshot dari Serial Monitor yang menunjukkan pesan pembacaan suhu dan kelembaban muncul hanya setelah tombol ditekan.
- <span style="color:red;">(10 Poin)</span> Rekam video singkat yang membuktikan:
- LED "heartbeat" berkedip secara teratur dan konstan.
- Saat tombol ditekan, data sensor langsung muncul di Serial Monitor.
- Kedipan LED tidak berhenti atau terganggu saat tombol ditekan dan sensor sedang dibaca.


https://youtu.be/AOD2iC6MTiA
#### 2. Jelaskan mengapa Queue menjadi pilihan yang tepat untuk berkomunikasi antara ISR dan Task dalam kasus ini, dibandingkan hanya menggunakan variabel global biasa. Kaitkan jawaban Anda dengan konsep race condition. <span style="color:red;">(10 Poin)</span>
---
Dikarenakan jika menggunakan variabel global, ada resiko terjadinya Race condition, data corruption, etc. Sedangkan keuntungan jika kita memakaai Wueue pada kasus ini adalah ada Blocking functions, sehingga running task akan lebih efektif ketika menunggu data, dalam segi management CPU, etc,
Queue juga menjamin urutan data dengan sistem FIFO (First In, First Out) dan menyediakan buffering yang memungkinkan multiple signals dari ISR dapat disimpan tanpa hilang.
#### 3. Mengapa proses pembacaan sensor (`dht.read...`) harus ditempatkan di dalam `sensorReaderTask` dan BUKAN di dalam `buttonISR`? Sebutkan dan jelaskan minimal dua "Golden Rules of ISRs" yang mendukung keputusan desain ini. <span style="color:red;">(10 Poin)</span>
---
Pembacaan sensor DHT11 harus ditempatkan di Task karena melanggar dua golden rules utama.
- Golden Rule #1: Keep ISRs Short and Fast
ISR harus dieksekusi secepat mungkin karena menghentikan eksekusi normal processor dan dapat mendisable interrupt lain. Pembacaan DHT11 membutuhkan waktu sekitar 18ms untuk komunikasi 1-wire protocol, yang merupakan durasi yang sangat lama untuk sebuah ISR. Waktu yang lama ini dapat menyebabkan missed interrupts dari sumber lain, menurunkan system responsiveness, dan masalah yang lain.
- Golden Rule #2: No Blocking Operations in ISRs
ISR tidak boleh menggunakan fungsi yang dapat blocking atau menggunakan delay. Fungsi dht.readTemperature() dan dht.readHumidity() menggunakan delayMicroseconds() untuk timing protocol komunikasi, melakukan loop waiting untuk response dari sensor, dan komunikasi serial yang dapat gagal dan memerlukan retry. Operasi-operasi ini dapat menyebabkan ISR terjebak dalam blocking state yang berpotensi menyebabkan deadlock atau system hang. Dengan menempatkan pembacaan sensor di Task, operasi berat ini dapat dilakukan dengan aman tanpa mengganggu sistem interrupt, sementara ISR hanya bertugas mengirim sinyal cepat melalui queue.
#### 4. Jelaskan perbedaan tujuan dan cara kerja antara Hardware Interrupt (yang digunakan untuk tombol) dan Software Timer (yang digunakan untuk LED) dalam konteks praktikum ini. <span style="color:red;">(10 Poin)</span>
---
Hardware Interrupt digunakan untuk memberikan respons real-time terhadap event eksternal yang tidak terprediksi, yaitu penekanan tombol oleh user. Cara kerjanya adalah melalui sinyal falling edge yang langsung memicu interrupt controller untuk menghentikan eksekusi normal CPU dan melompat ke ISR secara asinkron. Hardware interrupt memiliki prioritas tinggi dan bersifat preemptive, artinya dapat menginterrupt task yang sedang berjalan kapan saja. Karakteristiknya adalah asynchronous, external-driven, dan non-deterministic timing karena bergantung sepenuhnya pada input user yang tidak dapat diprediksi.
Software Timer, di sisi lain, digunakan untuk menyediakan event berkala yang terjadwal dan predictable, yaitu LED heartbeat yang berkedip setiap detik sebagai indikator bahwa sistem masih hidup. Cara kerjanya dikelola secara internal oleh RTOS scheduler menggunakan system tick sebagai referensi waktu, dimana callback timer dipanggil dari timer service task bukan dari ISR context. Software timer bersifat synchronous dengan timing yang deterministic.