#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// Pin Definitions
#define TRIG_PIN 13
#define ECHO_PIN 12
#define LDR_PIN 4
#define BUZZER_PIN 25
#define POMPA_PIN 32
#define LAMPU_PIN 15
// LCD I2C
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Variables
float levelAir = 0;
int kuatCahaya = 0;
bool pompaMenyala = false;
bool lampuMenyala = false;
bool alarmMenyala = false;
void setup() {
Serial.begin(115200);
// Setup pins
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LDR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(POMPA_PIN, OUTPUT);
pinMode(LAMPU_PIN, OUTPUT);
// Initial state
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(POMPA_PIN, LOW);
digitalWrite(LAMPU_PIN, LOW);
// Inisialisasi I2C untuk ESP32 default pins (SDA=21, SCL=22)
Wire.begin(21, 22);
// PENAMBAHAN DELAY KRITIS UNTUK MENCEGAH CRASH SAAT INISIALISASI I2C
delay(200);
// Initialize LCD
lcd.init();
lcd.backlight();
delay(100); // Jeda setelah init
lcd.setCursor(0, 0);
lcd.print("Sistem Monitoring");
lcd.setCursor(0, 1);
lcd.print("Tangki & Cahaya");
delay(2000);
lcd.clear();
}
void loop() {
// Baca sensor
levelAir = bacaLevelAir();
kuatCahaya = bacaKuatCahaya();
// Kontrol Sistem
kontrolLampu(kuatCahaya);
kontrolPompa(levelAir);
kontrolAlarm(levelAir, kuatCahaya);
// Tampilkan
tampilkanLCD();
// Debug ke Serial
Serial.print("Level Air: ");
Serial.print(levelAir);
Serial.print(" cm | Cahaya: ");
Serial.print(kuatCahaya);
Serial.print(" lux | Pompa: ");
Serial.print(pompaMenyala ? "ON" : "OFF");
Serial.print(" | Lampu: ");
Serial.print(lampuMenyala ? "ON" : "OFF");
Serial.print(" | Alarm: ");
Serial.println(alarmMenyala ? "ON" : "OFF");
delay(500);
}
float bacaLevelAir() {
// Trigger ultrasonic
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Baca echo
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
// Hitung jarak (cm)
float jarak = duration * 0.034 / 2;
// Konversi ke level air (Asumsi tinggi tangki 150 cm)
float tinggiTangki = 150.0;
float level = tinggiTangki - jarak;
// Batasi nilai
if (level < 0) level = 0;
if (level > tinggiTangki) level = tinggiTangki;
return level;
}
int bacaKuatCahaya() {
// Baca nilai ADC dari LDR (0 - 4095)
int nilaiADC = analogRead(LDR_PIN);
int lux;
// Asumsi LDR di Wokwi: ADC Rendah = Terang (Lux Tinggi), ADC Tinggi = Gelap (Lux Rendah)
// 1. Kasus Sangat Gelap (Pemetaan Agresif untuk Lux < 10):
// Fokus rentang ADC tertinggi (3900-4095) untuk menghasilkan Lux rendah (0-50).
if (nilaiADC > 3900) {
// Pemetaan terbalik dan agresif
lux = map(nilaiADC, 3900, 4095, 50, 0);
} else {
// 2. Kasus Normal/Terang:
// Pemetaan terbalik umum
lux = map(nilaiADC, 4095, 0, 0, 2000);
}
// CLAMPING: Memaksa nilai di bawah batas minimum simulasi (16 lux) menjadi 0.
if (lux < 16) {
lux = 0;
}
// Pastikan Lux tidak negatif
if (lux < 0) lux = 0;
return lux;
}
void kontrolLampu(int cahaya) {
if (cahaya > 1000) {
// Cahaya terang, lampu OFF
digitalWrite(LAMPU_PIN, LOW);
lampuMenyala = false;
} else if (cahaya < 100) {
// Cahaya gelap, lampu ON
digitalWrite(LAMPU_PIN, HIGH);
lampuMenyala = true;
}
// Hysteresis (100-1000) mempertahankan status terakhir
}
void kontrolPompa(float level) {
if (level > 100) {
// Tangki penuh, pompa OFF
digitalWrite(POMPA_PIN, LOW);
pompaMenyala = false;
} else if (level < 50) {
// Tangki kosong, pompa ON
digitalWrite(POMPA_PIN, HIGH);
pompaMenyala = true;
}
// Hysteresis (50-100) mempertahankan status terakhir
}
void kontrolAlarm(float level, int cahaya) {
if (level > 120 || cahaya < 10) {
// Kondisi bahaya (Air sangat penuh ATAU Cahaya sangat gelap)
digitalWrite(BUZZER_PIN, HIGH);
alarmMenyala = true;
} else {
// Kondisi normal
digitalWrite(BUZZER_PIN, LOW);
alarmMenyala = false;
}
}
void tampilkanLCD() {
lcd.clear();
// Baris 1: Level Air & Pompa
lcd.setCursor(0, 0);
lcd.print("Air:");
lcd.setCursor(5, 0);
lcd.print(levelAir, 0);
lcd.print("cm");
lcd.setCursor(12, 0);
lcd.print("Pompa:");
lcd.print(pompaMenyala ? "ON" : "OFF");
// Baris 2: Kuat Cahaya & Lampu
lcd.setCursor(0, 1);
lcd.print("Lux:");
lcd.setCursor(5, 1);
lcd.print(kuatCahaya);
lcd.setCursor(12, 1);
lcd.print("Lampu:");
lcd.print(lampuMenyala ? "ON" : "OFF");
// Baris 3: Status Alarm
lcd.setCursor(0, 2);
lcd.print("ALARM:");
lcd.setCursor(6, 2);
lcd.print(alarmMenyala ? "ON " : "OFF");
// Baris 4: Informasi Tambahan
lcd.setCursor(0, 3);
lcd.print("Sistem Aktif");
}