#include <DHT.h>
#include <BlynkSimpleEsp32.h>
#define RAIN_ANALOG 34
#define RAIN_DIGITAL 35
#define STEP_PIN_JENDELA 23 // Pin STEP untuk motor jendela
#define DIR_PIN_JENDELA 22 // Pin DIR untuk motor jendela
#define STEP_PIN_GORDEN 21 // Pin STEP untuk motor gorden
#define DIR_PIN_GORDEN 19 // Pin DIR untuk motor gorden
#define ENABLE_PIN 14 // Pin ENABLE untuk kedua motor
#define RELAY_PIN 12 // Pin untuk relay
#define RELAY_SOLENOID_PIN 13 // Pin untuk relay solenoid
// Pin untuk sensor DHT22
#define DHT_PIN 32 // Pin data untuk DHT22
#define DHT_TYPE DHT22 // Tipe sensor DHT
// 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
// Variabel intensitas hujan
int rainIntensity = 0; // Intensitas hujan dalam persen (1-100%)
// 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";
// 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
void setup() {
pinMode(RAIN_ANALOG, INPUT);
pinMode(RAIN_DIGITAL, INPUT);
pinMode(STEP_PIN_JENDELA, OUTPUT);
pinMode(DIR_PIN_JENDELA, OUTPUT);
pinMode(STEP_PIN_GORDEN, OUTPUT);
pinMode(DIR_PIN_GORDEN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
pinMode(RELAY_SOLENOID_PIN, OUTPUT); // Inisialisasi pin relay solenoid
pinMode(ENABLE_PIN, OUTPUT); // Inisialisasi pin ENABLE untuk kedua motor
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor di awal
Serial.begin(9600);
dht.begin();
// Blynk connection
Blynk.begin(auth, "Wokwi-GUEST", "", "iot.serangkota.go.id", 8080);
// Set teks statis "Check Rain Status" di V6
Blynk.virtualWrite(V6, " Welcome Back! ");
Blynk.virtualWrite(V7, " Ilham Dana ");
delay(5000);
Blynk.virtualWrite(V6, "Chk_Rain_Status");
}
void loop() {
Blynk.run();
// Monitoring sensor hujan
bool rainDetected = digitalRead(RAIN_ANALOG);
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, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, LOW, maxSteps - currentSteps); // Menutup jendela ke CCW
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, LOW, maxSteps - currentSteps); // Menutup gorden
currentSteps = maxSteps; // Set langkah saat ini ke maksimum
motorRunning = false; // Motor selesai berjalan
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan relay solenoid setelah motor selesai
ledSolenoid.on();
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
Serial.println("Window and curtains closed and locked.");
}
// Fungsi untuk memonitor intensitas hujan
int analogValue = analogRead(RAIN_ANALOG); // Baca nilai analog sensor hujan
rainIntensity = map(analogValue, 0, 4095, 0, 100); // Konversi ke persen (1-100%)
// 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
// Periksa apakah hujan sedang turun
isRaining = (rainIntensity > 10); // Anggap hujan jika intensitas > 10%
delay(200); // Sesuai permintaan, delay tetap dipertahankan
}
// 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, HIGH);
delayMicroseconds(1000); // Pengaturan kecepatan motor
digitalWrite(stepPin, LOW);
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, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, LOW, maxSteps - currentSteps);
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, LOW, maxSteps - currentSteps);
currentSteps = maxSteps;
delay(500); // Tunggu solenoid aktif
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan solenoid
ledSolenoid.on();
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
} 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(500); // Tunggu solenoid off
digitalWrite(ENABLE_PIN, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, HIGH, currentSteps); // Buka jendela
currentSteps = 0;
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
}
}
BLYNK_WRITE(V2) { // V2 untuk tutup jendela (arah motor CCW)
int value = param.asInt();
if (value == 1 && !isRaining) {
digitalWrite(ENABLE_PIN, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_JENDELA, DIR_PIN_JENDELA, LOW, maxSteps - currentSteps); // Tutup jendela
currentSteps = maxSteps;
delay(500); // Tunggu solenoid aktif
digitalWrite(RELAY_SOLENOID_PIN, HIGH); // Aktifkan solenoid
ledSolenoid.on();
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
}
}
BLYNK_WRITE(V3) { // V3 untuk kontrol gorden buka/tutup
int value = param.asInt();
if (value == 1) {
digitalWrite(ENABLE_PIN, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, LOW, maxSteps); // Buka gorden
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
} else {
digitalWrite(ENABLE_PIN, LOW); // Aktifkan motor (hidupkan kedua driver)
rotateMotor(STEP_PIN_GORDEN, DIR_PIN_GORDEN, HIGH, maxSteps); // Tutup gorden
digitalWrite(ENABLE_PIN, HIGH); // Nonaktifkan motor (matikan kedua driver)
}
}