![image](https://habrastorage.org/storage3/7cd/973/52c/7cd97352c356d4af43f5ab5ba85fa818.png)
Привет, уважаемые Хаброжители!
Недавно мне позвонил отец, рассказал, что у него есть цветок, который он постоянно забывает поливать или наливает чрезмерно много воды, в итоге тот, то засыхает, то наоборот страдает переизбытком влаги.
Будем решать эту проблему с помощью микроконтроллера и C#.
![](https://habrastorage.org/storage3/278/9a1/732/2789a17323caff187ec877e234cf4988.jpg)
Недолго посовещавшись, было решено автоматизировать данный процесс. Мы определили для себя основные требования к тому, что хотелось бы видеть:
- Это должно быть дешево, дешевле, чем аналоги на рынке
- Это должно очень просто программироваться, должен быть визуальный интерфейс на экране
- Информация должна собираться на основе датчиков (то есть никаких глупостей по таймеру – все аналоги на рынке на момент написания статьи работают по таймеру, или мы просто не нашли таковых)
- Цветок стоит рядом с компьютером, а значит можно (желательно, чтобы избежать блока питания) использовать USB
Часть 1. Аппаратная часть
Задав вопрос на Хабре (вопрос), получил массу предложений про Ардуино и прочие девайсы, однако остановился на AVR-USB-MEGA16 (спасибо Андрею, за консультации и помощь в освоении, а так же за оперативность доставки).
![](https://habrastorage.org/storage3/46b/0d6/b2b/46b0d6b2be722d1d1136e231174fae4b.jpg)
В итоге были куплены следующие компоненты:
- AVR-USB-MEGA16 – 500 руб.
- Датчик влажности почвы – 120 руб.
- Помпа аквариумная на 200 л/ч – 507 руб.
- Очиститель грунта (нужна была трубка из комплекта) – 330 руб.
- Душик аквариумный – 193 руб.
- Реле 5DC/220AC – 170 руб.
- Транзистор биополярный – 7,5 руб.
- Сопротивление – 10 р.
- Блок с клеммами – 100 р.
- Блок предохранителя – 50 р.
- Предохранитель — 22 руб.
- Провод USB – 220 руб.
Итого не считая всяких мелочей получилось около 2200 рублей.
![](https://habrastorage.org/storage3/fa5/137/504/fa5137504ffd41836a5a4961a759a928.png)
Все детали очень компактные, самое большое это помпа:
![](https://habrastorage.org/storage3/dd4/5d3/313/dd45d331369d7d5376bdb76db0f3f0dd.jpg)
Итак, все куплено, пришло время сборки. Схему включения реле посоветовал @AlekseyNovikov, за что ему огромное спасибо. Вот схема:
![](https://habrastorage.org/storage3/5b7/e5c/721/5b7e5c721dedd24230f5e6fdc348f5d3.gif)
Единственное, что решил убрать диод. Потратив вечер на пайку, получился вполне вменяемый результат:
![](https://habrastorage.org/storage3/cb3/376/77e/cb337677e1fda5cb3aed311d9957bd8b.jpg)
Теперь переходим к самому интересному – логика работы.
Часть 2. Программная часть
Перед началом реализации данной затеи, основным страхом или опасением была сложность программирования микроконтроллеров, отсутствие нормального дебага и прочие трудности, поэтому основной целью данной статьи является не описание как таковой идеи, потому как она не нова, а пропаганда простоты использования подобных девайсов с помощью современных языков программирования, таких как C#.
От платы нам потребуется лишь две вещи:
- Показания датчика влажности почвы
- Включение/выключение реле
Итак, я использовал WPF в связке с прошивкой Кухтецкого Сергея (подробнее, как это работает можно почитать здесь).
Программа представляет собой иконку в трее и маленькое ненавязчивое окошко.
![](https://habrastorage.org/storage3/0f5/b25/3c1/0f5b253c1efbe8143067cdd6d4df6aa7.png)
Настройки программы тоже максимально просты:
![](https://habrastorage.org/storage3/583/880/3ee/5838803eef88504c9e324c2ea5856d6c.png)
К основным сложностям в работе софта можно отнести следующие проблемы:
- Производительность насоса указанная на насосе не имеет почти ничего общего с действительностью
- Производительность насоса очень сильно зависит от высоты подъема воды, скажем, если помпа просто сливает воду, то производительность конкретно моего насоса достигает 350 литров в час, однако при высоте подъема в 80 см едва ли дотягивает до 40 литров в час.
- На глаз сложно определить емкость тары, в которой будет работать помпа
- Перед тем как вода дойдет до цветка, она должна пройти не простой путь по трубке наверх.
Для решения этих проблем был придуман простейший алгоритм на основе замеров. После того, как все стоит на своих местах, вода набрана в резервуар:
- Определяем скорость подъема воды: для этого достаточно нажать на соответствующее поле мышкой, затем нажать Enter, помпа начнет работать, как только появится первая капля воды снова нажимаем Enter и видим время, потраченное на подъем воды.
- Определяем производительность насоса на данной высоте: после определения времени, находим стакан, емкость которого заведомо известна, я взял детскую бутылочку для смесей, на ней нанесены мерные риски, устанавливаем значение «Объем полива» в 200 мл. Нажимаем мышкой на поле «Производительность насоса», нажимаем Enter и ждем пока в бутылочку не нальется ровно 200 мл, как только это произойдет снова нажимаем Enter и вуаля, имеем точную производительность насоса.
- Определяем объем резервуара: тут нам понадобится ведро или какая-нибудь большая емкость, по аналогии активируем нужное поле, нажимаем Enter и просто ждем, когда выльется почти вся вода, остановится нужно на том моменте, когда насос еще слегка покрыт водой. Имеем объем воды, которую можно использовать.
Все, система готова к работе. По первому параметру настроек – объем полива, он определяется автоматически на основе датчика влажности почвы и оптимальной влажности для данного вида растения (к сожалению, я не вынес его в интерфейс, оно устанавливается в XML файле)
Алгоритм работы АПЦ (Автоматическая Поливалка Цветка) прост:
Раз в десять минут снимаются показания с датчика влажности почвы (происходит ряд замеров, берется среднеарифметический ). На основе показаний принимается решение об ирригации почвы, если отклонение от нормы составляет более 5%, то происходит полив. Данные обо всех действиях записываются в БД, на их основе впоследствии строится прогноз полива, график и определяется необходимый объем полива. Алгоритм определения объема выливаемой жидкости так же очень прост. Есть некий эталон влажности, скажем 74% (указывается в XML файле под конкретное растение), происходит первый полив объемом в 100 мл, через 10 минут происходит очередной замер влажности и мы смотрим отклонение от эталонного уровня влажности, если влажность меньше чем необходима, то при следующем поливе добавляем с шагом в зависимости от отклонения (100 мл, 50 мл, 10 мл, 3 мл). Если уровень влажности не изменился +-5 единиц, то считаем, что в резервуаре закончилась вода, отправляем СМС.
К сожалению, я не люблю цветы, у меня их попросту нету, поэтому обкатать систему на реальном растении мне так и не удалось, мной была куплена экспериментальная хризантема, которая успешно погибла на первой неделе опытов. Механизм был успешно отправлен моему отцу (привет Почте России, посылка должна была дойти за неделю, уже идет три и пока неизвестно, что с ней), как только он все установит и запустит, обязательно снимет видео и я его добавлю.
К недостаткам данной системы можно отнести многое, во первых все таки зависимость от ПК, во вторых все это довольно массивно, большой резервуар, к нему идут провода, от него идет толстая трубка на верх к горшку, в горшка выходят провода с датчиков, все это включается в розетку, т.к. помпа 220В.
В планах на ближайшее будущее устранить все недостатки, хочу нарисовать 3D модель, которая будет включать все в один горшок – резервуар, помпа, каналы для воды, датчики, LCD экран и т.д., хочу, чтобы все это работало на батарейках минимум полгода, данный горшок будет работать на Ардуине Про Мини.
На данный момент осваиваю Blender (имею большой опыт в 3D Max’е), так как решил полностью отказаться от пиратского софта, после того как закончу, сдам модель в 3D печать, устраню все недостатки, запущу опытный образец и обязательно напишу продолжение данной статьи.
UPD: прилагаю актуальную схему устройства (без диода, в последствии его необходимо добавить)
![](https://habrastorage.org/storage3/25c/f5e/db9/25cf5edb944cfc490996c43c4a133f4a.png)
К самым интересным моментам стоит отнести подготовку устройства:
public static bool Init()
{
dev = new ATMega16(vid, pid); // Создаем объект dev класса ATMega16.
if (!dev.IsOpen()) // Если есть проблемы с USB
{
return false;
}
else // Если все хорошо, настроим микроконтроллер по USB
{
dev.DDRD |= 0x80; // Пин 7 порта D - на вывод
dev.PORTD &= 0x7F; // Выключим реле на плате
dev.ADMUX = (3 << ATMega16.REFS0); // Будем использовать внутренний источник опорного напряжения
// Внутренняя частота АЦП не должна превышать 200 кГц. Поэтому тактовая частота микроконтроллера
// должна быть поделена на 128 (биты ADPS0, ADPS1 и ADPS2 установим в 1). Т.о. получим 125 кГц.
// Время преобразования будет (1/125000)*13 = 104 мкс, соответственно частота - 9.6 кГц
// Установка бита ADEN в 1 разрешает работу АЦП
dev.ADCSRA = (1 << ATMega16.ADEN) | (1 << ATMega16.ADPS2) | (1 << ATMega16.ADPS1) | (1 << ATMega16.ADPS0);
}
return true;
}
Снятие показаний с датчика:
dev.ADMUX = (byte)((dev.ADMUX & 0xE0) | 0); // Работает один канал - ADC0
dev.ADCSRA |= (1 << ATMega16.ADSC); // Запуск АЦП
// Время преобразования мало (около 100 мкс). Поэтому просто подождем готовности в цикле
while ((dev.ADCSRA & (1 << ATMega16.ADIF)) == 0) ;
return (dev.ADCL + (((int)dev.ADCH) << 8)); // Формируем число
Преобразование показаний с датчика в % влажности, а в последствии в строчное значение:
var persantage = (int)(stateOfSoil / 8.4);
if (persantage < 10) result = "критическое";
else if (persantage < 20) result = "очень сухая";
else if (persantage < 30) result = "сухая";
else if (persantage < 40) result = "свежая";
else if (persantage < 50) result = "нормальная";
else if (persantage < 60) result = "влажная";
else if (persantage < 70) result = "сырая";
else if (persantage < 80) result = "мокрая";
else if (persantage < 90) result = "водянистая";
else result = "вода";
return String.Format("{0} ({1}%)", result, persantage);
Включение помпы:
dev.PORTD |= 0x80;
Отключение помпы:
dev.PORTD &= 0x7F;