Pengontrol Irigasi Pintar Berbasis Arduino – Pengairan Otomatis dengan Sensor Cuaca dan Cahaya
Komponen dan Perlengkapan
Berikut adalah komponen yang diperlukan untuk proyek ini:
Arduino Nano R3
×
1
IO Expander
×
1
IO Expander Bundle
×
1
Aplikasi dan Layanan Online
Arduino IDE
Tentang Proyek Ini
Buat Pengontrol Irigasi Pintar dengan Arduino
Irigasi halaman rumah Anda secara cerdas dengan siklus pengiriman air yang dinamis. Hentikan pengairan jika sedang hujan atau telah hujan sejak pengairan terakhir. Gunakan sensor cahaya untuk mendeteksi waktu terbit matahari dan secara otomatis sesuaikan waktu mulai pengairan. Hentikan pengairan jika terlalu dingin di luar.
Daftar Fitur
Sensor suhu luar ruangan
Sensor hujan luar ruangan
Sensor cahaya luar ruangan
Jam real-time dengan cadangan baterai untuk jadwal mingguan
Penyimpanan non-volatile - tidak pernah kehilangan jadwal pengairan akibat pemadaman listrik
Deteksi terbit matahari
Pengairan pintar menghemat tagihan air Anda
Sirami sebelum terbit matahari untuk waktu rendaman yang tepat
Hentikan pengairan ketika terlalu dingin di luar
Mengurangi pertumbuhan jamur
Kontrol jadwal yang mudah
Komponen yang Diperlukan untuk Membangun Pengontrol Irigasi Pintar
IO Expander
x2 1-Wire ke I2C
1-Wire Junction
Optical Connector
Splitter
Arduino Nano
Relay DC 5V 4 Channel
Sensor Cahaya TSL2561
Sensor Suhu Waterproof DS18B20
Sensor Tinggi Air Infrared Optik
Jam Real-Time Presisi DS3231 AT24C32 IIC
Layar OLED I2C SSD1306 128x64
Kotak Plastik Waterproof Jernih 200x120x75mm
Kotak Plastik Waterproof Jernih 100x68x50mm
Kabel Gland Nylon Waterproof IP68 PG7
Kabel Gland Nylon Waterproof IP68 PG11
Jack Terminal Obeng RJ11 Keystone
Kabel RJ11 4C4P 50 kaki
Kabel RJ11 4C4P 6 kaki
Kabel Header 2.54mm
x2 Tombol Push Micro Switch SPST 2 Pin
Adaptor Dinding 12VDC 1A
Diagram Kabeling
Tampilan OLED
Tekan tombol Menu untuk menampilkan menu dan terus menekan tombol untuk melalui semua opsi menu. Menu akan otomatis hilang setelah 30 saat tidak ada aktivitas. Tekan tombol Select untuk melakukan fungsi menu yang diinginkan.
Mengapa Menggunakan IO Expander?
Lebih mudah dirancang
Komponen siap pakai
Tidak perlu menulis driver 1-Wire
Tidak perlu menulis driver DS3231 RTC
Tidak perlu menulis driver EEPROM
Tidak perlu menulis driver layar OLED
Tidak perlu font display yang mengambil ruang kode Arduino
Tidak perlu menulis driver sensor suhu
Tidak perlu menulis driver sensor hujan optik
Hemat ruang kode Arduino; hanya 12710 byte (39%)
Hanya butuh tiga hari untuk menulis kode
Mudah dirakit dengan kabel telepon RJ11 standar
Tidak ada masalah panjang kabel sensor
Lebih murah dibangun dibanding sistem komersial serupa
Mudah untuk melakukan perubahan guna menyesuaikan kebutuhan individual
Satu sumber daya listrik
Bangun Sistem
Hubungkan Arduino Nano ke IO Expander dan program dengan kode berikut. Header 6 pin adalah port debug serial perangkat lunak dan tidak diperlukan dalam instalasi akhir.
Pastikan Anda mengubah alamat yang ditentukan ONEWIRE_TO_I2C_ROM1 dan ONEWIRE-TO_I2C_ROM2 agar cocok dengan alamat 1-Wire ke I2C Anda.
Serial.println(); if (SerialReadUntilDone()) { if (init_board) { SerialCmdDone(INIT_BOARD); init_board = false; }
if (init_oled) { if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) { SerialCmdDone(I2C_OLED ";si;sc;sd"); init_oled = false; } }
if (SerialCmdDone(RTC_SENSOR)) { error_rtc = !SerialReadTime(&rtc); if (!error_rtc) { clk = rtc; // mktime() can change struct tm rtc_time = mktime(&clk); localtime_r(&rtc_time, &rtc); // Get wday. }
if (read_nvram) { if (SerialCmdNoError(I2C_EEPROM)) { SerialReadEEPROM((uint8_t*)&nvram, 0, sizeof(nvram)); if (nvram.crc != crc8((uint8_t*)&nvram, sizeof(nvram)-sizeof(uint8_t))) { //swSerial.println("CRC8 Failure!"); // Initialize nvram memset(&nvram, 0, sizeof(nvram)); clk = rtc; clk.tm_hour = 6; clk.tm_min = 0; clk.tm_sec = 0; nvram.sunrise_time = mktime(&clk); if (nvram.sunrise_time < rtc_time) nvram.sunrise_time + SEC_IN_DAY; update_nvram = true; } // Check last water time no less than one week if (rtc_time - nvram.last_water_time > SEC_IN_WEEK) nvram.last_water_time = rtc_time - SEC_IN_WEEK; // Check sunrise time if (rtc_time > nvram.sunrise_time) { localtime_r(&nvram.sunrise_time, &sunrise_clk); clk = rtc; clk.tm_hour = sunrise_clk.tm_hour; clk.tm_min = sunrise_clk.tm_min; clk.tm_sec = sunrise_clk.tm_sec; nvram.sunrise_time = mktime(&clk); if (nvram.sunrise_time < rtc_time) nvram.sunrise_time + SEC_IN_DAY; } if (nvram.water_duration) { nvram.water_duration++; water_time = nvram.last_water_time; } else { clk_time = (nvram.last_water_time) ? nvram.last_water_time : rtc_time; water_time = NextScheduleTime(clk_time, &water_schedule); } read_nvram = false; } } }
// Process only once every minute if (rtc.tm_min != last_min) { // Request a 1-Wire temperature measurement. Read it later. error_temp = !SerialCmdNoError(ONEWIRE_TEMPERATURE); if (!error_temp) SerialCmdDone("tt");
error_light = !SerialCmdNoError(ONEWIRE_TO_I2C_ROM2 ";oo0"); if (!error_light) { SerialCmdDone(I2C_LIGHT); // Do not use overdrive SerialCmd("sr"); SerialReadInt(&lux); SerialReadUntilDone(); }
if (SerialCmd(OPTICAL_SENSOR)) { SerialReadFloat(&rain); SerialReadUntilDone(); }
error_temp = !SerialCmdNoError(ONEWIRE_TEMPERATURE); if (!error_temp) { SerialCmd("tr"); SerialReadFloat(&temp); SerialReadUntilDone(); }
// Is it sunrise? if (lux < SUNRISE_LUX) { if (sunrise_counter > 0) sunrise_counter--; else check_sunrise = true; } else { if (sunrise_counter < MIN_IN_HOUR) { sunrise_counter++; if (check_sunrise && sunrise_counter == MIN_IN_HOUR) { nvram.sunrise_time = rtc_time + (SEC_IN_DAY - SEC_IN_HOUR); check_sunrise = false; update_nvram = true; } } }
// Is it raining? if (rain <= RAIN_DETECT_LEVEL) { for (i = 0; i < MAX_ZONES; i++) { if (nvram.rain[i] < -1) nvram.rain[i]++; } update_nvram = true; }
// Do we need to water? if (nvram.water_duration) { WaterScheduleTime(); if (!nvram.water_duration) water_time = NextScheduleTime(water_time, &water_schedule); }
last_min = rtc.tm_min; update_oled = true; }
// Check buttons button1 = SerialReadButton(BUTTON1); if (button1) { if (menu_select == -1) menu_select = 0; else { if (++menu_select >= MENU_OPTIONS) menu_select = 0; } menu_time = rtc_time; update_oled = true; } if (menu_select >= 0) { button2 = SerialReadButton(BUTTON2); if (button2) { clk_time = rtc_time; switch(menu_select) { case MENU_NEXT: case MENU_RESET: if (nvram.water_duration) { nvram.water_duration = 1; WaterScheduleTime(); } water_time = NextScheduleTime((menu_select == MENU_NEXT) ? water_time : rtc_time, &water_schedule); break; case MENU_WATER: StartScheduleTime(water_time, water_schedule); WaterScheduleTime(); break; case MENU_CLOCK_MIN_PLUS: clk_time += SEC_IN_MIN; break; case MENU_CLOCK_MIN_MINUS: clk_time -= SEC_IN_MIN; break; case MENU_CLOCK_HOUR_PLUS: clk_time += SEC_IN_HOUR; break; case MENU_CLOCK_HOUR_MINUS: clk_time -= SEC_IN_HOUR; break; case MENU_ON_OFF: nvram.state ^= STATE_ON_OFF; update_nvram = true; break; } if (clk_time != rtc_time) { if (SerialCmdDone(RTC_SENSOR)) { localtime_r(&clk_time, &clk); SerialWriteTime(&clk); rtc_time = clk_time; } } menu_time = rtc_time; update_oled = true; } } if (menu_select >= 0 && rtc_time - menu_time > MENU_TIME) { menu_select = -1; update_oled = true; }
if (update_oled) { if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) { Serial.print("st10;so1;sc;sf0;sa0;sd0,0,\"\""); if (nvram.water_duration) Serial.print(nvram.water_duration); else { if ((nvram.state & STATE_ON_OFF) == OFF) Serial.print("OFF"); else if (rain <= RAIN_DETECT_LEVEL) Serial.print("Rain"); else if (temp <= DO_NOT_WATER_TEMP) Serial.print("Cold"); else Serial.print("v1.1"); } Serial.print("\"");sf2;sa1;sd75,0,\"\""); if (menu_select == 7) { // Sunrise clk_time = nvram.sunrise_time; localtime_r(&clk_time, &clk); } else clk = rtc; Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0)); Serial.print(":"); if (clk.tm_min < 10) Serial.print("0"); Serial.print(clk.tm_min); Serial.println("\""); SerialReadUntilDone();
Catatan: Jika Anda menggunakan port USB untuk memprogram Arduino Nano, Anda harus memutuskannya dari IO Expander karena keduanya menggunakan port serial yang sama. Sebaliknya, jika ingin melakukan debug, gunakan port ICSP untuk memprogram ATmega328P. Untuk mengaktifkan port debug perangkat lunak, hilangkan komentar pada definisi SERIAL_DEBUG.
Splitter harus dikonfigurasi terlebih dahulu untuk mengisolasi baris data sensor inframerah optik dari baris sensor remote 1-Wire. Pasang resistor nol ohm 0603 di R2.
Buat lubang 7/16 inci di kotak kecil dan lubang 11/16 inci di kotak besar di sisi kanan untuk PG7 dan PG11. Gunakan alat Dremel untuk memperbesar lubang sedikit hingga gland pas erat. PG7 akan mengakomodasi sensor remote dan PG11 untuk kabel 12VDC, 24VAC, Manifold, dan kabel sensor remote RJ11.
Rangkaikan tombol push micro switch SPST momentary dan hubungkan ke terminal obeng RJ11. Gunakan tubing heat shrink untuk mengisolasi kontak.
Hubungkan semua kabel dan rangkai seluruh bagian ke dalam kotak besar. Kabel RJ11 50 kaki Anda untuk sensor remote seharusnya cukup melewati gland PG11 tanpa harus memotongnya.
Buat lubang 9/16 inci di sisi atas kotak kecil untuk sensor air inframerah optik. Gunakan alat Dremel untuk memperbesar lubang sedikit hingga sensor pas. Kotak sensor remote kecil sangat sempit, tetapi jika isinya diletakkan dalam orientasi yang direkomendasikan, seharusnya cukup muat. Membuat kabel RJ11 sempendek mungkin akan membantu memasukkan semuanya ke dalam kotak yang lebih kecil. Setelah dirangkaikan, disarankan untuk menambahkan sedikit lem laut ke pelapis nut gland sebelum memasang nut, untuk menciptakan seal yang lebih baik.
Pasang kotak sensor remote di luar dan pasang di sisi timur rumah Anda dengan ketinggian, dengan sensor air inframerah optik dan sensor cahaya menghadap ke langit tanpa penghalang.
Buat lubang 1/4 inci di tengah atas bawah kotak besar dan pasang tombol. Gunakan alat Dremel untuk memperbesar lubang sedikit hingga tombol pas.
Uji sistem dan pastikan semuanya beroperasi dengan benar. Untuk menguji relay dan sensor, putuskan Arduino dari IO Expander dan hubungkan langsung ke komputer Anda untuk mengontrolnya secara manual. Setelah Anda memverifikasi semuanya beroperasi, rangkai semua bagian ke dalam kotak menggunakan double-sided tape dan foam pengemasan untuk mengamankan papan Anda, dan nikmati manfaat serta penghematan dari Pengontrol Irigasi Pintar Anda.
Video Operasi
Update 9/12/2019
Dirilis v1.1 yang memperbaiki masalah startup jika sistem kehilangan daya selama beberapa hari.
Update 10/2/2019
Saat menghubungkan 1-Wire ke I2C ke DS3231 dan kemudian ke layar OLED SSD1306, Anda akan memiliki total tiga pullup yang berbeda pada garis SDA dan SCL seperti yang ditunjukkan di lingkaran pada gambar di bawah ini. Ini akan secara efektif menghasilkan pullup 4.7k / 3 = 1.56k yang terlalu kuat dan dapat mengakibatkan kerusakan layar secara acak.
Karena DS3231 menggunakan resistor pack yang digunakan oleh garis lain, hapus resistor pullup lain:
1-Wire ke I2C R3 dan R4.
SSD1306 OLED R6 dan R7.
Kode
Pengontrol Irigasi Pintar
Pengontrol Irigasi PintarC/C++
Gunakan Arduino Anda untuk menyirami halaman atau taman Anda secara cerdas.