#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h> // Library LCD
const int RAIN_ANALOG = 34; // Pin untuk sensor hujan (gunakan pin ADC ESP32)
const int STEP_PIN_JENDELA = 18; // Pin STEP untuk motor jendela
const int DIR_PIN_JENDELA = 19; // Pin DIR untuk motor jendela
const int ENABLE_PIN_JENDELA = 21; // Pin ENABLE untuk motor jendela
const int STEP_PIN_GORDEN = 22; // Pin STEP untuk motor gorden
const int DIR_PIN_GORDEN = 23; // Pin DIR untuk motor gorden
const int ENABLE_PIN_GORDEN = 25; // Pin ENABLE untuk motor gorden
const int RELAY_PIN = 26; // Pin untuk relay
const int RELAY_SOLENOID_PIN = 27; // Pin untuk relay solenoid
// Pin untuk sensor DHT22
const int DHT_PIN = 32; // Pin data untuk DHT22
#define DHT_TYPE DHT22 // Tipe sensor DHT
// Ganti pin I2C ke GPIO 21 (SDA) dan GPIO 22 (SCL) untuk ESP32
const int I2C_SDA = 3; // SDA pin
const int I2C_SCL = 1; // SCL pin
// Variabel untuk motor gorden dan jendela
const int maxSteps = 1000; // Jumlah langkah maksimum untuk motor
int currentSteps = 0; // Jumlah langkah yang telah ditempuh oleh motor
bool motorRunning = false; // Status motor sedang berjalan
bool isRaining = false; // Status hujan
// Deklarasi WidgetLED untuk relay solenoid
WidgetLED ledSolenoid(V8); // Gunakan Virtual Pin V8 untuk LED solenoid
// Inisialisasi sensor DHT
DHT dht(DHT_PIN, DHT_TYPE);
// Blynk Auth Token
char auth[] = "8kN0Di4Fl_vm3SbbGxUToF48v9NAahw0";
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Variabel scrolling
unsigned long lastScrollTime = 0; // Waktu terakhir teks di-scroll
int scrollInterval = 10; // Interval waktu scroll dalam milidetik
int scrollPos = 0; // Posisi scroll teks
// Inisialisasi LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C 0x3F, ukuran LCD 16x2
// Variabel untuk timer bergantian tampilan
int displayState = 0; // Status tampilan (0: Temperature, 1: Humidity)
void setup() {
// Pindahkan komunikasi Serial jika masih diperlukan
Serial.begin(115200);
Serial.println("Using GPIO 21 and 22 for I2C.");
// Inisialisasi Blynk
Blynk.begin(auth, ssid, pass, "iot.serangkota.go.id", 8080);
// Inisialisasi pin DHT dan relay
dht.begin();
pinMode(RAIN_ANALOG, INPUT);
pinMode(STEP_PIN_JENDELA, OUTPUT);
pinMode(DIR_PIN_JENDELA, OUTPUT);
pinMode(ENABLE_PIN_JENDELA, OUTPUT); // Pin ENABLE motor jendela
pinMode(STEP_PIN_GORDEN, OUTPUT);
pinMode(DIR_PIN_GORDEN, OUTPUT);
pinMode(ENABLE_PIN_GORDEN, OUTPUT); // Pin ENABLE motor gorden
pinMode(RELAY_PIN, OUTPUT);
pinMode(RELAY_SOLENOID_PIN, OUTPUT); // Inisialisasi pin relay solenoid
// Memastikan pin ENABLE motor dalam keadaan off (HIGH) saat pertama kali
digitalWrite(ENABLE_PIN_JENDELA, HIGH);
digitalWrite(ENABLE_PIN_GORDEN, HIGH);
// Inisialisasi I2C di GPIO 21 dan 22
Wire.begin(I2C_SDA, I2C_SCL); // Gunakan pin SDA dan SCL untuk I2C
Wire.setClock(400000); // I2C Fast Mode (400kHz)
// Inisialisasi LCD
lcd.init();
lcd.clear();
lcd.backlight();
// Set teks statis "Check Rain Status" di Blynk
Blynk.virtualWrite(V6, " Welcome Back! ");
Blynk.virtualWrite(V7, " KELOMPOK 8 ");
delay(5000);
Blynk.virtualWrite(V6, "Chk_Rain_Status");
}
void loop() {
Blynk.run();
// Monitoring sensor hujan
int analogValue = analogRead(RAIN_ANALOG); // Baca nilai analog sensor hujan
float rainIntensity = map(analogValue, 0, 4095, 0, 100); // Konversi ke persen (1-100%)
// Menentukan apakah hujan terdeteksi berdasarkan intensitas hujan
bool rainDetected = (rainIntensity > 20); // Jika intensitas lebih dari 20%, hujan terdeteksi
if (rainDetected != isRaining) {
isRaining = rainDetected;
Serial.println(isRaining ? "It's raining!" : "The rain has stopped.");
}
// Kirim status hujan ke Blynk dengan teks bergulir
String rainStatus = isRaining ? "It's raining!" : "The rain has stopped.";
sendScrollingText(rainStatus);
// Jalankan motor untuk menutup jendela jika hujan terdeteksi dan belum mencapai langkah maksimum
if (isRaining && !motorRunning && currentSteps < maxSteps) {
Serial.println("Starting motor to close window...");
motorRunning = true;
digitalWrite(ENABLE_PIN_JENDELA, LOW); // Aktifkan motor jendela
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, HIGH, maxSteps - currentSteps); // Menutup jendela ke CW
currentSteps = maxSteps; // Set langkah saat ini ke maksimum
motorRunning = false; // Motor selesai berjalan
digitalWrite(ENABLE_PIN_JENDELA, HIGH); // Nonaktifkan motor jendela
delay(1000);
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan relay solenoid setelah motor selesai
ledSolenoid.on();
Serial.println("Window and curtains closed and locked.");
}
// Monitoring DHT
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temperature) && !isnan(humidity)) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" °C\t");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.print(" % ");
// Kirim data ke Blynk
Blynk.virtualWrite(V4, temperature); // V4 untuk monitoring suhu
Blynk.virtualWrite(V5, humidity); // V5 untuk monitoring kelembapan
} else {
Serial.println("Failed to read from DHT sensor!");
}
// Tampilkan intensitas hujan di Serial Monitor
Serial.print("Rain Intensity: ");
Serial.print(rainIntensity);
Serial.println(" %");
Blynk.virtualWrite(V9, rainIntensity); // V4 untuk monitoring suhu
// Tampilkan data ke LCD 16x2
lcd.clear(); // Bersihkan layar LCD
// Ganti tampilan setiap interval delay
if (displayState == 0) {
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperature);
lcd.print("C");
displayState = 1; // Ganti ke tampilan kelembapan
} else if (displayState == 1) {
lcd.setCursor(0, 0);
lcd.print("Humidity: ");
lcd.print(humidity);
lcd.print("%");
displayState = 0; // Ganti kembali ke tampilan suhu
}
// Menampilkan intensitas hujan di baris kedua
lcd.setCursor(0, 1); // Baris kedua
lcd.print("Rain: ");
lcd.print(rainIntensity);
lcd.print("%");
delay(2000); // Delay 2 detik sebelum berganti tampilan
}
// Fungsi untuk mengirim teks bergulir
void sendScrollingText(String text) {
String scrolledText = text;
int textLength = scrolledText.length();
if (textLength > 16) {
unsigned long currentMillis = millis();
if (currentMillis - lastScrollTime >= scrollInterval) {
lastScrollTime = currentMillis;
scrolledText = scrolledText.substring(scrollPos) + scrolledText.substring(0, scrollPos);
scrollPos++;
if (scrollPos >= textLength) {
scrollPos = 0;
}
Blynk.virtualWrite(V7, scrolledText);
}
} else {
Blynk.virtualWrite(V7, text);
}
}
// Fungsi untuk menggerakkan motor
void rotateMotor(int stepPin, int dirPin, int direction, int steps) {
for (int i = 0; i < steps; i++) {
digitalWrite(dirPin, direction);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000); // Pengaturan kecepatan motor
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000); // Pengaturan kecepatan motor
}
}
// Fungsi untuk kontrol relay
BLYNK_WRITE(V0) { // V0 untuk kontrol relay
int value = param.asInt();
if (value == 1 && !isRaining) {
digitalWrite(RELAY_PIN, HIGH); // Aktifkan relay
digitalWrite(ENABLE_PIN_JENDELA, LOW); // Aktifkan motor jendela
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, HIGH, maxSteps - currentSteps);
currentSteps = maxSteps;
delay(1000); // Tunggu solenoid aktif
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan solenoid
ledSolenoid.on();
digitalWrite(ENABLE_PIN_JENDELA, HIGH); // Nonaktifkan motor jendela
} else {
digitalWrite(RELAY_PIN, LOW); // Matikan relay
}
}
// Fungsi untuk kontrol motor jendela lewat Blynk
BLYNK_WRITE(V1) { // V1 untuk buka jendela (arah motor CW)
int value = param.asInt();
if (value == 1 && !isRaining) {
digitalWrite(RELAY_SOLENOID_PIN, LOW); // Lepaskan solenoid
ledSolenoid.off();
delay(1000); // Tunggu solenoid off
digitalWrite(ENABLE_PIN_JENDELA, LOW); // Aktifkan motor jendela
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, LOW, currentSteps); // Buka jendela
currentSteps = 0;
digitalWrite(ENABLE_PIN_JENDELA, HIGH); // Nonaktifkan motor jendela
}
}
BLYNK_WRITE(V2) { // V2 untuk tutup jendela (arah motor CCW)
int value = param.asInt();
if (value == 1 && !isRaining) {
digitalWrite(ENABLE_PIN_JENDELA, LOW); // Aktifkan motor jendela
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, HIGH, maxSteps - currentSteps); // Tutup jendela
currentSteps = maxSteps;
delay(1000); // Tunggu solenoid aktif
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan solenoid
ledSolenoid.on();
digitalWrite(ENABLE_PIN_JENDELA, HIGH); // Nonaktifkan motor jendela
}
}
BLYNK_WRITE(V3) { // V3 untuk kontrol gorden buka/tutup
int value = param.asInt();
if (value == 1) {
digitalWrite(ENABLE_PIN_GORDEN, LOW); // Aktifkan motor gorden
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, HIGH, maxSteps); // Buka gorden
digitalWrite(ENABLE_PIN_GORDEN, HIGH); // Nonaktifkan motor gorden
} else {
digitalWrite(ENABLE_PIN_GORDEN, LOW); // Aktifkan motor gorden
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, LOW, maxSteps); // Tutup gorden
digitalWrite(ENABLE_PIN_GORDEN, HIGH); // Nonaktifkan motor gorden
}
}