#define BLYNK_TEMPLATE_ID "TMPL6MtRMXr09"
#define BLYNK_TEMPLATE_NAME "lampu otomatis"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#define SOUND_PIN 34 // PIN SENSOR TEPUK
#define BUZZER_PIN 13
#define RELAY_PIN 23
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "7ermN_WTuQ-5NdR0-H9kvbtwAZnI4qLA";
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000);
// Alarm settings
bool alarmActive = false;
int alarmHour = 0;
// Alarm runtime
bool alarmRunning = false;
unsigned long alarmStart = 0;
const unsigned long alarmDuration = 600; // 10 menit
// Status lampu utama
bool lampStatus = false;
// Sensor tepuk (detect double clap)
int THRESHOLD = 2500;
int clapCount = 0;
unsigned long firstClapTime = 0;
const unsigned long clapTimeout = 600; // 0.6 detik untuk double clap
void setup() {
Serial.begin(115200);
pinMode(SOUND_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
lcd.init();
lcd.backlight();
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Blynk.begin(auth, ssid, pass);
timeClient.begin();
}
void loop() {
Blynk.run();
timeClient.update();
// ==================================================================
// DETEKSI 2x TEPUK
// ==================================================================
int soundValue = analogRead(SOUND_PIN);
if (soundValue > THRESHOLD) {
if (clapCount == 0) {
firstClapTime = millis();
clapCount = 1;
Serial.println("Tepuk 1 Terdeteksi");
}
else if (clapCount == 1 && millis() - firstClapTime < clapTimeout) {
clapCount = 2;
Serial.println("Tepuk 2 Terdeteksi");
// AMBIL KEPUTUSAN
if (!lampStatus) {
lampStatus = true; // Nyalakan
Serial.println("Lampu DIHIDUPKAN (Double Tepuk)");
} else {
lampStatus = false; // Matikan
Serial.println("Lampu DIMATIKAN (Double Tepuk)");
}
digitalWrite(RELAY_PIN, lampStatus ? HIGH : LOW);
Blynk.virtualWrite(V3, lampStatus);
clapCount = 0; // reset
}
delay(150); // Debounce tepukan
}
// Reset jika tepuk kedua tidak datang
if (clapCount == 1 && millis() - firstClapTime > clapTimeout) {
clapCount = 0;
Serial.println("Double Clap Timeout — Reset");
}
// ==================================================================
// LOGIKA ALARM
// ==================================================================
int currentHour = timeClient.getHours();
if (alarmActive && !alarmRunning) {
if (currentHour == alarmHour) {
alarmRunning = true;
alarmStart = timeClient.getEpochTime();
Serial.println("ALARM STARTED!");
}
}
if (alarmRunning) {
unsigned long now = timeClient.getEpochTime();
if (now - alarmStart < alarmDuration) {
digitalWrite(BUZZER_PIN, HIGH);
} else {
digitalWrite(BUZZER_PIN, LOW);
alarmRunning = false;
alarmActive = false;
Blynk.virtualWrite(V2, 0);
Serial.println("ALARM STOP");
}
} else {
digitalWrite(BUZZER_PIN, LOW);
}
// LCD display
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(timeClient.getFormattedTime());
}
// ==================================================================
// BLYNK HANDLERS
// ==================================================================
BLYNK_WRITE(V1) {
alarmHour = param.asInt();
Serial.print("Alarm Set Hour = ");
Serial.println(alarmHour);
}
BLYNK_WRITE(V2) {
alarmActive = param.asInt();
if (!alarmActive) {
alarmRunning = false;
digitalWrite(BUZZER_PIN, LOW);
}
}
BLYNK_WRITE(V3) {
lampStatus = param.asInt();
digitalWrite(RELAY_PIN, lampStatus ? HIGH : LOW);
}