TKK_E32232430/kontrol_kekeruhan_dan_volum...

473 lines
9.9 KiB
C++

#include <WiFi.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include <time.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ArduinoJson.h>
// ================= 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);
}