commit 9c1af6339ee8a4f33abc224d6b008112c4162b75 Author: nekopride <158025518+nekopride@users.noreply.github.com> Date: Fri Jul 17 15:22:57 2026 +0700 first commit diff --git a/kontrol_kekeruhan_dan_volume_air.cpp b/kontrol_kekeruhan_dan_volume_air.cpp new file mode 100644 index 0000000..3a7caa9 --- /dev/null +++ b/kontrol_kekeruhan_dan_volume_air.cpp @@ -0,0 +1,473 @@ +#include +#include +#include +#include +#include +#include +#include + +// ================= LCD ================= +LiquidCrystal_I2C lcd(0x27, 16, 2); + +// ================= MQTT ================= +const char* mqtt_server = "broker.emqx.io"; +const int mqtt_port = 1883; + +WiFiClient espClient; +PubSubClient client(espClient); + +// ================= PIN ================= +#define TURBIDITY_PIN 34 +#define TRIG_PIN 5 +#define ECHO_PIN 18 + +#define RELAY_MASUK 26 +#define RELAY_KELUAR 27 + +// ================= SENSOR ================= +long duration; +float distance; +int turbidityValue; + +// ================= FILTER ================= +float filteredDistance = 0; +float alphaDistance = 0.1; + + +// ================= STATUS RELAY ================= +bool relayMasuk = false; +bool relayKeluar = false; + + +// ===================================================== +// WIFI MANAGER +// ===================================================== +void setup_wifi() { + + Serial.println("Memulai WiFiManager..."); + + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print("Connecting WiFi"); + + lcd.setCursor(0, 1); + lcd.print("Please wait..."); + + WiFiManager wm; + + bool res; + + res = wm.autoConnect("AutoConnectAP", "password"); + + if (!res) { + + Serial.println("Gagal connect WiFi"); + + lcd.clear(); + lcd.setCursor(0, 0); + lcd.print("WiFi Failed"); + + delay(800); + + ESP.restart(); + + } else { + + Serial.println("WiFi Connected!"); + + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + + lcd.clear(); + + lcd.setCursor(0, 0); + lcd.print("WiFi Connected"); + + lcd.setCursor(0, 1); + lcd.print(WiFi.localIP()); + + delay(800); + } +} +void WiFiEvent(WiFiEvent_t event) { + + switch(event) { + + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + Serial.println("WiFi Lost"); + WiFi.reconnect(); + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + Serial.print("IP : "); + Serial.println(WiFi.localIP()); + break; + + default: + break; + } +} +// ===================================================== +// PUBLISH STATUS RELAY +// ===================================================== +void publishRelayStatus() { + + StaticJsonDocument<200> doc; + + doc["pompa_masuk"] = relayMasuk ? 1 : 0; + doc["pompa_keluar"] = relayKeluar ? 1 : 0; + + char buffer[200]; + + serializeJson(doc, buffer); + + client.publish("aquamonn/relay_status", buffer); +} + +// ===================================================== +// CONTROL RELAY MASUK +// ===================================================== +void setRelayMasuk(bool state) { + + relayMasuk = state; + + // RELAY ACTIVE LOW + digitalWrite(RELAY_MASUK, state ? LOW : HIGH); +} + +// ===================================================== +// CONTROL RELAY KELUAR +// ===================================================== +void setRelayKeluar(bool state) { + + relayKeluar = state; + + // RELAY ACTIVE LOW + digitalWrite(RELAY_KELUAR, state ? LOW : HIGH); +} + +// ===================================================== +// MQTT CALLBACK +// ===================================================== +void callback(char* topic, byte* payload, unsigned int length) { + + Serial.println(); + Serial.println("========== MQTT CALLBACK =========="); + Serial.print("Waktu (ms): "); + Serial.println(millis()); + + Serial.print("Topic : "); + Serial.println(topic); + + String message = ""; + + for (unsigned int i = 0; i < length; i++) { + message += (char)payload[i]; + } + + Serial.print("Payload : "); + Serial.println(message); + + StaticJsonDocument<200> doc; + DeserializationError error = deserializeJson(doc, message); + + if (error) { + Serial.print("JSON Error : "); + Serial.println(error.c_str()); + return; + } + + if (String(topic) == "aquamonn/relay1") { + + if (doc.containsKey("pompa_masuk")) { + bool state = doc["pompa_masuk"] == 1; + Serial.print("Pompa Masuk : "); + Serial.println(state ? "ON" : "OFF"); + setRelayMasuk(state); + } + + if (doc.containsKey("pompa_keluar")) { + bool state = doc["pompa_keluar"] == 1; + Serial.print("Pompa Keluar : "); + Serial.println(state ? "ON" : "OFF"); + setRelayKeluar(state); + } + + publishRelayStatus(); + } + + Serial.println("=================================="); + Serial.println(); +} + +// ===================================================== +// MQTT RECONNECT +// ===================================================== +void reconnect() { + + if (client.connected()) + return; + + if (WiFi.status() != WL_CONNECTED) + return; + + Serial.println("Connecting MQTT..."); + + String clientId = + "ESP32-" + String(random(0xffff), HEX); + + if (client.connect(clientId.c_str())) { + + Serial.println("MQTT Connected"); + client.subscribe("aquamonn/relay1"); + + } else { + + Serial.print("MQTT Failed rc="); + Serial.println(client.state()); + } +} +// ===================================================== +// ULTRASONIC STABLE +// ===================================================== +float readUltrasonicStable() { + + const int samples = 5; + float data[samples]; + + for (int i = 0; i < samples; i++) { + + digitalWrite(TRIG_PIN, LOW); + delayMicroseconds(2); + + digitalWrite(TRIG_PIN, HIGH); + delayMicroseconds(10); + + digitalWrite(TRIG_PIN, LOW); + + long duration = pulseIn(ECHO_PIN, HIGH, 30000); + + if (duration == 0) { + data[i] = 0; + } else { + data[i] = duration * 0.034 / 2; + } + + delay(20); + } + + // Sorting + for (int i = 0; i < samples - 1; i++) { + for (int j = i + 1; j < samples; j++) { + + if (data[j] < data[i]) { + + float temp = data[i]; + data[i] = data[j]; + data[j] = temp; + } + } + } + + // Ambil rata-rata data tengah + float avg = 0; + + for (int i = 1; i < 4; i++) { + avg += data[i]; + } + + return avg / 3.0; +} +// ===================================================== +// SETUP +// ===================================================== +void setup() { + + Serial.begin(115200); + analogReadResolution(12); + analogSetAttenuation(ADC_11db); + + randomSeed(micros()); + + // ================= PIN ================= + pinMode(TRIG_PIN, OUTPUT); + pinMode(ECHO_PIN, INPUT); + + pinMode(RELAY_MASUK, OUTPUT); + pinMode(RELAY_KELUAR, OUTPUT); + + // RELAY OFF + digitalWrite(RELAY_MASUK, HIGH); + digitalWrite(RELAY_KELUAR, HIGH); + + // ================= I2C ================= + Wire.begin(21, 22); + + // ================= LCD ================= + lcd.begin(); + lcd.backlight(); + + lcd.setCursor(0, 0); + lcd.print("System Ready"); + + delay(2000); + + lcd.clear(); + + // ================= WIFI ================= + setup_wifi(); + + WiFi.onEvent(WiFiEvent); + + // Sinkronisasi waktu dari internet (WIB) + configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov"); + + Serial.print("Mengambil waktu"); + + struct tm timeinfo; + while (!getLocalTime(&timeinfo)) { + Serial.print("."); + delay(500); + } + + Serial.println("\nWaktu berhasil disinkronkan"); + + // ================= MQTT ================= + client.setServer(mqtt_server, mqtt_port); + + client.setCallback(callback); + + client.setBufferSize(512); + filteredDistance = readUltrasonicStable(); +} + +// ===================================================== +// LOOP +// ===================================================== +void loop() { + + // ================= WIFI RECONNECT ================= + if (WiFi.status() != WL_CONNECTED) { + + Serial.println("WiFi Disconnect... reconnect"); + + WiFi.reconnect(); + + unsigned long start = millis(); + + while (WiFi.status() != WL_CONNECTED && + millis() - start < 10000) { + + delay(500); + Serial.print("."); + } + + if (WiFi.status() == WL_CONNECTED) { + Serial.println("\nWiFi Connected"); + } else { + Serial.println("\nReconnect WiFi Failed"); + } + + return; // jangan lanjut MQTT + } + // ================= MQTT ================= + if (!client.connected()) { + + reconnect(); + } + Serial.print("client.loop() : "); + Serial.println(millis()); + + client.loop(); + + // ================= ULTRASONIC ================= + float rawDistance = readUltrasonicStable(); + + filteredDistance = + (alphaDistance * rawDistance) + + ((1.0 - alphaDistance) * filteredDistance); + + distance = filteredDistance; + + + // ================= TURBIDITY ================= + turbidityValue = analogRead(TURBIDITY_PIN); + + // Hitung tegangan sensor + float voltage = turbidityValue * (3.3 / 4095.0); + + // Persamaan hasil kalibrasi + float turbidityNTU = -0.8261 * turbidityValue + 1633.94; + + // Batasi nilai + turbidityNTU = constrain(turbidityNTU, 10.0, 400.0); + // ================= JSON MQTT ================= + StaticJsonDocument<200> doc; + + doc["adc"] = turbidityValue; + doc["turbidity"] = turbidityNTU; + doc["distance"] = distance; + + doc["pompa_masuk"] = + relayMasuk ? 1 : 0; + + doc["pompa_keluar"] = + relayKeluar ? 1 : 0; + + char buffer[200]; + + serializeJson(doc, buffer); + + // ================= PUBLISH ================= + client.publish( + "aquamonn/kekeruhan", + buffer + ); + + // ================= SERIAL ================= + struct tm timeinfo; + + if (getLocalTime(&timeinfo)) { + + char waktu[25]; + strftime(waktu, sizeof(waktu), "%d-%m-%Y %H:%M:%S", &timeinfo); + + Serial.print("Tanggal: "); + Serial.print(waktu); + + Serial.print(" | ADC: "); + Serial.print(turbidityValue); + + Serial.print(" | NTU: "); + Serial.print(turbidityNTU); + + Serial.print(" | Tegangan: "); + Serial.print(voltage, 3); + Serial.print(" V"); + + Serial.print(" | Distance: "); + Serial.print(distance); + + Serial.print(" | Pompa Masuk: "); + Serial.print(relayMasuk ? "ON" : "OFF"); + + Serial.print(" | Pompa Keluar: "); + Serial.println(relayKeluar ? "ON" : "OFF"); + } + // ================= LCD ================= + lcd.clear(); + + lcd.setCursor(0, 0); + lcd.print("NTU:"); + lcd.print(turbidityNTU, 1); + + lcd.setCursor(0, 1); + + lcd.print("M:"); + lcd.print(relayMasuk ? "ON" : "OFF"); + + lcd.print(" K:"); + lcd.print(relayKeluar ? "ON" : "OFF"); + + delay(800); +} \ No newline at end of file