/*
* MODUL PRAKTIKUM: SMART HOME IoT DENGAN ESP32 & BLYNK
* Deskripsi: Program ini mengintegrasikan berbagai sensor dan aktuator
* untuk menciptakan sistem rumah pintar yang dapat dimonitor dan dikontrol
* melalui aplikasi Blynk.
* * Fitur:
* - Monitoring Suhu & Kelembapan (DHT11)
* - Deteksi Gas (MQ-6)
* - Deteksi Api (Flame Sensor)
* - Deteksi Hujan (Raindrop Sensor)
* - Kontrol Pintu Otomatis (Ultrasonic & Servo)
* - Kontrol Lampu Otomatis (LDR & Relay)
* - Notifikasi & Kontrol via Blynk dengan mode Manual/Otomatis
*/
// Definisi untuk Blynk (JANGAN UBAH)
#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "TMPxxxxxxxxx" // Ganti dengan Template ID Blynk Anda
#define BLYNK_TEMPLATE_NAME "Smart Home ESP32" // Ganti dengan Nama Template Blynk Anda
// Library yang dibutuhkan
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <ESP32Servo.h>
// --- KONFIGURASI BLYNK & WIFI ---
char auth[] = "MASUKKAN_AUTH_TOKEN_ANDA"; // Ganti dengan Auth Token dari email Blynk
char ssid[] = "NAMA_WIFI_ANDA"; // Ganti dengan SSID WiFi Anda
char pass[] = "PASSWORD_WIFI_ANDA"; // Ganti dengan password WiFi Anda
// --- DEFINISI PIN ---
// Sensor
#define DHT_PIN 4 // Pin data DHT11
#define MQ6_PIN 34 // Pin analog AOUT MQ-6
#define FLAME_PIN 18 // Pin digital DO Flame Sensor
#define RAIN_PIN 19 // Pin digital DO Raindrop Sensor
#define TRIG_PIN 5 // Pin Trig HC-SR04
#define ECHO_PIN 17 // Pin Echo HC-SR04
#define LDR_PIN 35 // Pin analog LDR
// Aktuator
#define BUZZER_PIN 23 // Pin Buzzer
#define SERVO_PIN 13 // Pin sinyal Servo
#define RELAY_SUHU_PIN 26 // Pin Relay untuk kontrol suhu (misal: kipas)
#define RELAY_LAMPU_PIN 27 // Pin Relay untuk lampu
// --- INISIALISASI OBJEK ---
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C mungkin 0x3F, sesuaikan jika perlu
DHT dht(DHT_PIN, DHT11);
Servo servoPintu;
BlynkTimer timer;
// --- VARIABEL GLOBAL ---
// Nilai Sensor
float temperature = 0.0;
float humidity = 0.0;
int gasValue = 0;
bool isFlameDetected = false;
bool isRainDetected = false;
long duration;
int distance;
int ldrValue = 0;
// Variabel Kontrol & Status
bool isManualMode_Suhu = false; // false = Otomatis, true = Manual
bool isManualMode_Lampu = false; // false = Otomatis, true = Manual
bool isDoorOpen = false; // Status pintu (servo)
// Thresholds (Ambang Batas)
const int SUHU_THRESHOLD = 33; // Suhu (C) untuk menyalakan relay
const int GAS_THRESHOLD = 700; // Nilai analog MQ6 untuk peringatan gas
const int LDR_THRESHOLD = 1500; // Nilai LDR untuk menyalakan lampu (gelap)
const int JARAK_PINTU_THRESHOLD = 10; // Jarak (cm) untuk membuka pintu
// Variabel untuk timing tanpa delay
unsigned long lastWarningTime = 0;
const long warningCooldown = 5000; // Cooldown 5 detik untuk peringatan buzzer
// --- FUNGSI KONTROL VIA BLYNK ---
// Tombol Mode Relay Suhu (Otomatis/Manual)
BLYNK_WRITE(V10) {
isManualMode_Suhu = param.asInt(); // 0 untuk Otomatis, 1 untuk Manual
if (isManualMode_Suhu) {
Blynk.virtualWrite(V11, digitalRead(RELAY_SUHU_PIN));
Serial.println("Mode Relay Suhu: MANUAL");
} else {
Serial.println("Mode Relay Suhu: OTOMATIS");
}
}
// Tombol Switch Manual Relay Suhu
BLYNK_WRITE(V11) {
if (isManualMode_Suhu) {
digitalWrite(RELAY_SUHU_PIN, param.asInt());
}
}
// Tombol Mode Lampu (Otomatis/Manual)
BLYNK_WRITE(V12) {
isManualMode_Lampu = param.asInt(); // 0 untuk Otomatis, 1 untuk Manual
if (isManualMode_Lampu) {
Blynk.virtualWrite(V13, digitalRead(RELAY_LAMPU_PIN));
Serial.println("Mode Lampu: MANUAL");
} else {
Serial.println("Mode Lampu: OTOMATIS");
}
}
// Tombol Switch Manual Lampu
BLYNK_WRITE(V13) {
if (isManualMode_Lampu) {
digitalWrite(RELAY_LAMPU_PIN, param.asInt());
}
}
// Tombol Buka/Tutup Pintu
BLYNK_WRITE(V14) {
if(param.asInt() == 1) {
if (isDoorOpen) {
servoPintu.write(0); // Tutup pintu
isDoorOpen = false;
Serial.println("Pintu ditutup manual");
} else {
servoPintu.write(90); // Buka pintu
isDoorOpen = true;
Serial.println("Pintu dibuka manual");
}
}
}
// --- FUNGSI UTAMA ---
void setup() {
Serial.begin(115200);
// Inisialisasi pin mode
pinMode(BUZZER_PIN, OUTPUT);
pinMode(RELAY_SUHU_PIN, OUTPUT);
pinMode(RELAY_LAMPU_PIN, OUTPUT);
pinMode(FLAME_PIN, INPUT);
pinMode(RAIN_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// Set kondisi awal aktuator
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RELAY_SUHU_PIN, LOW);
digitalWrite(RELAY_LAMPU_PIN, LOW);
// Inisialisasi komponen
dht.begin();
servoPintu.attach(SERVO_PIN);
servoPintu.write(0); // Posisi awal pintu tertutup
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Sistem SmartHome");
lcd.setCursor(0, 1);
lcd.print("Menyambungkan...");
// Koneksi ke Blynk
Blynk.begin(auth, ssid, pass);
// Setup timer untuk menjalankan fungsi secara periodik
timer.setInterval(2000L, sendSensorDataToBlynk); // Kirim data ke Blynk setiap 2 detik
timer.setInterval(500L, runAutomation); // Jalankan logika otomatis setiap 0.5 detik
timer.setInterval(1000L, updateDisplay); // Update LCD setiap 1 detik
}
void loop() {
Blynk.run();
timer.run();
}
// --- FUNGSI-FUNGSI BANTU ---
void readAllSensors() {
// Baca DHT11
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Gagal membaca dari DHT11!");
return;
}
// Baca sensor lainnya
gasValue = analogRead(MQ6_PIN);
isFlameDetected = digitalRead(FLAME_PIN) == LOW; // Sensor aktif LOW
isRainDetected = digitalRead(RAIN_PIN) == LOW; // Sensor aktif LOW
ldrValue = analogRead(LDR_PIN);
// Baca HC-SR04
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH);
distance = duration * 0.034 / 2;
}
// Fungsi ini mengirim data ke Blynk
void sendSensorDataToBlynk() {
Blynk.virtualWrite(V0, temperature);
Blynk.virtualWrite(V1, humidity);
Blynk.virtualWrite(V2, gasValue);
Blynk.virtualWrite(V3, isFlameDetected ? 255 : 0); // Nyalakan LED virtual
Blynk.virtualWrite(V4, gasValue > GAS_THRESHOLD ? 255 : 0);
Blynk.virtualWrite(V5, isRainDetected ? 255 : 0);
}
// Fungsi ini menjalankan semua logika otomatis
void runAutomation() {
readAllSensors(); // Baca semua sensor terlebih dahulu
// --- Logika Otomatisasi ---
// 1. Kontrol Relay Suhu
if (!isManualMode_Suhu) {
if (temperature > SUHU_THRESHOLD) {
digitalWrite(RELAY_SUHU_PIN, HIGH); // Nyalakan kipas/pendingin
} else {
digitalWrite(RELAY_SUHU_PIN, LOW); // Matikan
}
Blynk.virtualWrite(V11, digitalRead(RELAY_SUHU_PIN));
}
// 2. Kontrol Relay Lampu
if (!isManualMode_Lampu) {
if (ldrValue > LDR_THRESHOLD) { // Asumsi nilai LDR tinggi saat gelap
digitalWrite(RELAY_LAMPU_PIN, HIGH); // Nyalakan lampu
} else {
digitalWrite(RELAY_LAMPU_PIN, LOW); // Matikan
}
Blynk.virtualWrite(V13, digitalRead(RELAY_LAMPU_PIN));
}
// 3. Peringatan Bahaya (Api & Gas)
bool isDanger = isFlameDetected || (gasValue > GAS_THRESHOLD);
if (isDanger && (millis() - lastWarningTime > warningCooldown)) {
digitalWrite(BUZZER_PIN, HIGH);
delay(1000); // Buzzer berbunyi selama 1 detik
digitalWrite(BUZZER_PIN, LOW);
lastWarningTime = millis(); // Reset timer cooldown
}
// 4. Kontrol Servo Jendela (saat hujan)
if (isRainDetected) {
servoPintu.write(0); // Tutup jendela/pintu saat hujan
isDoorOpen = false;
}
// 5. Kontrol Servo Pintu (sensor jarak)
if (!isRainDetected) { // Jangan buka pintu jika hujan
if (distance < JARAK_PINTU_THRESHOLD && !isDoorOpen) {
servoPintu.write(90); // Buka pintu
isDoorOpen = true;
Serial.println("Pintu terbuka otomatis");
} else if (distance >= JARAK_PINTU_THRESHOLD && isDoorOpen) {
// Opsi: bisa ditambahkan logika menutup otomatis setelah beberapa waktu
}
}
}
// Fungsi ini mengupdate tampilan LCD
void updateDisplay() {
lcd.clear();
// Peringatan prioritas utama
if (isFlameDetected) {
lcd.setCursor(0, 0);
lcd.print("AWAS ADA API! ");
lcd.setCursor(0, 1);
lcd.print("SEGERA EVAKUASI!");
} else if (gasValue > GAS_THRESHOLD) {
lcd.setCursor(0, 0);
lcd.print("!! GAS BOCOR !!");
lcd.setCursor(0, 1);
lcd.print("Nilai: ");
lcd.print(gasValue);
} else {
// Tampilan default
lcd.setCursor(0, 0);
lcd.print("Suhu: ");
lcd.print(temperature, 1);
lcd.print((char)223); // Simbol derajat
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Lembap: ");
lcd.print(humidity, 1);
lcd.print("%");
}
}