643 lines
22 KiB
C++
643 lines
22 KiB
C++
#define BLYNK_TEMPLATE_ID "TMPL6G1uKAeN1"
|
|
#define BLYNK_TEMPLATE_NAME "testingCopy"
|
|
#define BLYNK_AUTH_TOKEN "0QsM_PxN7blv9Zn1Rnroft8uxdJ7zCHR"
|
|
#define relay 4
|
|
#define soilMoisture 34
|
|
#define floot_water 25
|
|
#define buzzer 26
|
|
|
|
#include <WiFi.h>
|
|
#include <WiFiClient.h>
|
|
#include <BlynkSimpleEsp32.h>
|
|
#include <WiFiManager.h>
|
|
#include <ArduinoOTA.h>
|
|
#include <time.h>
|
|
#include <LiquidCrystal_I2C.h>
|
|
#include <Wire.h>
|
|
#include <MySQL_Connection.h>
|
|
#include <MySQL_Cursor.h>
|
|
#include <HTTPClient.h>
|
|
#include <ArduinoJson.h>
|
|
#include <EEPROM.h>
|
|
|
|
// Define constants
|
|
#define BLYNK_TEMPLATE_ID_LEN 20
|
|
#define BLYNK_TEMPLATE_NAME_LEN 40
|
|
#define BLYNK_AUTH_TOKEN_LEN 40
|
|
#define MAX_LEN 40
|
|
|
|
LiquidCrystal_I2C lcd(0X27, 16, 2);
|
|
WiFiClient client;
|
|
MySQL_Connection conn((Client *)&client);
|
|
|
|
bool relayState = false;
|
|
bool relayTurnedOnToday = false;
|
|
bool ManualButtonCondition = false;
|
|
bool AutoButtonCondition = false;
|
|
bool buzzerEnabled = true;
|
|
bool buzzerState = false;
|
|
|
|
int moistureLevelLo = 0;
|
|
int moistureLevelHi = 0;
|
|
float lastSoilMoisture = 0.0;
|
|
|
|
char ssid[64];
|
|
char pass[64];
|
|
char kebun_id[MAX_LEN];
|
|
char blynk_template_id[BLYNK_TEMPLATE_ID_LEN];
|
|
char blynk_template_name[BLYNK_TEMPLATE_NAME_LEN];
|
|
char blynk_auth_token[BLYNK_AUTH_TOKEN_LEN];
|
|
|
|
char created_at[50];
|
|
const char* ntpServer = "pool.ntp.org";
|
|
const long gmtOffset_sec = 25200;
|
|
const int daylightOffset_sec = 0;
|
|
|
|
const char* otaPassword = "admin123"; // Kata sandi OTA
|
|
const char* otaHostname = "ESP32"; // Hostname OTA
|
|
|
|
float soilMoistureValue = analogRead(soilMoisture);
|
|
float calibratedMoisture = map(soilMoistureValue, 4095, 533, 0, 100);
|
|
|
|
unsigned long lastBuzzerStartTime = 0;
|
|
const unsigned long buzzerDuration = 300000;
|
|
const unsigned long buzzerOffDuration = 60000;
|
|
unsigned long lastBuzzerOffTime = 0;
|
|
unsigned long lastPumpStartTime = 0;
|
|
const unsigned long pumpRunDuration = 1 * 60 * 1000;
|
|
unsigned long lastHttpPostTime = 0;
|
|
unsigned long httpPostInterval = 60 * 1000;
|
|
unsigned long pumpManualOnTime = 0;
|
|
|
|
void setup() {
|
|
WiFi.mode(WIFI_STA);
|
|
Serial.begin(115200);
|
|
EEPROM.begin(512);
|
|
pinMode(floot_water, INPUT_PULLUP);
|
|
pinMode(buzzer, OUTPUT);
|
|
digitalWrite(relay, LOW);
|
|
pinMode(relay, OUTPUT);
|
|
lcd.init();
|
|
lcd.backlight();
|
|
// Membaca data dari EEPROM
|
|
String read_kebun_id = EEPROM.readString(0);
|
|
String read_blynk_template_id = EEPROM.readString(20);
|
|
String read_blynk_template_name = EEPROM.readString(60);
|
|
String read_blynk_auth_token = EEPROM.readString(100);
|
|
|
|
// Menampilkan data yang dibaca di Serial Monitor
|
|
Serial.println("Reading from EEPROM:");
|
|
Serial.println("kebun_id: " + read_kebun_id);
|
|
Serial.println("blynk_template_id: " + read_blynk_template_id);
|
|
Serial.println("blynk_template_name: " + read_blynk_template_name);
|
|
Serial.println("blynk_auth_token: " + read_blynk_auth_token);
|
|
|
|
// Inisialisasi WiFiManager
|
|
WiFiManager wifiManager;
|
|
bool needConfiguration = false;
|
|
|
|
// Memeriksa apakah data EEPROM valid
|
|
if (read_kebun_id.length() > 0 && read_blynk_template_id.length() > 0 &&
|
|
read_blynk_template_name.length() > 0 && read_blynk_auth_token.length() > 0) {
|
|
// Data valid, gunakan untuk konfigurasi Blynk
|
|
strncpy(kebun_id, read_kebun_id.c_str(), sizeof(kebun_id));
|
|
strncpy(blynk_template_id, read_blynk_template_id.c_str(), sizeof(blynk_template_id));
|
|
strncpy(blynk_template_name, read_blynk_template_name.c_str(), sizeof(blynk_template_name));
|
|
strncpy(blynk_auth_token, read_blynk_auth_token.c_str(), sizeof(blynk_auth_token));
|
|
|
|
Serial.println("Using saved data from EEPROM:");
|
|
Serial.println("kebun_id: " + String(kebun_id));
|
|
Serial.println("blynk_template_id: " + String(blynk_template_id));
|
|
Serial.println("blynk_template_name: " + String(blynk_template_name));
|
|
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
|
|
|
|
// Coba hubungkan ke WiFi dengan SSID yang disimpan
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("Connecting to");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("WiFi.........");
|
|
delay(5000);
|
|
WiFi.begin(ssid, pass);
|
|
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
|
Serial.println("Failed to connect to WiFi with saved credentials. Opening configuration portal...");
|
|
needConfiguration = true;
|
|
} else {
|
|
Serial.println("Connected to WiFi with saved credentials");
|
|
// Periksa apakah SSID telah berubah
|
|
if (String(WiFi.SSID()) != String(ssid)) {
|
|
Serial.println("SSID has changed, opening configuration portal...");
|
|
needConfiguration = true;
|
|
}
|
|
}
|
|
} else {
|
|
// Data tidak valid atau kosong, buka portal konfigurasi
|
|
Serial.println("No saved data in EEPROM or data invalid. Opening configuration portal...");
|
|
needConfiguration = true;
|
|
}
|
|
|
|
if (needConfiguration) {
|
|
WiFiManagerParameter custom_kebun_id("kebun_id", "Kebun ID", kebun_id, MAX_LEN);
|
|
WiFiManagerParameter custom_blynk_template_id("blynk_template_id", "Blynk Template ID", blynk_template_id, BLYNK_TEMPLATE_ID_LEN);
|
|
WiFiManagerParameter custom_blynk_template_name("blynk_template_name", "Blynk Template Name", blynk_template_name, BLYNK_TEMPLATE_NAME_LEN);
|
|
WiFiManagerParameter custom_blynk_auth_token("blynk_auth_token", "Blynk Auth Token", blynk_auth_token, BLYNK_AUTH_TOKEN_LEN);
|
|
|
|
wifiManager.addParameter(&custom_kebun_id);
|
|
wifiManager.addParameter(&custom_blynk_template_id);
|
|
wifiManager.addParameter(&custom_blynk_template_name);
|
|
wifiManager.addParameter(&custom_blynk_auth_token);
|
|
|
|
if (!wifiManager.autoConnect("TerraTech", "password")) {
|
|
Serial.println("Failed to connect to WiFi and hit timeout");
|
|
ESP.restart();
|
|
delay(1000);
|
|
}
|
|
|
|
// Simpan parameter kustom ke variabel
|
|
strncpy(ssid, WiFi.SSID().c_str(), sizeof(ssid));
|
|
strncpy(pass, WiFi.psk().c_str(), sizeof(pass));
|
|
strncpy(kebun_id, custom_kebun_id.getValue(), sizeof(kebun_id));
|
|
strncpy(blynk_template_id, custom_blynk_template_id.getValue(), sizeof(blynk_template_id));
|
|
strncpy(blynk_template_name, custom_blynk_template_name.getValue(), sizeof(blynk_template_name));
|
|
strncpy(blynk_auth_token, custom_blynk_auth_token.getValue(), sizeof(blynk_auth_token));
|
|
|
|
// Simpan parameter kustom ke EEPROM
|
|
EEPROM.writeString(0, kebun_id);
|
|
EEPROM.writeString(20, blynk_template_id);
|
|
EEPROM.writeString(60, blynk_template_name);
|
|
EEPROM.writeString(100, blynk_auth_token);
|
|
EEPROM.commit();
|
|
|
|
// Tampilkan data yang ditulis ke EEPROM di Serial Monitor
|
|
Serial.println("Saved new data to EEPROM:");
|
|
Serial.println("kebun_id: " + String(kebun_id));
|
|
Serial.println("blynk_template_id: " + String(blynk_template_id));
|
|
Serial.println("blynk_template_name: " + String(blynk_template_name));
|
|
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
|
|
}
|
|
|
|
// Initialize Blynk with obtained credentials
|
|
Blynk.begin(blynk_auth_token, ssid, pass);
|
|
ArduinoOTA.setPassword(otaPassword);
|
|
ArduinoOTA.setHostname(otaHostname);
|
|
ArduinoOTA.begin();
|
|
|
|
// Menampilkan data yang digunakan ke Serial Monitor
|
|
Serial.println("Final data used:");
|
|
Serial.println("kebun_id: " + String(kebun_id));
|
|
Serial.println("blynk_template_id: " + String(blynk_template_id));
|
|
Serial.println("blynk_template_name: " + String(blynk_template_name));
|
|
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
|
|
|
|
buzzTwice();
|
|
uploadWireless();
|
|
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("SSID: ");
|
|
lcd.print(WiFi.SSID());
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("IP: ");
|
|
lcd.print(WiFi.localIP());
|
|
delay(5000);
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print(" Penyiram");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(" Otomatis");
|
|
delay(5000);
|
|
lcd.clear();
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
sendSoilMoistureData();
|
|
delay(500);
|
|
}
|
|
|
|
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
|
|
// Ensure time is properly set up
|
|
// Wait for time to be set
|
|
struct tm timeinfo;
|
|
if (!getLocalTime(&timeinfo)) {
|
|
Serial.println("Failed to obtain time");
|
|
return;
|
|
} else {
|
|
Serial.println("Time obtained successfully");
|
|
Serial.print("Current time: ");
|
|
Serial.printf("%02d-%02d-%04d %02d:%02d:%02d\n",
|
|
timeinfo.tm_mday,
|
|
timeinfo.tm_mon + 1,
|
|
timeinfo.tm_year + 1900,
|
|
timeinfo.tm_hour,
|
|
timeinfo.tm_min,
|
|
timeinfo.tm_sec);
|
|
|
|
lcd.setCursor(0, 0);
|
|
lcd.printf("%02d-%02d-%04d %02d:%02d:%02d",
|
|
timeinfo.tm_mday,
|
|
timeinfo.tm_mon + 1,
|
|
timeinfo.tm_year + 1900,
|
|
timeinfo.tm_hour,
|
|
timeinfo.tm_min,
|
|
timeinfo.tm_sec);
|
|
}
|
|
}
|
|
|
|
void loop() {
|
|
ArduinoOTA.handle();
|
|
Blynk.run();
|
|
getDateTime();
|
|
checkWiFiConnection();
|
|
|
|
unsigned long currentMillis = millis();
|
|
// Kirim data ke server web setiap 1 menit
|
|
if (currentMillis - lastHttpPostTime >= httpPostInterval) {
|
|
int kebun_id_int = atoi(kebun_id);
|
|
sendHttpPost(calibratedMoisture, buzzerState, relayState, kebun_id_int, created_at);
|
|
lastHttpPostTime = currentMillis;
|
|
}
|
|
|
|
// Kirim data ke Blynk setiap 2 detik
|
|
static unsigned long lastBlynkUpdateTime = 0;
|
|
const unsigned long blynkUpdateInterval = 2000; // Waktu interval dalam milidetik (2 detik)
|
|
if (currentMillis - lastBlynkUpdateTime >= blynkUpdateInterval) {
|
|
sendSoilMoistureData(); // Memanggil fungsi untuk mengirim data ke Blynk
|
|
sendRelayStatusToBlynk();
|
|
sendBuzzerStatusToBlynk();
|
|
lastBlynkUpdateTime = currentMillis;
|
|
}
|
|
|
|
// Diperbarui nilai kelembaban tanah
|
|
soilMoistureValue = analogRead(soilMoisture);
|
|
calibratedMoisture = map(soilMoistureValue, 4095, 533, 0, 100);
|
|
calibratedMoisture = constrain(calibratedMoisture, 0, 100);
|
|
|
|
bool isDry = (calibratedMoisture < moistureLevelLo);
|
|
bool isPumpOn = relayState;
|
|
displayLCD(isDry, calibratedMoisture, isPumpOn);
|
|
|
|
// Cek jadwal pompa dan kontrol pompa berdasarkan jadwal
|
|
checkPumpSchedule();
|
|
handleFlootWater();
|
|
// Kontrol relay berdasarkan kelembaban tanah
|
|
controlRelayBasedOnSoilMoisture();
|
|
|
|
delay(1000); // Delay singkat untuk menjaga agar loop tidak terlalu cepat
|
|
}
|
|
|
|
void checkWiFiConnection() {
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println("WiFi connection lost.");
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("WiFi connection lost.");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Reconnecting....");
|
|
|
|
// Start WiFi Manager again for reconnection attempt
|
|
WiFiManager wifiManager;
|
|
|
|
// Custom parameters to configure in WiFi Manager
|
|
WiFiManagerParameter custom_kebun_id("kebun_id", "Kebun ID", kebun_id, MAX_LEN);
|
|
WiFiManagerParameter custom_blynk_template_id("blynk_template_id", "Blynk Template ID", blynk_template_id, BLYNK_TEMPLATE_ID_LEN);
|
|
WiFiManagerParameter custom_blynk_template_name("blynk_template_name", "Blynk Template Name", blynk_template_name, BLYNK_TEMPLATE_NAME_LEN);
|
|
WiFiManagerParameter custom_blynk_auth_token("blynk_auth_token", "Blynk Auth Token", blynk_auth_token, BLYNK_AUTH_TOKEN_LEN);
|
|
|
|
wifiManager.addParameter(&custom_kebun_id);
|
|
wifiManager.addParameter(&custom_blynk_template_id);
|
|
wifiManager.addParameter(&custom_blynk_template_name);
|
|
wifiManager.addParameter(&custom_blynk_auth_token);
|
|
|
|
if (!wifiManager.autoConnect("TerraTech", "password")) {
|
|
Serial.println("Failed to connect and hit timeout");
|
|
// Handle failure (e.g., restart)
|
|
ESP.restart();
|
|
}
|
|
|
|
// Check if connected after trying to connect
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
Serial.println("\nWiFi reconnected");
|
|
lcd.clear();
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("Connected to");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(WiFi.SSID());
|
|
|
|
// Update credentials
|
|
strncpy(ssid, WiFi.SSID().c_str(), sizeof(ssid));
|
|
strncpy(pass, WiFi.psk().c_str(), sizeof(pass));
|
|
strncpy(kebun_id, custom_kebun_id.getValue(), sizeof(kebun_id));
|
|
strncpy(blynk_template_id, custom_blynk_template_id.getValue(), sizeof(blynk_template_id));
|
|
strncpy(blynk_template_name, custom_blynk_template_name.getValue(), sizeof(blynk_template_name));
|
|
strncpy(blynk_auth_token, custom_blynk_auth_token.getValue(), sizeof(blynk_auth_token));
|
|
|
|
EEPROM.writeString(0, kebun_id);
|
|
EEPROM.writeString(20, blynk_template_id);
|
|
EEPROM.writeString(60, blynk_template_name);
|
|
EEPROM.writeString(100, blynk_auth_token);
|
|
EEPROM.commit();
|
|
|
|
Serial.println("Saved new data to EEPROM:");
|
|
Serial.println("kebun_id: " + String(kebun_id));
|
|
Serial.println("blynk_template_id: " + String(blynk_template_id));
|
|
Serial.println("blynk_template_name: " + String(blynk_template_name));
|
|
Serial.println("blynk_auth_token: " + String(blynk_auth_token));
|
|
|
|
// Reinitialize Blynk with new credentials
|
|
Blynk.begin(blynk_auth_token, ssid, pass);
|
|
} else {
|
|
Serial.println("\nFailed to reconnect WiFi. Restarting...");
|
|
ESP.restart();
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleFlootWater() {
|
|
unsigned long currentMillis = millis();
|
|
|
|
if (buzzerEnabled) { // Only handle buzzer if it's enabled
|
|
if (digitalRead(floot_water) == HIGH && (currentMillis - lastBuzzerOffTime >= buzzerOffDuration)) { // Floot water up
|
|
if (!buzzerState) {
|
|
digitalWrite(buzzer, HIGH);
|
|
buzzerState = true;
|
|
lastBuzzerStartTime = millis();
|
|
}
|
|
} else { // Floot water down
|
|
if (buzzerState) {
|
|
digitalWrite(buzzer, LOW);
|
|
buzzerState = false;
|
|
lastBuzzerOffTime = millis();
|
|
Blynk.virtualWrite(V10, "Hidupkan Mode Otomatis atau Manual");
|
|
}
|
|
}
|
|
// Turn off the buzzer after the specified duration if floot water stays high
|
|
if (buzzerState && (currentMillis - lastBuzzerStartTime >= buzzerDuration)) {
|
|
digitalWrite(buzzer, LOW);
|
|
buzzerState = false;
|
|
lastBuzzerOffTime = millis(); // Record the time when the buzzer was turned off
|
|
}
|
|
} else {
|
|
digitalWrite(buzzer, LOW);
|
|
buzzerState = false;
|
|
}
|
|
}
|
|
|
|
void sendHttpPost(float calibratedMoisture, bool buzzerState, bool relayState, int kebun_id, const char* created_at) {
|
|
HTTPClient http;
|
|
Serial.println("Starting HTTP POST...");
|
|
|
|
http.begin("https://kantorku.cloud/terratech/upload/upload.php");
|
|
http.addHeader("Content-Type", "application/json");
|
|
StaticJsonDocument<200> jsonDoc;
|
|
jsonDoc["soil_moisture"] = calibratedMoisture;
|
|
jsonDoc["buzzer_state"] = buzzerState;
|
|
jsonDoc["relay_state"] = relayState;
|
|
jsonDoc["kebun_id"] = kebun_id;
|
|
jsonDoc["created_at"] = created_at;
|
|
String jsonString;
|
|
serializeJson(jsonDoc, jsonString);
|
|
|
|
// Send POST request with JSON payload
|
|
int httpResponseCode = http.POST(jsonString);
|
|
|
|
if (httpResponseCode > 0) {
|
|
Serial.print("HTTP Response code: ");
|
|
Serial.println(httpResponseCode);
|
|
String response = http.getString();
|
|
Serial.println(response);
|
|
Serial.println("---------------------------------");
|
|
} else {
|
|
Serial.print("Error code: ");
|
|
Serial.println(httpResponseCode);
|
|
Serial.println("---------------------------------");
|
|
}
|
|
|
|
http.end();
|
|
}
|
|
|
|
void uploadWireless() {
|
|
ArduinoOTA.setHostname(otaHostname); // Hostname OTA
|
|
ArduinoOTA.setPassword(otaPassword); // Kata sandi OTA
|
|
ArduinoOTA.onStart([]() {
|
|
String type;
|
|
if (ArduinoOTA.getCommand() == U_FLASH)
|
|
type = "sketch";
|
|
else // U_SPIFFS
|
|
type = "filesystem";
|
|
|
|
Serial.println("Start updating " + type);
|
|
})
|
|
.onEnd([]() {
|
|
Serial.println("\nEnd");
|
|
})
|
|
.onProgress([](unsigned int progress, unsigned int total) {
|
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
|
})
|
|
.onError([](ota_error_t error) {
|
|
Serial.printf("Error[%u]: ", error);
|
|
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
|
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
|
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
|
if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
|
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
|
});
|
|
|
|
ArduinoOTA.begin();
|
|
|
|
Serial.println("Ready");
|
|
Serial.print("IP address: ");
|
|
Serial.println(WiFi.localIP());
|
|
}
|
|
|
|
void displayLCD(bool isDry, float moistureValue, bool isPumpOn) {
|
|
lcd.clear();
|
|
char moistureStr[6]; // Menyimpan string untuk kelembaban tanah
|
|
|
|
// Format nilai kelembaban ke dalam format dua digit dengan angka nol di depan jika diperlukan
|
|
sprintf(moistureStr, "%05.2f", moistureValue);
|
|
|
|
if (isDry) {
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("T Kering: ");
|
|
lcd.print(moistureStr);
|
|
lcd.print("%");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Pompa : ");
|
|
lcd.print(isPumpOn ? "Hidup" : "Mati");
|
|
} else {
|
|
lcd.setCursor(0, 0);
|
|
lcd.print("T Basah: ");
|
|
lcd.print(moistureStr);
|
|
lcd.print("%");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Pompa : ");
|
|
lcd.print(isPumpOn ? "Hidup" : "Mati");
|
|
}
|
|
}
|
|
|
|
void sendRelayStatusToBlynk() {
|
|
// Mengirim status relay ke pin virtual 14 di Blynk
|
|
Blynk.virtualWrite(V14, relayState ? "Hidup" : "Mati");
|
|
}
|
|
|
|
void sendBuzzerStatusToBlynk() {
|
|
// Mengirim status buzzer ke pin virtual 15 di Blynk
|
|
Blynk.virtualWrite(V15, buzzerState ? "Habis" : "Penuh");
|
|
}
|
|
|
|
void getDateTime() {
|
|
struct tm timeinfo;
|
|
if (!getLocalTime(&timeinfo)) {
|
|
Serial.println("Failed to obtain time");
|
|
snprintf(created_at, sizeof(created_at), "0000-00-00 00:00:00");
|
|
} else {
|
|
snprintf(created_at, sizeof(created_at), "%04d-%02d-%02d %02d:%02d:%02d",
|
|
timeinfo.tm_year + 1900,
|
|
timeinfo.tm_mon + 1,
|
|
timeinfo.tm_mday,
|
|
timeinfo.tm_hour,
|
|
timeinfo.tm_min,
|
|
timeinfo.tm_sec);
|
|
}
|
|
}
|
|
|
|
void controlRelayBasedOnSoilMoisture() {
|
|
static unsigned long lastTurnOnTime = 0;
|
|
static unsigned long lastTurnOffTime = 0;
|
|
unsigned long currentTime = millis();
|
|
|
|
|
|
if (digitalRead(floot_water) == HIGH) { // Check if floot water is HIGH
|
|
// If flood water is low, turn off the relay
|
|
digitalWrite(relay, LOW); // Matikan pompa
|
|
relayState = false;
|
|
Serial.println("Pompa dimatikan karena floot water rendah");
|
|
Blynk.virtualWrite(V10, "Air Habis Penyiraman Nonaktif");
|
|
handleFlootWater();
|
|
return; // Exit the function
|
|
}
|
|
|
|
if (AutoButtonCondition) {
|
|
// Mode otomatis aktif
|
|
if (calibratedMoisture < moistureLevelLo && !relayState) {
|
|
digitalWrite(relay, HIGH); // Nyalakan pompa
|
|
relayState = true;
|
|
lastTurnOnTime = currentTime;
|
|
Serial.println("Pompa dinyalakan otomatis karena kelembaban rendah");
|
|
} else if (calibratedMoisture >= moistureLevelHi && relayState) {
|
|
digitalWrite(relay, LOW); // Matikan pompa
|
|
relayState = false;
|
|
lastTurnOffTime = currentTime;
|
|
Serial.println("Pompa dimatikan otomatis karena kelembaban cukup tinggi");
|
|
}
|
|
} else if (ManualButtonCondition) {
|
|
// Mode manual aktif
|
|
digitalWrite(relay, HIGH); // Nyalakan pompa
|
|
relayState = true;
|
|
pumpManualOnTime = currentTime; // Set the manual on time
|
|
Serial.println("Pompa dinyalakan secara manual");
|
|
} else {
|
|
// Matikan pompa jika tidak dalam mode otomatis atau manual
|
|
digitalWrite(relay, LOW); // Matikan pompa
|
|
relayState = false;
|
|
Serial.println("Pompa dimatikan karena tidak dalam mode otomatis atau manual");
|
|
}
|
|
}
|
|
|
|
void sendSoilMoistureData() {
|
|
if (calibratedMoisture != lastSoilMoisture) {
|
|
lastSoilMoisture = calibratedMoisture;
|
|
Blynk.virtualWrite(V11, calibratedMoisture);
|
|
Serial.print("Soil Moisture: ");
|
|
Serial.println(soilMoistureValue);
|
|
Serial.print("kalibrasi: ");
|
|
Serial.println(calibratedMoisture);
|
|
Serial.println("Relay: " + (String)(relayState ? "Hidup" : "Mati"));
|
|
Serial.println("Moisture Lo: " + (String)moistureLevelLo);
|
|
Serial.println("Moisture Hi: " + (String)moistureLevelHi);
|
|
Serial.println("buzzer: " + (String)(buzzerState ? "Hidup" : "Mati"));
|
|
Serial.println("Level Air: " + (String)floot_water);
|
|
Serial.println("Soil Moisture data sent to Blynk");
|
|
Serial.println("---------------------------------");
|
|
}
|
|
}
|
|
|
|
void buzzTwice() {
|
|
for (int i = 0; i < 2; i++) {
|
|
digitalWrite(buzzer, HIGH);
|
|
delay(100); // Buzz duration
|
|
digitalWrite(buzzer, LOW);
|
|
delay(100); // Pause between buzzes
|
|
}
|
|
}
|
|
|
|
void checkPumpSchedule() {
|
|
unsigned long currentMillis = millis();
|
|
struct tm timeinfo;
|
|
|
|
// Check if the current time is 9 AM
|
|
if (getLocalTime(&timeinfo)) {
|
|
if (timeinfo.tm_hour == 9 && timeinfo.tm_min == 0 && !relayTurnedOnToday) {
|
|
digitalWrite(relay, HIGH); // Turn on the pump
|
|
relayState = true;
|
|
lastPumpStartTime = currentMillis;
|
|
relayTurnedOnToday = true;
|
|
Serial.println("Pompa dinyalakan pada pukul 9 pagi");
|
|
}
|
|
}
|
|
|
|
// Turn off the pump after the run duration
|
|
if (relayTurnedOnToday && (currentMillis - lastPumpStartTime >= pumpRunDuration)) {
|
|
digitalWrite(relay, LOW); // Turn off the pump
|
|
relayState = false;
|
|
relayTurnedOnToday = false; // Reset for the next day
|
|
Serial.println("Pompa dimatikan setelah 1 menit");
|
|
}
|
|
}
|
|
|
|
BLYNK_WRITE(V8) {
|
|
moistureLevelLo = param.asInt();
|
|
Serial.print("Set low moisture level: ");
|
|
Serial.println(moistureLevelLo);
|
|
}
|
|
|
|
BLYNK_WRITE(V9) {
|
|
moistureLevelHi = param.asInt();
|
|
Serial.print("Set high moisture level: ");
|
|
Serial.println(moistureLevelHi);
|
|
}
|
|
|
|
BLYNK_WRITE(V6) {
|
|
AutoButtonCondition = param.asInt();
|
|
if (AutoButtonCondition == 1) {
|
|
Serial.println("Automatic mode activated");
|
|
Blynk.virtualWrite(V10, "Penyiraman Otomatis Hidup");
|
|
} else {
|
|
Serial.println("Automatic mode deactivated");
|
|
Blynk.virtualWrite(V10, "Penyiraman Mati");
|
|
}
|
|
}
|
|
|
|
BLYNK_WRITE(V7) {
|
|
relayState = param.asInt() == 1;
|
|
if (relayState == 1) {
|
|
digitalWrite(relay, HIGH);
|
|
ManualButtonCondition = true;
|
|
Blynk.virtualWrite(V8, created_at);
|
|
Blynk.virtualWrite(V10, "Penyiraman Manual Hidup");
|
|
} else {
|
|
digitalWrite(relay, LOW);
|
|
ManualButtonCondition = false;
|
|
Blynk.virtualWrite(V10, "Penyiraman Mati");
|
|
}
|
|
}
|
|
|
|
BLYNK_WRITE(V13) { // New Blynk virtual pin for buzzer control
|
|
buzzerEnabled = param.asInt() == 1;
|
|
if (buzzerEnabled) {
|
|
Serial.println("Buzzer enabled");;
|
|
} else {
|
|
Serial.println("Buzzer disabled");
|
|
digitalWrite(buzzer, LOW);
|
|
buzzerState = false;
|
|
}
|
|
} |