// Пин, к которому подключен датчик минимального уровня питательного раствора #define LOWLEVEL 7 // Пин, к которому подключен датчик максимального уровня питательного раствора #define MAXLEVEL 6 // Пин, к которому подключен датчик уровня заполнения верхнего резервуара #define FLOODLEVEL 4 // Пин, к которому подключен светодиодный индикатор #define LEDPIN 13 // Пин, к которому подключена помпа #define PUMPPIN 12 // Пин, к которому подключен потенциометр регулировки #define POTPIN A0 // Переменные для хранения времени long previousMillis = 0; long blinkPreviousMillis = 0; unsigned long interval; // два часа = 7200000, 15 минут = 900000 // Переменные-флаги для хранения состояния работы гидрогоршка bool blinkState = 0; bool waterStart = 0; bool pumpState = 0; // Переменные для хранения состояния датчиков уровня bool lowLevelState; bool maxLevelState; bool floodLevelState; // Переменная для хранения состояния мигающего светодиода bool ledState; void setup() { // Притянем пины датчиков уровня к плюсу pinMode(LOWLEVEL, INPUT_PULLUP); pinMode(MAXLEVEL, INPUT_PULLUP); pinMode(FLOODLEVEL, INPUT_PULLUP); // Установим пины светодиода и помпы как выходы pinMode(LEDPIN, OUTPUT); pinMode(PUMPPIN, OUTPUT); // Проверим уровень раствора. Если уровень меньше минимального - зажигаем светодиодный индикатор. // Ждем срабатывания датчика максимального уровня, после этого гасим светодиод. if (digitalRead(LOWLEVEL)) { while (!digitalRead(MAXLEVEL)) { digitalWrite(LEDPIN, 1); } } digitalWrite(LEDPIN, 0); // Сохраняем текущее время для подсчета интервалов затопления. previousMillis = millis(); // Устанавливаем флаг для начала работы помпы. pumpState = 1; } void loop() { // Считываем значение потенциометра для установки следующего затопления. interval = map(analogRead(POTPIN), 0, 1023, 900000, 7200000); // Присваиваем переменным состояния датчиков уровня. // Некоторые датчики установлены "вверх ногами", поэтому значения с них нужно инвертировать. lowLevelState = !digitalRead(LOWLEVEL); maxLevelState = digitalRead(MAXLEVEL); floodLevelState = digitalRead(FLOODLEVEL); // Проверяем, настало ли время затапливать корневую систему растения. // Если настало - устанавливаем флаг затопления. if (millis() - previousMillis > interval) { waterStart = 1; } // Если необходимо затапливать корни, и уровень в резервуаре выше минимального - // включаем помпу и сбрасываем флаг затопления. if (waterStart && lowLevelState) { pumpState = 1; waterStart = 0; } // Проверяем, в каком состоянии находится флаг работы помпы. // В зависимости от этого включаем её или выключаем. if (pumpState) { digitalWrite(PUMPPIN, HIGH); } else { digitalWrite(PUMPPIN, LOW); } // Если сработал датчик уровня затопления - выключаем помпу и обновляем переменную хранения времени. // Если вдруг раствора стало слишком мало и сработал датчик минимального уровня - выключаем помпу. if (!lowLevelState || floodLevelState) { pumpState = 0; previousMillis = millis(); } // Если сработал датчик минимального уровня раствора - устанавливаем флаг мигания светодиода. if (!lowLevelState) { blinkState = 1; } // Если установлен флаг мигания светодиода - мигаем им ))) if (blinkState) { Alarm (); } // Если светодиод мигает, сигнализируя о нехватке уровня раствора, и в этот момент сработал // датчик максимального уровня - значит раствор долили и светодиод гаснет. if (blinkState && maxLevelState) { blinkState = 0; digitalWrite(LEDPIN, 0); } } // Функция мигания светодиодом void Alarm () { if (millis() - blinkPreviousMillis > 300) { blinkPreviousMillis = millis(); if (!ledState) { ledState = 1; } else { ledState = 0; } digitalWrite(LEDPIN, ledState); } }