TIF_NGANJUK_E41211669/ESP8266/ESP8266.ino

256 lines
7.3 KiB
C++

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// === WiFi & MQTT ===
const char* ssid = "Fansyah";
const char* password = "12345678";
const char* mqtt_server = "203.194.113.47";
WiFiClient espClient;
PubSubClient client(espClient);
// === NTP (UTC+7) ===
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200);
// === Pin ===
#define RELAY1 D0
#define RELAY2 D4
#define SERVO_PIN D5
Servo myServo;
// === Jadwal Pakan ===
int morningHour = 6, morningMinute = 0;
int eveningHour = 17, eveningMinute = 30;
bool morningFed = false, eveningFed = false, modeOtomatis = true;
// === Servo Timer ===
bool servoActive = false;
unsigned long servoStartTime = 0;
const unsigned long SERVO_DURATION = 60000;
// === Data pH & Tegangan ===
float pHValue = 0.0;
float voltageValue = 0.0;
unsigned long lastDataReceivedTime = 0;
// === Threshold Relay ===
const float pH_THRESHOLD_LOW = 6.5;
const float pH_THRESHOLD_HIGH = 7.5;
// === Mode Pompa ===
bool modePompaOtomatis = true; // default otomatis
String perintahManual = "netral"; // default netral
void setup() {
Serial.begin(9600);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
myServo.attach(SERVO_PIN);
myServo.write(0); // Posisi awal servo
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print(".");
}
Serial.println("\nWiFi Terhubung: " + WiFi.localIP().toString());
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
timeClient.begin();
Serial.println("Menunggu data pH dari Arduino...");
}
void loop() {
if (!client.connected()) reconnectMQTT();
client.loop();
timeClient.update();
checkSchedule();
readSerialData();
checkServo();
sendCurrentTimeToMQTT();
checkpHLevel(); // Periksa dan kontrol relay
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Menghubungkan ke MQTT...");
if (client.connect("ESPFeederClient")) {
Serial.println(" Terhubung!");
client.subscribe("feeder/jadwal/siang");
client.subscribe("feeder/jadwal/sore");
client.subscribe("feeder/mode");
client.subscribe("feeder/modepompa");
client.subscribe("feeder/manual/kontrol");
client.publish("feeder/status", "ESP Terhubung");
} else {
Serial.print(" Gagal ("); Serial.print(client.state());
Serial.println("). Coba lagi 5 detik...");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
msg.trim();
if (String(topic) == "feeder/jadwal/siang") {
int sep = msg.indexOf(':');
morningHour = msg.substring(0, sep).toInt();
morningMinute = msg.substring(sep + 1).toInt();
Serial.println("[MQTT] Jadwal Siang: " + msg);
} else if (String(topic) == "feeder/jadwal/sore") {
int sep = msg.indexOf(':');
eveningHour = msg.substring(0, sep).toInt();
eveningMinute = msg.substring(sep + 1).toInt();
Serial.println("[MQTT] Jadwal Sore: " + msg);
} else if (String(topic) == "feeder/mode") {
modeOtomatis = (msg == "otomatis");
Serial.println("[MQTT] Mode: " + msg);
} else if (String(topic) == "feeder/modepompa") {
modePompaOtomatis = (msg == "otomatis");
Serial.println("[MQTT] Mode Pompa: " + msg);
} else if (String(topic) == "feeder/manual/kontrol") {
perintahManual = msg;
Serial.println("[MQTT] Perintah Manual Pompa: " + msg);
}
}
void checkSchedule() {
int h = timeClient.getHours();
int m = timeClient.getMinutes();
if (modeOtomatis) {
if (h == morningHour && m == morningMinute && !morningFed) {
triggerFeeding("Pagi");
morningFed = true;
eveningFed = false;
}
if (h == eveningHour && m == eveningMinute && !eveningFed) {
triggerFeeding("Sore");
eveningFed = true;
morningFed = false;
}
if (h != morningHour || m != morningMinute) morningFed = false;
if (h != eveningHour || m != eveningMinute) eveningFed = false;
}
}
void triggerFeeding(String waktu) {
Serial.println(">> MEMBERI PAKAN " + waktu + " (" + timeClient.getFormattedTime() + ")");
myServo.write(90); // Aktifkan servo
servoStartTime = millis();
servoActive = true;
String notif = "Pakan diberikan - " + waktu + " | " + timeClient.getFormattedTime();
client.publish("feeder/notifikasi", notif.c_str());
Serial.println("[MQTT] " + notif);
}
void checkServo() {
if (servoActive && millis() - servoStartTime >= SERVO_DURATION) {
myServo.write(0); // Kembalikan ke posisi awal
servoActive = false;
Serial.println("[INFO] Servo dimatikan");
}
}
void readSerialData() {
if (Serial.available()) {
String in = Serial.readStringUntil('\n');
in.trim();
int sep = in.indexOf(',');
if (sep > 0) {
float pH = in.substring(0, sep).toFloat();
float volt = in.substring(sep + 1).toFloat();
String t = timeClient.getFormattedTime();
String ph_payload = String(pH, 2) + " | " + t;
String volt_payload = String(volt, 3) + " V | " + t;
client.publish("feeder/pH", ph_payload.c_str());
client.publish("feeder/tegangan", volt_payload.c_str());
Serial.printf("[DATA] pH: %.2f | V: %.3f | %s\n", pH, volt, t.c_str());
lastDataReceivedTime = millis();
pHValue = pH;
voltageValue = volt;
}
}
if (millis() - lastDataReceivedTime > 10000 && lastDataReceivedTime != 0) {
String t = timeClient.getFormattedTime();
client.publish("feeder/pH", ("0 | " + t).c_str());
client.publish("feeder/tegangan", ("0 V | " + t).c_str());
Serial.println("[WARNING] Timeout data pH");
lastDataReceivedTime = 0;
}
}
void kirimStatusPompa(String status) {
client.publish("feeder/statuspompa", status.c_str());
Serial.println("[MQTT] Status Pompa: " + status);
}
void checkpHLevel() {
String status = "Pompa OFF";
if (modePompaOtomatis) {
Serial.print(">> [Otomatis] Pemeriksaan pH: "); Serial.println(pHValue, 2);
if (pHValue < pH_THRESHOLD_LOW) {
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, HIGH);
status = "Pompa 1 Aktif (Otomatis - pH rendah)";
} else if (pHValue > pH_THRESHOLD_HIGH) {
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
status = "Pompa 2 Aktif (Otomatis - pH tinggi)";
} else {
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
status = "Tidak ada Pompa Aktif (Otomatis - pH normal)";
}
} else {
Serial.print(">> [Manual] Perintah: "); Serial.println(perintahManual);
if (perintahManual == "ph_rendah") {
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, HIGH);
status = "Pompa 1 Aktif (Manual - pH rendah)";
} else if (perintahManual == "ph_tinggi") {
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
status = "Pompa 2 Aktif (Manual - pH tinggi)";
} else {
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, HIGH);
status = "Tidak ada Pompa Aktif (Manual - Netral)";
}
}
kirimStatusPompa(status);
}
void sendCurrentTimeToMQTT() {
static unsigned long last = 0;
if (millis() - last >= 1000) {
last = millis();
String t = timeClient.getFormattedTime();
client.publish("feeder/waktu", t.c_str());
Serial.println("[MQTT] Waktu dikirim: " + t);
}
}