From 4a0af9c7d8637944062744bdb2ad62718dd386eb Mon Sep 17 00:00:00 2001 From: MuhammadIchwanDawanAnggaRamadhan230905 Date: Thu, 30 Jul 2026 12:08:20 +0700 Subject: [PATCH] Upload files to "/" --- kode_arduino.ino | 468 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 kode_arduino.ino diff --git a/kode_arduino.ino b/kode_arduino.ino new file mode 100644 index 0000000..3f451cc --- /dev/null +++ b/kode_arduino.ino @@ -0,0 +1,468 @@ +#include +#include +#include + +// ================= WIFI ================= +#define WIFI_SSID "Angga" +#define WIFI_PASSWORD "upinipinupin" + +// ================= FIREBASE ================= +#define DATABASE_URL "https://tomat2-default-rtdb.asia-southeast1.firebasedatabase.app" +#define DATABASE_SECRET "EsSGEME2IMqmVvWx2VZLkLSKAnJ4Meg6AblUOyxO" + +FirebaseData fbdo; +FirebaseAuth auth; +FirebaseConfig config; + +// ================= PIN ================= +#define SOIL_PIN 34 +#define PIR_PIN 27 +#define RELAY_PIN 26 +#define BUZZER_PIN 25 + +// ================= KALIBRASI ================= +#define SOIL_DRY 2400 +#define SOIL_WET 1100 + +// ================= GLOBAL ================= +volatile bool pirFlag = false; +volatile unsigned long lastInterrupt = 0; + +int pirState = 0; +unsigned long pirHoldTime = 0; +const int pirActiveDuration = 3000; + +int lastMoist = -1; +int lastPir = -1; +int lastPump = -1; + +int lastPumpState = 0; + +String mode = "auto"; +int pumpManual = 0; + +int minMoist = 60; +int maxMoist = 80; + +unsigned long lastSend = 0; +unsigned long lastRead = 0; + +const int sendInterval = 10000; +const int readInterval = 7000; + +// ================= OFFLINE ================= +bool offlineMode = false; + +unsigned long lastOfflineCheck = 0; +const int offlineCheckInterval = 10000; + +// ================= BUZZER ================= +unsigned long lastBuzz = 0; +unsigned long buzzerStart = 0; + +bool buzzerActive = false; + +const int buzzCooldown = 5000; +const int buzzerDuration = 2000; + +bool sendPirNow = false; + +// ================= ISR ================= +void IRAM_ATTR pirISR() { + +  if (millis() - lastInterrupt > 200) { + +    pirFlag = true; +    lastInterrupt = millis(); +  } +} + +// ================= WIFI ================= +void connectWiFi() { + +  static unsigned long lastAttempt = 0; + +  // sudah connect +  if (WiFi.status() == WL_CONNECTED) { +    return; +  } + +  // retry tiap 10 detik +  if (millis() - lastAttempt < 10000) { +    return; +  } + +  lastAttempt = millis(); + +  Serial.println("Connecting WiFi..."); + +  WiFi.disconnect(); + +  WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +} + +// ================= OFFLINE CHECK ================= +void checkOfflineMode() { + +  // cek tiap 10 detik +  if (millis() - lastOfflineCheck < offlineCheckInterval) { +    return; +  } + +  lastOfflineCheck = millis(); + +  // ===== WIFI PUTUS ===== +  if (WiFi.status() != WL_CONNECTED) { + +    if (!offlineMode) { +      Serial.println("⚠️ OFFLINE MODE"); +    } + +    offlineMode = true; +    return; +  } + +  // ===== WIFI NORMAL ===== +  if (offlineMode) { +    Serial.println("✅ BACK ONLINE"); +  } + +  offlineMode = false; +} + +// ================= SAFE SEND ================= +bool sendData(FirebaseJson &json) { + +  // jangan kirim saat offline +  if ( +    offlineMode || +    WiFi.status() != WL_CONNECTED +  ) { +    return false; +  } + +  // firebase belum ready +  if (!Firebase.ready()) { +    return false; +  } + +  // kirim 1x saja +  return Firebase.RTDB.setJSON( +    &fbdo, +    "/sensor", +    &json +  ); +} + +// ================= SETUP ================= +void setup() { + +  Serial.begin(115200); + +  pinMode(PIR_PIN, INPUT); + +  pinMode(RELAY_PIN, OUTPUT); +  pinMode(BUZZER_PIN, OUTPUT); + +  // relay OFF +  digitalWrite(RELAY_PIN, HIGH); + +  digitalWrite(BUZZER_PIN, LOW); + +  analogSetAttenuation(ADC_11db); + +  attachInterrupt( +    digitalPinToInterrupt(PIR_PIN), +    pirISR, +    RISING +  ); + +  // ===== WIFI ===== +  WiFi.mode(WIFI_STA); +  WiFi.setSleep(false); + +  connectWiFi(); + +  WiFi.setAutoReconnect(true); +  WiFi.persistent(true); + +  // ===== FIREBASE ===== +  config.database_url = DATABASE_URL; + +  config.signer.tokens.legacy_token = +    DATABASE_SECRET; + +  Firebase.begin(&config, &auth); + +  Firebase.reconnectWiFi(true); + +  fbdo.setBSSLBufferSize(2048, 512); + +  config.timeout.serverResponse = 3000; + +  // ===== WATCHDOG ===== +  esp_task_wdt_config_t wdt_config = { +    .timeout_ms = 10000, +    .idle_core_mask = (1 << portNUM_PROCESSORS) - 1, +    .trigger_panic = true +  }; + +  esp_task_wdt_init(&wdt_config); + +  esp_task_wdt_add(NULL); + +  Serial.println("System Ready"); +} + +// ================= LOOP ================= +void loop() { + +  esp_task_wdt_reset(); + +  // ===== CHECK ONLINE/OFFLINE ===== +  checkOfflineMode(); + +  // ===== RECONNECT WIFI ===== +  connectWiFi(); + +  // ================= PIR ================= +  if (pirFlag) { + +    pirFlag = false; + +    Serial.println("⚠️ GERAKAN!"); + +    pirState = 1; + +    pirHoldTime = millis(); + +    sendPirNow = true; + +    // ===== BUZZER ===== +    if (millis() - lastBuzz > buzzCooldown) { + +      lastBuzz = millis(); + +      buzzerStart = millis(); + +      buzzerActive = true; +    } +  } + +  // ================= BUZZER ================= +  if (buzzerActive) { + +    static unsigned long lastToggle = 0; +    static bool state = false; + +    if (millis() - lastToggle > 100) { + +      lastToggle = millis(); + +      state = !state; + +      digitalWrite(BUZZER_PIN, state); +    } + +    // ===== STOP BUZZER ===== +    if (millis() - buzzerStart > buzzerDuration) { + +      buzzerActive = false; + +      digitalWrite(BUZZER_PIN, LOW); +    } +  } + +  // ================= RESET PIR ================= +  if ( +    pirState == 1 && +    millis() - pirHoldTime > pirActiveDuration +  ) { + +    pirState = 0; +  } + +  // ================= SENSOR ================= +  int soilRaw = analogRead(SOIL_PIN); + +  int moisture = map( +    soilRaw, +    SOIL_DRY, +    SOIL_WET, +    0, +    100 +  ); + +  moisture = constrain(moisture, 0, 100); + +  // ================================================== +  // ================= LOGIKA POMPA =================== +  // ================================================== + +  int pumpState = lastPumpState; + +  // ===== OFFLINE ===== +  if (offlineMode) { + +    // paksa AUTO lokal +    if (moisture < minMoist) { + +      pumpState = 1; + +    } else if (moisture > maxMoist) { + +      pumpState = 0; +    } + +  } else { + +    // ===== MODE NORMAL ===== +    if (mode == "manual") { + +      pumpState = pumpManual; + +    } else { + +      if (moisture < minMoist) { + +        pumpState = 1; + +      } else if (moisture > maxMoist) { + +        pumpState = 0; +      } +    } +  } + +  lastPumpState = pumpState; + +  // relay active LOW +  digitalWrite( +    RELAY_PIN, +    pumpState ? LOW : HIGH +  ); + +  // ================= DEBUG ================= +  Serial.printf( +    "OFF:%d Moist:%d Pump:%d PIR:%d WiFi:%d\n", +    offlineMode, +    moisture, +    pumpState, +    pirState, +    WiFi.status() +  ); + +  // ================================================== +  // ============== FIREBASE DI BAWAH ================= +  // ================================================== + +  // ================= READ FIREBASE ================= +  if ( +    !offlineMode && +    millis() - lastRead > readInterval +  ) { + +    if ( +      WiFi.status() == WL_CONNECTED && +      Firebase.ready() +    ) { + +      Firebase.RTDB.getString( +        &fbdo, +        "/control/mode" +      ); + +      if (fbdo.dataType() == "string") { +        mode = fbdo.stringData(); +      } + +      Firebase.RTDB.getInt( +        &fbdo, +        "/control/pump" +      ); + +      if (fbdo.dataType() == "int") { +        pumpManual = fbdo.intData(); +      } + +      Firebase.RTDB.getInt( +        &fbdo, +        "/config/min_moisture" +      ); + +      if (fbdo.dataType() == "int") { +        minMoist = fbdo.intData(); +      } + +      Firebase.RTDB.getInt( +        &fbdo, +        "/config/max_moisture" +      ); + +      if (fbdo.dataType() == "int") { +        maxMoist = fbdo.intData(); +      } +    } + +    lastRead = millis(); +  } + +  // ================= PIR REALTIME ================= +  if (sendPirNow) { + +    // reset flag dulu +    sendPirNow = false; + +    // hanya kirim kalau online +    if (!offlineMode) { + +      FirebaseJson json; + +      json.set("moisture", moisture); +      json.set("pir", 1); +      json.set("pump", pumpState); + +      if (sendData(json)) { +        Serial.println("🚀 PIR SENT"); +      } +    } +  } + +  // ================= PERIODIC SEND ================= +  if ( +    !offlineMode && +    millis() - lastSend > sendInterval +  ) { + +    if ( +      abs(moisture - lastMoist) > 3 || +      pirState != lastPir || +      pumpState != lastPump +    ) { + +      FirebaseJson json; + +      json.set("moisture", moisture); +      json.set("pir", pirState); +      json.set("pump", pumpState); + +      if (sendData(json)) { + +        Serial.printf( +          "SEND → M:%d PIR:%d P:%d\n", +          moisture, +          pirState, +          pumpState +        ); +      } + +      lastMoist = moisture; +      lastPir = pirState; +      lastPump = pumpState; +    } + +    lastSend = millis(); +  } + +  delay(20); +} \ No newline at end of file