Ранее делал автополив на ATTiny13 Автополив комнатных растений, а тут мне понадобился ещё автополив. Решил уже сам написать программу, потренироваться в оживлении каменного таракана китайского производства – микроконтроллере PY32F002A1556. Стоит такой МК смешные деньги: 17 руб. 50 коп. за штучку, зато флэш у него 20кБ. Можно писать программу не выверяя каждый Байтик.
Программу писал с учётом того, чего нет в прошлой разработке.
Прошлый автополив делал по уже написанной кем-то Источник: https://www.youtube.com/watch?v=dxrjaHmqwpE. Сейчас на youtube дорога нам закрыта (жаль, там много разных интересных технических проектов и не только по программированию и Ардуино). Поэтому, чтобы потренироваться на новых МК решил написать свой автополив.
Вначале определяюсь, что должно быть и как всё должно управляться, замысел такой:
Нужен полив через 1, 2, 3 дня на выбор.
Время работы насоса должно легко настраиваться, но не более 5 минут, т.к. и за 5 минут можно вообще всё залить напрочь.
Должна быть индикация, что программа не зависла, так как у меня был разок случай, когда программа зависла, а я думал, что поливает как надо.
Нужен показ через сколько дней идёт полив.
Управление одной кнопкой и пара светодиодов для обратной связи состояния программы.
Требования не особо сложные, поэтому и сама программа получилась простенькая.
Схема
Схема подобна прошлому проекту, только микроконтроллер другой, но в подобном корпусе: SOP-8.
Pic 1. Схема электрическая принципиальная
Описание программы
Программа, как обычно, хорошо закомментирована, пояснять там вроде нечего. Единственное необычное отличие в том, что вначале setup() (строчки 129-130) при нажатой кнопке Настройка программа уходит в безконечный цикл. Это нужно, чтобы можно было запрограммировать МК. Иначе МК уходит в сон и не успевает произойти программирование.
Поясню как работает настройка полива:
НАСТРОЙКА автополива
Включить питание - засветится красный светодиод (настройка).
Пока красный светодиод светится (2 секунды) - нажать кнопку Настройка.
Теперь красный светодиод будет поочерёдно промаргивать
количество дней между поливами.
После требуемого промежутка в днях - нажать кнопку Настройка.
Включится насос (зелёный светодиод) и будет работать,
пока не нажать кнопку Настройка, что ограничит время
работы насоса, а иначе насос проработает максимальное время
и сам остановится.
Далее идёт запись в EEPROM. После чего красный светодиод
моргнёт столько раз, сколько выбрано дней между поливами.
После этого программа переходит к работе. Насос работает
столько, сколько определено при настройке и переходит в режим
ожидания следующего полива.
В момент ожидания кратко промаргивает красный светодиод, что
указывает на работу программы, остутствие зависания.
Когда время ожидания закончилось, включается насос полива.
После завершения работы насоса красный светодиод моргнёт
продолжительно столько раз, сколько дней ожидания до
следующего полива.
Если нажать на кнопку Сброс-Reset, то программа начнёт
работу заново. Если при этом не нажимать кнопку Настройка,
то после гашения красного светодиода настройки, программа
переходит к считыванию настроек из EEPROM и далее включает
работу насоса. Потом переходит к ожиданию следующего полива
через заданное ранее число дней.
Это удобно для ручного принудительного полива.
/*************************************************************** 2026-05-20 Mr.ALB Проверка PY32F002AL1556 2026-06-24 Mr.ALB Автополив цветов - начало проекта 2026-06-26 Mr.ALB Отладка 2026-06-28 Mr.ALB Работает v1.0, проверка и оптимизация 2026-06-29 по 2026-07-11 Проверка и отладка промежутка между поливами. Добился очень точного повторения, срабатывает в одну и ту же минуту даже при поливе через 2 дня PY32F002AL1556TU SOP-8 ----------------------- +-\/-+ VCC 3.3V 1| |8 GND PA4/PA10 2| |7 PA1/BTN - защита от сна RX/PA3 3| |6 PA2/TX/PF2/!RST SWCLK/PA14/PB3 4| |5 PA13/SWDIO +----+ НАСТРОЙКА среды --------------- board part number: PY32F002Ax5 Optimize: Smallest (-Os) width LTO ПРОГРАММИРОВАНИЕ МК ------------------- 1. bin создать тут в Arduino IDE 2. Через DAPLINK программой PuyaCoFlash-1.5.1 записать bin ПОДКЛЮЧЕНИЕ ----------- BTN PY32F002A1556 1 - GND (pin8) 2 - PA1 (pin7) LED A -[5.1k]- PA4 (pin2) K -------- GND (pin8) RST_BTN 1 - PA2 (pin6) 2 - GND (pin8) PUMP_in 1 -[100]-- PA3 (pin3) PUMP_led A -[5.1k]- PA3 (pin3) K -------- GND (pin8) НАСТРОЙКА автополива -------------------- 1. Включить питание - засветится красный светодиод (настройка). 2. Пока красный светодиод светится - нажать кнопку [настройка]. 3. Теперь красный светодиод будет поочерёдно промаргивать количество дней между поливами. 4. После требуемого промежутка в днях - нажать кнопку [настройка]. 5. Включится насос (зелёный светодиод) и будет работать, пока не нажать кнопку [настройка], что ограничит время работы насоса, а иначе насос проработает максимальное время и сам остановится. 6. Далее идёт запись в EEPROM. После чего красный светодиод моргнёт столько раз, сколько выбрано дней между поливами. 7. После этого программа переходит к работе. Насос работает столько, сколько определено при настройке и переходит в режим ожидания следующего полива. 8. В момент ожидания кратко промаргивает красный светодиод, что указывает на работу программы, остутствие зависания. 9. Когда время ожидания закончилось, включается насос полива. После завершения работы насоса красный светодиод моргнёт продолжительно столько раз, сколько дней ожидания до следующего полива. 10. Если нажать на кнопку [сброс-reset], то программа начнёт работу заново. Если при этом не нажимать кнопку [Настройка], то после гашения красного светодиода настройки, программа переходит к считыванию настроек из EEPROM и далее включает работу насоса. Потом переходит к ожиданию следующего полива через заданное ранее число дней. Это удобно для ручного принудительного полива. --------------------------------------------------------------- Скетч использует 10528 байт (51%) памяти устройства. Всего доступно 20480 байт. Глобальные переменные используют 1384 байт (45%) динамической памяти, оставляя 1688 байт для локальных переменных. Максимум: 3072 байт. ****************************************************************/#include<EEPROM.h>// Библиотека памяти#include<PY32LowPower.h>// Библиотека сна#define BTN PA1 // Кнопка настройки#define LED PA4 // Светодиод настройки#define PUMP PA3 // Насос водяной
PY32LowPower lowPower; // Создание объекта для сна#define SLEEP_TM 4000 // Время сна 4000 мс = 4 c#define EEP_ADR 3 // Адрес данных#define MAX_PERIOD 3 // Максимальное число дней ожидания полива#define DEF_WORK_TIME 3000// Время работы насоса по умолчанию 3 сек// Если отладка не нужна, то закомментировать строчку ниже//#define DEBUG // Отладка#ifdef DEBUG
// Настройка для отладки// Множитель - дни в тики 10t => 10 тиков * 4 секунды = 40 секунд в день#define MULTIPLIFIER 10 // 10 тиков на день#define MAX_WORK_TIME 20000 // Макс.время работы насоса 20 секунд #else// Настройка для работы// Сутки 24 часа = 1440 минут = 86400 секунд// 86400 секунд / 4 секунды сна = 21600 тиков в день#define MULTIPLIFIER 21600 // Множитель - дни в тики#define MAX_WORK_TIME 300000 // Макс.время работы насоса 5 минут#define ADD_TICKS 165 // Поправка в день 163#endif// Структура данныхstruct MyObject
{
uint8_t dni = 1; // Период в дняхuint32_t work_time = DEF_WORK_TIME; // Время до конца работы в мс
};
MyObject myData; // Объявляем переменную с даннымиuint16_t tim; // Для паузuint32_t period_ticks = 0; // Время до конца периода в тикахuint32_t count = 0; // Счётчик тиков/***************************** ***** Функция НАСТРОЙКИ ***** ****************************/voidsetup()
{
// Защита от зависания во сне, для программирования МК// Если нажать кнопку перед включением, затем удерживать кнопку и// включить МК, то переход в безконечный цикл - можно программировать// Иначе кнопка далее используется для настройки поливаpinMode(BTN,INPUT_PULLUP); // Подтяжка к питаниюif (!digitalRead(BTN)) while (1);
// Светодиод настройкиpinMode(LED,OUTPUT); // Определение пина на выход// НасосpinMode(PUMP,OUTPUT); // Определение пина на выходdigitalWrite(PUMP,LOW); // Отключим насос/****************************************** НАСТРОЙКА значений переменни автополива *****************************************/bool flag =false; // Флаг нажатия кнопкиdigitalWrite(LED,HIGH); // Включим светодиод настройки// Даём 2 секунды на решение по настройке
tim =millis();
while ((millis() - tim) < 2000)
{
// Если нажать кнопку BTN, то переход в настройку поливаif (!digitalRead(BTN))
{
flag =true; // Выставим флаг нажатия кнопки настройкиbreak; // Выход из цикла
}
}
if (flag) // Если нажата кнопка [Настройка]
{
flag =false; // Сбросим флаг кнопкиdigitalWrite(LED,LOW); // Отключим красный сетодиодdelay(1000);
// Выбор времени ожидания в дняхwhile (1) // Пока не нажата кнопка [Настройка]---------------
{
fnLedBlink(myData.dni, 500); // Показ дней: 1,2,3
tim =millis();
while ((millis() - tim) < 1000) // Задержка 1 секунда
{
if (!digitalRead(BTN)) // Проверка нажатия кнопки
{
// Если нажата кнопка - выход из выбора дней
flag =true; // Выставим флаг нажатия кнопкиbreak;
}
}
if (flag)
break; // Выход из выбора днейelse
myData.dni++; // Переходим к следующему времени в днях// Ходим по кругу, пока не нажата кнопка [Настройка]if (myData.dni > MAX_PERIOD)myData.dni = 1;
}
// end of while(1)-------------------------------------------delay(1000); // Задержка 1 секунда// Определяем время работы насоса
tim =millis();
myData.work_time =millis();
digitalWrite(PUMP,HIGH); // Включаем насос// Задержка на работу насоса// Выход из задержки по кнопке или превышению времени работыwhile (digitalRead(BTN) && (millis() - tim) < MAX_WORK_TIME);
// Вычисляем время работы насоса
myData.work_time =millis() - myData.work_time; // В мсdigitalWrite(PUMP,LOW); // Отключаем насосdelay(1000); // Задержка 1 секунда// Запишем настройки в EEPROMEEPROM.put(EEP_ADR, myData);
// Сигнал записи в EEPROM - моргаем число выбранных дней
fnLedBlink(myData.dni, 500);
}
else// Кнопка не нажата - загрузим данные из EEPROM
{
digitalWrite(LED,LOW); // Отключим светодиод [Настройка]// Загрузить данные .dni, .work_time из EEPROMEEPROM.get(EEP_ADR, myData);
}
// Ограничения-----------------------------------if (myData.dni > MAX_PERIOD) myData.dni = 1;
if
(
myData.work_time > MAX_WORK_TIME ||
myData.work_time < DEF_WORK_TIME
)
// Время работы по умолчанию 3 секунды
myData.work_time = DEF_WORK_TIME;
//-----------------------------------------------// Вычислим время ожидания полива в тиках
period_ticks = myData.dni * MULTIPLIFIER; //
period_ticks += myData.dni * ADD_TICKS; // Поправка в тиках// Вычтем время работы насоса из общего числа тиков//period_ticks -= myData.work_time / SLEEP_TM;//2026-07-01 Опытным путём определилось, что время до следующего// полива за сутки на 5 минут меньше, поэтому убрал учёт времени// работы насоса из period_ticks, будет ближе к 1440 минутам
count = period_ticks; // Ожидание полива в тиках -> счётчик
fnPumpOperation(); // Работа насоса
lowPower.begin(); // Установка функции сна
}
// end of setup()/**************************** ***** Функция: РАБОТА ****** ****************************/voidloop()
{
if (!count) // Время ожидания закончилось
{
fnPumpOperation(); // Работа насоса// Возобновим время ожидания в тиках
count = period_ticks;
}
lowPower.deepSleep(SLEEP_TM); // Сон на SLEEP_TM мс
count--; // Уменьшаем после каждого сна// Показ работы программы после пробуждения - нет зависания
fnLedBlink(myData.dni, 1);
}
// end of loop()/************************** Подпрограммы / Функции **************************//*********************************************** Функция: Мигалка настроечным светодиодом num - количество переключений, tm - размер паузы***********************************************/void fnLedBlink(uint8_t num,uint8_t tm)
{
bool f =HIGH;
for (byte i = 0; i < num * 2; i++)
{
digitalWrite(LED, f); // Светодиод вкл./откл.delay(tm);
f =!f; // Меняем значение на обратное
}
}
// end of fnLedBlink()/********************************************* Функция: Работа насоса ********************************************/void fnPumpOperation(void)
{
digitalWrite(PUMP,HIGH); // Включим насосdelay(myData.work_time); // Время работы насосаdigitalWrite(PUMP,LOW); // Отключим насос// Сигнал - моргаем число дней до след. полива
fnLedBlink(myData.dni, 500);
}
// fnPumpOperation()
Конструкция
Разработал плату. Размеры 64,77 * 31,75 мм. Насос у меня со штекером USB-A, поэтому на плате установил розетку под USB-A.
На плате установлена третья кнопка для контроля напряжения аккумулятора. Сейчас продаются микроплатки с уровневым светодиодным индикатором напряжения Li-Ion аккумулятора. Такие платки в последнее время устанавливаю в фонарики и другую технику питающуюся от аккумуляторов. При нажатии на кнопку SB3, можно посмотреть уровень напряжения на аккумуляторе, чтобы вовремя его зарядить.
Pic 2. Фотовид платы
Собрал всё на монтажной одностороннеей плате. Микроконтроллер у меня установлен на плату переходник SOP-8 в DIP-8. На плате установлена панелька DIP-8. Повышающий преобразователь для насоса сделан самодельный на микросхеме MT3608, можно было бы использовать покупной, но такого в наличии у меня не оказалось, ждать с Али пару недель не захотелось.
Pic 3. Автополив. Вид сверху
Соединения с помощью проводников, хотя разрабатывал печатную плату, а собирал без печатной платы, т.к. единичное устройство. А вот размещение деталей легче осуществить проектируя печатную плату.
Pic 4. Автополив. Оборотная сторона платы
Аккумулятор использую типа 18650. Он установлен в саможельный держатель, который укреплён на основании всей конструкции. Размер основания 80*40 мм из пластика ABS.
Pic 5. Автополив. Аккумулятор
Модуль заряда аккумулятора сделан на микросхеме LTC4054 по моей доработанной схеме, как раз был в запасе, пригодился. Работает он как и модули на микросхеме TP4056. Разъём для подключения зарядки типа microUSB, как и в первом устройстве автополива.
Pic 6. Автополив. Модуль заряда аккумулятора
Конструкция устройства повторяет предыдущую конструкцию. На основании из ABS закреплён аккумулятор, выше промежуточная пластина из ABS, на которой установлена плата устройства, а сверху всё прикрыто пластиной из оргстекла.
Pic 7. Автополив. Разные виды
Части устройства соеденены стойками из требочек от пустых стержней гелевых авторучек. Верхняя пластана из оргстекла держится двумя винтами на стойках из ABS.
Pic 8. Автополив. Разные виды
Устройство собрано и подключено к насосу. Стоит на крышке контейнера на 3 литра воды. В контейнер положены несколько таблеток серебра, чтобы не заводились патогенные бактерии.
Pic 9. Автополив. Разные виды
Интересно, что микроконтроллер настолько экономичный, что если отключить питание, то он на заряде конденсаторов С2 220 мкФ и С3 1000 мкФ проработал 170 тиков – 170 * 4 секунды = 680 секунд = 11,33 минуты.
Приложение
Все, что необходимо для повторения конструкции, можно скачать по ссылкам: