#define BLYNK_TEMPLATE_ID "TMPL6SwnyGHYy"
#define BLYNK_TEMPLATE_NAME "Monitoring Rumah Pintar"
#define BLYNK_AUTH_TOKEN "GYN_n6umjO44FMaXV_OKCEQwc3Sc-I3c"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>
#include <NewPing.h>
// Pin definitions
#define DHTPIN 4 // GPIO4 for DHT22
#define DHTTYPE DHT22 // DHT22 type
#define BUTTON_PIN 15 // GPIO15 for button
#define LIGHT_PIN 13 // GPIO12 for light
#define MOTION_PIN 2 // GPIO2 for motion sensor
#define PUMP_PIN 12 // GPIO13 for water pump
#define BUZZER_PIN 14 // GPIO14 for buzzer
#define TRIGGER_PIN 5 // GPIO5 for ultrasonic trigger
#define ECHO_PIN 18 // GPIO18 for ultrasonic echo
#define MAX_DISTANCE 300 // 300cm max distance
// Initialize ultrasonic sensor
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
// WiFi credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = ""; // Use "" for Wokwi, or "Your_WiFi_Password" for real hardware
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;
// Global variables
bool lightState = false;
bool lastButtonState = HIGH;
bool motionDetected = false;
bool pumpState = false;
bool alarmState = false;
unsigned long lastMotionTime = 0;
unsigned long lastDebounceTime = 0;
unsigned long lastConnectionAttempt = 0;
const unsigned long debounceDelay = 100; // 100ms debounce
const unsigned long connectionInterval = 30000; // Retry every 30 seconds
static unsigned int lastValidLevel = 300; // Last valid water level
int pumpOnLevel = 100; // Configurable pump ON threshold
int pumpOffLevel = 200; // Configurable pump OFF threshold
float alarmTemp = 30.0; // Configurable alarm temperature
unsigned long motionTimeout = 20000; // Configurable motion timeout (ms)
// Connect to WiFi
void connectWiFi() {
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nFailed to connect to WiFi!");
}
}
// Read water level
void readWaterLevel() {
unsigned int waterLevel = sonar.ping_cm();
if (waterLevel == 0) {
waterLevel = lastValidLevel; // Use last valid reading
Serial.println("Error reading water level! Using last valid value.");
} else {
lastValidLevel = waterLevel; // Update valid reading
Serial.print("Level Air: ");
Serial.print(waterLevel);
Serial.println(" cm");
}
// Control water pump
if (waterLevel < pumpOnLevel && !pumpState) {
pumpState = true;
digitalWrite(PUMP_PIN, HIGH);
Blynk.virtualWrite(V5, 1);
Serial.println("Pompa air: ON");
} else if (waterLevel > pumpOffLevel && pumpState) {
pumpState = false;
digitalWrite(PUMP_PIN, LOW);
Blynk.virtualWrite(V5, 0);
Serial.println("Pompa air: OFF");
}
Blynk.virtualWrite(V2, waterLevel);
}
// Read all sensors
void readSensors() {
// Read DHT22
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Gagal membaca DHT sensor!");
return;
}
// Read motion sensor
motionDetected = digitalRead(MOTION_PIN);
// Update last motion time
if (motionDetected) {
lastMotionTime = millis();
if (!lightState) {
lightState = true;
digitalWrite(LIGHT_PIN, HIGH);
Blynk.virtualWrite(V3, 1);
Serial.println("Lampu: ON (Gerakan terdeteksi)");
}
}
// Auto-off light after timeout
if (millis() - lastMotionTime > motionTimeout && lightState) {
lightState = false;
digitalWrite(LIGHT_PIN, LOW);
Blynk.virtualWrite(V3, 0);
Serial.println("Lampu: OFF (Timeout)");
}
// Read water level
readWaterLevel();
// Control alarm
unsigned int waterLevel = lastValidLevel;
if (waterLevel > pumpOffLevel || temperature > alarmTemp) {
alarmState = true;
digitalWrite(BUZZER_PIN, HIGH);
Blynk.virtualWrite(V6, 1);
Serial.println("ALARM: ON");
} else {
alarmState = false;
digitalWrite(BUZZER_PIN, LOW);
Blynk.virtualWrite(V6, 0);
}
// Send data to Blynk
Blynk.virtualWrite(V0, temperature);
Blynk.virtualWrite(V1, humidity);
Serial.print("Suhu: ");
Serial.print(temperature);
Serial.print("°C, Kelembaban: ");
Serial.print(humidity);
Serial.println("%");
}
// Blynk virtual pin controls
BLYNK_WRITE(V7) { // Manual light control
int btnState = param.asInt();
if (btnState == HIGH) {
lightState = !lightState;
digitalWrite(LIGHT_PIN, lightState);
Blynk.virtualWrite(V3, lightState);
if (lightState) {
lastMotionTime = millis();
}
Serial.print("Lampu dikontrol manual: ");
Serial.println(lightState ? "ON" : "OFF");
}
}
BLYNK_WRITE(V8) { // Pump ON threshold
pumpOnLevel = param.asInt();
Serial.print("Pump ON threshold set to: ");
Serial.println(pumpOnLevel);
}
BLYNK_WRITE(V9) { // Pump OFF threshold
pumpOffLevel = param.asInt();
Serial.print("Pump OFF threshold set to: ");
Serial.println(pumpOffLevel);
}
BLYNK_WRITE(V10) { // Alarm temperature threshold
alarmTemp = param.asFloat();
Serial.print("Alarm temperature set to: ");
Serial.println(alarmTemp);
}
BLYNK_WRITE(V11) { // Motion timeout (seconds)
motionTimeout = param.asLong() * 1000;
Serial.print("Motion timeout set to: ");
Serial.print(motionTimeout / 1000);
Serial.println(" seconds");
}
BLYNK_CONNECTED() {
Serial.println("Terhubung ke server Blynk!");
Blynk.syncVirtual(V3, V5, V6, V8, V9, V10, V11);
}
// Check and reconnect WiFi and Blynk
void checkConnection() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi disconnected! Reconnecting...");
connectWiFi();
}
if (!Blynk.connected() && WiFi.status() == WL_CONNECTED) {
Serial.println("Blynk disconnected! Reconnecting...");
Blynk.connect();
}
}
void setup() {
Serial.begin(115200);
Serial.println("Memulai sistem monitoring rumah...");
// Initialize pins
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LIGHT_PIN, OUTPUT);
pinMode(MOTION_PIN, INPUT);
pinMode(PUMP_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Set initial states
digitalWrite(LIGHT_PIN, LOW);
digitalWrite(PUMP_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
// Start sensors
dht.begin();
// Connect to WiFi
connectWiFi();
// Configure Blynk
Blynk.config(BLYNK_AUTH_TOKEN);
Blynk.connect();
// Setup timers
timer.setInterval(5000L, readSensors); // 5-second interval for sensors
timer.setInterval(connectionInterval, checkConnection); // Check connection every 30 seconds
// Initial sensor test
Serial.println("Testing sensor awal:");
readSensors();
}
void loop() {
if (Blynk.connected()) {
Blynk.run();
}
timer.run();
// Physical button control with debouncing
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (buttonState == LOW && lastButtonState == HIGH) {
lightState = !lightState;
digitalWrite(LIGHT_PIN, lightState);
Blynk.virtualWrite(V3, lightState);
if (lightState) {
lastMotionTime = millis();
}
Serial.print("Tombol fisik ditekan - Lampu: ");
Serial.println(lightState ? "ON" : "OFF");
}
}
lastButtonState = buttonState;
}