Pendahuluan — Penutup Seri 2 ESP32/IoT Lanjutan
Selamat! Kamu sudah menempuh 28 artikel Seri 2 — dari deep sleep (#11) hingga HTTPS (#38). Artikel ini adalah capstone penutup yang menggabungkan sensor, aktuator, broker MQTT, dan dashboard ke dalam satu proyek nyata: smart greenhouse (rumah kaca pintar).
Di capstone Seri 1 (#10), kamu membangun dashboard hybrid Web + MQTT untuk satu sensor DHT22. Di capstone Seri 2, skala naik: multi-sensor (udara + tanah + cahaya), multi-aktuator (pompa air + ventilasi), multi-node (gateway utama + node kebun hemat baterai), dan dashboard histori di Grafana (#19).
Prasyarat wajib: Sudah paham BME280 I2C (#13), broker Mosquitto (#16), soil moisture ADC (#35), dan idealnya sudah baca PIR (#24) serta deep sleep (#11).
Apa yang Akan Kamu Bangun?
Sistem greenhouse skala rumahan / UMKM kecil dengan komponen berikut:
- Gateway utama — ESP32 di dalam rumah kaca: BME280 (suhu, kelembaban udara, tekanan) + soil moisture capacitive + LDR cahaya
- Node aktuator — ESP32 + relay modul: kontrol pompa irigasi dan lampu grow (opsional)
- Node kebun (opsional) — ESP32 deep sleep di ujung lahan: kirim data tanah periodik
- Sensor gerak (opsional) — PIR di pintu greenhouse untuk lampu koridor
- Broker MQTT — Mosquitto pribadi di Raspberry Pi / VPS (#16)
- Dashboard — Grafana panel suhu, kelembaban tanah, status pompa; alert Telegram opsional
- Backup offline — log CSV ke SD Card (#37) saat WiFi putus
Arsitektur Sistem Greenhouse
┌─────────────────────────────────────────────────────────────────┐
│ Broker Mosquitto 192.168.1.50:1883 (auth kindo_esp32) │
│ Topic: kodingindonesia/esp32/... │
└────────────┬───────────────────────────────────────┬──────────────┘
│ publish sensor │ subscribe kontrol
┌────────▼────────┐ ┌────────▼────────┐
│ Gateway utama │ │ Node aktuator │
│ BME280 + soil │ │ Relay pompa │
│ + LDR (GPIO) │ │ + lampu grow │
└────────┬────────┘ └────────┬────────┘
│ │
┌────────▼────────┐ ┌────────▼────────┐
│ Node deep sleep │ │ Servo flap (#33)│
│ (opsional) │ │ ventilasi │
└─────────────────┘ └─────────────────┘
│
┌────────▼────────────────────────────────────────┐
│ InfluxDB + Grafana (#19) · HA (#21) · Node-RED │
└─────────────────────────────────────────────────┘
Alur data: sensor publish JSON ke MQTT → subscriber Python/InfluxDB menyimpan histori → Grafana menampilkan grafik → otomasi (Node-RED / HA / firmware) mengontrol pompa berdasarkan threshold kelembaban tanah.
Estimasi Biaya Hardware
| Komponen | Qty | Estimasi (IDR) |
|---|---|---|
| ESP32 DevKit | 2–3 | ~90.000–135.000 |
| BME280 module I2C | 1 | ~35.000 |
| Soil moisture capacitive | 1–2 | ~25.000–50.000 |
| LDR + resistor 10kΩ | 1 | ~5.000 |
| Relay modul 2-ch | 1 | ~20.000 |
| Pompa DC mini + power supply | 1 | ~40.000–80.000 |
| Raspberry Pi / VPS broker | 1 | ~500.000+ (atau pakai PC lama) |
| Total minimal | ~215.000 (tanpa broker baru) |
Software stack (Mosquitto, InfluxDB, Grafana, ESP32 firmware) gratis open source. Biaya listrik broker 24/7 diperhitungkan terpisah.
Hierarki Topic MQTT Greenhouse
Konvensi Seri 2 — semua node memakai prefix kodingindonesia/esp32/:
| Topic | Arah | Payload | Sumber artikel |
|---|---|---|---|
.../bme280/data | publish | {"suhu":28.1,"kelembaban":72.0,"tekanan":1008.5,"unix":1782977400} | #13 |
.../tanah/data | publish | {"kelembaban_tanah":42,"unix":1782977400} | #35 |
.../cahaya/data | publish | {"cahaya_percent":78,"unix":1782977400} | #35 |
.../pompa/kontrol | subscribe | ON / OFF / AUTO | capstone |
.../pir/gerak | publish | {"gerak":true,"lampu":"ON"} | #24 |
.../servo/sudut | subscribe | 120 (derajat flap) | #33 |
Timestamp unix: 1782977400 = 2026-07-02T14:30:00 UTC — konsisten dengan NTP (#34) di seluruh Seri 2.
Catatan topic pompa: di #35, relay pompa masih memakai kodingindonesia/esp32/lampu/kontrol. Di capstone ini kita pakai .../pompa/kontrol agar irigasi terpisah dari lampu koridor PIR (.../lampu/kontrol) — pola relay tetap sama seperti #8.
Persiapan Broker Mosquitto
Gunakan broker pribadi yang sudah dikonfigurasi di artikel #16:
- Host:
192.168.1.50(ganti IP broker kamu) - Port:
1883(plain) atau8883dengan TLS (#17) - User:
kindo_esp32· Password:GANTI_PASSWORD_MQTT
mosquitto_sub -h 192.168.1.50 -u kindo_esp32 -P GANTI_PASSWORD_MQTT \
-t "kodingindonesia/esp32/#" -v
Wildcard # memudahkan debug seluruh traffic greenhouse sekaligus.
Gateway Utama — BME280 + Soil + LDR
Node ini menggabungkan pola BME280 (#13) dan ADC soil/LDR (#35) dalam satu firmware.
Wiring I2C BME280
| BME280 | ESP32 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
Wiring Soil Moisture & LDR
| Sensor | ESP32 | Catatan |
|---|---|---|
| Soil VCC | 3.3V | Capacitive — hindari korosi probe resistif |
| Soil OUT | GPIO 34 (ADC1) | Kalibrasi kering/basah |
| LDR + divider | GPIO 35 (ADC1) | Resistor 10kΩ ke GND |
Sketch Gateway — Publish Multi-Sensor
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#define SOIL_PIN 34
#define LDR_PIN 35
const char* ssid = "GANTI_NAMA_WIFI";
const char* pass = "GANTI_PASSWORD_WIFI";
const char* mqtt_host = "192.168.1.50";
const char* mqtt_user = "kindo_esp32";
const char* mqtt_pass = "GANTI_PASSWORD_MQTT";
const char* topic_bme = "kodingindonesia/esp32/bme280/data";
const char* topic_tanah = "kodingindonesia/esp32/tanah/data";
const char* topic_cahaya = "kodingindonesia/esp32/cahaya/data";
const int SOIL_DRY = 3200;
const int SOIL_WET = 1400;
Adafruit_BME280 bme;
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
int soilPercent(int raw) {
return constrain(map(raw, SOIL_DRY, SOIL_WET, 0, 100), 0, 100);
}
int readFiltered(uint8_t pin) {
long sum = 0;
for (int i = 0; i < 10; i++) { sum += analogRead(pin); delay(5); }
return (int)(sum / 10);
}
void reconnectMqtt() {
while (!mqtt.connected()) {
if (mqtt.connect("kindo-greenhouse-gw", mqtt_user, mqtt_pass)) {
Serial.println("MQTT OK");
} else { delay(2000); }
}
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
Wire.begin(21, 22);
if (!bme.begin(0x76)) { Serial.println("BME280 fail"); while(1); }
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) delay(300);
mqtt.setServer(mqtt_host, 1883);
reconnectMqtt();
}
void loop() {
if (!mqtt.connected()) reconnectMqtt();
mqtt.loop();
static unsigned long last = 0;
if (millis() - last < 15000) return;
last = millis();
float t = bme.readTemperature();
float h = bme.readHumidity();
float p = bme.readPressure() / 100.0F;
int soil = soilPercent(readFiltered(SOIL_PIN));
int ldr = constrain(map(readFiltered(LDR_PIN), 500, 3500, 0, 100), 0, 100);
char buf[128];
snprintf(buf, sizeof(buf),
"{\"suhu\":%.1f,\"kelembaban\":%.1f,\"tekanan\":%.1f,\"unix\":1782977400}",
t, h, p);
mqtt.publish(topic_bme, buf);
snprintf(buf, sizeof(buf), "{\"kelembaban_tanah\":%d,\"unix\":1782977400}", soil);
mqtt.publish(topic_tanah, buf);
snprintf(buf, sizeof(buf), "{\"cahaya_percent\":%d,\"unix\":1782977400}", ldr);
mqtt.publish(topic_cahaya, buf);
Serial.printf("GW: suhu=%.1f tanah=%d%% cahaya=%d%%\n", t, soil, ldr);
}
PlatformIO — Gateway
lib_deps =
knolleary/PubSubClient
adafruit/Adafruit BME280 Library
adafruit/Adafruit Unified Sensor
Node Aktuator — Relay Pompa & Lampu
Ikuti pola relay MQTT (#8) dengan topic khusus pompa:
- GPIO relay pompa:
GPIO 26(active LOW — sesuaikan modul kamu) - GPIO relay lampu grow:
GPIO 27 - Subscribe:
kodingindonesia/esp32/pompa/kontrol
const char* topicPompa = "kodingindonesia/esp32/pompa/kontrol";
#define RELAY_POMPA 26
#define RELAY_LAMPU 27
void mqttCallback(char* topic, byte* payload, unsigned int len) {
char msg[8] = {0};
memcpy(msg, payload, min(len, (unsigned)7));
if (strcmp(msg, "ON") == 0) {
digitalWrite(RELAY_POMPA, LOW);
digitalWrite(RELAY_LAMPU, LOW);
} else if (strcmp(msg, "OFF") == 0) {
digitalWrite(RELAY_POMPA, HIGH);
digitalWrite(RELAY_LAMPU, HIGH);
}
// AUTO: logika threshold di Node-RED / HA
}
void setup() {
pinMode(RELAY_POMPA, OUTPUT);
pinMode(RELAY_LAMPU, OUTPUT);
digitalWrite(RELAY_POMPA, HIGH);
digitalWrite(RELAY_LAMPU, HIGH);
mqtt.setCallback(mqttCallback);
reconnectMqtt();
mqtt.subscribe(topicPompa);
}
void loop() {
if (!mqtt.connected()) reconnectMqtt();
mqtt.loop();
}
Pola lengkap WiFi + mqtt.connect sama seperti relay (#8) — pastikan mqtt.loop() dipanggil setiap iterasi agar callback kontrol pompa responsif.
Otomasi Pompa — Threshold Kelembaban Tanah
Logika irigasi dengan hysteresis anti-flicker (sama prinsip debounce PIR (#24)):
- Jika
kelembaban_tanah < 30%→ publishONkekodingindonesia/esp32/pompa/kontrol - Jika
kelembaban_tanah > 60%→ publishOFF - Zona 30–60%: pertahankan status terakhir
Implementasi bisa di Node-RED (#23): mqtt in kodingindonesia/esp32/tanah/data → function node cek threshold → mqtt out kodingindonesia/esp32/pompa/kontrol. Atau di Home Assistant (#21) dengan automation for: 2 minutes agar pompa tidak cepat on/off.
Ventilasi Servo Flap (Opsional)
Tambahkan servo SG90 (#33) untuk membuka flap saat suhu BME280 > 32°C:
- Subscribe
kodingindonesia/esp32/servo/sudut— payload angka 0–180 - Sudut 0° = tertutup · 120° = ventilasi cukup · 180° = terbuka penuh
Ramp perlahan (2° per 20 ms) melindungi engsel plastik — detail di artikel #33.
Node Deep Sleep di Ujung Kebun (Opsional)
Untuk probe tanah jauh dari stop kontak, pakai pola deep sleep (#11):
- Bangun tiap 15 menit (timer wakeup)
- Baca soil moisture → publish
kodingindonesia/esp32/tanah/datadengan fieldnode: "kebun-barat" - Matikan WiFi →
esp_deep_sleep(15 * 60 * 1000000ULL)
Baterai 18650 + modul charge bisa bertahan berminggu-minggu — cocok untuk kebun luas tanpa kabel listrik.
PIR di Pintu Greenhouse (Opsional)
Integrasikan PIR (#24) untuk lampu koridor: gerak terdeteksi → publish ke kodingindonesia/esp32/pir/gerak → relay lampu ON selama 60 detik (hold time). Topic kontrol tetap kompatibel dengan kodingindonesia/esp32/lampu/kontrol dari artikel #8.
Backup SD Card Saat WiFi Putus
Tambahkan modul microSD SPI seperti artikel #37 pada gateway utama. Saat mqtt.publish() gagal, append baris CSV ke /greenhouse.csv:
unix,suhu,kelembaban_udara,kelembaban_tanah,cahaya_percent
1782977400,28.1,72.0,42,78
Saat WiFi kembali, baca file dan publish batch ke MQTT — data histori tidak hilang.
Dashboard Grafana — Panel Greenhouse
Setelah data masuk InfluxDB lewat subscriber Python (#18), buat dashboard di Grafana (#19):
- Panel Time series — suhu BME280 (
suhu) + kelembaban udara - Panel Gauge — kelembaban tanah real-time (threshold merah < 30%)
- Panel Stat — status pompa (ON/OFF dari topic kontrol)
- Alert rule — suhu > 35°C selama 10 menit → notifikasi Telegram
Query Flux contoh: from(bucket:"sensor") |> range(start:-24h) |> filter(fn:(r) => r._measurement == "tanah")
Integrasi Home Assistant & Node-RED
Home Assistant — entity dari MQTT discovery:
sensor.greenhouse_suhu← topicbme280/data· template{{ value_json.suhu }}sensor.greenhouse_tanah← topickodingindonesia/esp32/tanah/dataswitch.greenhouse_pompa← topickodingindonesia/esp32/pompa/kontrol· commandON/OFF
Node-RED — flow visual: gauge tanah + tombol manual pompa + automasi threshold — lihat pola lengkap di #23.
Keamanan Produksi
- MQTT auth — jangan pakai broker tanpa password di production (#16)
- TLS — aktifkan port 8883 untuk traffic terenkripsi (#17)
- Webhook HTTPS — alert Grafana ke Telegram via WiFiClientSecure (#38) jika perlu notifikasi dari ESP32 langsung
- OTA — update firmware node tanpa kabel USB (#15)
- WiFiManager — ganti SSID tanpa reflash (#12)
Pro tip: Pisahkan VLAN atau SSID khusus IoT di router rumah — node greenhouse tidak perlu akses ke laptop/kantor. Broker Mosquitto cukup expose ke LAN, bukan internet publik, kecuali kamu sudah paham hardening TLS + firewall.
Perbandingan Jalur yang Digabung
| Jalur Seri 2 | Artikel | Peran di Greenhouse |
|---|---|---|
| A — Hardware | #11, #13, #24, #35 | Sensor + deep sleep + PIR |
| B — Infrastruktur | #16, #17, #18, #19 | Broker, TLS, histori, Grafana |
| C — Smart home | #21, #23 | HA entity + Node-RED otomasi |
| D — Jarak jauh | #26, #28 | LoRa node kebun luas (opsional) |
| E — Tooling | #29, #31 | PlatformIO monorepo + FreeRTOS |
| Tier 2 | #33, #37, #38 | Servo flap, SD backup, HTTPS alert |
Checklist Uji Coba End-to-End
- Broker Mosquitto hidup —
systemctl status mosquitto mosquitto_sub -t "kodingindonesia/esp32/#" -vmenampilkan traffic- Gateway publish BME280 + tanah + cahaya setiap 15 detik
- Node aktuator merespons
mosquitto_pub -h 192.168.1.50 -u kindo_esp32 -P GANTI_PASSWORD_MQTT -t "kodingindonesia/esp32/pompa/kontrol" -m ON - Pompa fisik menyala — cek arus relay sebelum sambung ke pompa besar
- Grafana panel menampilkan data histori 1 jam terakhir
- Otomasi threshold: tanah < 30% → pompa ON tanpa intervensi manual
- (Opsional) SD Card mencatat saat WiFi dimatikan sementara
- (Opsional) Alert Grafana Telegram saat suhu > 35°C
Troubleshooting
- BME280 tidak terbaca: Cek alamat I2C
0x76vs0x77— ganti dibme.begin() - Soil selalu 0% atau 100%: Kalibrasi ulang
SOIL_DRY/SOIL_WETdi air vs tanah kering - Pompa tidak mati: Cek hysteresis — mungkin threshold terlalu dekat; tambah
for: 2 minutesdi HA - MQTT rc=-2: Broker tidak terjangkau — ping
192.168.1.50dari ESP32 serial monitor - Grafana kosong: Pastikan subscriber Python jalan dan bucket InfluxDB menerima measurement
tanah - Relay terbalik: Banyak modul active LOW —
LOW= ON,HIGH= OFF
Indeks Lengkap Seri 2 ESP32/IoT Lanjutan (29 Artikel)
Ini adalah indeks resmi Seri 2 — diselaraskan dengan capstone Seri 1 (#10):
- Deep sleep ESP32 + DHT22 hemat baterai
- NVS + WiFiManager
- Broker Mosquitto pribadi + autentikasi
- I2C + sensor BME280
- OLED SSD1306
- OTA update firmware ESP32
- Home Assistant + ESP32 MQTT
- ESPHome flash ESP32 tanpa Arduino
- Node-RED dashboard IoT MQTT
- Sensor gerak PIR + lampu MQTT
- MQTT TLS + QoS + LWT
- NTP & timestamp ESP32
- Subscriber Python → MySQL
- InfluxDB + Grafana
- REST API vs MQTT
- ESP-NOW antar ESP32 tanpa router WiFi
- LoRa ESP32 + SX1278 jarak jauh
- ESP32-CAM MJPEG streaming
- Gateway LoRa → MQTT
- Migrasi ke PlatformIO di VS Code
- ESP32 + Firebase Realtime Database
- FreeRTOS multi-task Sensor + WiFi + MQTT
- Bluetooth BLE kirim data sensor ke smartphone
- Kontrol Servo & PWM gerakan presisi via MQTT
- ADC ESP32: Soil Moisture & LDR via MQTT
- ESP8266 / NodeMCU vs ESP32
- SD Card & SPI logging offline
- HTTPS & sertifikat ESP32 (WiFiClientSecure)
- Smart Greenhouse capstone — artikel ini (penutup Seri 2)
FAQ — Pertanyaan Umum Greenhouse IoT
- Apakah bisa pakai satu ESP32 untuk semua sensor dan relay?
- Ya untuk prototipe skala kecil — gateway utama di artikel ini sudah menggabungkan BME280 + soil + LDR. Untuk produksi, pisahkan node aktuator agar reset sensor tidak mematikan pompa secara tidak sengaja.
- Broker test.mosquitto.org cukup untuk greenhouse?
- Tidak untuk data produksi — pakai broker sendiri (#16). Broker publik cocok hanya untuk uji coba 15 menit pertama.
- Soil moisture resistif vs capacitive?
- Capacitive lebih awet di tanah basah — sudah dibahas di #35. Probe resistif murah tapi korosi dalam berminggu-minggu.
- Berapa lama baterai node deep sleep?
- Dengan 18650 3000 mAh dan wake tiap 15 menit, estimasi 2–4 minggu — tergantung durasi WiFi connect. Optimasi: kurangi payload JSON, matikan LED board.
- Apakah Seri 2 berakhir setelah artikel ini?
- Ya — 29/29 artikel inti selesai. Topik Fase 3 (MicroPython, GPRS, Zigbee) akan ditulis jika ada permintaan komunitas.
Penutup — Terima Kasih Mengikuti Seri 2!
Kamu sekarang punya fondasi lengkap IoT embedded: dari sensor digital & analog, protokol MQTT & HTTPS, broker & dashboard, hingga smart home & cloud. Proyek greenhouse ini bisa dikembangkan ke skala komersial — tambah kamera (#27), gateway LoRa (#28), atau Firebase (#30) untuk monitoring mobile.
Seri 2 selesai — 29/29 artikel. Share proyek greenhouse kamu ke komunitas, dan pantau artikel baru di Koding Indonesia untuk topik Fase 3 (MicroPython, GPRS, Zigbee, dan lainnya).