#include #include #include #include #include #include // Tambahkan WiFiManager #define API_KEY "AIzaSyBfSo7wVseHLUJepuOv4f0nUKSMpkdaG4c" #define DATABASE_URL "https://femonitor-87369-default-rtdb.asia-southeast1.firebasedatabase.app/" #define LEGACY_TOKEN "wOznU9rBFBFG5UauVrkfaVOKrc8SCBMW7pmgV7ZT" #define LDR_SEBELUM 34 #define LDR_SESUDAH 32 #define RELAY_PIN 14 #define LED1_PIN 12 FirebaseData fbdo; FirebaseAuth auth; FirebaseConfig config; LiquidCrystal_I2C lcd(0x27, 16, 2); WebServer server(80); unsigned long lastUpdate = 0; unsigned long interval = 5000; float faktorKalibrasiSebelum = 1.0; float offsetKalibrasiSebelum = 0.0; float faktorKalibrasiSesudah = 1.0; float offsetKalibrasiSesudah = 0.0; #define LDR_SMOOTH_COUNT 10 int ldrBufferSebelum[LDR_SMOOTH_COUNT] = {0}; int ldrBufferSesudah[LDR_SMOOTH_COUNT] = {0}; int bufferIndex = 0; float lastFeSebelum = 0.0; float lastFeSesudah = 0.0; float deltaFeThreshold = 0.2; int ldrSebelum = 0; int ldrSesudah = 0; float feSebelum = 0.0; float feSesudah = 0.0; void handleRoot() { String html = "Data Sensor"; html += "

Data Sensor

"; html += "

LDR Sebelum: " + String(ldrSebelum) + "

"; html += "

LDR Sesudah: " + String(ldrSesudah) + "

"; html += "

Fe Sebelum (ppm): " + String(feSebelum, 2) + "

"; html += "

Fe Sesudah (ppm): " + String(feSesudah, 2) + "

"; html += "

Kalibrasi Sebelum:

"; html += "

Faktor: " + String(faktorKalibrasiSebelum, 6) + "

"; html += "

Offset: " + String(offsetKalibrasiSebelum, 6) + "

"; html += "

Kalibrasi Sesudah:

"; html += "

Faktor: " + String(faktorKalibrasiSesudah, 6) + "

"; html += "

Offset: " + String(offsetKalibrasiSesudah, 6) + "

"; html += ""; server.send(200, "text/html", html); } void updateKalibrasi() { if (Firebase.RTDB.getFloat(&fbdo, "/kalibrasi/sebelum/faktor")) { faktorKalibrasiSebelum = fbdo.floatData(); } if (Firebase.RTDB.getFloat(&fbdo, "/kalibrasi/sebelum/offset")) { offsetKalibrasiSebelum = fbdo.floatData(); } if (Firebase.RTDB.getFloat(&fbdo, "/kalibrasi/sesudah/faktor")) { faktorKalibrasiSesudah = fbdo.floatData(); } if (Firebase.RTDB.getFloat(&fbdo, "/kalibrasi/sesudah/offset")) { offsetKalibrasiSesudah = fbdo.floatData(); } } int smoothLDR(int pin, int* buffer) { buffer[bufferIndex] = analogRead(pin); long total = 0; for (int i = 0; i < LDR_SMOOTH_COUNT; i++) { total += buffer[i]; } return total / LDR_SMOOTH_COUNT; } void sendDataToFirebase() { Firebase.RTDB.setFloat(&fbdo, "/kadar_fe/sebelum", feSebelum); Firebase.RTDB.setFloat(&fbdo, "/kadar_fe/sesudah", feSesudah); } void setup() { Serial.begin(115200); Wire.begin(21, 22); lcd.init(); lcd.backlight(); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, LOW); pinMode(LED1_PIN, OUTPUT); digitalWrite(LED1_PIN, HIGH); lcd.setCursor(0, 0); lcd.print("WiFiManager..."); WiFiManager wm; bool res = wm.autoConnect("FeMonitorAP"); // Tanpa password if (!res) { Serial.println("Gagal connect WiFi. Restart..."); lcd.setCursor(0, 1); lcd.print("WiFi Failed"); delay(3000); ESP.restart(); } Serial.println("WiFi Connected!"); Serial.print("IP: "); Serial.println(WiFi.localIP()); lcd.clear(); lcd.setCursor(0, 0); lcd.print("WiFi Connected!"); config.api_key = API_KEY; config.database_url = DATABASE_URL; config.signer.tokens.legacy_token = LEGACY_TOKEN; Firebase.begin(&config, &auth); Firebase.reconnectWiFi(true); updateKalibrasi(); delay(2000); lcd.clear(); server.on("/", handleRoot); server.begin(); Serial.println("WebServer ready at: " + WiFi.localIP().toString()); } void loop() { if (millis() - lastUpdate >= interval && Firebase.ready()) { lastUpdate = millis(); updateKalibrasi(); ldrSebelum = smoothLDR(LDR_SEBELUM, ldrBufferSebelum); ldrSesudah = smoothLDR(LDR_SESUDAH, ldrBufferSesudah); bufferIndex = (bufferIndex + 1) % LDR_SMOOTH_COUNT; feSebelum = (ldrSebelum * faktorKalibrasiSebelum) + offsetKalibrasiSebelum; feSesudah = (ldrSesudah * faktorKalibrasiSesudah) + offsetKalibrasiSesudah; feSebelum = constrain(feSebelum, 0.0, 10.0); feSesudah = constrain(feSesudah, 0.0, 10.0); Serial.println("===== SENSOR ====="); Serial.print("LDR Sebelum: "); Serial.println(ldrSebelum); Serial.print("LDR Sesudah: "); Serial.println(ldrSesudah); Serial.print("Fe Sebelum: "); Serial.println(feSebelum, 2); Serial.print("Fe Sesudah: "); Serial.println(feSesudah, 2); Serial.println("=================="); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Fe Seb: "); lcd.print(feSebelum, 2); lcd.setCursor(0, 1); lcd.print("Fe Ses: "); lcd.print(feSesudah, 2); sendDataToFirebase(); if (Firebase.RTDB.getBool(&fbdo, "/relay/pompa")) { if (fbdo.dataType() == "boolean") { bool statusRelay = fbdo.boolData(); digitalWrite(RELAY_PIN, statusRelay ? HIGH : LOW); Serial.print("Relay: "); Serial.println(statusRelay ? "ON" : "OFF"); } } } server.handleClient(); }