#define BLYNK_TEMPLATE_ID "TMPL6lOjQRche"
#define BLYNK_TEMPLATE_NAME "iot smart garden"
#define BLYNK_AUTH_TOKEN "vSE9a-WyRAcQOwVGrzjjKjcOwu6UiIGj"
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
// Pin sensor kelembapan tanah dan termistor
#define SOIL_MOISTURE_PIN 34
#define NTC_ANALOG_PIN 35
// Pin untuk mengendalikan output pompa (relay)
#define CONTROL_PIN 14
// Pin untuk tombol manual
#define BUTTON_PIN 13
// Definisi ukuran layar OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Konfigurasi OLED SSD1306
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Parameter untuk kelembapan tanah
int minMoistureValue = 1725; // Nilai ADC pada tanah kering
int maxMoistureValue = 3500; // Nilai ADC pada tanah basah
int thresholdMoisture = 30; // Minimal kelembapan untuk menghidupkan pompa otomatis
// Parameter untuk sensor NTC
const float BETA = 3950;
const float calibrationOffset = 0.03; // Faktor kalibrasi suhu
float suhu = 0.0;
// Status pompa
bool isPumpOn = false;
bool manualMode = false; // Menandakan apakah pompa dikendalikan secara manual
// Untuk debounce tombol
int lastButtonState = HIGH; // Status tombol sebelumnya
unsigned long lastDebounceTime = 0; // Waktu terakhir tombol berubah
unsigned long debounceDelay = 200; // Delay debounce (200ms)
// WiFi credentials
const char* ssid = "Wokwi-GUEST"; // Ganti dengan SSID WiFi Anda
const char* password = ""; // Ganti dengan password WiFi Anda
// Timer untuk Blynk
BlynkTimer timer;
// Fungsi untuk membaca nilai dari sensor NTC
float bacaSensorNTC() {
int analogValue = analogRead(NTC_ANALOG_PIN);
float celsius = 1 / (log(1 / (4095.0 / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
celsius += calibrationOffset; // Menambahkan faktor kalibrasi untuk hasil lebih akurat
return celsius;
}
// Fungsi Blynk untuk mengendalikan pompa via Virtual Pin (V0)
BLYNK_WRITE(V0) {
int pinValue = param.asInt(); // Membaca nilai dari aplikasi Blynk (0 atau 1)
isPumpOn = pinValue; // Atur status pompa sesuai nilai dari Blynk
digitalWrite(CONTROL_PIN, isPumpOn ? HIGH : LOW); // Kontrol relay pompa
manualMode = true; // Aktifkan mode manual ketika dikendalikan via Blynk
Blynk.virtualWrite(V4, isPumpOn ? "ON" : "OFF"); // Kirim status pompa ke Blynk (V4)
}
// Fungsi untuk mengirim data sensor ke Blynk
void sendSensorData() {
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
int humidityPercent = map(soilMoistureValue, minMoistureValue, maxMoistureValue, 0, 100);
humidityPercent = constrain(humidityPercent, 0, 100);
suhu = bacaSensorNTC();
// Kirim data ke Blynk
Blynk.virtualWrite(V1, humidityPercent); // Kelembapan tanah dalam persen
Blynk.virtualWrite(V2, suhu); // Suhu dalam Celsius
Blynk.virtualWrite(V3, thresholdMoisture); // Kirim nilai threshold kelembapan ke Blynk
}
BLYNK_WRITE(V3) {
thresholdMoisture = param.asInt(); // Terima threshold kelembapan dari Blynk
// Di sini, param.asInt() akan menerima nilai kelembapan minimum dari aplikasi Blynk
}
void reconnectWiFi() {
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Blynk.connect(); // Reconnect ke server Blynk
}
}
void setup() {
// Inisialisasi OLED dan pin kontrol pompa
pinMode(CONTROL_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Tombol di-pin 13 menggunakan pull-up internal
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (true); // Loop tidak berhenti jika OLED gagal diinisialisasi
}
display.display();
delay(2000);
display.clearDisplay();
// WiFi setup
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Connecting to WiFi...");
display.display();
unsigned long startAttemptTime = millis(); // Mulai waktu percobaan koneksi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
if (millis() - startAttemptTime >= 30000) { // Cek apakah sudah 30 detik
display.clearDisplay();
display.setCursor(0, 0);
display.print("WiFi Connection Failed!");
display.display();
break; // Lompat keluar dari while jika sudah 30 detik
}
delay(500);
display.print(".");
display.display();
}
// Jika koneksi WiFi berhasil
if (WiFi.status() == WL_CONNECTED) {
display.clearDisplay();
display.setCursor(0, 0);
display.print("WiFi Connected!");
display.setCursor(0, 10);
display.print("IP: ");
display.print(WiFi.localIP());
display.display();
delay(2000); // Tunggu sebentar setelah berhasil koneksi WiFi
}
// Inisialisasi Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, password);
// Setup timer untuk pengiriman data
timer.setInterval(1000L, sendSensorData); // Kirim data setiap 1 detik
}
void loop() {
reconnectWiFi();
Blynk.run(); // Menjalankan fungsi Blynk
timer.run(); // Menjalankan fungsi timer
// Membaca nilai kelembapan tanah
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
int humidityPercent = map(soilMoistureValue, minMoistureValue, maxMoistureValue, 0, 100);
humidityPercent = constrain(humidityPercent, 0, 100);
// Membaca suhu dari sensor NTC
suhu = bacaSensorNTC();
// Logika untuk kontrol pompa otomatis hanya jika belum diatur manual
if (!manualMode) {
if (humidityPercent <= thresholdMoisture && !isPumpOn) {
digitalWrite(CONTROL_PIN, HIGH); // Pompa menyala otomatis
isPumpOn = true;
Blynk.virtualWrite(V4, "ON"); // Kirim status pompa ke Blynk (V4)
} else if (humidityPercent > thresholdMoisture && isPumpOn) {
digitalWrite(CONTROL_PIN, LOW); // Pompa mati otomatis
isPumpOn = false;
Blynk.virtualWrite(V4, "OFF"); // Kirim status pompa ke Blynk (V4)
}
}
// Membaca status tombol untuk kontrol manual
int buttonState = digitalRead(BUTTON_PIN);
// Cek apakah tombol ditekan dan deteksi perubahan status tombol
if (buttonState == LOW && lastButtonState == HIGH) {
manualMode = !manualMode; // Toggle mode manual
if (manualMode) {
isPumpOn = !isPumpOn; // Toggle status pompa
digitalWrite(CONTROL_PIN, isPumpOn ? HIGH : LOW); // Mengatur status pompa sesuai
}
lastDebounceTime = millis(); // Update waktu debounce
}
// Menampilkan data ke OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Kelembapan Tanah: ");
display.print(humidityPercent);
display.print("%");
display.setCursor(0, 20);
display.print("Suhu: ");
display.print(suhu, 2); // Menampilkan suhu dengan 2 desimal
display.print(" C");
display.setCursor(0, 40);
display.print("Pompa: ");
display.print(isPumpOn ? "ON" : "OFF");
display.setCursor(0, 50);
display.print("WiFi: ");
display.print(WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected");
display.display();
lastButtonState = buttonState; // Update status tombol sebelumnya
delay(100); // Delay untuk penghindaran debouncing tambahan
}