Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Pengontrol Irigasi Cerdas

Komponen dan persediaan

Arduino Nano R3
× 1
IO Expander
× 1
Io Expander Bundle
× 1

Aplikasi dan layanan online

Arduino IDE

Tentang proyek ini

Buat Pengontrol Irigasi Cerdas dengan Arduino

Mengairi halaman Anda secara cerdas dengan siklus air yang dinamis. Berhentilah menyirami halaman Anda jika hujan atau telah turun hujan sejak penyiraman terakhir Anda. Gunakan sensor cahaya untuk mendeteksi waktu matahari terbit dan menyesuaikan waktu mulai air secara otomatis. Berhentilah menyirami halaman Anda jika terlalu dingin.

Daftar Fitur

  • Sensor suhu luar
  • Sensor hujan luar
  • Sensor cahaya luar
  • Jam real-time yang didukung baterai untuk penjadwalan mingguan
  • Penyimpanan non-volatil - tidak pernah kehilangan air karena kehilangan daya
  • Deteksi matahari terbit
  • Penyiraman cerdas menghemat tagihan air Anda
  • Siram sebelum matahari terbit untuk memberikan waktu perendaman yang tepat
  • Berhenti menyiram jika di luar terlalu dingin
  • Mengurangi pertumbuhan jamur
  • Kontrol jadwal yang mudah

Suku Cadang yang Dibutuhkan untuk Membuat Pengontrol Irigasi Cerdas

  • Pengembang IO
  • x2 1-Kabel ke I2C.
  • Persimpangan 1-Kawat
  • Konektor Optik
  • Pemisah
  • Arduino Nano.
  • Relai DC 5V 4 Saluran.
  • Sensor Cahaya TSL2561.
  • Sensor Suhu Tahan Air DS18B20.
  • Sensor Ketinggian Air Inframerah Optik.
  • Jam Waktu Nyata Presisi DS3231 AT24C32 IIC.
  • Layar I2C SSD1306 OLED 128x64.
  • Enclosure Plastik Tahan Air Bening 200x120x75mm.
  • 100x68x50mm Kandang Plastik Tahan Air Bening.
  • ip68 pg7 Kelenjar Kabel Nilon Tahan Air.
  • ip68 pg11 Kelenjar Kabel Nilon Tahan Air.
  • Soket Terminal Sekrup Keystone RJ11.
  • Kawat RJ11 4C4P 50ft.
  • Kabel RJ11 4C4P 6 kaki.
  • Kabel Header 2.54mm.
  • x2 2 Pin Tombol Tekan Sesaat SPST Saklar Mikro
  • Catu Daya Adaptor Dinding 12VDC 1A.

Diagram Pengkabelan

Tampilan OLED

Tekan tombol Menu untuk menampilkan menu dan terus tekan tombol untuk menelusuri semua opsi menu. Menu akan secara otomatis dihapus setelah 30 detik tidak aktif. Tekan tombol Pilih untuk menjalankan fungsi menu yang diinginkan.

Jadi Mengapa Menggunakan IO Expander?

  • Desain lebih sederhana
  • Suku cadang siap pakai
  • Tidak ada driver 1-Wire untuk ditulis
  • Tidak ada driver DS3231 RTC untuk ditulis
  • Tidak ada driver EEPROM untuk ditulis
  • Tidak ada driver tampilan OLED untuk ditulis
  • Tidak ada font tampilan untuk mengambil ruang kode Arduino
  • Tidak ada driver sensor suhu untuk ditulis
  • Tidak ada pengering sensor hujan optik untuk menulis
  • Menghemat ruang kode di Arduino; hanya 12710 byte (39%)
  • Hanya tiga hari untuk menulis kode
  • Mudah disambungkan menggunakan kabel telepon RJ11 standar
  • Tidak ada masalah panjang kabel sensor
  • Lebih murah untuk dibuat daripada sistem komersial serupa
  • Mudah membuat perubahan untuk beradaptasi dengan kebutuhan individu
  • Sumber daya tunggal

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 sesuai dengan alamat 1-Wire ke I2C Anda.

/* Sketsa IO Expander dioptimalkan
*
* Sistem Irigasi v1.1
*
*/

#include
#include // Lokasi file \Program Files (x86)\Arduino\hardware\tools\avr\avr\include\time.h
#include
#include
#include
#include "IOExpander.h"

#define FAHRENHEIT
#define INIT_BOARD "g5w1;g11w1;g11d0,75;g12w1;g12d0,75;rsf"
#define ONEWIRE_TO_I2C_ROM1 "i4scc"
#define ONEWIRE_TO_I2C_ROM2"#define RTC_SENSOR "s4te"
#define I2C_EEPROM "s4tf"
#define I2C_OLED "s4t10"
#define I2C_LIGHT "s3t9;sc0"
# definisikan OPTICAL_SENSOR "g5a"
#define BUTTON1 "g11d"
#define BUTTON2 "g12d"

#define WATER_TIME_BEFORE_SUNRISE 60
#define SUNRISE_LUX 100
# definisikan RAIN_DETECT_LEVEL 4.0
#define DO_NOT_WATER_TEMP 4.4444 // 40F

#define MAX_ZONES 4

#define HOUR_IN_DA Y 24L
#define MIN_IN_HOUR 60L
#define SEC_IN_MIN 60L
#define SEC_IN_HOUR (MIN_IN_HOUR * SEC_IN_MIN)
#define SEC_IN_DAY (HOUR_IN_DAY * SEC_WE_IN_HOUR)
#define SEC_IN_WEEK (SEC_IN_DAY * DAYS_IN_WEEK)

#define SUN 0x01
#define SEN 0x02
#define TUE 0x04
#define RABU 0x08
#define THR 0x10
#define FRI 0x20
#define SAT 0x40
#define SETIAP HARI (MINGGU | SEN | SEL | RABU | THR | Jumat | SAT)

#define SUNRISE 0x80

#define MENU_OPTIONS 9
#define MENU_TIME 30

#define OFF 0
#define ON 1

#define STATE_ON_OFF 0x01

//#define SERIAL_DEBUG

#ifdef SERIAL_DEBUG
SoftwareSerial swSerial(8,7 );
#endif

char weekday[][4] ={"SUN","MON","TUE","WED","KAMI","FRI"," SAT"};

char menu[][13] ={"Selanjutnya",
"Air",
"Reset",
"Jam Min +" ,
"Jam Min -",
"Jam +",
"Jam -",
"Matahari Terbit",
"ON/OFF"};

enum {
MENU_NEXT,
MENU_WATER,
MENU_RESET,
MENU_CLOCK_MIN_PLUS,
MENU_CLOCK_MIN_MINUS,
MENU_CLOCK_HOUR_PLUS,
MENU_CLOCK_HOUR_MINUS,
MENU_SUNRISE,
MENU_ON_OFF
};

typedef struct {
char description[16];
uint8_t relay;
} ZONE;

typedef struct {
uint8_t zone;
uint8_t hari;
int8_t jam;
int8_t mnt;
durasi uint8_t;
} JADWAL;

typedef struct {
time_t sunrise_time;
time_t last_water_time;
uint8_t water_schedule;
uint8_t water_duration;
uint8_t rain[MAX_ZONES];
uint8_t state;
uint8_t crc;
} NVRAM;

enum {
ZONE1,
ZONE2,
ZONE3,
ZONE4
};

enum {
RELAY1 =1,
RELAY2,
RELAY3,
RELAY4
};

ZONE zone[] ={
{"Front Right", RELAY1},
{"Front Left", RELAY2},
{"Semak", RELAY3},
{"Sisi Kiri", RELAY4},
};

Jadwal JADWAL[] ={
{ZONE1, SUNRISE | SETIAP HARI, -1, 0, 4},
{ZONE2, SETIAP HARI, 6, 15, 5},
{ZONE3, SETIAP HARI, 6, 0, 10},
{ZONE4, SETIAP HARI , 6, 10, 6},
};

NVRAM nvram;
bool update_nvram =false;

uint8_t crc8(uint8_t* data, uint16_t panjang)
{
uint8_t crc =0;

while (panjang--) {
crc =_crc8_ccitt_update(crc, *data++);
}
return crc;
}

int led =13;
bool init_oled =true;
bool update_oled =true;
bool init_board =true;

#ifdef FAHRENHEIT
#define C2F(temp) CelsiusToFahrenheit(temp)
float CelsiusToFahrenheit(float celsius)
{
return ((celsius) * 9) / 5) + 32;
}
#else
#define C2F(temp) (temp)
#endif

void SerialPrint( const char* str, float desimal, char error)
{
Serial.print(str);
if (error) Serial.print(F("NA"));
else Serial.print(desimal, 1);
}

time_t NextScheduleTime(time_t last_time, uint8_t* next_schedule)
{
time_t next_time =-1;
time_t clk_time;
uint8_t i;
tm clk;
uint8_t wday;

for (i =0; i if (jadwal[i].hari &SUNRISE) {
clk_time =nvram.sunrise_time;
clk_time +=jadwal[i].jam * SEC_IN_HOUR;
clk_time +=jadwal[i].min * SEC_IN_MIN;
localtime_r(&clk_time, &clk);
}
else {
localtime_r(&last_time, &clk);
clk. tm_hour =jadwal[i].jam;
clk.tm_min =jadwal[i].min;
clk.tm_sec =0;
clk_time =mktime(&clk);
}
wday =clk.tm_wday;
while (clk_time <=last_time || !(schedule[i].days &(1 < {
clk_time + =SEC_IN_DAY;
jika (++wday> SABTU) wday =MINGGU;
jika (wday ==clk.tm_wday) break; // Hanya periksa satu minggu
}
if (clk_time next_time =clk_time;
*next_schedule =i;
}
}
return next_time;
}

void StartScheduleTime(time_t start_time, uint8_t start_schedule)
{
uint8_t i;

nvram. last_water_time =start_time;
nvram.water_schedule =start_schedule;
nvram.water_duration =schedule[start_schedule].duration+1;
update_nvram =true;
// Periksa apakah hujan
i =schedule[start_schedule].zone;
if (i 0) {
if (nvram.rain[i]> nvram.water_duration) nvram .water_duration =0;
else nvram.water_duration -=nvram.rain[i];
nvram.rain[i] =0;
}
}

void WaterScheduleTime(void)
{
uint8_t i;

nvram.water_duration--;
update_nvram =true;
i =schedule[ nvram.water_schedule].zone;
if (i Serial.print("r");
Serial.print(zone[i].relay);
if (nvram.water_duration> 0) Serial.println("o");
else Serial.println("f");
SerialReadUntilDone();
}
}

void setup() {
Serial.begin(115200);
#ifdef SERIAL_DEBUG
swSerial.begin(115200);
#endif
pinMode(led, OUTPUT);
//delay(1000);
wdt_enable(WDTO_8S);
}

void loop() {
static tm rtc;
tm clk, sunrise_clk;
time_t rtc_time;
time_t clk_time;
static time_t next_time;
static uint8_t last_sec;
static uint8_t last_min;
bool error_rtc;
bool error_light;
bool error_temp;
static long lux =0;
static float temp, rain;
static uint8_t sunrise_counter =MIN_IN_HOUR;
static bool check_sunrise =false;
uint8_t i;
static bool read_nvram =true;
static time_t water_time;
static uint8_t water_schedule;
uint8_t sz;
uint8_t wday;
panjang n;
bool button1, button2;
static int8_t menu_select =-1;
static time_t menu_time =0;

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() dapat mengubah struct tm
rtc_time =mktime(&clk);
localtime_r(&rtc_time, &rtc); // Dapatkan hari.
}

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 Gagal! ");
// Inisialisasi 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 update_nvram =true;
}
// Periksa waktu air terakhir tidak kurang dari satu minggu
if (rtc_time - nvram.last_water_time> SEC_IN_WEEK) nvram.last_water_time =rtc_time - SEC_IN_WEEK;
// Periksa waktu matahari terbit
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 }
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;
}
}
}

// Proses hanya sekali setiap menit
if (rtc.tm_min !=last_min)
{
// Meminta pengukuran suhu 1-Kabel. Baca nanti.
error_temp =!SerialCmdNoError(ONEWIRE_TEMPERATURE);
if (!error_temp) SerialCmdDone("tt");

error_light =!SerialCmdNoError(ONEWIRE_TO_I2C_ROM2 ";oo0" );
if (!error_light) {
SerialCmdDone(I2C_LIGHT); // Jangan gunakan 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();
}

// Apakah matahari terbit?
if (lux if (sunrise_counter> 0) sunrise_counter--;
else check_sunrise =true;
}
else {
if (sunrise_counter sunrise_counter++;
if (check_sunrise &&sunrise_counter ==MIN_IN_HOUR) {
nvram.sunrise_time =rtc_time + (SEC_IN_DAY - SEC_IN_HOUR);
check_sunrise;
update_nvram =true;
}
}
}

// Apakah hujan?
if (hujan <=RAIN_DETECT_LEVEL) {
untuk (i =0; i if (nvram.rain[i] <-1) nvram.rain[i]++; }
update_nvram =true;
}

// Periksa jadwal
if (menu_select ==-1 &&!nvram.water_duration) {
while (water_time + (schedule[water_schedule].duration * SEC_IN_MIN) water_time =NextScheduleTime(water_time, &water_schedule);
}
if (water_time <=rtc_time) {
StartScheduleTime(water_time, water_schedule);
if (temp <=DO_NOT_WATER_TEMP || nvram.state &STATE_ON_OFF ==OFF)
nvram.water_duration =0;
}
}

// Apakah kita perlu air?
jika (nvram.water_duration) {
WaterScheduleTime();
if (!nvram.water_duration)
water_time =NextScheduleTime(water_time, &water_schedule);
}

last_min =rtc.tm_min;
update_oled =true;
}

// Periksa tombol
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;
}

jika (update_oled) {
jika (S erialCmdNoError(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 (hujan <=RAIN_DETECT_LEVEL) Serial.print ("Hujan");
else if (temp <=DO_NOT_WATER_TEMP) Serial.print("Dingin");
else Serial.print("v1.1");
}
Serial.print("\";sf2;sa1;sd75,0,\"");
if (menu_select ==7) { // Matahari terbit
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();

Serial.print("sf1;sa0;sd79,8,\"");
Serial .print((clk.tm_hour>12)?"PM":"AM");
Serial.print("\";sf0;sa1;sd127,1,\"");
Serial .print(hari kerja[clk.tm_wday]);
Serial.print("\";sd127,13,\"");
Serial.print(clk.tm_mon+1);
Serial.print("/");
Serial.print(clk.tm_mday);
Serial.println("\"");
SerialReadUntilDone();

Serial.print("sf0;sa0;sd1 ,36,\"");
i =schedule[water_schedule].zone;
if (i localtime_r(&water_time , &clk);
if (waktu_air - rtc_time> SEC_IN_DAY) {
Serial.print("\";sa1;sd126,36,\"");
Serial.print(clk. tm_mon+1);
Serial.print("/");
Serial.print(clk.tm_mday);
Serial.print(" ");
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.print(" ");
}
else {
Serial.print("\ ";sf1;sa1;sd111,30,\"");
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);
Seria l.print("\";sf0;sd126,36,\"");
}
Serial.print((clk.tm_hour>12)?"PM":"AM");
if (nvram.water_duration) Serial.print("\";so2;sc0,29,128,19");
Serial.println();
SerialReadUntilDone();

if (menu_select ==-1) {
//Serial.print("\";sa0;sd0,52,\"");
//Serial.print(rain);
SerialPrint("\";so1;sa2;sd63,52,\"", C2F(temp), error_temp);
if (!error_temp) Serial.print("\",248,\ ""
#ifdef FAHRENHEIT
"F"
#else
"C"
#endif
);
Serial.print(" / ");
Serial.print(lux);
}
else {
Serial.print("\";so0;sc0,51,128,14;sf0;sa2; sd63,52,\"");
if (menu_select ==MENU_ON_OFF) {
Serial.print((nvram.state &STATE_ON_OFF) ? "OFF" :"ON");
}
else Serial.print(menu[menu_select]);
}
Serial.println("\";sd");
SerialReadUntilDone();
update_oled =false;
}
else init_oled =true;
}

if (update_nvram) {
if (SerialCmdNoError(I2C_EEPROM)) {
nvram.crc =crc8((uint8_t*)&nvram, sizeof(nvram)-sizeof(uint8_t));
//swSerial.println(nvram.crc , HEX);
SerialWriteEEPROM((uint8_t*)&nvram, 0, sizeof(nvram));
update_nvram =false;
}
}

delay(50);
}
else {
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
init_board =true;
init_oled =true;
}
wdt_reset();
}

Catatan: Jika Anda menggunakan port USB untuk memprogram Arduino Nano, Anda harus melepaskannya dari IO Expander karena port ini juga menggunakan port serial tunggal yang sama, sebaliknya jika Anda ingin men-debug gunakan port ICSP untuk memprogram ATmega328P. Untuk mengaktifkan port debug perangkat lunak, batalkan komentar pada definisi SERIAL_DEBUG.

Pemisah harus terlebih dahulu dikonfigurasi untuk mengisolasi jalur data sensor inframerah optik dari jalur sensor jarak jauh 1-Kabel. Solder dalam resistor nol ohm 0603 di R2.

Bor lubang 7/16" di enklosur kecil dan lubang 11/16" di enklosur yang lebih besar di sisi kanan untuk PG7 dan PG11. Gunakan alat dremel untuk memperbesar lubang sedikit sampai kelenjar pas. PG7 akan memasukkan sensor jarak jauh dan PG11 untuk kabel 12VDC, 24VAC, Manifold, dan kabel sensor jarak jauh RJ11.

Pasang sakelar mikro tombol tekan SPST sesaat dan sambungkan ke terminal sekrup RJ11. Gunakan tabung heat shrink untuk mengisolasi kontak.

Hubungkan semua kabel dan rakit/masukkan semua bagian ke dalam selungkup besar. Kawat RJ11 50 kaki Anda untuk sensor jarak jauh harus pas melalui kelenjar PG11 tanpa harus memotongnya.

Bor lubang 9/16" di sisi atas selungkup kecil untuk sensor air inframerah optik. Gunakan alat dremel untuk memperbesar lubang sedikit hingga sensor pas. Selungkup sensor jarak jauh kecil pas, tetapi jika isinya diletakkan dalam orientasi yang direkomendasikan, itu harus pas. Membuat kabel RJ11 sesingkat mungkin akan membantu menjejalkan semuanya ke dalam selungkup yang lebih kecil. Setelah dirakit, disarankan untuk menambahkan beberapa lem laut ke dalam pencuci mur kelenjar sebelum memasang mur, untuk membuat segel yang lebih baik.

Pasang penutup sensor jarak jauh di luar dan pasang di tempat yang lebih tinggi ke sisi timur rumah Anda dengan sensor air inframerah optik dan sensor cahaya yang mengarah ke langit tanpa penghalang.

Bor lubang 1/4" di bagian tengah atas penutup besar dan pasang kancingnya. Gunakan alat dremel untuk memperbesar lubang sedikit hingga kancingnya pas.

Uji sistem dan pastikan semuanya beroperasi dengan benar. Untuk menguji relai dan sensor, lepaskan Arduino dari IO Expander dan sambungkan langsung ke komputer Anda untuk mengontrolnya secara manual. Setelah Anda memverifikasi bahwa semuanya beroperasi, rakit semua bagian ke dalam enklosur menggunakan selotip dua sisi dan busa pengemas untuk mengamankan papan Anda, dan nikmati manfaat dan penghematan Pengontrol Irigasi Cerdas Anda.

Video dalam Operasi

Perbarui 9/12/2019

Rilis v1.1 yang memperbaiki masalah startup jika sistem kehilangan daya selama beberapa hari.

Pembaruan 10/2/2019

Saat menghubungkan 1-Wire ke I2C ke DS3231 dan kemudian ke layar OLED SSD1306, Anda akan memiliki total tiga pullup berbeda pada jalur SDA dan SCL seperti yang ditunjukkan pada gambar di bawah yang dilingkari. Ini akan secara efektif menghasilkan pull-up 4,7k / 3 =1,56k yang bisa terlalu kuat dan mengakibatkan kerusakan layar secara acak.

Karena DS3231 menggunakan paket resistor yang digunakan oleh jalur lain, lepaskan resistor pullup lainnya:

  • 1-Kabel ke I2C R3 dan R4.
  • SSD1306 OLED R6 dan R7.

Kode

  • Pengontrol Irigasi Cerdas
Pengontrol Irigasi CerdasC/C++
Gunakan Arduino Anda untuk menyirami halaman atau taman Anda dengan cerdas.
/* Sketsa IO Expander dioptimalkan * * Sistem Irigasi v1.1 * */#include #include  // Lokasi file \Program File (x86)\Arduino\hardware\tools\avr\avr\include\time.h#include #include #include #include "IOExpander. h"#define FAHRENHEIT#define INIT_BOARD "g5w1;g11w1;g11d0,75;g12w1;g12d0,75;rsf"#define ONEWIRE_TO_I2C_ROM1 "i4scc"#define ONEWIRE_TO_I2C_ROM2 "i6s4s" definisikan I2C_EEPROM "s4tf"#define I2C_OLED "s4t10"#define I2C_LIGHT "s3t9;sc0"#define OPTICAL_SENSOR "g5a"#define BUTTON1 "g11d"#define BUTTON2 "g12d_LUXdefine#REECT_SUNLEXUNRISTER_LUX" tentukan DO_NOT_WATER_TEMP 4.4444 // 40F#menentukan MAX_ZONES 4#menentukan HOUR_IN_DAY 24L#menentukan MIN_IN_HOUR 60L#menentukan SEC_IN_MIN 60L#menentukan SEC_IN_HOUR (MIN_IN_HOUR * SEC_IN_MIN)#DEFINE SEC KAMI)#menentukan DAYS_IN_WEEK 7#menentukan SEC_IN_WEEK (SEC_IN_DAY * DAYS_IN_WEEK)#menentukan SUN 0x01#menentukan SEN 0x02#menentukan TUE 0x04#menentukan RABU 0x08#menentukan THR 0x10#menentukan JUMAT 0x20 | SEN | SEL | RABU | THR | Jumat | SAT)#menentukan SUNRISE 0x80#menentukan MENU_OPTIONS 9#menentukan MENU_TIME 30#menentukan OFF 0#menentukan ON 1#menentukan STATE_ON_OFF 0x01//#menentukan SERIAL_DEBUG#ifdef SERIAL_DEBUGSoftwareSerial =hari kerja;#Serial(4) {"SUN","MON","TUE","WED","THU","FRI","SAT"};char menu[][13] ={"Berikutnya", "Air", "Reset" , "Jam Min +", "Jam Min -", "Jam +", "Jam -", "Matahari Terbit", "ON/OFF"};enum { MENU_NEXT, MENU_WATER, MENU_RESET, MENU_CLOCK_MIN_PLUS, MENU_CLOCK_MIN_MINUS, MENU_CLOCK_HOUR_PLUS, MENU_CLOCK_HOUR_MINUS, MENU_SUNRISE, MENU_ON_OFF};typedef struct { deskripsi karakter[16]; uint8_t relay;} ZONE;typedef struct { zona uint8_t; uint8_t hari; int8_t jam; int8_t menit; durasi uint8_t;} JADWAL;typedef struct { waktu_t sunrise_time; waktu_t last_water_time; uint8_t water_schedule; uint8_t water_duration; uint8_t hujan[MAX_ZONES]; status uint8_t; uint8_t crc;} NVRAM;enum { ZONE1, ZONE2, ZONE3, ZONE4};enum { RELAY1 =1, RELAY2, RELAY3, RELAY4};ZONE zone[] ={ {"Kanan Depan", RELAY1}, {"Kiri Depan" , RELAY2}, {"Bushes", RELAY3}, {"Sisi Kiri", RELAY4},};JADWAL jadwal[] ={ {ZONE1, SUNRISE | SETIAP HARI, -1, 0, 4}, {ZONE2, SETIAP HARI, 6, 15, 5}, {ZONE3, SETIAP HARI, 6, 0, 10}, {ZONE4, SETIAP HARI, 6, 10, 6},}; NVRAM nvram;bool update_nvram =false;uint8_t crc8(data uint8_t*, panjang uint16_t){ uint8_t crc =0; while (panjang--) { crc =_crc8_ccitt_update(crc, *data++); } return crc;}int led =13;bool init_oled =true;bool update_oled =true;bool init_board =true;#ifdef FAHRENHEIT#define C2F(temp) CelsiusToFahrenheit(temp)float CelsiusToFahrenheit(float celsius){ return ((celsius * 9) / 5) + 32;}#else#define C2F(temp) (temp)#endifvoid SerialPrint(const char* str, float desimal, char error){ Serial.print(str); if (kesalahan) Serial.print(F("NA")); else Serial.print(desimal, 1);}time_t NextScheduleTime(time_t last_time, uint8_t* next_schedule){ time_t next_time =-1; waktu_t clk_waktu; uint8_t saya; tm clk; uint8_t hari; for (i =0; i  SABTU) wday =MINGGU; if (wday ==clk.tm_wday) break; // Hanya periksa satu minggu } if (clk_time  0) { if (nvram.rain[i]> nvram.water_duration) nvram.water_duration =0; else nvram.water_duration -=nvram.rain[i]; nvram.rain[i] =0; }}void WaterScheduleTime(void) { uint8_t i; nvram.water_duration--; update_nvram =benar; i =jadwal[nvram.water_schedule].zone; if (i  0) Serial.println("o"); else Serial.println("f"); SerialReadSampai Selesai(); }}pengaturan batal() { Serial.begin(115200);#ifdef SERIAL_DEBUG swSerial.begin(115200);#endif pinMode(led, OUTPUT); //tunda(1000); wdt_enable(WDTO_8S);}void loop() { static tm rtc; tm clk, sunrise_clk; waktu_t rtc_waktu; waktu_t clk_waktu; static time_t next_time; uint8_t last_sec statis; uint8_t last_min statis; bool error_rtc; bool error_light; bool error_temp; lux panjang statis =0; suhu float statis, hujan; static uint8_t sunrise_counter =MIN_IN_HOUR; static bool check_sunrise =false; uint8_t saya; static bool read_nvram =true; static time_t water_time; uint8_t water_schedule statis; uint8_t sz; uint8_t hari; panjang n; tombol bool1, tombol2; statis int8_t menu_select =-1; static time_t menu_time =0; Serial.println(); if (SerialReadUntilDone()) { if (init_board) { SerialCmdDone(INIT_BOARD); init_board =salah; } 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  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  0) sunrise_counter--; else check_sunrise =true; } else { if (sunrise_counter =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); merusak; case MENU_WATER:StartScheduleTime(water_time, water_schedule); WaterScheduleTime(); merusak; case MENU_CLOCK_MIN_PLUS:clk_time +=SEC_IN_MIN; merusak; case MENU_CLOCK_MIN_MINUS:clk_time -=SEC_IN_MIN; merusak; case MENU_CLOCK_HOUR_PLUS:clk_time +=SEC_IN_HOUR; merusak; case MENU_CLOCK_HOUR_MINUS:clk_time -=SEC_IN_HOUR; merusak; case MENU_ON_OFF:nvram.state ^=STATE_ON_OFF; update_nvram =true; merusak; } 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(); Serial.print("sf1;sa0;sd79,8,\""); Serial.print((clk.tm_hour>12)?"PM":"AM"); Serial.print("\";sf0;sa1;sd127,1,\""); Serial.print(weekday[clk.tm_wday]); Serial.print("\";sd127,13,\""); Serial.print(clk.tm_mon+1); Serial.print("/"); Serial.print(clk.tm_mday); Serial.println("\""); SerialReadUntilDone(); Serial.print("sf0;sa0;sd1,36,\""); i =schedule[water_schedule].zone; if (i  SEC_IN_DAY) { Serial.print("\";sa1;sd126,36,\""); Serial.print(clk.tm_mon+1); Serial.print("/"); Serial.print(clk.tm_mday); Serial.print(" "); 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.print(" "); } else { Serial.print("\";sf1;sa1;sd111,30,\""); 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.print("\";sf0;sd126,36,\""); } Serial.print((clk.tm_hour>12)?"PM":"AM"); if (nvram.water_duration) Serial.print("\";so2;sc0,29,128,19"); Serial.println(); SerialReadUntilDone(); if (menu_select ==-1) { //Serial.print("\";sa0;sd0,52,\""); //Serial.print(rain); SerialPrint("\";so1;sa2;sd63,52,\"", C2F(temp), error_temp); if (!error_temp) Serial.print("\",248,\"" #ifdef FAHRENHEIT "F" #else "C" #endif ); Serial.print(" / "); Serial.print(lux); } else { Serial.print("\";so0;sc0,51,128,14;sf0;sa2;sd63,52,\""); if (menu_select ==MENU_ON_OFF) { Serial.print((nvram.state &STATE_ON_OFF) ? "OFF" :"ON"); } else Serial.print(menu[menu_select]); } Serial.println("\";sd"); SerialReadUntilDone(); update_oled =false; } else init_oled =true; } if (update_nvram) { if (SerialCmdNoError(I2C_EEPROM)) { nvram.crc =crc8((uint8_t*)&nvram, sizeof(nvram)-sizeof(uint8_t)); //swSerial.println(nvram.crc, HEX); SerialWriteEEPROM((uint8_t*)&nvram, 0, sizeof(nvram)); update_nvram =false; } } delay(50); } else { digitalWrite(led, HIGH); delay(500); digitalWrite(led, LOW); delay(500); init_board =true; init_oled =true; } wdt_reset();}

Skema

Intelligently water your yard or garden

Proses manufaktur

  1. Merancang sistem pertanian pintar sumber terbuka
  2. Papan sensor pintar mempercepat pengembangan AI tepi
  3. 433MHz Smart Home Controller dengan Sensorflare dan RaspberryPi
  4. Sensor Suhu Raspberry Pi
  5. IoT Seluler:Tempat Sampah Cerdas
  6. Bartender Cerdas
  7. Sensor Emosi / EEG
  8. Pengontrol Irigasi Win10 IOT dengan Sensor Kelembaban
  9. Sensor Ultra-Sensitif dan Tangguh untuk Tekstil Cerdas
  10. Sensor Ultra Tipis untuk Lensa Kontak Cerdas