Proyek Rumah Kaca Pintar Arduino: Sensor, Penyiraman, Kipas, dan Kode
Bangun rumah kaca pintar Arduino: ukur dengan DHT22, sensor kelembapan tanah, dan LDR; kendalikan kipas, pemanas, pompa, dan LED lewat relay dan MOSFET, plus histeresis, LCD, dan kode ESP32.
Proyek rumah kaca pintar Arduino adalah sistem otomasi tempat Arduino atau ESP32 mengukur suhu udara, kelembapan, kelembapan tanah, dan cahaya di dalam rumah kaca, lalu menjalankan kipas, pemanas, pompa air, dan lampu tanam dengan sendirinya. Ini salah satu topik favorit untuk pameran sains, lomba sekolah, dan pelajaran teknologi karena hasilnya mudah dilihat: pompa menyala ketika tanah mengering, kipas berputar ketika bagian dalam terlalu panas, dan LED menyala ketika sore tiba. Lebih asyik lagi, hampir tidak ada perbedaan rangkaian maupun kode antara maket rumah kaca dari kotak penyimpanan dan rumah kaca mini sungguhan di balkonmu.
Di panduan ini kita mulai dari apa yang sebenarnya dibutuhkan tanaman, lalu membangun maket rumah kaca langkah demi langkah: daftar komponen dan perkiraan biaya, pengkabelan sensor (DHT22, sensor kelembapan tanah kapasitif, LDR) dan aktuator (kipas, pemanas, pompa, dan LED lewat relay dan MOSFET), rencana daya, serta tabel pin. Setelah itu kita bahas logika ambang dan histeresis yang mencegah relay terus berbunyi klik, kode Arduino lengkap tanpa delay(), dan LCD 16x2. Di bagian akhir kamu akan menemukan cara memantau rumah kaca dari ponsel dengan ESP32, versi MicroPython untuk Raspberry Pi Pico, tips presentasi di sekolah dan lomba sains, serta kesalahan yang sering terjadi.





Bagaimana cara kerja rumah kaca pintar?
Setiap rumah kaca pintar menjalankan siklus empat langkah yang sama: ukur, putuskan, jalankan, tampilkan. Sensor mengukur lingkungan: seberapa hangat bagian dalam, seberapa lembap udaranya, apakah tanahnya sudah kering, apakah cahayanya cukup? Arduino membandingkan nilai-nilai ini dengan aturan yang kamu tetapkan: “kalau suhu di atas 30 °C, nyalakan kipas”, “kalau kelembapan tanah turun di bawah 35%, siram”. Aktuator melaksanakan keputusan itu: relay menyalakan dan mematikan kipas, pemanas, dan pompa, sedangkan MOSFET mengatur kecerahan LED strip. Terakhir, LCD dan ponselmu menunjukkan kondisi rumah kaca terkini. Komputer iklim di rumah kaca komersial sungguhan bekerja dengan siklus yang persis sama; bedanya hanya sensornya lebih banyak dan motornya lebih besar.
| Apa yang diukur? | Sensor | Aktuator | Aturan (contoh) |
|---|---|---|---|
| Suhu udara | DHT22 | Kipas dan pemanas | Kipas menyala pada 30 °C, pemanas menyala pada 16 °C |
| Kelembapan relatif | DHT22 | Kipas | Kipas menyala pada 85% dan berhenti pada 75% |
| Kelembapan tanah | Sensor kelembapan tanah kapasitif | Pompa celup mini | Menyiram dalam denyut 3 detik di bawah 35% |
| Cahaya | LDR | LED strip (MOSFET) | Ketika hari gelap, LED menyala paling lama 4 jam |
| Air di tangki | Saklar level pelampung | Kunci pompa | Kalau tangki kosong, pompa tidak pernah menyala |
Apa yang dibutuhkan tanaman? Target suhu, kelembapan, dan cahaya
Sebelum menulis aturan apa pun, kamu perlu tahu apa yang ingin dicapai. Kebanyakan tanaman menginginkan suhu yang berbeda pada siang dan malam hari; sedikit lebih sejuk di malam hari membantu tanaman beristirahat. Kalau kelembapan bertahan di atas 85% dalam waktu lama, air mengembun di permukaan daun dan penyakit jamur seperti kapang dan embun bulu (downy mildew) cepat menyebar; karena itulah kipas di rumah kaca menyala bukan hanya untuk mendinginkan, tetapi juga untuk membuang kelembapan. Untuk cahaya, kebanyakan bibit sayuran butuh 14–16 jam sehari, tetapi juga perlu periode gelap minimal 6–8 jam; membiarkan LED menyala sepanjang malam lebih banyak merugikan daripada menguntungkan tanaman. Nilai di bawah ini adalah panduan awal yang baik; sesuaikan dengan tanaman yang kamu tanam.
| Tanaman | Siang | Malam | Kelembapan relatif | Catatan |
|---|---|---|---|---|
| Tomat | 21–27 °C | 15–18 °C | 60–75% | Bunga bisa rontok di atas 32 °C |
| Cabai | 21–29 °C | 16–20 °C | 60–75% | Lebih peka terhadap dingin daripada tomat |
| Selada dan bayam | 15–20 °C | 10–15 °C | 60–70% | Cepat berbunga (bolting) ketika panas dan hari panjang |
| Stroberi | 18–24 °C | 10–13 °C | 60–75% | Risiko kapang kelabu naik pada kelembapan tinggi |
| Bibit dan perkecambahan | 20–25 °C | 18–20 °C | 70–85% | Suhu tanah lebih penting daripada suhu udara |
Membuat maket rumah kaca
Badan yang paling mudah dan murah adalah kotak penyimpanan plastik bening bertutup: kotak 40–60 liter cukup untuk dua atau tiga pot, tahan air, dan mudah dilubangi dengan cutter atau ujung logam yang dipanaskan. Kalau ingin tampilan yang lebih realistis, buat rangka dari bilah kayu dan lapisi dengan lembaran akrilik bening (Plexiglas) atau PETG setebal 2–3 mm; rumah kaca beratap pelana terlihat jauh lebih bagus ketika presentasi. Ukuran sekitar 50×35×40 cm adalah titik awal yang baik. Badan mana pun yang kamu pilih, tutup atau salah satu dinding sampingnya harus bisa dibuka; kamu akan memasukkan tangan ke dalam untuk menyiram tanaman, memindahkan sensor, dan merapikan kabel.
- Elektronik di luar: Bagian dalam rumah kaca lembap, dan pada pagi hari air mengembun di dindingnya. Letakkan Arduino, modul relay, dan catu daya di kotak terpisah di luar rumah kaca; yang masuk ke dalam hanya sensor, kipas, pemanas, selang pompa, dan LED.
- Ventilasi: Udara hangat naik, jadi pasang kipas di bagian atas salah satu dinding pendek, mengembus udara ke luar. Buat lubang masuk udara seukuran kipas di bagian bawah dinding seberangnya dan tutup dengan kasa nyamuk; udara segar lalu masuk dari bawah, dan udara hangat yang lembap keluar dari atas.
- Pemanas: Pasang pemanas di dekat lantai di atas pelat aluminium atau ubin keramik, minimal 5 cm dari dinding plastik dan tanaman. Udara hangat beredar ke seluruh rumah kaca sambil naik.
- Lampu LED: Tempelkan LED strip di sisi dalam tutup, 15–30 cm di atas tanaman. Kalau strip ditempel di profil aluminium tipis, panasnya lebih mudah terbuang dan perekatnya tidak lepas seiring waktu.
- Sensor: Letakkan DHT22 setinggi tanaman, di tempat yang tidak terkena sinar matahari langsung atau cahaya LED. Tanam sensor kelembapan tanah di zona akar, jauh dari tepi pot. LDR tidak boleh melihat LED: letakkan di luar rumah kaca, di atap, menghadap langit.
- Tangki air: Wadah 1–2 liter sudah cukup untuk pompa dan saklar pelampung. Taruh tatakan di bawah pot; kelebihan air terkumpul di tatakan, bukan menggenangi dasar kotak.
Daftar komponen dan biaya
| Komponen | Jumlah | Tugas | Tingkat harga |
|---|---|---|---|
| Arduino Uno R3 atau ESP32 DevKit | 1 | Otak rumah kaca | Sedang |
| Modul suhu dan kelembapan DHT22 (AM2302) | 1 | Suhu dan kelembapan udara | Rendah |
| Sensor kelembapan tanah kapasitif (v1.2) | 1 (satu per pot) | Kelembapan tanah | Rendah |
| LDR (GL5528) dan resistor 10 kΩ | 1 + 1 | Cahaya sekitar | Sangat rendah |
| Saklar level air pelampung | 1 | Mengunci pompa ketika tangki kosong | Rendah |
| Modul relay 5 V 4 channel (dengan optocoupler, ada JD-VCC) | 1 | Kipas, pemanas, dan pompa | Rendah |
| MOSFET N-channel logic level (IRLZ44N), resistor 220 Ω dan 100 kΩ | 1 set | Kecerahan LED strip (PWM) | Sangat rendah |
| Pompa celup mini 3–6 V dan selang silikon 1 m | 1 | Penyiraman | Rendah |
| Kipas komputer 12 V 80 mm | 1–2 | Ventilasi dan pembuangan kelembapan | Rendah |
| Pemanas PTC 12 V (10–30 W) dan sekring termal | 1 + 1 | Pemanasan | Rendah |
| LED strip 12 V (grow light atau putih dingin), sekitar 1 m | 1 | Pencahayaan tambahan | Rendah |
| LCD I2C 16x2 | 1 | Layar status | Rendah – sedang |
| Adaptor daya 12 V 5 A dan buck converter LM2596 | 1 + 1 | Daya | Sedang |
| Dioda 1N5819 atau 1N4007, kapasitor 470 µF, terminal sekrup, kabel jumper | – | Proteksi dan sambungan | Sangat rendah |
| Kotak penyimpanan bening bertutup atau lembaran akrilik, pot, tatakan | – | Badan rumah kaca | Sedang |
Harga sangat bervariasi antarpenjual, jadi berikut perkiraan anggaran kasar, bukan angka pasti. Tanpa board, versi dasar (DHT22, sensor kelembapan tanah, LDR, relay 2 channel, pompa, dan kipas 5 V) biasanya sekitar 25–40 dolar AS. Versi lengkap dengan pemanas, LED strip, LCD, adaptor 12 V, LM2596, saklar pelampung, dan badan rumah kaca biasanya mencapai sekitar 70–120 dolar AS; sebagian besar anggaran habis untuk board, adaptor, layar, dan badan. Kalau kamu punya Starter Kit Arduino, board, breadboard, kabel, LDR, resistor, dan sering kali LCD sudah tersedia. Kalau anggaran terbatas, tunda pemanas dan LED ke tahap kedua; penyiraman dan ventilasi saja sudah menjadi proyek yang bermakna dan berfungsi.
Sensor: DHT22, sensor kelembapan tanah, dan LDR
Untuk rumah kaca, kami menyarankan DHT22 (AM2302). Harganya sedikit lebih mahal daripada DHT11, tetapi ia mengukur suhu dari −40 sampai 80 °C dengan akurasi ±0,5 °C dan kelembapan di rentang 0–100% dengan akurasi sekitar ±2%; DHT11 hanya akurat ±2 °C di antara 0 dan 50 °C dan tidak bisa membaca kelembapan di atas 90%. Karena kelembapan rumah kaca bisa melewati 90% di pagi hari dan suhunya bisa di bawah titik beku ketika musim dingin, DHT22 jauh lebih cocok. Sensor ini hanya bisa membaca paling sering sekali setiap 2 detik, jadi kode membacanya setiap 2,5 detik. Kalau sensor diletakkan di tempat yang langsung terkena sinar matahari atau LED, badannya ikut panas dan hasilnya beberapa derajat di atas suhu udara; menaunginya dengan penutup putih berlubang mencegah hal ini. Detail pengkabelan dan library ada di artikel sensor suhu dan kelembapan DHT11 dan DHT22.

Untuk kelembapan tanah, pilih sensor kapasitif. Sensor resistif murah (YL-69, FC-28) punya dua kaki logam yang bersentuhan langsung dengan tanah, dan kalau terus dialiri daya, keduanya terkorosi dalam beberapa minggu karena elektrolisis; sensor seperti ini tidak cocok untuk sistem yang akan berjalan berbulan-bulan. Elektroda sensor kapasitif dilapisi, jadi tidak ada logam yang menyentuh tanah. Keluarannya analog dan turun ketika tanah makin basah: di Uno, sensor yang dipegang di udara membaca sekitar 500–600, dan ketika dicelupkan ke air sekitar 250–300. Angka ini berbeda untuk tiap sensor, jadi sebelum meng-upload kode utama, baca nilai sensormu sendiri di udara dan di air lewat Serial Monitor, lalu tulis ke konstanta SOIL_DRY_RAW dan SOIL_WET_RAW. Kode mengubah dua nilai ini menjadi 0–100% dengan map(). Detail lebih lanjut ada di artikel sensor kelembapan tanah.
Untuk cahaya, LDR (GL5528) dari kit-mu sudah cukup. Pasang LDR sebagai pembagi tegangan dengan resistor 10 kΩ: 5V → LDR → A1 → 10 kΩ → GND. Makin terang, hambatan LDR makin kecil dan nilai di A1 naik; kode juga mengubah nilai ini menjadi 0–100%, berdasarkan dua angka yang kamu ukur dalam gelap dan di bawah sinar matahari. LDR bukan lux meter yang presisi, tetapi bisa diandalkan untuk menjawab “sudah gelap belum, mendung, atau cerah?”. Kalau ingin pembacaan cahaya yang lebih akurat, kamu bisa beralih ke sensor cahaya I2C seperti BH1750. Pakai kalkulator pembagi tegangan untuk hitungan pembaginya dan artikel sensor cahaya LDR untuk detailnya.
Aktuator: relay atau MOSFET?
Satu pin Arduino hanya bisa memberi sekitar 20 mA, sedangkan kipas, pemanas, pompa, dan LED strip menarik ratusan miliampere bahkan beberapa ampere. Karena itu setiap beban dikendalikan lewat relay atau MOSFET. Relay adalah saklar mekanis: ia menyalakan dan mematikan beban di rangkaian yang benar-benar terpisah, AC maupun DC, tetapi hanya bisa nyala atau mati, berbunyi klik setiap kali berpindah, dan umur kontaknya terbatas. MOSFET adalah saklar elektronik yang senyap; ia hanya bekerja untuk beban DC, tetapi karena bisa berpindah ratusan kali per detik, ia bisa mengatur kecerahan dan kecepatan dengan PWM. Di proyek ini kita memakai modul relay 4 channel untuk pemanas, kipas, dan pompa, serta MOSFET untuk kecerahan LED strip.
| Beban | Nilai umum | Penggerak | Kenapa? |
|---|---|---|---|
| Pemanas PTC 12 V | 10–30 W, sekitar 1–2,5 A | Relay (IN2) | Arus tinggi, cukup nyala/mati |
| Kipas 12 V 80 mm | 0,1–0,2 A | Relay (IN1) atau MOSFET | Relay itu sederhana; MOSFET juga memungkinkan pengaturan kecepatan PWM |
| Pompa celup mini 3–6 V | 0,1–0,25 A, lebih besar ketika mulai | Relay (IN3) atau MOSFET dengan dioda | Berjalan dalam denyut singkat; derau motor harus diredam |
| LED strip 12 V (5050, 60 LED/m) | Sekitar 1,2 A per meter | MOSFET logic level | Pengaturan kecerahan PWM dan kerja senyap |

Tergantung tinggi selang, pompa celup mini mengalirkan sekitar 1–1,5 liter per menit, jadi denyut 3 detik memberi pot 50–75 mL air. Karena itu kita tidak menjalankan pompa terus-menerus “sampai tanah basah”, tetapi dalam denyut singkat: siram 3 detik, tunggu 60 detik agar air meresap, lalu ukur lagi. Kalau sensor dibaca lagi sebelum air sampai ke sana, tanah masih terlihat kering dan pompa akan terus menyala sampai pot meluap. Pompa yang berjalan tanpa air menjadi panas dan rusak dalam beberapa menit; saklar pelampung di tangki mengunci pompa ketika air habis. Setiap kali motor berhenti, kumparannya menghasilkan lonjakan tegangan balik; dioda yang dipasang terbalik di terminal pompa (1N5819 atau 1N4007, ujung bergaris ke sisi +) melindungi kontak relay sekaligus Arduino dari derau ini. Pemilihan pompa dan cara menggerakkannya dibahas di artikel pompa air mini.
Untuk pemanasan, pakai pemanas PTC 12 V. Hambatan elemen keramik PTC (positive temperature coefficient, koefisien suhu positif) naik ketika makin panas, sehingga suhu permukaannya membatasi diri sendiri pada nilai tertentu; ini jauh lebih aman daripada kawat pemanas telanjang yang membara. Di badan plastik, pilih model suhu rendah yang permukaannya dibatasi sekitar 80 °C. Menurut P = V × I, pemanas 24 W menarik 2 A pada 12 V; selama beberapa detik pertama ketika masih dingin, arusnya sedikit lebih tinggi. Untuk pencahayaan, kamu bisa memakai LED strip grow light merah-biru atau LED strip putih dingin; tanaman paling banyak memakai cahaya merah (sekitar 660 nm) dan biru (sekitar 450 nm) untuk fotosintesis. Kendalikan strip dengan MOSFET logic level seperti IRLZ44N: gate terhubung ke D9 lewat resistor 220 Ω dan ke GND lewat resistor 100 kΩ; kutub + strip ke 12 V, kutub − ke drain MOSFET, dan source ke GND. Modul MOSFET standar seperti IRF520 tidak menyala penuh dengan tegangan gate 5 V dan menjadi panas pada beban beberapa ampere; detailnya ada di artikel Memakai MOSFET dengan Arduino. Kamu bisa memakai kalkulator hukum Ohm untuk menghitung arus dan daya.
Rencana daya: jalur 12 V dan 5 V
Masalah yang paling sering muncul di rumah kaca pintar (“Arduino reset ketika pompa menyala”, “karakter aneh muncul di LCD”) berasal dari catu daya. Solusi paling rapi adalah mengambil dua jalur dari satu adaptor 12 V 5 A. Jalur 12 V langsung memberi daya ke pemanas, kipas, dan LED strip, dan juga masuk ke jack DC Arduino Uno. Tegangan 12 V yang sama juga masuk ke buck converter LM2596 yang diatur ke 5 V; kumparan relay, pompa, dan LCD berjalan dari jalur 5 V ini. Kalau jumper JD-VCC di modul relay dilepas, arus kumparan sepenuhnya datang dari LM2596 dan sisi Arduino hanya menyalakan LED optocoupler. Beri daya sensor (DHT22, sensor kelembapan tanah, dan pembagi LDR) dari pin 5V Arduino sendiri: analogRead() mengukur relatif terhadap 5 V milik board itu, jadi memberi daya sensor analog dari tegangan yang sama menjaga pembacaan tetap stabil. Selalu satukan GND adaptor, LM2596, dan Arduino.
| Beban | Jalur | Perkiraan arus |
|---|---|---|
| Pemanas PTC (24 W) | 12 V | 2 A (lebih besar di momen pertama ketika dingin) |
| LED strip (1 m) | 12 V | 1–1,2 A |
| Dua kipas 80 mm | 12 V | 0,2–0,4 A |
| Arduino Uno dan sensor (lewat jack DC) | 12 V | Sekitar 0,06–0,08 A |
| Input LM2596 (ketika sisi 5 V menarik 1 A) | 12 V | Sekitar 0,5 A |
| Modul relay (tiga relay aktif) | 5 V | 0,2–0,25 A |
| Pompa celup mini | 5 V | 0,1–0,25 A (lebih besar ketika mulai) |
| LCD I2C (lampu latar menyala) | 5 V | 20–30 mA |
Bahkan kalau semuanya menyala bersamaan, total arusnya sekitar 4–4,5 A, jadi adaptor 12 V 5 A (60 W) masih menyisakan cadangan yang cukup. Dalam praktiknya, pemanas dan kipas suhu tidak pernah menyala bersamaan, karena ada jarak lebar di antara ambangnya. Sebelum menyambungkan LM2596 ke rangkaian, ukur keluarannya dengan multimeter dan atur ke 5,0 V dengan trimpot di board-nya; dalam kondisi baru dari kotak, modul ini bisa meneruskan hampir seluruh 12 V begitu saja. Kamu bisa memberi daya Arduino dari USB ketika meng-upload kode dan dari jack DC di lapangan; keduanya tersambung bersamaan tidak masalah untuk Uno. Detailnya ada di panduan Cara Memberi Daya ke Arduino.
Pengkabelan dan tabel pin
Tabel di bawah menunjukkan pin yang dipakai oleh tiga program di panduan ini. Di Uno, kita menghubungkan MOSFET yang menggerakkan LED strip ke D9, yang mendukung PWM; di Uno, PWM hanya tersedia di D3, D5, D6, D9, D10, dan D11. Saklar pelampung dan relay tidak butuh PWM. Karena LCD hanya memakai bus I2C (A4 dan A5), pin yang terpakai sangat sedikit; di Uno, A2, A3, dan beberapa pin digital masih kosong untuk sensor tanah kedua atau tombol. Di ESP32, kita menghubungkan sensor analog ke pin ADC1 (GPIO 34 dan 35), yang tetap berfungsi ketika Wi-Fi aktif. Kamu bisa melihat tata letak pin board-mu di alat diagram pin.
| Sambungan | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| DHT22 DATA | D2 | GPIO 4 | GP15 |
| Saklar pelampung (kaki lain ke GND) | D3 | GPIO 13 | GP14 |
| Relay IN3: pompa | D4 | GPIO 25 | GP18 |
| Relay IN1: kipas | D7 | GPIO 26 | GP16 |
| Relay IN2: pemanas | D8 | GPIO 27 | GP17 |
| Gate MOSFET (lewat 220 Ω): LED | D9 | GPIO 18 | GP19 |
| AOUT sensor kelembapan tanah | A0 | GPIO 34 | GP26 |
| Titik tengah pembagi LDR | A1 | GPIO 35 (pembagi dari 3V3) | GP27 (pembagi dari 3V3) |
| I2C LCD SDA / SCL | A4 / A5 | GPIO 21 / 22 | GP4 / GP5 |
| Catu daya sensor | 5V | 3V3 | 3V3 |
Ambang dan histeresis: kenapa relay terus berbunyi klik?
Bayangkan mengendalikan kipas dengan satu ambang saja: “nyalakan kalau suhu di atas 30 °C, kalau tidak matikan”. Ketika suhu naik turun di antara 29,9 dan 30,1 °C (yang sering terjadi karena derau sensor), relay menyala dan mati di setiap pembacaan. Kontak relay dan motor kipas sama-sama cepat aus, dan untuk pemanas, kabel serta adaptor ikut terbebani sia-sia setiap kali menyala. Solusinya adalah histeresis: kamu memakai dua ambang terpisah untuk menyalakan dan mematikan. Kipas menyala pada 30 °C, tetapi baru berhenti ketika suhu sudah turun ke 27 °C. Di zona mati 3 derajat di antaranya, sistem mempertahankan keadaan terakhirnya. Termostat ruangan untuk pemanas air dan kulkas bekerja dengan prinsip yang sama.
| Kendali | Menyala | Mati | Zona mati |
|---|---|---|---|
| Kipas (suhu) | ≥ 30 °C | ≤ 27 °C | 3 °C |
| Kipas (kelembapan) | ≥ 85% | ≤ 75% | 10% |
| Pemanas | ≤ 16 °C | ≥ 19 °C | 3 °C |
| Penyiraman | Tanah ≤ 35% | Tanah ≥ 50% | 15% |
| Lampu LED | Cahaya ≤ 25% | Cahaya ≥ 35% atau setelah 4 jam | 10% |
Lebar zona mati adalah soal kompromi: terlalu sempit, relay tetap sering berpindah; terlalu lebar, suhu melenceng terlalu jauh dari target. Sekitar 2–3 °C untuk suhu, 8–10% untuk kelembapan, dan 10–15% untuk kelembapan tanah adalah awal yang baik. Kita juga menyisakan jarak lebar antara 19 °C, titik pemanas mati, dan 30 °C, titik kipas menyala, sehingga pemanas dan kipas suhu tidak pernah saling melawan. Di kode, histeresis dikumpulkan di fungsi kecil hysteresis() agar tidak perlu ditulis ulang untuk setiap kendali: kalau ambang nyala lebih besar daripada ambang mati, artinya “nyalakan ketika naik” (kipas); kalau lebih kecil, artinya “nyalakan ketika turun” (pemanas, penyiraman, LED). Kalau kamu juga ingin menghaluskan lonjakan di data sensor, lihat artikel menyaring data sensor.
Struktur kode: ukur, putuskan, jalankan, tampilkan
Aturan terpenting di kode rumah kaca adalah tidak ada tugas yang menunggu tugas lain. Kalau kamu menunggu satu menit penuh dengan delay(60000) setelah pompa, kipas tidak akan menyala dan layar tidak diperbarui selama itu. Karena itu kode terdiri dari fungsi-fungsi kecil yang mengukur waktu dengan millis(), masing-masing bertanggung jawab atas satu tugas; loop() memanggilnya bergiliran ribuan kali per detik, dan setiap fungsi hanya bertindak kalau waktunya sudah tiba. Penyiraman adalah state machine kecil dengan tiga keadaan: menunggu (IDLE), menyiram (PUMPING), dan membiarkan air meresap (SOAKING). Semua pengaturan berada sebagai konstanta di bagian atas kode, jadi kamu tidak perlu menelusuri seluruh kode untuk mengubah ambang. Alasan di balik pendekatan ini ada di artikel millis() dan delay() serta state machine Arduino. Kode ini juga punya langkah-langkah pengaman berikut:
- Mulai dengan aman: Nilai “mati” ditulis ke pin relay sebelum pinMode() dipanggil, sehingga relay tidak aktif sekejap pun ketika Arduino menyala.
- Sensor rusak: Kalau DHT22 gagal dibaca tiga kali berturut-turut, kode beralih ke keadaan aman: mematikan pemanas, menyalakan kipas, dan menampilkan “Sensor hatasi” (error sensor) di LCD. Sistem yang tidak tahu suhunya tidak boleh membiarkan pemanas menyala.
- Proteksi tangki: Ketika saklar pelampung menandakan tangki kosong, pompa sama sekali tidak menyala, dan kalau sedang menyala langsung berhenti.
- Proteksi luapan: Kalau kelembapan tanah tidak mencapai 50% setelah enam denyut dalam satu siklus penyiraman, mungkin sensornya tercabut dari tanah atau selangnya lepas; kode menghentikan penyiraman dan menampilkan “Sulama hatasi” (gangguan penyiraman). Peringatan ini hilang sendiri begitu tanah basah lagi.
- Pencatatan data: Setiap 10 detik, kode menulis hasil pengukuran ke Serial Monitor sebagai baris yang dipisahkan koma (CSV); kamu bisa menyalin baris-baris ini dan membuat grafik di Excel.
Perakitan dan pengujian langkah demi langkah
- Siapkan badan rumah kaca: buat lubang untuk kipas, lubang masuk udara, selang, dan kabel, lalu letakkan kotak elektronik di luar rumah kaca.
- Pasang jalur daya: sambungkan adaptor 12 V ke terminal sekrup, atur LM2596 ke 5,0 V dengan multimeter, dan satukan semua GND.
- Sambungkan LCD I2C dan tampilkan sebuah teks. Kalau layar tidak menampilkan apa pun, coba sketch scanner dan trimpot kontras dari artikel LCD I2C.
- Tambahkan sensor satu per satu dan uji di Serial Monitor: catat pembacaan DHT22, nilai mentah sensor tanah di udara dan di air, serta nilai LDR dalam gelap dan di bawah sinar matahari.
- Uji relay dulu tanpa beban sambil memperhatikan LED-nya dan mendengarkan bunyi kliknya. Setelah itu sambungkan kipas, pompa (dengan tangki penuh), dan terakhir pemanas.
- Sambungkan LED strip lewat MOSFET dan ubah nilai analogWrite() untuk melihat kecerahannya berubah.
- Upload kode utama, masukkan nilai kalibrasimu ke konstanta, dan jalankan sistem beberapa jam di bawah pengawasan: adakah penyiraman yang salah, relay yang terus berbunyi klik, atau komponen yang terlalu panas?
Kode lengkap untuk Arduino Uno
Untuk mengompilasi kode, instal library DHT sensor library dari Adafruit (beserta dependensinya, Adafruit Unified Sensor) dan library LiquidCrystal I2C dari Frank de Brabander lewat Library Manager; Wire sudah ikut bersama Arduino IDE. Alamat LCD biasanya 0x27, dan 0x3F di beberapa modul. Sebelum meng-upload, tulis nilai kalibrasi yang kamu ukur ke konstanta SOIL_DRY_RAW, SOIL_WET_RAW, LDR_DARK_RAW, dan LDR_BRIGHT_RAW. Kalau saklar pelampungmu justru terbuka (bukan tertutup) ketika ada air, ubah TANK_OK menjadi HIGH; kalau modul relay-mu aktif HIGH, tukar nilai RELAY_ON dan RELAY_OFF.
1#include <Wire.h>
2#include <LiquidCrystal_I2C.h>
3#include <DHT.h>
4
5// Pinler / Pins
6const byte DHT_PIN = 2, FLOAT_PIN = 3, PUMP_RELAY = 4, FAN_RELAY = 7, HEATER_RELAY = 8;
7const byte LED_PIN = 9; // MOSFET gate (PWM)
8const byte SOIL_PIN = A0, LDR_PIN = A1;
9
10// Kalibrasyon: kendi ölçümlerini yaz / Calibration: write your own readings
11const int SOIL_DRY_RAW = 520, SOIL_WET_RAW = 260; // havada ve suda / in air and in water
12const int LDR_DARK_RAW = 60, LDR_BRIGHT_RAW = 900; // karanlık ve güneş / dark and sunlight
13
14// Eşikler (açma, kapama) / Thresholds (on, off)
15const float FAN_ON_C = 30, FAN_OFF_C = 27; // sıcaklıkta fan / fan on heat
16const float HUM_ON = 85, HUM_OFF = 75; // nemde fan / fan on humidity
17const float HEAT_ON_C = 16, HEAT_OFF_C = 19; // ısıtıcı / heater
18const float SOIL_DRY = 35, SOIL_OK = 50; // sulama başla, dur / start, stop watering
19const float DARK_ON = 25, DARK_OFF = 35; // ışık % / light %
20
21// Zamanlar / Timing
22const unsigned long READ_MS = 2500; // DHT22: en az 2 sn / at least 2 s
23const unsigned long PUMP_MS = 3000; // tek sulama darbesi / one watering pulse
24const unsigned long SOAK_MS = 60000; // suyun yayılması / let the water soak in
25const byte MAX_PULSES = 6; // fazlası arıza / more means a fault
26const unsigned long EXTRA_LIGHT_MS = 4UL * 3600000UL; // günü 4 saat uzat / extend the day by 4 h
27const byte LED_LEVEL = 200; // LED parlaklığı 0-255 / LED brightness 0-255
28const byte RELAY_ON = LOW, RELAY_OFF = HIGH; // aktif LOW röle / active-LOW relay
29const byte TANK_OK = LOW; // şamandıra suyla kapanır / float closes with water
30
31DHT dht(DHT_PIN, DHT22);
32LiquidCrystal_I2C lcd(0x27, 16, 2);
33
34float tempC = NAN, hum = NAN, soil = 0, light = 0;
35byte dhtErrors = 0, pulses = 0, page = 0;
36bool fanByTemp = false, fanByHum = false, fanOn = false, heaterOn = false;
37bool needWater = false, pumpFault = false, isDark = false, ledOn = false, tankOk = true;
38unsigned long lastRead = 0, lastLcd = 0, lastLog = 0, pumpAt = 0, darkSince = 0;
39
40enum PumpState { IDLE, PUMPING, SOAKING };
41PumpState pumpState = IDLE;
42
43// onAt > offAt: yükselince aç (fan) / turn on when rising (fan)
44// onAt < offAt: düşünce aç (ısıtıcı) / turn on when falling (heater)
45bool hysteresis(bool state, float value, float onAt, float offAt) {
46 if (onAt > offAt) {
47 if (value >= onAt) return true;
48 if (value <= offAt) return false;
49 } else {
50 if (value <= onAt) return true;
51 if (value >= offAt) return false;
52 }
53 return state; // ölü bölgede durumu koru / keep state in the dead band
54}
55
56void setRelay(byte pin, bool on) {
57 digitalWrite(pin, on ? RELAY_ON : RELAY_OFF);
58}
59
60float readPercent(byte pin, int raw0, int raw100) {
61 long sum = 0;
62 for (byte i = 0; i < 10; i++) sum += analogRead(pin); // 10 ölçüm ortalaması / average of 10
63 long pct = map(sum / 10, raw0, raw100, 0, 100);
64 return constrain(pct, 0, 100);
65}
66
67void setup() {
68 Serial.begin(9600);
69 setRelay(PUMP_RELAY, false); pinMode(PUMP_RELAY, OUTPUT); // açılışta kapalı / off at boot
70 setRelay(FAN_RELAY, false); pinMode(FAN_RELAY, OUTPUT);
71 setRelay(HEATER_RELAY, false); pinMode(HEATER_RELAY, OUTPUT);
72 pinMode(LED_PIN, OUTPUT);
73 pinMode(FLOAT_PIN, INPUT_PULLUP);
74 dht.begin();
75 lcd.init();
76 lcd.backlight();
77 lcd.print(F("BlueGrays Sera"));
78 Serial.println(F("sn,sicaklik,nem,toprak,isik,fan,isitici,pompa,led")); // CSV başlığı / CSV header
79 delay(2000); // DHT22 açılış süresi / DHT22 start-up time
80 readSensors();
81 lastRead = millis();
82}
83
84void loop() {
85 unsigned long now = millis();
86 if (now - lastRead >= READ_MS) {
87 lastRead = now;
88 readSensors();
89 }
90 controlClimate();
91 controlLight(now);
92 controlPump(now);
93 updateLcd(now);
94 logCsv(now);
95}
96
97// 1) Ölç / Measure
98void readSensors() {
99 float t = dht.readTemperature();
100 float h = dht.readHumidity();
101 if (isnan(t) || isnan(h)) {
102 if (dhtErrors < 255) dhtErrors++; // okuma hatası / read error
103 } else {
104 tempC = t;
105 hum = h;
106 dhtErrors = 0;
107 }
108 soil = readPercent(SOIL_PIN, SOIL_DRY_RAW, SOIL_WET_RAW);
109 light = readPercent(LDR_PIN, LDR_DARK_RAW, LDR_BRIGHT_RAW);
110 tankOk = digitalRead(FLOAT_PIN) == TANK_OK;
111}
112
113// 2) Fan ve ısıtıcı / Fan and heater
114void controlClimate() {
115 if (dhtErrors >= 3) { // sensör yok: güvenli durum / no sensor: safe state
116 heaterOn = false;
117 fanByTemp = true;
118 } else {
119 fanByTemp = hysteresis(fanByTemp, tempC, FAN_ON_C, FAN_OFF_C);
120 fanByHum = hysteresis(fanByHum, hum, HUM_ON, HUM_OFF);
121 heaterOn = hysteresis(heaterOn, tempC, HEAT_ON_C, HEAT_OFF_C);
122 }
123 fanOn = fanByTemp || fanByHum;
124 setRelay(FAN_RELAY, fanOn);
125 setRelay(HEATER_RELAY, heaterOn);
126}
127
128// 3) LED aydınlatma / LED grow light
129void controlLight(unsigned long now) {
130 bool wasDark = isDark;
131 isDark = hysteresis(isDark, light, DARK_ON, DARK_OFF);
132 if (isDark && !wasDark) darkSince = now; // akşam oldu / dusk detected
133 ledOn = isDark && (now - darkSince < EXTRA_LIGHT_MS);
134 analogWrite(LED_PIN, ledOn ? LED_LEVEL : 0);
135}
136
137// 4) Sulama: darbe + bekleme / Watering: pulse + soak
138void controlPump(unsigned long now) {
139 needWater = hysteresis(needWater, soil, SOIL_DRY, SOIL_OK);
140 if (!needWater) {
141 pulses = 0;
142 pumpFault = false; // toprak ıslandı / soil is wet again
143 }
144 switch (pumpState) {
145 case IDLE:
146 if (needWater && tankOk && !pumpFault) {
147 if (pulses >= MAX_PULSES) {
148 pumpFault = true; // nem yükselmiyor / moisture is not rising
149 } else {
150 pumpState = PUMPING;
151 pumpAt = now;
152 pulses++;
153 }
154 }
155 break;
156 case PUMPING:
157 if (now - pumpAt >= PUMP_MS || !tankOk) {
158 pumpState = SOAKING;
159 pumpAt = now;
160 }
161 break;
162 case SOAKING:
163 if (now - pumpAt >= SOAK_MS) pumpState = IDLE;
164 break;
165 }
166 setRelay(PUMP_RELAY, pumpState == PUMPING);
167}
168
169// 5) LCD: üç sayfa / three pages
170void updateLcd(unsigned long now) {
171 if (now - lastLcd < 3000) return;
172 lastLcd = now;
173 page = (page + 1) % 3;
174 lcd.clear();
175 if (page == 0) {
176 lcd.print(F("Sicaklik: "));
177 if (isnan(tempC)) lcd.print(F("--")); else lcd.print(tempC, 1);
178 lcd.print('C');
179 lcd.setCursor(0, 1);
180 lcd.print(F("Hava nemi: %"));
181 if (isnan(hum)) lcd.print(F("--")); else lcd.print(hum, 0);
182 } else if (page == 1) {
183 lcd.print(F("Toprak: %"));
184 lcd.print(soil, 0);
185 lcd.setCursor(0, 1);
186 lcd.print(F("Isik: %"));
187 lcd.print(light, 0);
188 } else {
189 lcd.print(F("F:")); lcd.print(fanOn);
190 lcd.print(F(" I:")); lcd.print(heaterOn);
191 lcd.print(F(" P:")); lcd.print(pumpState == PUMPING);
192 lcd.print(F(" L:")); lcd.print(ledOn);
193 lcd.setCursor(0, 1);
194 if (dhtErrors >= 3) lcd.print(F("Sensor hatasi"));
195 else if (!tankOk) lcd.print(F("Depo bos!"));
196 else if (pumpFault) lcd.print(F("Sulama hatasi"));
197 else lcd.print(F("Sistem normal"));
198 }
199}
200
201// 6) Seri port CSV kaydı / Serial CSV log
202void logCsv(unsigned long now) {
203 if (now - lastLog < 10000) return;
204 lastLog = now;
205 Serial.print(now / 1000); Serial.print(',');
206 Serial.print(tempC, 1); Serial.print(',');
207 Serial.print(hum, 0); Serial.print(',');
208 Serial.print(soil, 0); Serial.print(',');
209 Serial.print(light, 0); Serial.print(',');
210 Serial.print(fanOn); Serial.print(',');
211 Serial.print(heaterOn); Serial.print(',');
212 Serial.print(pumpState == PUMPING); Serial.print(',');
213 Serial.println(ledOn);
214}| Fungsi | Tugas | Seberapa sering? |
|---|---|---|
| readSensors() (membaca sensor) | Membaca DHT22, kelembapan tanah, LDR, dan saklar pelampung; mengubah nilai analog menjadi 0–100% memakai rata-rata 10 pembacaan | Setiap 2,5 detik |
| controlClimate() (kendali iklim) | Menggerakkan kipas dengan histeresis suhu atau kelembapan dan pemanas dengan histeresis suhu; beralih ke keadaan aman kalau sensor gagal | Setiap loop |
| controlLight() (kendali cahaya) | Menyalakan LED dengan PWM ketika hari gelap dan mematikannya paling lama setelah 4 jam | Setiap loop |
| controlPump() (kendali pompa) | State machine penyiraman: siram 3 dtk, tunggu 60 dtk, ukur lagi; dengan proteksi tangki dan luapan | Setiap loop |
| updateLcd() (memperbarui LCD) | Bergantian menampilkan tiga halaman: pembacaan udara, kelembapan tanah dan cahaya, serta status perangkat | Setiap 3 detik |
| logCsv() (mencatat CSV) | Menulis hasil pengukuran dan status ke Serial Monitor sebagai baris CSV | Setiap 10 detik |
Halaman pertama LCD menampilkan suhu dan kelembapan udara, halaman kedua kelembapan tanah dan tingkat cahaya, dan halaman ketiga status perangkat: “F:1 I:0 P:0 L:1” berarti kipas menyala, pemanas (I, huruf awal kata Turki untuk pemanas) dan pompa mati, dan LED menyala. Baris bawah menampilkan salah satu pesan “Sistem normal” (semua baik), “Depo bos!” (tangki kosong), “Sulama hatasi” (gangguan penyiraman), atau “Sensor hatasi” (error sensor); kamu bisa dengan mudah menerjemahkan teks-teks ini di kode. Setelah dikompilasi, kode ini memakai sekitar 31% memori program Uno dan 25% RAM-nya, jadi masih banyak ruang untuk menambahkan sensor tanah kedua, buzzer, atau modul jam RTC. Karena Uno tidak punya jam sungguhan, aturan LED bekerja sebagai “paling lama 4 jam setelah senja”, cara yang bagus untuk memperpanjang hari yang pendek di musim dingin. Kalau ingin LED menyala pada jam tertentu setiap hari, tambahkan modul RTC atau beralih ke versi ESP32 di bawah.
Memantau dan menyiram dari ponsel dengan ESP32

Uno tidak punya Wi-Fi. Kalau kamu ingin melihat status rumah kaca di ponsel dan menyiram dari jauh, ganti otaknya dengan ESP32. Kode di bawah memindahkan logika kendali yang sama ke ESP32 dan menjalankan web server kecil. Dengan ponselmu di jaringan Wi-Fi yang sama, buka alamat IP yang tampil di Serial Monitor di browser, dan kamu akan melihat suhu, kelembapan, kelembapan tanah, cahaya, status tangki, serta apakah setiap perangkat menyala atau mati; halamannya memuat ulang sendiri setiap 10 detik. Tombol Water now (siram sekarang) menjalankan pompa sekali selama 3 detik kalau ada air di tangki. Ketika mulai, ESP32 mengambil waktu dari internet (NTP), sehingga LED hanya menyala antara pukul 06.00 dan 20.00 dan hanya ketika di luar gelap, dan tanaman bisa beristirahat di malam hari.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <DHT.h>
4#include <time.h>
5
6const char* ssid = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
7const char* password = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
8
9// Pinler / Pins
10const int DHT_PIN = 4, FLOAT_PIN = 13, PUMP_RELAY = 25, FAN_RELAY = 26, HEATER_RELAY = 27;
11const int LED_PIN = 18; // MOSFET gate (PWM)
12const int SOIL_PIN = 34, LDR_PIN = 35; // ADC1: Wi-Fi açıkken çalışır / works with Wi-Fi on
13
14// Kalibrasyon (0-4095): kendin ölç / Calibration (0-4095): measure your own
15const int SOIL_DRY_RAW = 2800, SOIL_WET_RAW = 1200;
16const int LDR_DARK_RAW = 200, LDR_BRIGHT_RAW = 3800;
17
18// Eşikler (açma, kapama) / Thresholds (on, off)
19const float FAN_ON_C = 30, FAN_OFF_C = 27, HUM_ON = 85, HUM_OFF = 75;
20const float HEAT_ON_C = 16, HEAT_OFF_C = 19, SOIL_DRY = 35, SOIL_OK = 50;
21const float DARK_ON = 25, DARK_OFF = 35;
22const int LIGHT_FROM = 6, LIGHT_TO = 20; // LED yalnız 06:00-20:00 / LEDs only 06:00-20:00
23
24const unsigned long READ_MS = 2500, PUMP_MS = 3000, SOAK_MS = 60000;
25const unsigned long EXTRA_LIGHT_MS = 4UL * 3600000UL; // saat yoksa yedek kural / fallback without a clock
26const int MAX_PULSES = 6, LED_LEVEL = 200;
27const int RELAY_ON = LOW, RELAY_OFF = HIGH; // aktif LOW röle / active-LOW relay
28const int TANK_OK = LOW; // şamandıra suyla kapanır / float closes with water
29
30DHT dht(DHT_PIN, DHT22);
31WebServer server(80);
32
33float tempC = NAN, hum = NAN, soil = 0, light = 0;
34int dhtErrors = 0, pulses = 0;
35bool fanByTemp = false, fanByHum = false, fanOn = false, heaterOn = false;
36bool needWater = false, pumpFault = false, isDark = false, ledOn = false, tankOk = true;
37unsigned long lastRead = 0, pumpAt = 0, darkSince = 0;
38
39enum PumpState { IDLE, PUMPING, SOAKING };
40PumpState pumpState = IDLE;
41
42bool hysteresis(bool state, float value, float onAt, float offAt) {
43 if (onAt > offAt) { // yükselince aç / turn on when rising
44 if (value >= onAt) return true;
45 if (value <= offAt) return false;
46 } else { // düşünce aç / turn on when falling
47 if (value <= onAt) return true;
48 if (value >= offAt) return false;
49 }
50 return state;
51}
52
53void setRelay(int pin, bool on) {
54 digitalWrite(pin, on ? RELAY_ON : RELAY_OFF);
55}
56
57float readPercent(int pin, int raw0, int raw100) {
58 long sum = 0;
59 for (int i = 0; i < 16; i++) sum += analogRead(pin); // 16 ölçüm ortalaması / average of 16
60 long pct = map(sum / 16, raw0, raw100, 0, 100);
61 return constrain(pct, 0, 100);
62}
63
64int hourNow() {
65 struct tm t;
66 if (!getLocalTime(&t, 0)) return -1; // saat henüz yok / time not set yet
67 return t.tm_hour;
68}
69
70void readSensors() {
71 float t = dht.readTemperature();
72 float h = dht.readHumidity();
73 if (isnan(t) || isnan(h)) {
74 dhtErrors++;
75 } else {
76 tempC = t;
77 hum = h;
78 dhtErrors = 0;
79 }
80 soil = readPercent(SOIL_PIN, SOIL_DRY_RAW, SOIL_WET_RAW);
81 light = readPercent(LDR_PIN, LDR_DARK_RAW, LDR_BRIGHT_RAW);
82 tankOk = digitalRead(FLOAT_PIN) == TANK_OK;
83}
84
85void controlClimate() {
86 if (dhtErrors >= 3) { // sensör yok: güvenli durum / no sensor: safe state
87 heaterOn = false;
88 fanByTemp = true;
89 } else {
90 fanByTemp = hysteresis(fanByTemp, tempC, FAN_ON_C, FAN_OFF_C);
91 fanByHum = hysteresis(fanByHum, hum, HUM_ON, HUM_OFF);
92 heaterOn = hysteresis(heaterOn, tempC, HEAT_ON_C, HEAT_OFF_C);
93 }
94 fanOn = fanByTemp || fanByHum;
95 setRelay(FAN_RELAY, fanOn);
96 setRelay(HEATER_RELAY, heaterOn);
97}
98
99void controlLight(unsigned long now) {
100 bool wasDark = isDark;
101 isDark = hysteresis(isDark, light, DARK_ON, DARK_OFF);
102 if (isDark && !wasDark) darkSince = now;
103 int h = hourNow();
104 if (h >= 0) ledOn = isDark && h >= LIGHT_FROM && h < LIGHT_TO; // saat kuralı / clock rule
105 else ledOn = isDark && (now - darkSince < EXTRA_LIGHT_MS); // yedek kural / fallback rule
106 analogWrite(LED_PIN, ledOn ? LED_LEVEL : 0);
107}
108
109void controlPump(unsigned long now) {
110 needWater = hysteresis(needWater, soil, SOIL_DRY, SOIL_OK);
111 if (!needWater) {
112 pulses = 0;
113 pumpFault = false;
114 }
115 if (pumpState == IDLE && needWater && tankOk && !pumpFault) {
116 if (pulses >= MAX_PULSES) {
117 pumpFault = true; // nem yükselmiyor / moisture is not rising
118 } else {
119 pumpState = PUMPING;
120 pumpAt = now;
121 pulses++;
122 }
123 } else if (pumpState == PUMPING && (now - pumpAt >= PUMP_MS || !tankOk)) {
124 pumpState = SOAKING;
125 pumpAt = now;
126 } else if (pumpState == SOAKING && now - pumpAt >= SOAK_MS) {
127 pumpState = IDLE;
128 }
129 setRelay(PUMP_RELAY, pumpState == PUMPING);
130}
131
132String row(const char* name, const String& value) {
133 return String("<tr><td>") + name + "</td><td><b>" + value + "</b></td></tr>";
134}
135
136String onOff(bool on) {
137 return on ? "ON" : "OFF";
138}
139
140void handleRoot() {
141 String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>"
142 "<meta name='viewport' content='width=device-width,initial-scale=1'>"
143 "<meta http-equiv='refresh' content='10'><title>BlueGrays Sera</title>"
144 "<style>body{font-family:sans-serif;max-width:420px;margin:auto;padding:12px}"
145 "td{padding:8px;border-bottom:1px solid #ddd}"
146 "a{display:block;margin-top:16px;padding:16px;border-radius:10px;background:#2e7d32;"
147 "color:#fff;text-align:center;text-decoration:none;font-size:18px}</style>"
148 "</head><body><h2>BlueGrays Sera</h2><table>";
149 html += row("Sıcaklık / Temperature", String(tempC, 1) + " °C");
150 html += row("Hava nemi / Humidity", "%" + String(hum, 0));
151 html += row("Toprak nemi / Soil", "%" + String(soil, 0));
152 html += row("Işık / Light", "%" + String(light, 0));
153 html += row("Fan", onOff(fanOn));
154 html += row("Isıtıcı / Heater", onOff(heaterOn));
155 html += row("Pompa / Pump", onOff(pumpState == PUMPING));
156 html += row("LED", onOff(ledOn));
157 html += row("Depo / Tank", tankOk ? "OK" : "BOŞ / EMPTY");
158 if (pumpFault) html += row("Uyarı / Warning", "Sulama hatası / Watering fault");
159 html += "</table><a href='/water'>Şimdi sula / Water now</a></body></html>";
160 server.send(200, "text/html", html);
161}
162
163void handleWater() { // elle tek darbe / one manual pulse
164 if (pumpState == IDLE && tankOk) {
165 pumpState = PUMPING;
166 pumpAt = millis();
167 }
168 server.sendHeader("Location", "/");
169 server.send(303);
170}
171
172void setup() {
173 Serial.begin(115200);
174 setRelay(PUMP_RELAY, false); pinMode(PUMP_RELAY, OUTPUT);
175 setRelay(FAN_RELAY, false); pinMode(FAN_RELAY, OUTPUT);
176 setRelay(HEATER_RELAY, false); pinMode(HEATER_RELAY, OUTPUT);
177 pinMode(LED_PIN, OUTPUT);
178 pinMode(FLOAT_PIN, INPUT_PULLUP);
179 dht.begin();
180 WiFi.begin(ssid, password);
181 while (WiFi.status() != WL_CONNECTED) {
182 delay(500);
183 Serial.print('.');
184 }
185 Serial.println();
186 Serial.println(WiFi.localIP()); // bu adresi telefonda aç / open this address on your phone
187 configTime(3 * 3600, 0, "pool.ntp.org"); // Türkiye UTC+3; kendi saat dilimini yaz / set your own time zone
188 server.on("/", handleRoot);
189 server.on("/water", handleWater);
190 server.begin();
191 readSensors();
192 lastRead = millis();
193}
194
195void loop() {
196 server.handleClient();
197 unsigned long now = millis();
198 if (now - lastRead >= READ_MS) {
199 lastRead = now;
200 readSensors();
201 }
202 controlClimate();
203 controlLight(now);
204 controlPump(now);
205}Inilah yang berubah dibandingkan kode Uno: ADC ESP32 adalah 12-bit dan memberi nilai dari 0 sampai 4095, jadi kamu perlu mengulang kalibrasi; karena sensor diberi daya dari 3V3, nilai mentahnya juga akan berbeda. Zona waktu diatur di baris configTime(); untuk Turki (UTC+3) kami menulis 3 × 3600 detik, jadi untuk WIB (UTC+7) ganti menjadi 7 × 3600, untuk WITA 8 × 3600, dan untuk WIT 9 × 3600 (Indonesia tidak memakai waktu musim panas). Untuk zona yang memakai waktu musim panas, ganti baris itu dengan configTzTime() dan string zona waktu POSIX, misalnya configTzTime("GMT0BST,M3.5.0/1,M10.5.0", "pool.ntp.org") untuk Inggris. Kalau tidak ada internet atau waktunya belum berhasil diambil, aturan LED kembali ke aturan “paling lama 4 jam” seperti di Uno. Halamannya tidak memakai kata sandi, jadi siapa pun di jaringan rumahmu bisa menyalakan pompa; menambahkan kata sandi sederhana dengan fungsi authenticate() dari library WebServer adalah kebiasaan yang baik. Kalau ingin memakai LCD juga di ESP32, kamu bisa menyalin fungsi updateLcd() dari kode Uno apa adanya; SDA di GPIO 21 dan SCL di GPIO 22.
| Metode | Akses dari luar rumah | Tingkat kesulitan | Paling cocok untuk |
|---|---|---|---|
| Web server ESP32 (kode di panduan ini) | Tidak, hanya jaringan yang sama | Menengah | Presentasi sekolah, demo tanpa internet |
| Blynk IoT | Ya | Mudah | Gauge, grafik, dan notifikasi siap pakai |
| Bot Telegram | Ya | Menengah | Peringatan “tangki kosong” dan “suhu terlalu tinggi” |
| Google Sheets | Ya | Menengah | Pencatatan data dan grafik selama berminggu-minggu |
| MQTT dan Home Assistant | Ya, perlu pengaturan | Mahir | Otomasi rumah dan kebun sungguhan |
Untuk presentasi sekolah, web server ESP32 adalah pilihan paling aman: tidak bergantung pada layanan cloud dan tetap berjalan di jaringannya sendiri meskipun aula tidak punya internet. Kalau kamu juga ingin mengecek dari luar rumah, Blynk IoT dengan ESP32 dengan gauge dan grafik siap pakainya adalah jalan termudah. Untuk menerima pesan di ponsel ketika tangki kosong atau suhu mencapai tingkat berbahaya, lihat panduan bot Telegram ESP32; untuk mengumpulkan data berminggu-minggu bagi laporanmu, mencatat data ESP32 ke Google Sheets; dan untuk menghubungkan rumah kaca ke otomasi rumah sungguhan, MQTT dan Home Assistant.
Versi MicroPython untuk Raspberry Pi Pico
Kamu juga bisa menjalankan rumah kaca yang sama dengan Raspberry Pi Pico dalam MicroPython. Firmware MicroPython untuk Pico sudah membawa driver DHT bawaan, jadi kamu tidak perlu menyalin file tambahan. Input analognya hanya GP26, GP27, dan GP28, dan read_u16() memberi nilai dari 0 sampai 65535; ukur angka kalibrasimu sesuai rentang ini. Karena Pico bekerja pada 3,3 V, beri daya sensor dari 3V3 dan modul relay dari VBUS (5 V dari USB) atau jalur LM2596. Kode di bawah berisi semua aturan kipas, pemanas, LED, dan penyiraman, dan mencetak nilainya ke shell Thonny. Kalau kamu menyimpan file di Pico dengan nama main.py, board tetap berjalan meskipun tidak tersambung ke komputer. Kalau kamu memakai Pico W yang punya Wi-Fi, kamu bisa menambahkan cara dari artikel web server Pico W untuk memantau nilainya dari ponsel.
1from machine import Pin, ADC, PWM
2import dht
3import time
4
5sensor = dht.DHT22(Pin(15)) # GP15: DHT22 DATA
6soil_adc = ADC(26) # GP26: toprak nem AOUT / soil moisture AOUT
7ldr_adc = ADC(27) # GP27: LDR bölücü (3V3) / LDR divider (3V3)
8tank = Pin(14, Pin.IN, Pin.PULL_UP) # şamandıra: suyla 0 / float switch: 0 with water
9fan = Pin(16, Pin.OUT, value=1) # aktif LOW röleler kapalı başlar / active-LOW relays start off
10heater = Pin(17, Pin.OUT, value=1)
11pump = Pin(18, Pin.OUT, value=1)
12led = PWM(Pin(19)) # MOSFET gate
13led.freq(1000)
14
15SOIL_DRY_RAW, SOIL_WET_RAW = 50000, 22000 # kendin ölç / measure your own
16LDR_DARK_RAW, LDR_BRIGHT_RAW = 2000, 60000
17EXTRA_LIGHT_MS = 4 * 3600 * 1000 # günü 4 saat uzat / extend the day by 4 h
18
19
20def percent(adc, raw0, raw100):
21 raw = sum(adc.read_u16() for _ in range(10)) // 10
22 pct = (raw - raw0) * 100 // (raw100 - raw0)
23 return max(0, min(100, pct))
24
25
26def hysteresis(state, value, on_at, off_at):
27 if on_at > off_at: # yükselince aç / turn on when rising
28 if value >= on_at:
29 return True
30 if value <= off_at:
31 return False
32 else: # düşünce aç / turn on when falling
33 if value <= on_at:
34 return True
35 if value >= off_at:
36 return False
37 return state # ölü bölge / dead band
38
39
40def relay(pin, on):
41 pin.value(0 if on else 1)
42
43
44t = h = None
45errors = pulses = 0
46fan_t = fan_h = heat_on = need_water = dark = led_on = False
47pump_state, pump_at, dark_since = "idle", 0, 0
48soil = light = 0
49tank_ok = True
50time.sleep(2) # DHT22 açılış süresi / DHT22 start-up time
51last_read = time.ticks_add(time.ticks_ms(), -2500)
52
53while True:
54 now = time.ticks_ms()
55 if time.ticks_diff(now, last_read) >= 2500: # 2,5 sn'de bir ölç / measure every 2.5 s
56 last_read = now
57 try:
58 sensor.measure()
59 t, h = sensor.temperature(), sensor.humidity()
60 errors = 0
61 except OSError:
62 errors += 1 # okuma hatası / read error
63 soil = percent(soil_adc, SOIL_DRY_RAW, SOIL_WET_RAW)
64 light = percent(ldr_adc, LDR_DARK_RAW, LDR_BRIGHT_RAW)
65 tank_ok = tank.value() == 0
66
67 if errors >= 3 or t is None: # güvenli durum / safe state
68 heat_on, fan_t = False, True
69 else:
70 fan_t = hysteresis(fan_t, t, 30, 27)
71 fan_h = hysteresis(fan_h, h, 85, 75)
72 heat_on = hysteresis(heat_on, t, 16, 19)
73 relay(fan, fan_t or fan_h)
74 relay(heater, heat_on)
75
76 was_dark = dark
77 dark = hysteresis(dark, light, 25, 35)
78 if dark and not was_dark:
79 dark_since = now # akşam oldu / dusk detected
80 led_on = dark and time.ticks_diff(now, dark_since) < EXTRA_LIGHT_MS
81 led.duty_u16(50000 if led_on else 0)
82
83 need_water = hysteresis(need_water, soil, 35, 50)
84 if not need_water:
85 pulses = 0
86 print("T", t, "N", h, "Toprak", soil, "Isik", light, "Pompa", pump_state,
87 "Depo OK" if tank_ok else "Depo BOS", "HATA" if pulses >= 6 else "")
88
89 # Sulama: 3 sn darbe, 60 sn bekleme / Watering: 3 s pulse, 60 s soak
90 if pump_state == "idle" and need_water and tank_ok and pulses < 6:
91 pump_state, pump_at = "pump", now
92 pulses += 1
93 elif pump_state == "pump" and (time.ticks_diff(now, pump_at) >= 3000 or not tank_ok):
94 pump_state, pump_at = "soak", now
95 elif pump_state == "soak" and time.ticks_diff(now, pump_at) >= 60000:
96 pump_state = "idle"
97 relay(pump, pump_state == "pump")
98 time.sleep_ms(100)Tips presentasi di sekolah dan lomba sains
Rumah kaca pintar adalah topik yang begitu populer sampai juri melihat puluhan maket yang mirip. Yang membuatmu menonjol bukan sekadar menunjukkan bahwa sistemnya berjalan, tetapi menjawab sebuah pertanyaan dengan hasil pengukuran. Di pameran sains (seperti TÜBİTAK 4006 di Turki), tujuan, metode, dan hasil yang diharapkan harus jelas; lomba penelitian (seperti TÜBİTAK 2204) mengharapkan eksperimen pembanding lengkap dengan data. Pertanyaan penelitian yang bagus untuk rumah kaca ini adalah: “Berapa banyak air yang dihemat oleh penyiraman berdasarkan kelembapan tanah dibandingkan penyiraman pada jam yang sama setiap hari, dan bagaimana pengaruhnya terhadap pertumbuhan tanaman?”
- Buat dua kelompok: Bagi bibit dari jenis dan tinggi yang sama ke dalam dua kelompok. Siram satu kelompok dengan sistem sensor dan kelompok lainnya dengan tangan dalam jumlah tetap setiap hari; jaga cahaya dan suhu tetap sama untuk kedua kelompok.
- Ukur dan catat: Buat tabel jumlah air mingguan (dengan mengukur tangki, dalam mL), tinggi tanaman (cm), dan jumlah daun. Keluaran CSV dari kode atau catatan Google Sheets langsung memberimu grafik suhu dan kelembapan.
- Gambar diagram blok: Sensor di kiri, Arduino di tengah, aktuator di kanan; beri label pada panah dengan kalimat aturan (“tanah < 35% → pompa”). Juri tidak akan membaca kodemu, tetapi mereka akan ingat diagram ini.
- Jelaskan histeresis: Dua grafik yang menunjukkan berapa kali kipas berambang tunggal dan kipas berhisteresis menyala dan mati dalam satu jam adalah cara terbaik untuk menunjukkan sisi rekayasa proyekmu kepada juri.
- Tulis skenario demo langsung: Hangatkan DHT22 dengan telapak tangan agar kipas menyala, pindahkan sensor tanah ke pot kering untuk menunjukkan denyut pompa, tutup LDR dengan tangan untuk menunjukkan LED menyala. Batasi setiap demo 10–20 detik.
- Hubungkan dengan kehidupan nyata: Bicarakan masalah nyata seperti pemakaian air dan energi di rumah kaca, penyakit jamur akibat kelembapan berlebih, dan beban kerja petani; tunjukkan dengan angka masalah mana yang dijawab oleh sistemmu.
- Siapkan rencana cadangan: Rekam video sistem yang sedang berjalan; bawa kabel, pompa, dan adaptor cadangan; tulis nilai kalibrasi dan pengaturan Wi-Fi di selembar kertas.
- Bersiap untuk pertanyaan juri: Siapkan jawaban singkat untuk “Apa yang terjadi kalau sensor rusak?”, “Apa yang terjadi pada tanaman kalau listrik padam?”, dan “Bagaimana kamu memperbesarnya untuk rumah kaca sungguhan?”. Keadaan aman dan proteksi luapan di kode adalah jawaban terbaik untuk pertanyaan-pertanyaan ini.
Kesalahan umum dan cara memperbaikinya
| Gejala | Kemungkinan penyebab | Solusi |
|---|---|---|
| Arduino reset atau LCD kacau ketika pompa menyala | Pompa dan relay diberi daya dari pin 5V Arduino, derau motor | Beri daya pompa dan kumparan relay dari LM2596, satukan GND, tambahkan dioda terbalik dan kapasitor 470 µF di pompa |
| Relay terus berbunyi klik | Memakai satu ambang saja atau pembacaannya berderau | Pakai ambang nyala dan mati yang terpisah (histeresis) dan rata-ratakan pembacaan analog |
| Air terus mengalir setelah pompa berhenti | Efek sifon: ujung selang di bawah permukaan air tangki | Letakkan tangki lebih rendah atau buat lubang udara kecil di bagian atas selang |
| Kelembapan tanah selalu 0% atau selalu 100% | Nilai kalibrasi salah, atau AOUT di pin yang salah | Ukur nilai mentah sensor di udara dan di air, lalu tulis ke konstanta |
| LED berkedip nyala-mati | LDR bisa melihat cahaya LED | Pindahkan LDR ke luar rumah kaca, menghadap langit |
| DHT22 mengembalikan nan | Pin salah, tidak ada resistor pull-up, atau dibaca lebih sering dari setiap 2 detik | Periksa pin, pakai modul, atau tambahkan 10 kΩ di antara DATA dan VCC |
| Suhu terbaca lebih tinggi dari seharusnya | Sinar matahari atau cahaya LED langsung mengenai sensor | Naungi dengan penutup putih berlubang dan jauhkan dari pemanas |
| Tetesan air dan jamur di dinding | Kelembapan terlalu tinggi, ventilasi terlalu lemah | Turunkan ambang kelembapan, perbesar lubang masuk udara, kurangi penyiraman |
| Di ESP32, pembacaan tanah kacau ketika Wi-Fi mulai aktif | Sensor terhubung ke pin ADC2 | Pindahkan ke pin ADC1 antara GPIO 32 dan 39 |
| Dengan ESP32, relay tidak pernah lepas | HIGH 3,3 V tidak bisa mematikan modul 5 V aktif LOW | Pisahkan JD-VCC atau pakai modul relay dengan pemicu 3,3 V |
Proyek rumah kaca pintar menggabungkan pembacaan sensor, kalibrasi, pengambilan keputusan dengan histeresis, penggerakan relay dan MOSFET, perencanaan daya, dan pemantauan nirkabel dalam satu proyek, dan pada akhirnya menumbuhkan sesuatu yang benar-benar hidup: sebuah tanaman. Mulailah dengan penyiraman dan ventilasi, uji setiap bagian secara terpisah, lalu tambahkan pemanas, LED, dan ponsel. Di aplikasi BlueGrays kamu akan menemukan proyek langkah demi langkah lengkap dengan skema rangkaian dan kode untuk mengukur suhu dan kelembapan dengan DHT11, membaca cahaya dengan LDR, stasiun penyiraman pintar, dan pencatat suhu dengan DHT22.
Pertanyaan umum
Apa saja yang kubutuhkan untuk proyek rumah kaca pintar?
Untuk rumah kaca pintar dasar, cukup Arduino Uno atau ESP32, sensor suhu dan kelembapan DHT22, sensor kelembapan tanah kapasitif, LDR dan resistor 10 kΩ, modul relay, pompa celup mini, dan kipas. Versi lengkap menambahkan pemanas PTC 12 V, LED strip yang dikendalikan MOSFET, LCD I2C, saklar level pelampung, adaptor 12 V 5 A, dan LM2596. Untuk badannya, kotak penyimpanan bening bertutup adalah solusi paling mudah dan murah.
Bagaimana cara kerja rumah kaca pintar?
Rumah kaca pintar bekerja dalam siklus ukur, putuskan, jalankan, tampilkan. Sensor mengukur suhu, kelembapan, kelembapan tanah, dan cahaya; Arduino membandingkan nilai-nilai ini dengan ambang lalu menyalakan dan mematikan kipas, pemanas, pompa, dan LED lewat relay atau MOSFET. Hasilnya ditampilkan di LCD dan, kalau memakai ESP32, di ponselmu.
Sebaiknya pakai DHT11 atau DHT22 di rumah kaca?
Pilih DHT22. DHT11 hanya akurat ±2 °C di antara 0 dan 50 °C dan tidak bisa membaca kelembapan di atas 90%, padahal kelembapan rumah kaca bisa melewati 90% di pagi hari dan suhunya bisa di bawah titik beku ketika musim dingin. DHT22 mengukur dari −40 sampai 80 °C dengan akurasi ±0,5 °C dan kelembapan dengan akurasi sekitar ±2%, dan kodenya hampir sama dengan kode DHT11.
Berapa biaya proyek rumah kaca Arduino?
Harga bervariasi antarpenjual, tetapi tanpa board, versi dasar (DHT22, sensor kelembapan tanah, LDR, relay, pompa, dan kipas) biasanya sekitar 25–40 dolar AS. Versi lengkap dengan pemanas, LED strip, LCD, adaptor 12 V, dan badan rumah kaca mencapai sekitar 70–120 dolar AS. Kalau kamu sudah punya starter kit Arduino, biayanya turun cukup banyak.
Bagaimana cara memantau rumah kacaku dari ponsel?
Cara termudah adalah mengganti otaknya dengan ESP32 dan menjalankan web server; kamu melihat nilainya dan menyalakan pompa dari browser ponselmu di jaringan Wi-Fi yang sama. Untuk akses dari luar rumah kamu bisa memakai Blynk IoT, untuk pesan peringatan bot Telegram, dan untuk pencatatan data jangka panjang Google Sheets.
Bagaimana cara mempresentasikan rumah kaca pintar di lomba sains?
Alih-alih hanya menunjukkan maket yang berjalan, tetapkan pertanyaan penelitian yang bisa diukur; misalnya, ukur selama beberapa minggu dengan dua kelompok tanaman berapa banyak air yang dihemat penyiraman berbasis sensor dibandingkan penyiraman terjadwal. Sajikan pemakaian air, tinggi tanaman, serta grafik suhu dan kelembapan dalam tabel dan grafik, jelaskan sistemnya dengan diagram blok, dan siapkan skenario singkat untuk demo langsung.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
Suhu dan Kelembapan dengan DHT11
Seberapa hangat kamarmu, dan apakah udaranya lembap atau kering? Sensor DHT11 mengukur suhu dan kelembapan, dan Arduino menulis nilainya di layar LCD dua baris, diperbarui setiap beberapa detik. Jika

Mengukur Intensitas Cahaya dengan LDR
Ingin melihat seberapa terang kamarmu dalam bentuk angka? LDR, komponen kecil yang bereaksi terhadap cahaya, mengukur cahaya di sekitarnya, dan Arduino menulis nilainya ke layar komputermu setiap sete

Membaca Intensitas Cahaya dengan Modul LDR ESP32
Memantau secara real-time di Serial Monitor nilai ADC mentah modul LDR dan persentase cahaya relatif yang dihitung dari nilai acuan gelap dan terang. Persentase ini bukan pengukuran lux. Mengajarkan logika kalibrasi modul. Ideal dikerjakan sebelum Proyek 10, karena dipakai untuk menentukan nilai ambang.

Stasiun Penyiraman Pintar
Tukang kebun yang menyiram tanamanmu sendiri, supaya tanaman tidak kering ketika kamu berlibur. Sensor kelembapan tanah mengukur seberapa basah tanahnya; ketika kering, Arduino menyalakan pompa air be

Suhu dan Kelembapan DHT22 ESP32 (dengan Layar LCD)
Proyek ini mengukur suhu dan kelembapan sekitar dengan sensor DHT22 dan menampilkan datanya secara real-time di LCD I2C 16x2. Data dibaca dari sensor dengan protokol satu kabel lewat library Adafruit DHT. Proyek ini menjadi dasar untuk stasiun cuaca IoT, otomasi rumah pintar, atau sistem pemantauan lingkungan di rumah kaca. Komunikasi dengan DHT22 dilakukan lewat pin GPIO 4 ESP32.

Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)
Buat pencatat suhu bercap waktu dengan ESP32! Baca suhu/kelembapan DHT22 setiap menit, ambil waktu sebenarnya dari RTC DS1307, dan catat ke kartu microSD sebagai CSV. OLED menampilkan suhu langsung (font besar), kelembapan, cap waktu, dan penghitung catatan. File /temp_log.csv bisa dibuka di Excel, Google Sheets, atau Python pandas; cocok untuk rumah kaca, suhu kamar, data laboratorium, penyimpanan makanan, atau sarang lebah.

Lampu Pintar ESP32 (PIR + LDR + Relay + OLED)
Ubah lorong, kamar mandi, atau gudangmu menjadi lampu pintar dengan ESP32! Dengan sensor gerak PIR, sensor cahaya LDR, dan modul relay, kita membuat skenario klasik "lampu menyala ketika ada gerakan dalam gelap"; jika sudah terang, gerakan TIDAK menyalakan lampu, jadi energi hemat di siang hari. Lampu menyala 30 detik; jika gerakan berlanjut, timer diulang. OLED SSD1306 menampilkan status dengan font besar (NYALA / SIANG / MENUNGGU) dan hitung mundur.
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

