From 38f3292434a3b17d77a6b2a8f4d9f00c7e2a07ae Mon Sep 17 00:00:00 2001 From: Lutfi Date: Thu, 10 Jul 2025 16:45:39 +0700 Subject: [PATCH] esp32 jemuran pintar --- ESP32_JemuranPintar.ino | 216 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 ESP32_JemuranPintar.ino diff --git a/ESP32_JemuranPintar.ino b/ESP32_JemuranPintar.ino new file mode 100644 index 0000000..7ae8568 --- /dev/null +++ b/ESP32_JemuranPintar.ino @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include + +// LCD configuration +int lcdColumns = 16; +int lcdRows = 2; +LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); + +// WiFi configuration +#define WIFI_SSID "Nofal" +#define WIFI_PASSWORD "123456789" + +// Firebase configuration +#define API_KEY "AIzaSyCncK2P7cCxBlwIikX-cxcQ8lneUalADVw" +#define DATABASE_URL "https://esp32-86fe1-default-rtdb.asia-southeast1.firebasedatabase.app/" +#define USER_EMAIL "lutfi@gmail.com" +#define USER_PASSWORD "1234567" + +// Pin configuration +#define LDR_PIN 13 +#define RD_PIN 35 +static const int servoPin = 14; + +Servo myServo; + +// Firebase & NTP objects +FirebaseData fbdo; +FirebaseAuth auth; +FirebaseConfig config; +WiFiUDP ntpUDP; +NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000); // GMT+7 + +unsigned long sendDataPrevMillis = 0; +int lastRainState = -1; +int lastLightValue = -1; +int lastPositionValue = -1; + +// LCD scroll text variables +String scrollText = ""; +int scrollIndex = 0; +unsigned long lastScrollTime = 0; +const int scrollDelay = 300; + +String getFormattedDate() { + time_t rawTime = timeClient.getEpochTime(); + struct tm *timeInfo = localtime(&rawTime); + char buffer[11]; + strftime(buffer, sizeof(buffer), "%Y-%m-%d", timeInfo); + return String(buffer); +} + +// Update LCD scroll text +void updateScrollText(int posValue, int rain, int light) { + String posText = (posValue == 0) ? "Jemuran di luar. " : "Jemuran di dalam. "; + String lightText, weatherText; + + if (rain == 1 && light == 1) { + lightText = "Light: overcast. "; + weatherText = "Weather: Cloudy. "; + } else if (rain == 0 && light == 0) { + lightText = "Light: Good. "; + weatherText = "Weather: Rainy. "; + } else if (rain == 0 && light == 1) { + lightText = "Light: Overcast. "; + weatherText = "Weather: Rainy. "; + } else { + lightText = "Light: Good. "; + weatherText = "Weather: Sunny. "; + } + + scrollText = posText + lightText + weatherText; +} + +// Display scroll text + WiFi status +void scrollTextToLCD(bool isOnline) { + if (millis() - lastScrollTime >= scrollDelay) { + lastScrollTime = millis(); + lcd.clear(); + lcd.setCursor(0, 0); + int len = scrollText.length(); + String toPrint = scrollText.substring(scrollIndex, scrollIndex + lcdColumns); + lcd.print(toPrint); + + lcd.setCursor(0, 1); + lcd.print(isOnline ? "Status: Online " : "Status:Offline"); + + scrollIndex++; + if (scrollIndex > len) scrollIndex = 0; + } +} + +void setup() { + pinMode(LDR_PIN, INPUT); + pinMode(RD_PIN, INPUT); + myServo.attach(servoPin); + Serial.begin(9600); + + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + Serial.print("Connecting to Wi-Fi"); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(300); + } + Serial.println("\nConnected with IP: " + WiFi.localIP().toString()); + + config.api_key = API_KEY; + auth.user.email = USER_EMAIL; + auth.user.password = USER_PASSWORD; + config.database_url = DATABASE_URL; + + Firebase.reconnectNetwork(true); + fbdo.setBSSLBufferSize(4096, 1024); + fbdo.setResponseSize(2048); + Firebase.begin(&config, &auth); + Firebase.setDoubleDigits(5); + config.timeout.serverResponse = 10 * 1000; + + lcd.init(); + lcd.backlight(); + + timeClient.begin(); +} + +void loop() { + timeClient.update(); + + // Baca sensor + int rainStateNow = digitalRead(RD_PIN); + int lightValueNow = digitalRead(LDR_PIN); + int currentPosition = lastPositionValue; + + // Update LCD lokal + updateScrollText(currentPosition, rainStateNow, lightValueNow); + bool isOnline = WiFi.status() == WL_CONNECTED; + scrollTextToLCD(isOnline); + + // Jika Wi-Fi dan Firebase ready + if (isOnline && Firebase.ready() && (millis() - sendDataPrevMillis > 1000 || sendDataPrevMillis == 0)) { + sendDataPrevMillis = millis(); + + String status; + if (Firebase.RTDB.getString(&fbdo, "/status/value")) { + status = fbdo.stringData(); + Serial.println("Status: " + status); + } else { + Serial.print("Error fetching status: "); + Serial.println(fbdo.errorReason().c_str()); + return; + } + + if (status == "Off") { + int positionValue = -1; + if (Firebase.RTDB.getInt(&fbdo, "/position/value")) { + positionValue = fbdo.intData(); + } + + if (positionValue == 1) { + lastPositionValue = 1; + return; + } + + myServo.write(55); + Firebase.RTDB.setInt(&fbdo, "/position/value", 1); + lastPositionValue = 1; + return; + } + + // Logika otomatis saat online + int newPositionValue = (rainStateNow == 1 && lightValueNow == 0) ? 0 : 1; + + if (rainStateNow != lastRainState || lightValueNow != lastLightValue) { + if (Firebase.RTDB.setInt(&fbdo, "/sensor/ldr", lightValueNow) && Firebase.RTDB.setInt(&fbdo, "/sensor/rd", rainStateNow)) { + Serial.println("Sensor updated."); + } + + lastRainState = rainStateNow; + lastLightValue = lightValueNow; + + FirebaseJson json; + json.set("tanggal", getFormattedDate()); + json.set("jam", timeClient.getFormattedTime()); + json.set("ldr", lightValueNow); + json.set("rd", rainStateNow); + + Firebase.RTDB.pushJSON(&fbdo, "/weather", &json); + } + + if (newPositionValue != lastPositionValue) { + if (Firebase.RTDB.setInt(&fbdo, "/position/value", newPositionValue)) { + if (newPositionValue == 0) { + myServo.write(110); + } else { + myServo.write(55); + } + } + lastPositionValue = newPositionValue; + } + } else { + // Mode offline: kontrol lokal + Serial.println("Firebase not ready or Wi-Fi lost. Running offline mode."); + int newPositionValue = (rainStateNow == 1 && lightValueNow == 0) ? 0 : 1; + + if (newPositionValue != lastPositionValue) { + if (newPositionValue == 0) { + myServo.write(110); // Jemuran masuk + } else { + myServo.write(55); // Jemuran keluar + } + lastPositionValue = newPositionValue; + } + } +}