#define BLYNK_TEMPLATE_ID "TMPL6oNoY-xHt"
#define BLYNK_TEMPLATE_NAME "Amzar"
#define BLYNK_AUTH_TOKEN "0t89CxFjKk0WEiUe5sS2_f9LZAROqIbD"
#include <WiFi.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <BlynkSimpleEsp32.h>
char auth[] = "0t89CxFjKk0WEiUe5sS2_f9LZAROqIbD";
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define RELAY1_PIN 5
#define RELAY2_PIN 18
DHT dht(DHT_PIN, DHT_TYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
BlynkTimer timer;
float temperature = 0;
float humidity = 0;
bool relay1State = false;
bool relay2State = false;
bool autoMode = true;
float tempThreshold = 28.0;
float humidThreshold = 60.0;
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 2000;
void setup() {
Serial.begin(115200);
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
dht.begin();
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Sistem Starting...");
lcd.setCursor(0, 1);
lcd.print("Connect WiFi...");
Blynk.begin(auth, ssid, pass);
timer.setInterval(2000L, blynkUpdate);
Serial.println("=== SISTEM SIAP ===");
lcd.clear();
lcd.print("Blynk ON");
delay(1000);
}
void loop() {
Blynk.run();
timer.run();
if (millis() - lastUpdate > updateInterval) {
readSensors();
updateDisplay();
printToSerial();
lastUpdate = millis();
}
}
void readSensors() {
temperature = dht.readTemperature();
humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println(" DHT Read Failed!");
temperature = 0;
humidity = 0;
return;
}
}
// ========================= BLYNK FUNCTIONS =========================
// Update data ke Blynk (3 widget: V0=Switch, V1=Suhu, V2=Kelembaban)
void blynkUpdate() {
Blynk.virtualWrite(V1, temperature); // Suhu ke Value Display V1
Blynk.virtualWrite(V2, humidity); // Kelembaban ke Value Display V2
}
// Blynk Switch V0 - Manual Control Relay
BLYNK_WRITE(V0) {
relay1State = param.asInt();
digitalWrite(RELAY1_PIN, relay1State);
Serial.println("Relay1: " + String(relay1State ? "ON" : "OFF"));
}
// Relay 2 Switch (V1) - Pelembab/Lampu
BLYNK_WRITE(V3) {
relay2State = param.asInt();
digitalWrite(RELAY2_PIN, relay2State);
Serial.println("Relay2: " + String(relay2State ? "ON" : "OFF"));
}
BLYNK_WRITE(V5) {
autoMode = param.asInt();
Serial.println("Auto Mode: " + String(autoMode ? "ON" : "OFF"));
}
// ========================= DISPLAY =========================
void updateDisplay() {
lcd.clear();
// Baris 1: Suhu & Kelembaban
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(temperature, 1);
lcd.print("C H:");
lcd.print(humidity, 1);
lcd.print("%");
// Baris 2: Relay + Threshold
lcd.setCursor(0, 1);
lcd.print("R1:");
lcd.print(relay1State ? "ON" : "OFF");
lcd.print(" R2:");
lcd.print(relay2State ? "ON" : "OFF");
}
void printToSerial() {
Serial.println("═════ STATUS ═════");
Serial.print(" Suhu: "); Serial.print(temperature, 1); Serial.println(" °C");
Serial.print(" Kelembaban: "); Serial.print(humidity, 1); Serial.println(" %");
Serial.print(" Relay1: "); Serial.println(relay1State ? "ON" : "OFF");
Serial.print(" Relay2: "); Serial.println(relay2State ? "ON" : "OFF");
Serial.print(" Threshold: "); Serial.print(tempThreshold); Serial.print("°C / "); Serial.print(humidThreshold); Serial.println("%");
Serial.println("══════════════════");
}