Upload files to "/"

This commit is contained in:
MuhammadIchwanDawanAnggaRamadhan230905 2026-07-30 12:08:20 +07:00
parent 55efaef6de
commit 4a0af9c7d8
1 changed files with 468 additions and 0 deletions

468
kode_arduino.ino Normal file
View File

@ -0,0 +1,468 @@
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <esp_task_wdt.h>
// ================= 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);
}