Upload files to "/"
This commit is contained in:
parent
55efaef6de
commit
4a0af9c7d8
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue