84

Автоматический полив. Схема и скетч

Продолжение поста про Автоматический полив растений своими руками

Управление максимально простое первая строка статична, вторая строка состоит и 3-ёх экранов, в которых настройка лампы, настройка 1-ого насоса (P1), настройка 2-ого насоса (P2).

Для фитолампы настраиваются время включения и выключения

Для насосов настраиваются следующие параметры:

100s - сколько секунд качает насос воду

3d(2) - период поливания 3 дня (осталось 2 дня до следующего полива, если 0 то значит сегодня)

20h - полив будет включаться в 20:00

Есть в запасе еще 3 реле, не сложно будет добавить еще экран для настройки параметров.

Автоматический полив. Схема и скетч

Схема в формате ПДФ в норм качестве - https://disk.yandex.ru/i/qEtdoScnoX2zMQ

Сам скетч такой:

#include <Wire.h>

#include "GyverEncoder.h"

#include <microDS3231.h>

#include <GyverHTU21D.h>

#include <LiquidCrystal_I2C.h>

#include <EEPROM.h>

// ПИНЫ

#define rele1 2 // Лампа

#define rele2 3 // Насос 1

#define rele3 4 // Насос 2 (добавь провод на этот пин)

#define CLK 7

#define DT 6

#define SW 5

Encoder enc1(CLK, DT, SW);

MicroDS3231 rtc;

GyverHTU21D htu;

LiquidCrystal_I2C lcd(0x27, 16, 2);

// ПЕРЕМЕННЫЕ НАСТРОЕК

int16_t a1, a2; // Лампа: a1 - старт, a2 - стоп

int16_t b1, b2, b3; // Насос 1: b1 - сек, b2 - дни, b3 - час

int16_t c1, c2, c3; // Насос 2: c1 - сек, c2 - дни, c3 - час

// СИСТЕМНЫЕ ПЕРЕМЕННЫЕ

uint8_t w = 0; // Состояние меню (0-просмотр, 1..8 - настройка)

uint8_t mode = 0; // Экран (0-LAMP, 1-P1, 2-P2)

uint32_t startDay1, startDay2; // Дни отсчета для полива

unsigned long pumpTimer1, pumpTimer2;

bool isWatering1 = false, isWatering2 = false;

bool wateredToday1 = false, wateredToday2 = false;

void setup() {

//rtc.setTime(COMPILE_TIME);

Serial.begin(9600);

htu.begin();

enc1.setType(TYPE2);

Wire.setWireTimeout(3000, true);

pinMode(rele1, OUTPUT);

pinMode(rele2, OUTPUT);

pinMode(rele3, OUTPUT);

digitalWrite(rele1, 1);

digitalWrite(rele2, 1);

digitalWrite(rele3, 1);

lcd.init();

lcd.backlight();

// ЗАГРУЗКА ИЗ EEPROM

EEPROM.get(0, a1); EEPROM.get(2, a2);

EEPROM.get(4, b1); EEPROM.get(6, b2); EEPROM.get(8, b3); EEPROM.get(10, startDay1);

EEPROM.get(14, c1); EEPROM.get(16, c2); EEPROM.get(18, c3); EEPROM.get(20, startDay2);

}

void loop() {

enc1.tick();

static uint32_t sensT;

if (millis() - sensT >= 2000) { sensT = millis(); htu.readTick(); }

handleEncoder();

static uint32_t dispT;

if (millis() - dispT >= 300) { dispT = millis(); updateDisplay(); }

controlHardware();

}

void handleEncoder() {

if (w == 0) {

// Порядок: 0 (LAMP) -> 1 (P1) -> 2 (P2)

if (enc1.isLeft()) { mode++; if (mode > 2) mode = 0; lcd.clear(); }

if (enc1.isRight()) { if (mode == 0) mode = 2; else mode--; lcd.clear(); }

if (enc1.isClick()) {

if (mode == 0) w = 1; // Настройка Лампы

else if (mode == 1) w = 3; // Настройка P1

else if (mode == 2) w = 6; // Настройка P2

}

}

else if (w == 1) {

if (enc1.isRight()) a1--; if (enc1.isLeft()) a1++;

if (a1 > 23) a1 = 0; if (a1 < 0) a1 = 23;

if (enc1.isClick()) { EEPROM.put(0, a1); w = 2; }

}

else if (w == 2) {

if (enc1.isRight()) a2--; if (enc1.isLeft()) a2++;

if (a2 > 23) a2 = 0; if (a2 < 0) a2 = 23;

if (enc1.isClick()) { EEPROM.put(2, a2); w = 0; lcd.clear(); }

}

else if (w == 3) {

if (enc1.isRight()) b1--; if (enc1.isLeft()) b1++;

if (b1 > 300) b1 = 1; if (b1 < 1) b1 = 300;

if (enc1.isClick()) { EEPROM.put(4, b1); w = 4; }

}

else if (w == 4) {

if (enc1.isRight()) b2--; if (enc1.isLeft()) b2++;

if (b2 > 9) b2 = 1; if (b2 < 1) b2 = 9;

if (enc1.isClick()) { EEPROM.put(6, b2); w = 5; }

}

else if (w == 5) {

if (enc1.isRight()) b3--; if (enc1.isLeft()) b3++;

if (b3 > 23) b3 = 0; if (b3 < 0) b3 = 23;

if (enc1.isClick()) {

startDay1 = rtc.getUnix(3) / 86400L;

EEPROM.put(10, startDay1); EEPROM.put(8, b3); w = 0; lcd.clear();

}

}

else if (w == 6) {

if (enc1.isRight()) c1--; if (enc1.isLeft()) c1++;

if (c1 > 300) c1 = 1; if (c1 < 1) c1 = 300;

if (enc1.isClick()) { EEPROM.put(14, c1); w = 7; }

}

else if (w == 7) {

if (enc1.isRight()) c2--; if (enc1.isLeft()) c2++;

if (c2 > 9) c2 = 1; if (c2 < 1) c2 = 9;

if (enc1.isClick()) { EEPROM.put(16, c2); w = 8; }

}

else if (w == 8) {

if (enc1.isRight()) c3--; if (enc1.isLeft()) c3++;

if (c3 > 23) c3 = 0; if (c3 < 0) c3 = 23;

if (enc1.isClick()) {

startDay2 = rtc.getUnix(3) / 86400L;

EEPROM.put(20, startDay2); EEPROM.put(18, c3); w = 0; lcd.clear();

}

}

}

void updateDisplay() {

int8_t hrs = rtc.getHours();

int8_t mins = rtc.getMinutes();

bool blink = (millis() / 500) % 2;

uint32_t currentDay = rtc.getUnix(3) / 86400L;

// --- ВЕРХНЯЯ СТРОКА ---

lcd.setCursor(0, 0);

if (hrs < 10) lcd.print('0'); lcd.print(hrs);

lcd.print(blink ? " " : ":");

if (mins < 10) lcd.print('0'); lcd.print(mins);

lcd.setCursor(6, 0); lcd.print("T:"); lcd.print((int)htu.getTemperature()); lcd.write(223);

lcd.setCursor(11, 0); lcd.print(" ");

lcd.setCursor(12, 0); lcd.print("H:"); lcd.print((int)htu.getHumidity());

// --- НИЖНЯЯ СТРОКА ---

// 1. РЕЖИМ ПРОСМОТРА (Главные экраны)

if (w == 0) {

lcd.setCursor(0, 1);

if (mode == 0) { // Экран LAMP

lcd.print(F("LAMP "));

if (a1 < 10) lcd.print('0'); lcd.print(a1); lcd.print(F(":00-"));

if (a2 < 10) lcd.print('0'); lcd.print(a2); lcd.print(F(":00 "));

}

else { // Экраны P1 или P2

int s = (mode == 1) ? b1 : c1;

int d = (mode == 1) ? b2 : c2;

int h = (mode == 1) ? b3 : c3;

uint32_t sd = (mode == 1) ? startDay1 : startDay2;

int daysToWait = ((currentDay - sd) % d);

lcd.print(mode == 1 ? F("P1") : F("P2"));

lcd.setCursor(2, 1); if (s < 100) lcd.print(' '); if (s < 10) lcd.print(' '); lcd.print(s); lcd.print('s');

lcd.setCursor(7, 1); lcd.print(d); lcd.print('d');

lcd.print('('); lcd.print(daysToWait); lcd.print(')');

lcd.setCursor(13, 1); if (h < 10) lcd.print('0'); lcd.print(h); lcd.print('h');

}

}

// 2. НАСТРОЙКА ЛАМПЫ (Вернули этот блок)

else if (w == 1 || w == 2) {

lcd.setCursor(0, 1);

lcd.print(F("LAMP "));

if (w == 1 && blink) lcd.print(F(" "));

else { if (a1 < 10) lcd.print('0'); lcd.print(a1); }

lcd.print(F(":00-"));

if (w == 2 && blink) lcd.print(F(" "));

else { if (a2 < 10) lcd.print('0'); lcd.print(a2); }

lcd.print(F(":00 "));

}

// 3. НАСТРОЙКА НАСОСОВ (P1: w=3-5, P2: w=6-8)

else if (w >= 3) {

bool isP1 = (w <= 5);

int s = isP1 ? b1 : c1;

int d = isP1 ? b2 : c2;

int h = isP1 ? b3 : c3;

lcd.setCursor(0, 1);

lcd.print(isP1 ? F("P1") : F("P2"));

// Сек (Позиция 2-4)

lcd.setCursor(2, 1);

if ((w == 3 || w == 6) && blink) lcd.print(F(" "));

else {

if (s < 100) lcd.print(' ');

if (s < 10) lcd.print(' ');

lcd.print(s);

}

lcd.print('s'); // Позиция 5

lcd.setCursor(7, 1);

if ((w == 4 || w == 7) && blink) {

lcd.print(F(" ")); // Один пробел для мигания одной цифры

} else {

lcd.print(d);

}

lcd.print(F("d ")); // Позиция 8

// Час запуска (Позиция 10)

lcd.setCursor(10, 1);

if ((w == 5 || w == 8) && blink) {

lcd.print(F(" "));

} else {

if (h < 10) lcd.print('0');

lcd.print(h);

}

lcd.print(F("h ")); // Очистка конца строки

}

}

void controlHardware() {

int8_t hrs = rtc.getHours();

uint32_t currentDay = rtc.getUnix(3) / 86400L;

// ЛАМПА

if (a1 < a2) digitalWrite(rele1, (hrs >= a1 && hrs < a2) ? 0 : 1);

else digitalWrite(rele1, (hrs >= a1 || hrs < a2) ? 0 : 1);

// ПОЛИВ P1

if (hrs == b3 && ((currentDay - startDay1) % b2 == 0) && !wateredToday1) {

digitalWrite(rele2, 0); pumpTimer1 = millis(); isWatering1 = true; wateredToday1 = true;

}

if (hrs != b3) wateredToday1 = false;

if (isWatering1 && (millis() - pumpTimer1 >= (unsigned long)b1 * 1000)) {

digitalWrite(rele2, 1); isWatering1 = false;

}

// ПОЛИВ P2

if (hrs == c3 && ((currentDay - startDay2) % c2 == 0) && !wateredToday2) {

digitalWrite(rele3, 0); pumpTimer2 = millis(); isWatering2 = true; wateredToday2 = true;

}

if (hrs != c3) wateredToday2 = false;

if (isWatering2 && (millis() - pumpTimer2 >= (unsigned long)c1 * 1000)) {

digitalWrite(rele3, 1); isWatering2 = false;

}

}


Всем спасибо за внимание:)

p.s. обновил схему питание насосов было от 5 В, а они на 12В

Arduino & Pi

1.5K поста20.9K подписчиков

Правила сообщества

В нашем сообществе запрещается:

• Добавлять посты не относящиеся к тематике сообщества, либо не несущие какой-либо полезной нагрузки (флуд)

• Задавать очевидные вопросы в виде постов, не воспользовавшись перед этим поиском

• Выкладывать код прямо в посте - используйте для этого сервисы ideone.com, gist.github.com или схожие ресурсы (pastebin запрещен)

• Рассуждать на темы политики

• Нарушать установленные правила Пикабу

3
Автор поста оценил этот комментарий
Дык в схеме же ты их от 5в питаешь. Разрисуй цвета правильно. +красный- черный. Сигналы синие. 220 линии коричневые. Так хоть можно понять где низковольтка.
раскрыть ветку (1)
0
Автор поста оценил этот комментарий
Блин точно от 12В должно быть, вечером поправлю
1
NightStalker
Автор поста оценил этот комментарий
А что за насосы?
раскрыть ветку (1)
0
Автор поста оценил этот комментарий
Насос для воды, браги мембранный R385 12В
https://ozon.ru/t/QiqG21x
показать ответы

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества