Versi lengkap penyiram otomatis: memantau tanah, suhu, dan kelembapan udara, menyiram saat tanah kering tetapi tidak di siang terik, membatasi lama sekali siram, dan melaporkan lama pompa menyala setiap hari. Semuanya terpantau di satu dashboard.
Dasarnya proyek 061 (penyiram otomatis) dan 070 (kebun mini), ditambah tiga aturan seperti tukang kebun berpengalaman: 1. Jangan menyiram di siang terik (10:00-15:00). Air cepat menguap dan daun bisa "terbakar". Jam diambil dari NTP. 2. Batas waktu siram 20 detik sekali jalan, supaya pot tidak banjir kalau sensor rusak atau tercabut. 3. Histeresis 15%: pompa menyala di bawah batas kering dan baru berhenti setelah 15% di atasnya.
Lama pompa menyala dijumlahkan setiap hari. Dari angka itu kamu bisa memperkirakan pemakaian air dan melihat apakah tanaman makin haus di musim kemarau.
Komponen
| Komponen | Qty | Harga |
|---|---|---|
| ESP32 DOIT DevKit V1 30 pin | 1 | Rp75.000 |
| Sensor kelembapan tanah + modul | 1 | Rp8.500 |
| Modul sensor DHT11 | 1 | Rp12.000 |
| Modul relay 1 channel 5V | 1 | Rp17.000 |
| Pompa air mini 3-4,5V | 1 | Rp13.000 |
| Holder baterai 3×AA + kabelbaterai AA dibeli terpisah | 1 | Rp6.000 |
| Selang 8/6 mmopsional, cek ukuran lubang pompa | 1 | Rp6.852 |
| Kabel jumper female-female 10 cm (isi 10)isi 10, terpakai 10 | 1 | Rp3.500 |
| Kabel micro USB data 30 cmopsional, kalau belum punya kabel micro USB data | 1 | Rp11.700 |
| Total (tanpa opsional) | Rp135.000 |
Langkah 1: Rangkai komponen
Sambungkan kabel sesuai gambar di atas. Kalau gambar dan tabel terlihat berbeda, ikuti tabel.
| Dari | Ke | Kabel | |
|---|---|---|---|
| Sensor kelembapan tanah VCC | → | 3V3 | merah |
| Sensor kelembapan tanah GND | → | GND | hitam |
| Sensor kelembapan tanah AO | → | D34 GPIO34 | hijau |
| DHT11 VCC | → | 3V3 | merah |
| DHT11 DATA | → | D4 GPIO4 | kuning |
| DHT11 GND | → | GND | hitam |
| Relay 1 ch 5V (jumper H) DC+ | → | VIN | oranye |
| Relay 1 ch 5V (jumper H) DC− | → | GND | hitam |
| Relay 1 ch 5V (jumper H) IN | → | D26 GPIO26 | biru |
| Baterai 3×AA (4,5V) + | → | Relay 1 ch 5V (jumper H) COM | merah |
| Relay 1 ch 5V (jumper H) NO | → | Pompa mini 3–4,5V + | merah |
| Pompa mini 3–4,5V − | → | Baterai 3×AA (4,5V) − | hitam |
Langkah 2: Siapkan dashboard Klenik
Cara cepat: unduh p142.json, ganti budi1234 dengan KODE-mu, lalu import di Klenik (menu titik tiga → Export / Import → Import → Ganti total). Langkah lengkapnya ada di Panduan Klenik.
| Widget | Topic | Setting |
|---|---|---|
| Gauge Tanah | ichibot/KODE/p142/tanah | 0–100 % |
| Gauge Suhu | ichibot/KODE/p142/suhu | 15–45 °C |
| Gauge Lembap Udara | ichibot/KODE/p142/udara | 0–100 % |
| Indikator Boolean Pompa | ichibot/KODE/p142/pompa | ON = 1 “MENYIRAM”, OFF = 0 |
| Slider Output Batas Kering | ichibot/KODE/p142/batas | 10–70 % |
| Switch Siram Sekarang | ichibot/KODE/p142/siram | payload ON / OFF |
| Text Log Catatan Kebun | ichibot/KODE/p142/log | menampilkan teks masuk |
Langkah 3: Upload kode
Library: PubSubClient (Nick O'Leary), DHT sensor library (Adafruit), Adafruit Unified Sensor. Board di Arduino IDE: ESP32 Dev Module.
Isi dulu nama WiFi dan password di bagian ISI DULU, lalu ganti budi1234 di baris topic dengan KODE-mu, lalu upload dan buka Serial Monitor (115200).
// Proyek 142 - Smart Garden Lengkap
// Board: ESP32 DOIT DevKit V1 | Dashboard: klenik.ichibot.id
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <time.h>
// ===== ISI DULU =====
const char* WIFI_NAMA = "nama-wifi-kamu";
const char* WIFI_PASS = "password-wifi-kamu";
// topic MQTT: ganti budi1234 dengan KODE-mu (sama dengan di dashboard Klenik)
const char* TOPIK_POMPA = "ichibot/budi1234/p142/pompa";
const char* TOPIK_LOG = "ichibot/budi1234/p142/log";
const char* TOPIK_SIRAM = "ichibot/budi1234/p142/siram";
const char* TOPIK_BATAS = "ichibot/budi1234/p142/batas";
const char* TOPIK_TANAH = "ichibot/budi1234/p142/tanah";
const char* TOPIK_SUHU = "ichibot/budi1234/p142/suhu";
const char* TOPIK_UDARA = "ichibot/budi1234/p142/udara";
const int NILAI_KERING = 3300, NILAI_BASAH = 1300; // kalibrasi sensor tanah (proyek 061)
const char* BROKER = "mqtt.ichibot.id";
WiFiClient wifi;
PubSubClient mqtt(wifi);
DHT dht(4, DHT11);
const int PIN_TANAH = 34, POMPA = 26;
const unsigned long MAKS_SIRAM = 20000; // sekali siram maksimal 20 detik
int batasKering = 40;
bool pompa = false;
unsigned long pompaSejak = 0, terakhir = 0;
float siramHariIni = 0; // detik pompa menyala hari ini
int hariTadi = -1;
void aturPompa(bool v, const char* sebab) {
if (v == pompa) return;
pompa = v;
digitalWrite(POMPA, v ? HIGH : LOW);
if (v) pompaSejak = millis();
else siramHariIni += (millis() - pompaSejak) / 1000.0;
mqtt.publish(TOPIK_POMPA, v ? "1" : "0", true);
mqtt.publish(TOPIK_LOG, (String(v ? "Mulai siram" : "Selesai siram") + " (" + sebab + ")").c_str());
}
void pesanMasuk(char* t, byte* isi, unsigned int panjang) {
String topik = t;
String p;
for (unsigned int i = 0; i < panjang; i++) p += (char)isi[i];
if (topik == TOPIK_BATAS) batasKering = p.toInt();
else if (topik == TOPIK_SIRAM && p == "ON") { aturPompa(true, "manual"); mqtt.publish(TOPIK_SIRAM, "OFF"); }
}
void langganan() {
mqtt.subscribe(TOPIK_BATAS);
mqtt.subscribe(TOPIK_SIRAM);
}
sambungWiFi() dan sambungMQTT(): sama di semua proyek (klik untuk lihat)
void sambungWiFi() {
WiFi.begin(WIFI_NAMA, WIFI_PASS);
Serial.print("WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" OK, IP " + WiFi.localIP().toString());
}
void sambungMQTT() {
while (!mqtt.connected()) {
if (mqtt.connect(WiFi.macAddress().c_str())) {
Serial.println("Terhubung ke Klenik");
langganan();
} else {
Serial.println("Broker gagal, coba lagi 3 detik");
delay(3000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(POMPA, OUTPUT);
dht.begin();
sambungWiFi();
configTime(7 * 3600, 0, "pool.ntp.org");
mqtt.setServer(BROKER, 1883);
mqtt.setCallback(pesanMasuk);
}
void loop() {
if (!mqtt.connected()) sambungMQTT();
mqtt.loop();
if (pompa && millis() - pompaSejak > MAKS_SIRAM) aturPompa(false, "waktu habis");
if (millis() - terakhir < 5000) return;
terakhir = millis();
int tanah = constrain(map(analogRead(PIN_TANAH), NILAI_KERING, NILAI_BASAH, 0, 100), 0, 100);
float suhu = dht.readTemperature();
float udara = dht.readHumidity();
mqtt.publish(TOPIK_TANAH, String(tanah).c_str());
if (!isnan(suhu)) {
mqtt.publish(TOPIK_SUHU, String(suhu, 1).c_str());
mqtt.publish(TOPIK_UDARA, String(udara, 0).c_str());
}
time_t t = time(nullptr);
struct tm* w = localtime(&t);
bool siang = t > 1700000000 && w->tm_hour >= 10 && w->tm_hour < 15; // hindari siram terik matahari
if (!pompa && tanah < batasKering && !siang) aturPompa(true, "tanah kering");
if (pompa && tanah > batasKering + 15) aturPompa(false, "tanah cukup basah");
if (t > 1700000000 && w->tm_mday != hariTadi) {
if (hariTadi != -1) mqtt.publish(TOPIK_LOG, ("Kemarin pompa menyala " + String(siramHariIni, 0) + " detik").c_str());
hariTadi = w->tm_mday;
siramHariIni = 0;
}
}Langkah 4: Pahami kodenya
- Aturan siang terik. Siram manual dari dashboard tetap boleh kapan saja.
- Pengaman paling penting: dicek di setiap putaran
loop(), di luar jeda 5 detik, supaya pompa pasti berhenti tepat waktu. - Saat pompa berhenti, lama nyalanya ditambahkan ke total hari ini.