SENSOR TANDON AIR DENGAN JSN-SR04T perhitungan volume tandon dan level air FINAL TERHUBUNG

#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