/*
* Proyek 5 v5: Lampu Teras Otomatis + LCD + Alarm
* Menambahkan Buzzer dan timer 5 detik menggunakan millis().
*/
// === Library (Sama) ===
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// === Inisialisasi LCD (Sama) ===
LiquidCrystal_I2C lcd(0x27, 16, 2);
// === Definisi Pin ===
#define PIN_TRIG 9
#define PIN_ECHO 10
#define PIN_LDR A0
#define PIN_LED 11
#define PIN_BUZZER 8 // <-- BARU: Pin untuk buzzer
// === Ambang Batas (Sama) ===
int ambangGelap = 300;
int ambangJarakDekat = 150;
// === Pengaturan Kecerahan (Sama) ===
int terangPenuh = 255;
int redup = 20;
int mati = 0;
// === Variabel Timer Alarm ===
unsigned long timerMulaiDeteksi = 0; // <-- BARU: Waktu saat objek pertama kali terdeteksi
boolean objekTerdeteksi = false; // <-- BARU: Status untuk menandai objek sedang dilacak
boolean alarmAktif = false; // <-- BARU: Status untuk menandai alarm sedang berbunyi
// === Variabel Timer Blink ===
unsigned long timerBlink = 0; // <-- BARU: Timer untuk kedip LED saat alarm
boolean ledBlinkState = true; // <-- BARU: Status kedip LED
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
// Pin mode
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
pinMode(PIN_BUZZER, OUTPUT); // <-- BARU
// Set kondisi awal
analogWrite(PIN_LED, mati);
digitalWrite(PIN_BUZZER, LOW); // <-- BARU: Pastikan buzzer mati
lcd.setCursor(0, 0);
lcd.print("Lampu Teras Auto");
}
void loop() {
// --- LANGKAH 1: Baca Sensor (Sama) ---
int nilaiLDR = bacaLDR();
long jarakCm = bacaJarak();
// --- LANGKAH 2: Logika Inti & Serial Monitor (Sama) ---
Serial.print("LDR: " + String(nilaiLDR));
Serial.print(" | Jarak: " + String(jarakCm) + "cm");
lcd.setCursor(0, 1); // Pindah kursor LCD ke baris 2
// Cek kondisi TERANG
if (nilaiLDR > ambangGelap) {
// === Skenario 1: Siang Hari ===
analogWrite(PIN_LED, mati);
digitalWrite(PIN_BUZZER, LOW); // Pastikan buzzer mati
Serial.println(" -> Status: Siang [LAMPU MATI]");
lcd.print("Siang: Mati ");
// Reset status deteksi
objekTerdeteksi = false;
alarmAktif = false;
} else {
// === Skenario 2: Gelap (Malam Hari) ===
// Cek jika ada orang
if (jarakCm < ambangJarakDekat) {
// --- Skenario 2a: Malam & Ada Orang ---
// Cek jika ini PERTAMA KALI orang terdeteksi
if (objekTerdeteksi == false) {
objekTerdeteksi = true;
timerMulaiDeteksi = millis(); // <-- BARU: Catat waktu mulai deteksi
Serial.println(" -> Status: Malam, Ada Orang [LAMPU TERANG]");
lcd.print("Malam: TERANG! ");
analogWrite(PIN_LED, terangPenuh); // Nyalakan lampu terang (solid)
} else {
// --- Objek MASIH terdeteksi ---
unsigned long selangWaktu = millis() - timerMulaiDeteksi; // <-- BARU: Hitung selisih waktu
// Cek jika sudah lebih dari 5 detik (5000 ms)
if (selangWaktu > 5000) {
// === ALARM AKTIF ===
alarmAktif = true;
Serial.println(" -> Status: ALARM AKTIF!");
lcd.print("!!! ALARM !!! ");
digitalWrite(PIN_BUZZER, HIGH); // <-- BARU: Nyalakan buzzer!
// Logika LED Berkedip (non-blocking)
if (millis() - timerBlink > 250) { // Kedip tiap 250ms
timerBlink = millis();
if (ledBlinkState) {
analogWrite(PIN_LED, mati);
ledBlinkState = false;
} else {
analogWrite(PIN_LED, terangPenuh);
ledBlinkState = true;
}
}
} else {
// --- Masih < 5 detik, lampu tetap terang (solid) ---
Serial.println(" -> Status: Malam, Ada Orang [LAMPU TERANG]");
lcd.print("Malam: TERANG! ");
analogWrite(PIN_LED, terangPenuh);
}
}
} else {
// --- Skenario 2b: Malam & Tidak Ada Orang ---
analogWrite(PIN_LED, redup); // Lampu kembali redup
digitalWrite(PIN_BUZZER, LOW); // Matikan buzzer
Serial.println(" -> Status: Malam, Sepi [LAMPU REDUP]");
lcd.print("Malam: Redup ");
// Reset status deteksi
objekTerdeteksi = false;
alarmAktif = false;
}
}
// Jeda kecil agar tidak spam, tapi tetap responsif
delay(100);
}
// --- Fungsi Pembantu (Tidak berubah) ---
int bacaLDR() {
return analogRead(PIN_LDR);
}
long bacaJarak() {
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
long durasi = pulseIn(PIN_ECHO, HIGH);
long jarak = durasi * 0.034 / 2;
return jarak;
}