Интеллектуальный контроллер полива
Компоненты и расходные материалы
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Приложения и онлайн-сервисы
|
Об этом проекте
Создайте интеллектуальный контроллер орошения с помощью Arduino
Интеллектуально орошайте свой двор с помощью динамических циклов воды. Прекратите поливать свой двор, если идет дождь или идет дождь с момента последнего полива. Используйте датчик освещенности, чтобы определить время восхода солнца и соответственно автоматически настроить время начала полива. Прекратите поливать двор, если слишком холодно.
Список возможностей
- Датчик наружной температуры
- Датчик наружного дождя
- Датчик внешнего освещения
- Часы реального времени с батарейным питанием для еженедельного планирования.
- Энергонезависимое хранилище - никогда не теряйте полив из-за потери мощности
- Обнаружение восхода солнца
- Умный полив экономит ваши счета за воду.
- Поливайте перед восходом солнца, чтобы дать время замачиваться.
- Прекратите полив, когда на улице слишком холодно
- Уменьшить рост грибка.
- Простое управление расписанием
Детали, необходимые для создания интеллектуального контроллера полива
- Расширитель ввода-вывода
- x2 1-Wire с I2C.
- Соединение 1-Wire
- Оптический разъем
- Разделитель
- Arduino Nano.
- 4-канальное реле постоянного тока 5 В
- Датчик освещенности TSL2561.
- Водонепроницаемый датчик температуры DS18B20.
- Оптический инфракрасный датчик уровня воды.
- DS3231 AT24C32 IIC Прецизионные часы реального времени.
- Дисплей I2C SSD1306 OLED 128x64.
- Прозрачный водонепроницаемый пластиковый корпус размером 200x120x75 мм.
- Прозрачный водонепроницаемый пластиковый корпус 100x68x50 мм.
- Водонепроницаемый нейлоновый кабельный ввод ip68 pg7.
- IP68 pg11 Водонепроницаемый нейлоновый кабельный ввод.
- Разъем RJ11 Keystone с винтовыми клеммами.
- 50-футовый провод 4C4P RJ11.
- 6-футовый провод 4C4P RJ11.
- Заголовок 2,54 мм.
- 2-контактный 2-контактный микропереключатель SPST с мгновенной кнопкой
- Блок питания от настенного блока питания 12 В постоянного тока, 1 А.
Схема подключения
OLED-дисплей
Нажмите кнопку «Меню», чтобы отобразить меню, и продолжайте нажимать кнопку, чтобы просмотреть все пункты меню. Меню будет автоматически удалено через 30 секунд бездействия. Нажмите кнопку выбора, чтобы выполнить желаемую функцию меню.
Так зачем использовать расширитель ввода-вывода?
- Упрощение проектирования.
- Готовые запчасти
- Нет драйвера 1-Wire для написания
- Нет драйвера DS3231 RTC для записи
- Нет драйвера EEPROM для записи
- Нет драйвера дисплея OLED для написания
- Нет отображаемых шрифтов, занимающих пространство кода Arduino.
- Не нужно писать драйвер датчика температуры
- Нет оптического датчика дождя для записи
- Экономит место для кода на Arduino; всего 12710 байт (39%)
- Всего три дня на написание кода.
- Простота подключения с помощью стандартного телефонного кабеля RJ11.
- Нет проблем с длиной кабеля датчика.
- Дешевле в сборке, чем аналогичные коммерческие системы.
- Легко вносить изменения для адаптации к индивидуальным требованиям.
- Один источник питания
Постройте систему
Подключите Arduino Nano к расширителю ввода-вывода и запрограммируйте его с помощью следующего кода. Шестиконтактный разъем - это последовательный порт отладки программного обеспечения, который не нужен при окончательной установке.
Убедитесь, что вы изменили определенный адрес ONEWIRE_TO_I2C_ROM1 и ONEWIRE-TO_I2C_ROM2, чтобы он соответствовал адресу 1-Wire на I2C.
/ * Оптимизирован эскиз модуля расширения ввода-вывода
*
* Система полива v1.1
*
* /
#include
Примечание. Если вы используете порт USB для программирования Arduino Nano, вы должны отключить его от расширителя ввода-вывода, поскольку он также использует тот же единственный последовательный порт, вместо этого, если вы хотите отладить, используйте порт ICSP для программирования ATmega328P. Чтобы включить порт отладки программного обеспечения, раскомментируйте определение SERIAL_DEBUG.
Сначала необходимо настроить разветвитель на изоляцию линии передачи данных оптического инфракрасного датчика от линии удаленного датчика 1-Wire. Припаяйте резистор 0603 с нулевым сопротивлением к резистору R2.
Просверлите отверстие 7/16 дюйма в маленьком корпусе и отверстие 11/16 дюйма в большом корпусе с правой стороны для PG7 и PG11. Воспользуйтесь инструментом dremel, чтобы немного увеличить отверстия, пока сальник не войдет в плотное соединение. PG7 будет питать удаленные датчики и PG11 для проводов 12 В постоянного тока, 24 В переменного тока, коллектора и провода удаленных датчиков RJ11.
Подключите микропереключатель кнопки мгновенного действия SPST и подключите его к винтовой клемме RJ11. Для изоляции контактов используйте термоусадочную трубку.
Подключите все провода и соберите / подайте все детали в большой корпус. Ваш 50-футовый провод RJ11 для удаленных датчиков должен просто проходить через сальник PG11, не разрезая его.
Просверлите отверстие 9/16 дюйма в верхней части небольшого корпуса для оптического инфракрасного датчика воды. Используйте инструмент dremel, чтобы немного увеличить отверстие, пока не поместится датчик. Корпус небольшого удаленного датчика плотно прилегает, но если содержимое укладываются в рекомендуемой ориентации, она должна точно подходить. Если сделать провода RJ11 как можно короче, это поможет втиснуть все это в меньший корпус. После сборки рекомендуется добавить немного морского клея в шайбу гайки сальника, прежде чем навинчивать гайку, чтобы создать лучшую печать.
Установите корпус дистанционного датчика снаружи и установите его на возвышении с восточной стороны вашего дома так, чтобы оптический инфракрасный датчик воды и датчик освещенности были направлены в небо без препятствий.
Просверлите отверстия диаметром 1/4 дюйма в верхней средней части большого корпуса и установите кнопки. Используйте инструмент dremel, чтобы немного увеличить отверстие до тех пор, пока кнопки не встанут на место.
Протестируйте систему и убедитесь, что все работает правильно. Чтобы проверить реле и датчики, отключите Arduino от IO Expander и подключите его напрямую к компьютеру, чтобы управлять им вручную. Убедившись, что все работает, соберите все части в корпус, используя двусторонний скотч и упаковочную пену, чтобы закрепить доски, и наслаждайтесь преимуществами и экономией вашего интеллектуального контроллера полива.
Видео в действии
Обновление от 12.09.2019
Выпущена версия 1.1, в которой исправлена проблема с запуском, если система теряла питание на несколько дней.
Обновление 02.10.2019
При подключении 1-Wire к I2C к DS3231, а затем к OLED-экрану SSD1306 у вас будет в общей сложности три разных подтяжки на линиях SDA и SCL, как показано на изображении ниже в кружке. Это фактически приведет к подтягиванию 4,7k / 3 =1,56k, которое может быть слишком сильным и привести к случайным искажениям экрана.
Поскольку DS3231 использует блок резисторов, который используется другими линиями, удалите другие подтягивающие резисторы:
- 1-Wire с I2C R3 и R4.
- SSD1306 OLED R6 и R7.
Код
- Интеллектуальный контроллер полива
Умный контроллер орошения C / C ++
Используйте Arduino для разумного полива вашего двора или сада./ * Оптимизирован эскиз IO Expander * * Система полива v1.1 * * / # include#include // Файл расположен \ Program Файлы (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_ROM1" i4scc "#define ONEWIRE_TO_I2C_ROM1" i4scc "#define ONEWIRE_TO_I2C_ROM" #################################### define I2C_EEPROM "s4tf" #define I2C_OLED "s4t10" #define I2C_LIGHT "s3t9; sc0" #define OPTICAL_SENSOR "g5a" #define BUTTON1 "g11d" #define BUTTON2 "g12d_SENSOR" #define BUTTON2 "g12d" define DO_NOT_WATER_TEMP 4.4444 // 40F # define MAX_ZONES 4 # define HOUR_IN_DAY 24L #define MIN_IN_HOUR 60L # define SEC_IN_MIN 60L # define SEC_IN_HOUR (MIN_IN_HOUR * SEC_IN_MIN) #define SEC_IN_IN_DAY (HOUR_IN_IN_DAY_ OUR) #define DAYS_IN_WEEK 7 # define SEC_IN_WEEK (SEC_IN_DAY * DAYS_IN_WEEK) #define SUN 0x01 # define MON 0x02 #define TUE 0x04 #define WED 0x08 # define THR 0x10 #define FRI 0x20 # define | ПН | ВТ | СР | THR | ПЯТ | 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_DEBUGSoftwareSerial swSerial (8,7); # endifcharday [] {«ВС», «ПН», «ВТ», «СР», «ЧТ», «ПТ», «СБ»}; char menu [] [13] ={«Далее», «Вода», «Сброс» , «Мин. Часов +», «Мин. Часов -», «Час часов +», «Часы -», «Восход», «ВКЛ / ВЫКЛ»}; enum {MENU_NEXT, MENU_WATER, MENU_RESET, MENU_CLOCK_MIN_PLUS, MENU_CLOCK_MIN_MINUS, MENU_CLOCK_HOUR_HOUR_HOUR_MIN_MINUS, MENU_CLOCK_HOUR_HOUR_ MENU_CLOCK_HOUR_MINUS, MENU_SUNRISE, MENU_ON_OFF}; typedef struct {описание символа [16]; uint8_t relay;} ZONE; typedef struct {uint8_t zone; uint8_t дней; int8_t час; int8_t min; uint8_t duration;} РАСПИСАНИЕ; typedef struct {time_t sunrise_time; time_t last_water_time; uint8_t water_schedule; uint8_t water_duration; uint8_t дождь [MAX_ZONES]; состояние uint8_t; uint8_t crc;} NVRAM; enum {ZONE1, ZONE2, ZONE3, ZONE4}; enum {RELAY1 =1, RELAY2, RELAY3, RELAY4}; ZONE zone [] ={{"Front Right", RELAY1}, {"Front Left" , RELAY2}, {"Втулки", RELAY3}, {"Left Side", RELAY4},}; РАСПИСАНИЕ расписание [] ={{ZONE1, SUNRISE | EVERYDAY, -1, 0, 4}, {ZONE2, EVERYDAY, 6, 15, 5}, {ZONE3, EVERYDAY, 6, 0, 10}, {ZONE4, EVERYDAY, 6, 10, 6},}; NVRAM nvram; bool update_nvram =false; uint8_t crc8 (uint8_t * данные, длина uint16_t) {uint8_t crc =0; while (длина--) {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 # определить C2F (temp) CelsiusToFahrenheit (temp) float CelsiusToFahrenheit (float celsius) {return ((celsiusToFahrenheit (float celsius) {return ((celsius 9) / 5) + 32;} # else # define C2F (temp) (temp) #endifvoid SerialPrint (const char * str, float decimal, char error) {Serial.print (str); если (ошибка) Serial.print (F ("NA")); иначе Serial.print (десятичный, 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 СУББОТА) wday =ВОСКРЕСЕНЬЕ; если (wday ==clk.tm_wday) перерыв; // Проверяем только одну неделю} if (clk_time 0) {if (nvram.rain [i]> nvram.water_duration) nvram.water_duration =0; иначе nvram.water_duration - =nvram.rain [i]; nvram.rain [i] =0; }} void WaterScheduleTime (void) {uint8_t i; nvram.water_duration--; update_nvram =правда; i =расписание [nvram.water_schedule] .zone; если (я 0) Serial.println ("o"); иначе Serial.println ("е"); SerialReadUntilDone (); }} void setup () {Serial.begin (115200); # ifdef SERIAL_DEBUG swSerial.begin (115200); # endif pinMode (led, OUTPUT); // задержка (1000); wdt_enable (WDTO_8S);} void loop () {static tm rtc; tm clk, sunrise_clk; time_t rtc_time; time_t clk_time; статический time_t next_time; статический uint8_t last_sec; статический uint8_t last_min; bool error_rtc; bool error_light; bool error_temp; статический длинный люкс =0; статическая температура поплавка, дождь; статический uint8_t sunrise_counter =MIN_IN_HOUR; static bool check_sunrise =false; uint8_t i; static bool read_nvram =true; статическое time_t water_time; статический uint8_t water_schedule; uint8_t sz; uint8_t wday; длинный п; bool button1, button2; статический int8_t menu_select =-1; статическое time_t menu_time =0; Serial.println (); если (SerialReadUntilDone ()) {если (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 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); ломать; case MENU_WATER:StartScheduleTime(water_time, water_schedule); WaterScheduleTime(); ломать; case MENU_CLOCK_MIN_PLUS:clk_time +=SEC_IN_MIN; ломать; case MENU_CLOCK_MIN_MINUS:clk_time -=SEC_IN_MIN; ломать; case MENU_CLOCK_HOUR_PLUS:clk_time +=SEC_IN_HOUR; ломать; case MENU_CLOCK_HOUR_MINUS:clk_time -=SEC_IN_HOUR; ломать; case MENU_ON_OFF:nvram.state ^=STATE_ON_OFF; update_nvram =true; ломать; } 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();}
Схема
Intelligently water your yard or gardenПроизводственный процесс
- Разработка систем интеллектуального земледелия с открытым исходным кодом
- Интеллектуальная сенсорная плата ускоряет разработку периферийного ИИ
- Контроллер умного дома 433 МГц с Sensorflare и RaspberryPi
- Датчик температуры Raspberry Pi
- Сотовый Интернет вещей:умный мусорный бак
- Умный бармен
- Датчик эмоций / ЭЭГ
- Контроллер полива Win10 IOT с датчиками влажности
- Сверхчувствительный и надежный датчик для смарт-текстиля
- Ультратонкий сенсор для умных контактных линз