#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>
#include <LiquidCrystal_I2C.h>
// -------------------- Konfigurasi Default --------------------
#define AP_SSID "TandonAir_Master"
#define AP_PASS "12345678"
Preferences prefs;
WebServer server(80);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// -------------------- Variabel WiFi --------------------
String wifiSSID, wifiPASS, wifiIP, wifiGW, displayIP;
IPAddress localIP, gateway, subnet(255,255,255,0);
// -------------------- Pin --------------------
#define TRIG_PIN 5
#define ECHO_PIN 18
#define RELAY_SOLENOID 25
#define RELAY_POMPA 26
// -------------------- Variabel Tandon --------------------
float jarakPenuh = 30; // cm
float jarakKosong = 100; // cm
float tinggiTandon = 100; // cm
float diameterTandon = 60; // cm
float distanceCm;
float levelPersen;
float volumeLiter;
// -------------------- Timer Kirim ke Display --------------------
unsigned long lastSendTime = 0;
unsigned long sendInterval = 5000; // 5 detik
// -------------------- Fungsi WiFi --------------------
void setupWiFi() {
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(AP_SSID, AP_PASS);
Serial.print("AP IP: "); Serial.println(WiFi.softAPIP());
wifiSSID = prefs.getString("ssid", "");
wifiPASS = prefs.getString("pass", "");
wifiIP = prefs.getString("ip", "192.168.1.200");
wifiGW = prefs.getString("gw", "192.168.1.1");
displayIP = prefs.getString("display", "192.168.1.201");
if (wifiSSID != "") {
localIP.fromString(wifiIP);
gateway.fromString(wifiGW);
WiFi.config(localIP, gateway, subnet);
WiFi.begin(wifiSSID.c_str(), wifiPASS.c_str());
Serial.println("Connecting to WiFi...");
unsigned long start = millis();
while(WiFi.status()!=WL_CONNECTED && millis()-start<10000){
delay(500); Serial.print(".");
}
Serial.println(WiFi.status()==WL_CONNECTED?"\nConnected!":"\nFailed, AP only");
}
}
// -------------------- Sensor --------------------
long bacaJarak() {
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
return duration * 0.034 / 2;
}
void updateSensor() {
distanceCm = bacaJarak();
levelPersen = (jarakKosong - distanceCm) / (jarakKosong - jarakPenuh) * 100.0;
if(levelPersen < 0) levelPersen = 0;
if(levelPersen > 100) levelPersen = 100;
float tinggiAir = tinggiTandon * (levelPersen / 100.0);
float radius = diameterTandon / 2.0;
volumeLiter = 3.1416 * radius * radius * tinggiAir / 1000.0;
}
void kontrolRelay() {
if(levelPersen < 80) digitalWrite(RELAY_SOLENOID, LOW);
else if(levelPersen >= 100) digitalWrite(RELAY_SOLENOID, HIGH);
if(levelPersen < 20) digitalWrite(RELAY_POMPA, HIGH);
else digitalWrite(RELAY_POMPA, LOW);
}
void tampilLCD() {
lcd.clear();
int bars = (levelPersen/100.0)*16;
lcd.setCursor(0,0);
for(int i=0;i<bars;i++) lcd.print((char)255);
for(int i=bars;i<16;i++) lcd.print(" ");
lcd.setCursor(0,1);
lcd.print((int)levelPersen); lcd.print("% ");
lcd.print((int)volumeLiter); lcd.print("L");
}
// -------------------- Kirim ke ESP Display --------------------
void kirimKeDisplay() {
if (WiFi.status() != WL_CONNECTED) return;
if (displayIP == "") return;
WiFiClient client;
if (client.connect(displayIP.c_str(), 80)) {
String data = "level=" + String(levelPersen, 1) + "&volume=" + String(volumeLiter, 1);
client.println("POST /update HTTP/1.1");
client.println("Host: " + displayIP);
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: "); client.println(data.length());
client.println();
client.print(data);
client.stop();
} else {
Serial.println("Gagal kirim ke display");
}
}
// -------------------- Web Interface --------------------
void handleRoot() {
String html="<h2>Monitoring Tandon Air</h2>";
html+="Level Air: "+String(levelPersen,1)+"%<br>";
html+="Volume Air: "+String(volumeLiter,1)+" L<br>";
html+="Relay Selenoid: "+String(digitalRead(RELAY_SOLENOID)==LOW?"ON":"OFF")+"<br>";
html+="Relay Pompa: "+String(digitalRead(RELAY_POMPA)==LOW?"ON":"OFF")+"<br><br>";
html+="<a href='/wifi'>Konfigurasi WiFi</a> | <a href='/tandon'>Set Volume Air</a>";
server.send(200,"text/html",html);
}
void handleWiFiConfig() {
if(server.method()==HTTP_POST){
prefs.putString("ssid", server.arg("ssid"));
prefs.putString("pass", server.arg("pass"));
prefs.putString("ip", server.arg("ip"));
prefs.putString("gw", server.arg("gw"));
prefs.putString("display", server.arg("display"));
server.send(200,"text/html","<h3>Disimpan! Restart ESP...</h3>");
delay(2000); ESP.restart(); return;
}
String html="<h2>Konfigurasi WiFi Master</h2><form method='POST'>";
html+="SSID: <input name='ssid' value='"+wifiSSID+"'><br>";
html+="Password: <input name='pass' value='"+wifiPASS+"'><br>";
html+="IP Statis: <input name='ip' value='"+wifiIP+"'><br>";
html+="Gateway: <input name='gw' value='"+wifiGW+"'><br>";
html+="IP Display: <input name='display' value='"+displayIP+"'><br>";
html+="<input type='submit' value='Simpan & Restart'></form>";
html+="<br><a href='/'>Kembali</a>";
server.send(200,"text/html",html);
}
void handleTandonConfig() {
if(server.method()==HTTP_POST){
jarakPenuh = server.arg("penuh").toFloat();
jarakKosong = server.arg("kosong").toFloat();
tinggiTandon = server.arg("tinggi").toFloat();
diameterTandon = server.arg("diameter").toFloat();
prefs.putFloat("penuh", jarakPenuh);
prefs.putFloat("kosong", jarakKosong);
prefs.putFloat("tinggi", tinggiTandon);
prefs.putFloat("diameter", diameterTandon);
server.send(200,"text/html","<h3>Disimpan!</h3><a href='/'>Kembali</a>");
return;
}
String html="<h2>Set Parameter Tandon</h2><form method='POST'>";
html+="Jarak Penuh (cm): <input name='penuh' value='"+String(jarakPenuh)+"'><br>";
html+="Jarak Kosong (cm): <input name='kosong' value='"+String(jarakKosong)+"'><br>";
html+="Tinggi Tandon (cm): <input name='tinggi' value='"+String(tinggiTandon)+"'><br>";
html+="Diameter Tandon (cm): <input name='diameter' value='"+String(diameterTandon)+"'><br>";
html+="<input type='submit' value='Simpan'></form>";
html+="<br><a href='/'>Kembali</a>";
server.send(200,"text/html",html);
}
void handleData(){
String data = String(levelPersen,1)+","+String(volumeLiter,1);
server.send(200,"text/plain",data);
}
// -------------------- Setup & Loop --------------------
void setup() {
Serial.begin(115200);
lcd.init(); lcd.backlight();
pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT);
pinMode(RELAY_SOLENOID, OUTPUT); pinMode(RELAY_POMPA, OUTPUT);
digitalWrite(RELAY_SOLENOID, HIGH); digitalWrite(RELAY_POMPA, HIGH);
prefs.begin("config", false);
jarakPenuh = prefs.getFloat("penuh", jarakPenuh);
jarakKosong = prefs.getFloat("kosong", jarakKosong);
tinggiTandon = prefs.getFloat("tinggi", tinggiTandon);
diameterTandon = prefs.getFloat("diameter", diameterTandon);
setupWiFi();
server.on("/", handleRoot);
server.on("/wifi", handleWiFiConfig);
server.on("/tandon", handleTandonConfig);
server.on("/data", handleData);
server.begin();
}
void loop() {
updateSensor();
kontrolRelay();
tampilLCD();
server.handleClient();
if (millis() - lastSendTime > sendInterval) {
kirimKeDisplay();
lastSendTime = millis();
}
delay(500);
}
Comments
Post a Comment