From 7ace429544d32685aab8ba47ada6a04d2659b8ce Mon Sep 17 00:00:00 2001 From: roihan49 Date: Wed, 1 Jul 2026 09:14:21 +0700 Subject: [PATCH] Upload files to "/" --- smartwatering.ino | 318 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 smartwatering.ino diff --git a/smartwatering.ino b/smartwatering.ino new file mode 100644 index 0000000..2545db8 --- /dev/null +++ b/smartwatering.ino @@ -0,0 +1,318 @@ +#include +#include "Adafruit_SHT31.h" +#include +#include +#include + +// ================= WIFI ================= +#define WIFI_SSID "Toge" +#define WIFI_PASSWORD "123123123" + +// ================= FIREBASE ================= +#define DATABASE_URL "https://smarttoge-default-rtdb.firebaseio.com/" +#define DATABASE_SECRET "0CWsHxiRJar3qXSx4uGX385rf0VAnpKKOhQ1wbok" + +// ================= PIN ================= +#define RELAY_PIN 5 + +// ================= OBJECT ================= +Adafruit_SHT31 sht31 = Adafruit_SHT31(); +RTC_DS3231 rtc; + +FirebaseData fbdo; +FirebaseAuth auth; +FirebaseConfig config; + +FirebaseJson json; +FirebaseJsonData result; + +// ================= VAR GLOBAL ================= +bool relayOn = false; +bool pumpRunning = false; +bool pumpManual = false; +bool humidityNotifSent = false; +bool wateringDoneNotifSent = false; +String activeScheduleKey = ""; + + +// TIMER +unsigned long lastSensor = 0; +unsigned long lastFirebase = 0; +unsigned long lastSchedule = 0; +unsigned long lastManual = 0; + +// DATA GLOBAL +float suhu = 0; +float kelembaban = 0; + +String rtcDate = ""; +String rtcTime = ""; + +// ================= SET RTC DARI SERIAL ================= +void setRTCFromSerial() { + + if (Serial.available()) { + + String input = Serial.readStringUntil('\n'); + input.trim(); + + int year, month, day, hour, minute, second; + + if (sscanf(input.c_str(), "%d-%d-%d %d:%d:%d", + &year, &month, &day, + &hour, &minute, &second) == 6) { + + rtc.adjust(DateTime(year, month, day, hour, minute, second)); + + Serial.println("RTC berhasil di-set!"); + } else { + Serial.println("Format salah! Gunakan: YYYY-MM-DD HH:MM:SS"); + } + } +} + +// ================= SETUP ================= +void setup() { + + Serial.begin(115200); + + pinMode(RELAY_PIN, OUTPUT); + digitalWrite(RELAY_PIN, HIGH); + + Wire.begin(21, 22); + + if (!sht31.begin(0x44)) { + Serial.println("Sensor tidak ditemukan!"); + while (1); + } + + if (!rtc.begin()) { + Serial.println("RTC tidak ditemukan!"); + while (1); + } + + // Set otomatis kalau RTC kehilangan daya + if (rtc.lostPower()) { + rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); + } + + Serial.println("Masukkan waktu RTC format:"); + Serial.println("YYYY-MM-DD HH:MM:SS"); + + // ================= WIFI ================= + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + Serial.print("Connecting WiFi"); + + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(500); + } + + Serial.println("\nWiFi Connected"); + + config.database_url = DATABASE_URL; + config.signer.tokens.legacy_token = DATABASE_SECRET; + + Firebase.begin(&config, &auth); + Firebase.reconnectWiFi(true); +} + +// ================= LOOP ================= +void loop() { + + setRTCFromSerial(); // 🔥 input waktu dari serial + + unsigned long nowMillis = millis(); + + // ================= SENSOR ================= + if (nowMillis - lastSensor > 2000) { + lastSensor = nowMillis; + + suhu = sht31.readTemperature(); + kelembaban = sht31.readHumidity(); + + DateTime now = rtc.now(); + + char tgl[11]; + sprintf(tgl, "%02d-%02d-%04d", now.day(), now.month(), now.year()); + rtcDate = String(tgl); + + char jam[9]; + sprintf(jam, "%02d:%02d:%02d", now.hour(), now.minute(), now.second()); + rtcTime = String(jam); + + Serial.println("Sensor Update"); + } + + // ================= MANUAL ================= + if (nowMillis - lastManual > 2000) { + lastManual = nowMillis; + + if (Firebase.RTDB.getBool(&fbdo, "/pump/status")) { + pumpManual = fbdo.boolData(); + } + } + + // ================= SCHEDULE ================= + if (nowMillis - lastSchedule > 15000) { + lastSchedule = nowMillis; + + relayOn = false; + + if (Firebase.RTDB.getJSON(&fbdo, "/schedules")) { + + json = fbdo.jsonObject(); + size_t len = json.iteratorBegin(); + + String key, value; + int type; + + for (size_t i = 0; i < len; i++) { + + json.iteratorGet(i, type, key, value); + + String scheduleTime, scheduleDate, scheduleStatus; + + if (json.get(result, key + "/time")) + scheduleTime = result.to(); + + if (json.get(result, key + "/date")) + scheduleDate = result.to(); + + if (json.get(result, key + "/status")) + scheduleStatus = result.to(); + + int schHour = 0, schMinute = 0; + sscanf(scheduleTime.c_str(), "%d:%d", &schHour, &schMinute); + + DateTime now = rtc.now(); + int hour = now.hour(); + int minute = now.minute(); + +if (rtcDate == scheduleDate && + (hour > schHour || (hour == schHour && minute >= schMinute)) && + scheduleStatus == "idle" && + kelembaban < 85) { + + relayOn = true; + + activeScheduleKey = key; + + Firebase.RTDB.setString( + &fbdo, + "/schedules/" + key + "/status", + "watering"); + + Serial.println("TRIGGER SCHEDULE"); +} + + else if (scheduleStatus == "watering" && !pumpRunning) { + Firebase.RTDB.setString(&fbdo, + "/schedules/" + key + "/status", + "done"); + } + } + + json.iteratorEnd(); + } + } + + // ================= RELAY ================= + if (pumpManual) { + digitalWrite(RELAY_PIN, LOW); + } + +else if (relayOn && !pumpRunning) { + + digitalWrite(RELAY_PIN, LOW); + pumpRunning = true; + + Serial.println("POMPA ON"); +} + +// ================= AUTO OFF SAAT KELEMBAPAN >= 85 ================= +if (pumpRunning && kelembaban >= 85) { + + digitalWrite(RELAY_PIN, HIGH); + + pumpRunning = false; + relayOn = false; + + Serial.println("POMPA OFF - KELEMBAPAN SUDAH 85%"); + + // UPDATE STATUS JADWAL MENJADI DONE + if (activeScheduleKey != "") { + + Firebase.RTDB.setString( + &fbdo, + "/schedules/" + activeScheduleKey + "/status", + "done"); + + activeScheduleKey = ""; + } + + // NOTIFIKASI + Firebase.RTDB.setString( + &fbdo, + "/notification/type", + "watering_done"); + + Firebase.RTDB.setString( + &fbdo, + "/notification/message", + "Penyiraman selesai. Kelembapan telah mencapai 85%"); + + Firebase.RTDB.setInt( + &fbdo, + "/notification/timestamp", + millis()); + + wateringDoneNotifSent = true; +} + + // ================= DEFAULT OFF ================= + if (!relayOn && !pumpRunning && !pumpManual) { + digitalWrite(RELAY_PIN, HIGH); + } + + // ================= FIREBASE UPDATE ================= + if (nowMillis - lastFirebase > 5000) { + lastFirebase = nowMillis; + + Firebase.RTDB.setFloat(&fbdo, "/sht/temperature", suhu); + Firebase.RTDB.setFloat(&fbdo, "/sht/humidity", kelembaban); + Firebase.RTDB.setString(&fbdo, "/sht/time", rtcTime); + Firebase.RTDB.setString(&fbdo, "/sht/date", rtcDate); + +// ================= NOTIFIKASI KELEMBAPAN ================= +if (kelembaban < 70) { + + if (!humidityNotifSent) { + + Firebase.RTDB.setString( + &fbdo, + "/notification/type", + "humidity_low"); + + Firebase.RTDB.setString( + &fbdo, + "/notification/message", + "Kelembapan rendah, segera lakukan penyiraman"); + + Firebase.RTDB.setInt( + &fbdo, + "/notification/timestamp", + millis()); + + humidityNotifSent = true; + wateringDoneNotifSent = false; + } + +} else { + + humidityNotifSent = false; +} + + Serial.println("Firebase Update"); + } +} \ No newline at end of file