#define BLYNK_TEMPLATE_ID "TMPL21a8uOBPn"
#define BLYNK_TEMPLATE_NAME "home automation"
#define BLYNK_AUTH_TOKEN "8LvvlB-VozdN_yh826TsS6WNJFGU2z6j"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// ======================================================
// RELAY
// ======================================================
int relayPin[4] = {2, 5, 18, 22};
// ======================================================
// BUTTON
// ======================================================
int buttonPin[4] = {14, 19, 21, 23};
// ======================================================
// AUTO MODE
// ======================================================
int autoButtonPin = 27;
int autoLed = 26;
// ======================================================
// PIR
// ======================================================
int pirPin = 25;
// ======================================================
// ULTRASONIC
// ======================================================
int trigPin = 32;
int echoPin = 33;
// ======================================================
// KALIBRASI TANDON
// ======================================================
// air penuh
float fullDistance = 120.0;
// air kosong
float emptyDistance = 160.0;
// ======================================================
// STATE
// ======================================================
bool relayState[4] = {
false,
false,
false,
false
};
bool lastButtonState[4] = {
HIGH,
HIGH,
HIGH,
HIGH
};
bool lastAutoButton = HIGH;
bool autoMode = true;
// PIR EVENT
bool lastMotionState = false;
// ======================================================
// SENSOR CACHE
// ======================================================
float lastTemp = -999;
float lastHum = -999;
float lastWaterPercent = -999;
// ======================================================
// LDR
// ======================================================
int ldrPin = 34;
// ======================================================
// DHT22
// ======================================================
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// ======================================================
// BUZZER
// ======================================================
int buzzer = 13;
// ======================================================
// TIMER
// ======================================================
BlynkTimer timer;
// ======================================================
// LDR SMOOTH
// ======================================================
int readLDR() {
int total = 0;
for (int i = 0; i < 5; i++) {
total += analogRead(ldrPin);
delay(2);
}
return total / 5;
}
// ======================================================
// ULTRASONIC RAW
// ======================================================
float readDistanceCM() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// timeout 30ms
long duration =
pulseIn(echoPin,
HIGH,
30000);
// gagal baca
if (duration == 0) {
return emptyDistance;
}
float distance =
duration * 0.034 / 2;
return distance;
}
// ======================================================
// SMOOTH TEMPERATURE
// ======================================================
float readSmoothTemperature() {
float total = 0;
int valid = 0;
for (int i = 0; i < 5; i++) {
float t =
dht.readTemperature();
if (!isnan(t)) {
total += t;
valid++;
}
delay(10);
}
if (valid == 0) {
return NAN;
}
return total / valid;
}
// ======================================================
// SMOOTH HUMIDITY
// ======================================================
float readSmoothHumidity() {
float total = 0;
int valid = 0;
for (int i = 0; i < 5; i++) {
float h =
dht.readHumidity();
if (!isnan(h)) {
total += h;
valid++;
}
delay(10);
}
if (valid == 0) {
return NAN;
}
return total / valid;
}
// ======================================================
// SMOOTH ULTRASONIC
// ======================================================
float readSmoothDistance() {
float total = 0;
for (int i = 0; i < 5; i++) {
total += readDistanceCM();
delay(10);
}
return total / 5.0;
}
// ======================================================
// SYNC RELAY
// ======================================================
void syncRelay() {
for (int i = 0; i < 4; i++) {
Blynk.virtualWrite(
V0 + i,
!relayState[i]
);
}
}
// ======================================================
// SEND SENSOR
// ======================================================
void sendSensor() {
float temp =
readSmoothTemperature();
float hum =
readSmoothHumidity();
if (isnan(temp) || isnan(hum)) {
Serial.println("DHT Error");
return;
}
// ==================================================
// ULTRASONIC
// ==================================================
float distance =
readSmoothDistance();
if (distance > emptyDistance) {
distance = emptyDistance;
}
if (distance < fullDistance) {
distance = fullDistance;
}
// ==================================================
// WATER PERCENT
// ==================================================
float waterPercent =
((emptyDistance - distance)
/ (emptyDistance - fullDistance))
* 100.0;
// ==================================================
// PIR
// ==================================================
bool motion =
digitalRead(pirPin);
// ==================================================
// TEMPERATURE
// ==================================================
if (abs(temp - lastTemp) >= 0.5) {
Blynk.virtualWrite(V5, temp);
lastTemp = temp;
}
// ==================================================
// HUMIDITY
// ==================================================
if (abs(hum - lastHum) >= 2) {
Blynk.virtualWrite(V6, hum);
lastHum = hum;
}
// ==================================================
// WATER LEVEL
// ==================================================
if (abs(waterPercent
- lastWaterPercent) >= 2) {
Blynk.virtualWrite(
V7,
waterPercent
);
lastWaterPercent =
waterPercent;
}
// ==================================================
// PIR EVENT
// ==================================================
if (motion != lastMotionState) {
Blynk.virtualWrite(
V8,
motion
);
if (motion) {
Serial.println(
"ALARM MOTION DETECTED"
);
Blynk.logEvent(
"motion_alert",
"Motion detected in smart home!"
);
}
else {
Serial.println(
"MOTION CLEARED"
);
}
lastMotionState = motion;
}
// ==================================================
// SERIAL
// ==================================================
Serial.println(
"========== SENSOR =========="
);
Serial.print("Temperature : ");
Serial.println(temp);
Serial.print("Humidity : ");
Serial.println(hum);
Serial.print("Distance : ");
Serial.println(distance);
Serial.print("Water Level : ");
Serial.print(waterPercent);
Serial.println("%");
Serial.print("Motion : ");
Serial.println(motion);
Serial.print("Mode : ");
if (autoMode) {
Serial.println("AUTO");
} else {
Serial.println("MANUAL");
}
// ==================================================
// BUZZER ALARM
// ==================================================
if (motion || temp > 30) {
digitalWrite(
buzzer,
HIGH
);
} else {
digitalWrite(
buzzer,
LOW
);
}
}
// ======================================================
// BLYNK CONNECT
// ======================================================
BLYNK_CONNECTED() {
Blynk.syncVirtual(V4);
syncRelay();
Blynk.virtualWrite(
V4,
autoMode
);
}
// ======================================================
// SETUP
// ======================================================
void setup() {
Serial.begin(115200);
// ==================================================
// RELAY
// ==================================================
for (int i = 0; i < 4; i++) {
pinMode(
relayPin[i],
OUTPUT
);
digitalWrite(
relayPin[i],
HIGH
);
}
// ==================================================
// BUTTON
// ==================================================
for (int i = 0; i < 4; i++) {
pinMode(
buttonPin[i],
INPUT_PULLUP
);
}
pinMode(
autoButtonPin,
INPUT_PULLUP
);
// ==================================================
// OUTPUT
// ==================================================
pinMode(
autoLed,
OUTPUT
);
pinMode(
buzzer,
OUTPUT
);
// ==================================================
// PIR
// ==================================================
pinMode(
pirPin,
INPUT
);
// ==================================================
// ULTRASONIC
// ==================================================
pinMode(
trigPin,
OUTPUT
);
pinMode(
echoPin,
INPUT
);
// ==================================================
// DHT
// ==================================================
dht.begin();
// ==================================================
// WIFI
// ==================================================
WiFi.begin(ssid, pass);
Serial.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi Connected");
// ==================================================
// BLYNK
// ==================================================
Blynk.config(BLYNK_AUTH_TOKEN);
Serial.println("Connecting Blynk...");
Blynk.connect(10000);
if (Blynk.connected()) {
Serial.println("Blynk Connected");
} else {
Serial.println("Blynk Failed");
}
// ==================================================
// TIMER
// ==================================================
timer.setInterval(
5000L,
sendSensor
);
Serial.println(
"SYSTEM START"
);
}
// ======================================================
// LOOP
// ======================================================
void loop() {
if (Blynk.connected()) {
Blynk.run();
} else {
Serial.println(
"Blynk Disconnected"
);
}
timer.run();
// ==================================================
// MANUAL MODE
// ==================================================
if (!autoMode) {
for (int i = 0; i < 4; i++) {
bool currentState =
digitalRead(buttonPin[i]);
if (lastButtonState[i] == HIGH &&
currentState == LOW) {
relayState[i] =
!relayState[i];
digitalWrite(
relayPin[i],
relayState[i]
? LOW
: HIGH
);
syncRelay();
}
lastButtonState[i] =
currentState;
}
}
// ==================================================
// AUTO BUTTON
// ==================================================
bool autoBtn =
digitalRead(autoButtonPin);
if (lastAutoButton == HIGH &&
autoBtn == LOW) {
autoMode = !autoMode;
Blynk.virtualWrite(
V4,
autoMode
);
Serial.print(
"AUTO MODE: "
);
Serial.println(
autoMode
? "ON"
: "OFF"
);
}
lastAutoButton = autoBtn;
// ==================================================
// AUTO LED
// ==================================================
digitalWrite(
autoLed,
autoMode
? HIGH
: LOW
);
// ==================================================
// AUTO MODE
// ==================================================
if (autoMode) {
int light =
readLDR();
int threshold = 1000;
bool lampu =
(light < threshold);
bool changed = false;
// ==============================================
// RELAY 1-3
// ==============================================
for (int i = 0; i < 3; i++) {
if (relayState[i] != lampu) {
relayState[i] = lampu;
digitalWrite(
relayPin[i],
relayState[i]
? LOW
: HIGH
);
changed = true;
}
}
// ==============================================
// WATER LEVEL
// ==============================================
float distance =
readSmoothDistance();
if (distance > emptyDistance) {
distance = emptyDistance;
}
if (distance < fullDistance) {
distance = fullDistance;
}
float waterPercent =
((emptyDistance - distance)
/ (emptyDistance - fullDistance))
* 100.0;
// ==============================================
// POMPA AIR
// ==============================================
if (waterPercent < 30) {
if (!relayState[3]) {
relayState[3] = true;
digitalWrite(
relayPin[3],
LOW
);
changed = true;
Serial.println(
"POMPA AIR ON"
);
}
}
if (waterPercent > 90) {
if (relayState[3]) {
relayState[3] = false;
digitalWrite(
relayPin[3],
HIGH
);
changed = true;
Serial.println(
"POMPA AIR OFF"
);
}
}
// ==============================================
// UPDATE RELAY
// ==============================================
if (changed) {
syncRelay();
Serial.println(
"Relay Updated"
);
}
}
delay(20);
}
// ======================================================
// RELAY 1
// ======================================================
BLYNK_WRITE(V0) {
if (!autoMode) {
relayState[0] =
!param.asInt();
digitalWrite(
relayPin[0],
relayState[0]
? LOW
: HIGH
);
syncRelay();
}
}
// ======================================================
// RELAY 2
// ======================================================
BLYNK_WRITE(V1) {
if (!autoMode) {
relayState[1] =
!param.asInt();
digitalWrite(
relayPin[1],
relayState[1]
? LOW
: HIGH
);
syncRelay();
}
}
// ======================================================
// RELAY 3
// ======================================================
BLYNK_WRITE(V2) {
if (!autoMode) {
relayState[2] =
!param.asInt();
digitalWrite(
relayPin[2],
relayState[2]
? LOW
: HIGH
);
syncRelay();
}
}
// ======================================================
// RELAY 4
// ======================================================
BLYNK_WRITE(V3) {
if (!autoMode) {
relayState[3] =
!param.asInt();
digitalWrite(
relayPin[3],
relayState[3]
? LOW
: HIGH
);
syncRelay();
}
}
// ======================================================
// AUTO MODE
// ======================================================
BLYNK_WRITE(V4) {
autoMode =
param.asInt();
digitalWrite(
autoLed,
autoMode
? HIGH
: LOW
);
Serial.print(
"AUTO MODE FROM BLYNK: "
);
Serial.println(
autoMode
? "ON"
: "OFF"
);
} tombol relay
tombol on off auto
ldr sensor
dht22 sensor
resistor 220
jalur 3.3 v
jalur 5 v
lampu on off auto
ultrasonic sensor
motion sensor
relay pompa air