Для клубнички Arduino+DHT11+реле.

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Идея заключается в следующем:

Необходимо создать микро климат для выращивания клубники, т.е.

1. При понижении температуры включается обогрев, а при понижении влажности включается орошитель воздуха на форсунках.

2. При повышении температуры включается охладитель воздуха, а при повышении влажности канальный вентилятор.

Имеется: arduino, датчик влажности и температуры DHT11, 8-и релейный модуль.

 Так как для выращивания клубники все параметры: влажность (70-80%) и температура (20-25°С) известны, то и регулировать эти параметры не будем, а просто зададим их в программе.

#include <DHT.h> // Подключаем библиотеку для работы с датчиком 

#define DHTPIN 12 // Считывающий пин с датчика 
#define DHTTYPE DHT11 // Модель датчика 
#define tPIN 4 // Пин управления температурой 
//#define t2PIN 5 // Пин управления температурой
#define hPIN 6 // Пин управления влажностью 
//#define h2PIN 7 // Пин управления влажностью

DHT dht(DHTPIN, DHTTYPE); // Создаем объект dht 

int tStatus = HIGH; // определяем переменную, отвечающую за состоянеие нагревателя HIGH=выкл, LOW=вкл 
int temp = 30; // Желаемая температура в градусах Цельсия (изменить на нужную) 
int hStatus = HIGH; // определяем переменную, отвечающую за состоянеие увлажнителя HIGH=выкл, LOW=вкл 
int hum = 45; // Желаемая влажность (изменить на нужную) 

void setup()  
{ 
  Serial.begin(9600); // Инициализируем COM-порт 
  dht.begin(); // Инициализируем датчик 
  
  pinMode(tPIN, OUTPUT); // Определяем пин для управления температурой как Вывод 
  digitalWrite(tPIN, tStatus); // Притягиваем пин к начальному статусу (Выкл) 
  
  pinMode(hPIN, OUTPUT); // Определяем пин для управления температурой как Вывод 
  digitalWrite(hPIN, tStatus); // Притягиваем пин к начальному статусу (Выкл) 
} 

void loop()
{ 
  int h = dht.readHumidity(); // Считываем влажность 
  int t = dht.readTemperature(); // Считываем температуру 
  tStatus = (t < temp) ? LOW:HIGH; // Если температура меньше желаемой, то статус обогревателя=Вкл, в противном случае Выкл 
  digitalWrite(tPIN, tStatus); 
  //hStatus (h < hum) hStatus ? LOW:HIGH;
  if (h < hum) hStatus = LOW; else hStatus = HIGH; // Если влажность меньше желаемой, то статус увлажнителя=Вкл, в противном случае Выкл 
  digitalWrite(hPIN, hStatus); 
  delay(1000); // Задержка в 1 секунду 
  Serial.print("t="); 
  Serial.print(t); 
  Serial.print(" h%="); 
  Serial.println(h); // Отправляем информацю о климате на COM-порт 
} 

Уважаемые гуру, подскажите пожалуйста по пункту №2. Никак не могу разобраться.

Хочу довести проект до логического конца, и опубликовать с фото-отчетом.

 

bwn
Offline
Зарегистрирован: 25.08.2014

А что вас в этом пункте смущает?

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Не могу разобратся как задействовать еще два реле на повышение темпиратуры и влажности.

 

Можно ли эти пораметры в две строчки исполнить (не принципиально)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

дык, создайте граф состояния вашей системы и условия перехода из одного состояния в другое - из этого всё станет ясно.... ну, типа - когда чо делать :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

При повышении температуры включается охладитель воздуха

чо за охладитель ? 

bwn
Offline
Зарегистрирован: 25.08.2014

SU-27-16 пишет:

дык, создайте граф состояния вашей системы и условия перехода из одного состояния в другое - из этого всё станет ясно.... ну, типа - когда чо делать :)

Задействовать как и предыдущие, только с другими условиями.

Это ко 2 посту

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16, охладитель воздуха - в отдельную комнату (аккумулятор) поступает воздух с улицы (теплый - холодный). Если холодный, то через обагреватель, если теплый то через радиатор (автомобильный) по которому самотеком идет в ванную комнату холодная вода. (вся система в подвале). Если интересно могу набросать схему (план) сооружения.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Задействовать как и предыдущие, только с другими условиями.

задействуйте как и предыдущие, только с другими условиями ! 

тока Ифами резведите по нормальному, по понятиям.... :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

aleks3905 пишет:

SU-27-16, охладитель воздуха - в отдельную комнату (аккумулятор) поступает воздух с улицы (теплый - холодный). Если холодный, то через обагреватель, если теплый то через радиатор (автомобильный) по которому самотеком идет в ванную комнату холодная вода. (вся система в подвале). Если интересно могу набросать схему (план) сооружения.

вообще нормально это - схема, код, пояснения

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

aleks3905 пишет:

SU-27-16, охладитель воздуха - в отдельную комнату (аккумулятор) поступает воздух с улицы (теплый - холодный). Если холодный, то через обагреватель, если теплый то через радиатор (автомобильный) по которому самотеком идет в ванную комнату холодная вода. (вся система в подвале). Если интересно могу набросать схему (план) сооружения.

по этой схеме - неопрадованный расход воды будет !

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

При темпиратуре 19 градусов включается вентилятор с обагревателем и выключается при t 23 , при темпиратуре 25 включается вентилятор охладителя и выключается при t 23 . 

При влажности воздуха меньше 70% включаются форсунки на 1 сек. до тех пор пока влажность не достигнет 70 - 80%, если влажность более 85% то включается дополнительная вытяжка.  

Как то так.

 

Схему с пояснениями счас сделаю, код в первом посте.

Воды много уходить не будет. Форсунки использую десперсные (туманом экономично распыляют (самодельные) )

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

охладитель воздуха - в отдельную комнату (аккумулятор) поступает воздух с улицы (теплый - холодный). Если холодный, то через обагреватель, если теплый то через радиатор (автомобильный) по которому самотеком идет в ванную комнату холодная вода.

ток воды - постоянный, или я не так понял ? 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

из #10 - у вас два канала = греть/неГреть , увлажнять/неУвлажнять ? так ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

При влажности воздуха меньше 70% включаются форсунки на 1 сек. до тех пор пока влажность не достигнет 70 - 80%, если влажность более 85% то включается дополнительная вытяжка.  

не до тех пор "сразу".... а с задержкой анализа на 3......5 мин - иначе будет тропический дождь :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

состояние влажности и температуры определённого объёма воздуха невозможно изменить за 1....4 сек !

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16 пишет:

При влажности воздуха меньше 70% включаются форсунки на 1 сек. до тех пор пока влажность не достигнет 70 - 80%, если влажность более 85% то включается дополнительная вытяжка.  

не до тех пор "сразу".... а с задержкой анализа на 3......5 мин - иначе будет тропический дождь :(

Этот пораметр необходимо подбирать имперически.

А можно фарсунки включать на 15 - 30 мс потом пауза в 1 минуту до достижения необходимого результата.

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16 пишет:

охладитель воздуха - в отдельную комнату (аккумулятор) поступает воздух с улицы (теплый - холодный). Если холодный, то через обагреватель, если теплый то через радиатор (автомобильный) по которому самотеком идет в ванную комнату холодная вода.

ток воды - постоянный, или я не так понял ? 

Ток воды - как получится. Все равно охлаждение будет в нужном диапозоне. 

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16 пишет:

из #10 - у вас два канала = греть/неГреть , увлажнять/неУвлажнять ? так ?

Да так.

должно работать четыре реле а сейчас два (не могу разобратся прошу помощи). У меня в скече закоментирована 6 и 8 строка.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

строка #33 -  условие и действие......

в строке #42A -  пропишите новое/другое условие и действие......

.....и т.д., и т.п.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

зачем охладитель ? если не нагревать экстремально то и охлаждать не нано будет.....

.....если у вас летом +47 то охладить можно вытяжкой и установкой определённой влажности

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

у вас в лупе Т измеряется и регулируется раз в секунду......

- уходите от delay();

- переходите к millis();

........дальше всё решится по логике :)

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Спасибо, буду пробовать!

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

иииииииии разбейте задачу на 4 подзадачи..... и решайте их по очереди ПО ВРЕМЕНИ ( в масштабах миллисекунд ) 

.........будет время - накидаю код :) НО !!!!!!!!!!!!!!! 2 первых ягодки - мне ! :)-

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16 пишет:

иииииииии разбейте задачу на 4 подзадачи..... и решайте их по очереди ПО ВРЕМЕНИ ( в масштабах миллисекунд ) 

.........будет время - накидаю код :) НО !!!!!!!!!!!!!!! 2 первых ягодки - мне ! :)-

Даговорились!!!

bwn
Offline
Зарегистрирован: 25.08.2014

SU-27-16 пишет:

Задействовать как и предыдущие, только с другими условиями.

задействуйте как и предыдущие, только с другими условиями ! 

тока Ифами резведите по нормальному, по понятиям.... :)

Не получится в данном варианте по понятиям развести. Малость я чертежи попутал. Лекарство:

Уберите свои tStatus и hStatus из управления реле. Управляйте реле напрямую HIGH, LOW. Тогда простейший код уложится в 4-ре if-а. Не забудте задать значения срабатывания.

Далее вдумчиво изучаем пример: http://arduino.ru/tutorials/BlinkWithoutDelay

это основа всех ваших задержек по времени для анализа и действий. Научившись с ним работать, берем листок бумаги и рисуем себе алгоритм по каждой задаче: 1. Померить влажность 2.Если ниже-включить форсунку на 0,1сек. 3.Запомнить время отработки. 4. Ничего не делаем 5минут. 5. Пройти на п.1   2.1 Если влажность выше - ушли на п.3 и далее. Аналогично по остальным 3-м.

Чтобы не разводить бардак в основном цикле вычленяем самодостаточные задачи и оформляем их отдельными функциями. Сейчас их у вас 5 - 1.Замер влажности температуры. 2.Температура высокая 3.Температура низкая 4.Влажность высокая 5.Влажность низкая.

В итоге ваш loop превратится во что то типа этого.

void loop()
{
  tempHum();
  if(t>temp) tempHigh();
  ..... tempLow();
  ..... humHigh();
  ..... humLow();
}

А в каждой функции уже обрабатываете задержки, исполнение и прочии фантазии. В итоге, если появилось желание что то изменить или добавить, вам уже не придется продиратся через дебри сплошного кода, а достаточно модифицировать функцию или добавить новую.

Функция для примера будет выглядеть так:

void tempHum()
{ 
  h = dht.readHumidity(); // Считываем влажность 
  t = dht.readTemperature(); // Считываем температуру 
} 

Переменные h и t объявляем как глобальные. Также задайте вторые пределы  влажности и температуры,  для получения гистерезиса, иначе будете постоянно греть-охлаждать.

Эк меня на эпистоляр пробило)))

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

bwn , вектор приблизительно вижу. Буду мозгавать. Спасибо.  

bwn
Offline
Зарегистрирован: 25.08.2014

aleks3905 пишет:

bwn , вектор приблизительно вижу. Буду мозгавать. Спасибо.  

Не на чем, в принципе для вашей сегодняшней задачи, все что писал по функциям не нужно (у вас и так 20 строчек получится). Но лучше привыкать сразу.

bwn
Offline
Зарегистрирован: 25.08.2014

Я бы кстати добавил еще перемешивающий вентилятор (забор сверху - выход снизу) усредните температуру и влажность по объему + на отоплении сэкономите.

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

bwn пишет:

Я бы кстати добавил еще перемешивающий вентилятор (забор сверху - выход снизу) усредните температуру и влажность по объему + на отоплении сэкономите.

Это лишнее, размер (конденцатора) камнаты 1.5 на 1.5 метра, и самой комнаты для клубники 2 на 1.5 метра. 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
#include <DHT.h>
#define DHTPIN 12
#define DHTTYPE DHT11
#define relayTup 4         // греть
#define relayTdown 5       // охлаждать
#define relayHup 6         // увлажнять
#define relayFan 7         // вытяжка
DHT dht(DHTPIN, DHTTYPE);
const int setTemp = 30;         // Желаемая температура в градусах Цельсия (изменить на нужную) 
const int setHum = 80;          // Желаемая влажность (изменить на нужную) 
int realT;
int realH;
unsigned long oldMillis;
//=================================================================================
void setup()  
{ 
  Serial.begin(9600);
  dht.begin();
  pinMode(relayTup,OUTPUT);
  digitalWrite(relayTup,HIGH);
  pinMode(relayTdown,OUTPUT);
  digitalWrite(relayTdown,HIGH);
  pinMode(relayHup, OUTPUT);
  digitalWrite(relayHup,HIGH);
  pinMode(relayFan, OUTPUT);
  digitalWrite(relayFan,HIGH);
  oldMillis=millis();
} 
//=================================================================================
void loop()
{
  if((millis()-oldMillis)>60000)
  {
    realT = dht.readHumidity();
    realH = dht.readTemperature();

    Serial.print(" T = "); Serial.print(realT); Serial.print("    H = "); Serial.println(realH);
  
    if(realT<(setTemp-2)) digitalWrite(relayTup,LOW); else digitalWrite(relayTup,HIGH);       // греть-неГреть
    if(realT>(setTemp+1)) digitalWrite(relayTdown,LOW); else digitalWrite(relayTdown,HIGH);   // охлаждать-неОхлаждать
    if(realH<(setHum-5))
    {
      digitalWrite(relayHup,LOW);
      delay(50);                         // 50 mS - распыление тумана
      digitalWrite(relayHup,HIGH);
    }
    if(realH>(setHum+5)) digitalWrite(relayFan,LOW); else digitalWrite(relayFan,HIGH);        // продувать- неПродувать
    
    oldMillis=millis();
  }
}
//=================================================================================

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

раз в минуту снятие данных с датчика и выполнение действий в ифах

цыферки в строках 9, 10, 32, 39, 40, 41, 44, 47 - подпором по практике/интуиции :)

код не боевой - так.... для чтобы вам посмотреть про миллис() :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

aleks3905 пишет:

bwn пишет:

Я бы кстати добавил еще перемешивающий вентилятор (забор сверху - выход снизу) усредните температуру и влажность по объему + на отоплении сэкономите.

Это лишнее, размер (конденцатора) камнаты 1.5 на 1.5 метра, и самой комнаты для клубники 2 на 1.5 метра. 

ну и здря ! :(

вверху будет мокрее и теплее, внизу - наоборот..... как в бане.....

 

свет....

клубнике не надо знать что день или ночь ? или ей всё время форсажный ДЕНЬ в приказном порядке ?

bwn
Offline
Зарегистрирован: 25.08.2014

У ТС еще четыре релая в запасе, не пугай так сразу. Будет еще и RTC и кнопки и меню, аппетит он во время еды обычно приходит)))

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

:) ещё и тензодатчики.... чтобы вести статистику - заколосились удои или ещё нет :)

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

bwn пишет:

У ТС еще четыре релая в запасе, не пугай так сразу. Будет еще и RTC и кнопки и меню, аппетит он во время еды обычно приходит)))

100% так!

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Разрешите встрять? Дело в том, что температура и влажность воздуха очень сильно взаимосвязаны. Это я как птицевод с инкубаторами говорю. Увлажнение, а особенно увлажнение разбрызгиванием воды, очень здорово охлаждает воздух. В жару может на 10 градусов рубануть. Влажность воздуха относительную принять измерять. Относительная влажность, это то количество воды, которое может уместить воздух при данной температуре. Так вот, холодный воздух вмещает мало жидкости, а теплый гораздо больше. То есть относительная влажность без температуры не измеряется и полностью от нее зависит. Впустили мы в холодное время холодный воздух в камеру, подогрели и уменьшили его относительную влажность вдвое. Увлажнили и потеряли температуру, при охлаждении воздуха влага в него уже не вмещается и получаем конденсат на всех холодных поверхностях. Для охлаждаемого воздуха влажность будет к 100% стремиться, даже если в теплом она была не высокой. А Ардуина опять обогрев влупит. И влажность опять вниз поползет. Не так всё просто, как нам кажется.

Дальше, зачем греть воздух если на улице тепло? Зачем охлаждать, если прохладно снаружи? Нужен контроль температуры (а лучше и влажности) за бортом. Если снаружи зима, а мы нагрели воздух до верхнего порога температуры, то нужно просто выключить подогрев и ждать, пока температура не опустится к нижнему порогу. Потом опять подогреть. После нагрева увлажнить, выждать время пока устаканится. Потом повторить воздействие и так далее. Воздух он быстро прогревается, если  массивные предметы внутри теплые. Плотность у воздуха низкая, а ИК лучи так вообще его не греют напрямую. И охладитель вообще не нужен скорее всего, хватит тумана. Так в теплицах промышленных в Израиле и Турции урожай спасают от перегрева. А климат там потеплее будет. Да и температра почвы имхо важнее температуры воздуха. Можно и лучше почву прогревать до нужной температуры, а воздух сам быстро нагреется. А высокая влажность легко проветриванием убирается.

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

SU-27-16 пишет:

:) ещё и тензодатчики.... чтобы вести статистику - заколосились удои или ещё нет :)

За урожаем смотреть будут IP видеокамеры.

По освещению: клубника в стадии рассады будет на свету 19 часов, а в вегитотивной стадии 16-17. Для обеспечения этих режимов использую электронный таймер "Robiton el-02", а светить будут светодиоды разных спектров.

 

Спасибо за код. Сейчас буду тестировать!!!

 

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Umka, все так, для этого программа и должна настраиватся имперически. А землю точно, нужно контролировать и влиять на темпиратуру.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Топикстартер, у меня есть для Вас готовый код с хорошими и интересными возможностями. Я его писал для управления климатом в помещении с перепелками. Система состоит из 2 блоков, внешний включает датчик освещенности, термометр, пару светодиодов для сигнализации и пьезо-сирену. Внутри мозги и все остальное. Датчик влажности, датчик качества воздуха, датчик уровня воды в емкости (автомобильный из бака), часы, сетевая карта 28J60 (какая была) для показа текущего состояния на простенькой web-страничке. При желании проект можно хорошо развить, поставить туда Мегу, православные цифровые датчики, хорошую сетевуху и слать статистику на облачный сервис, плюс рулить оттуда режимами. Кто хочет - допиливайте. Код написан, но еще не внедрен, могут быть баги.

Не благодарите! :)

/*Сиситема климатической автоматики для птичника.
 (с) Um-ka GPL_V2
 http://www.perepel.com/forum/viewtopic.php?f=36&t=3838
 
 */


//подключаем библиотеки
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM2.h>
#include <SimpleTimer.h>
#include "RTClib.h"
#include "etherShield.h"
#include "ETHER_28J60.h"


//объявляем пины
#define heater_pin 9                  // нагреватель
#define fan_pin 8                     // вентилятор
#define lamp_Pin 7                    //пин освещения
#define ledG_pin 10                    //пин зеленого светодиода
#define dht_pin 5                     //DHT22
#define ledR_pin 11                    //красный светодиод
#define horn_pin 12                    //сирена в наружном блоке
#define setSampleTime 1000            //время цикла ПИД
#define vsensor_pin 6                 //вход А6 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В.
#define lsensor_pin 1                 //вход А1 детектор уровня освещенности.
#define buttonRead_pin 7              //пин чтения кнопок
#define gsensor_pin 2                 //аналоговый вход детектора качества воздуха
#define wsensor_pin 3                 //аналоговый вход датчика уровня воды
#define tempOut_pin 0                 //аналоговый вход наружного термометра
#define T_correction -0.4             // коррекция температуры SHT10
#define humGasHiseresis 10            // при каком снижении влажности или загазованности выключаем вентиляцию
#define FanTempHisteresis 5           // при каком снижении температуры вентиляцию отключаем 
#define lightThreshold 40             // порог освещенности для включения досветки
//объявляем переменные
boolean button_minus = 0;              // переменная для хранения состояния кнопки "минус"
boolean button_plus = 0;               // переменная для хранения состояния кнопки "плюс"
boolean button_enter = 0;              // переменная для хранения состояния кнопки "enter"
int temperature = 0;                   // переменная температуры внутри 
int histeresis = 2;                    // гистерезис включения обогрева
int tempOut = 0;                       // переменная температуры на улице 
int humidity = 0;                      // переменная влажности
int lightlevel = 0;                    // переменная освещенности
int gaslevel = 0;                      // переменная качества газа
int waterlevel =0;                     // переменная уровня воды в баке
int del = 80;                          // переменная ожидания между выборами меню
unsigned int interval = 100;           // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)

static uint8_t mac[6] = {
  0x54, 0x55, 0x58, 0x10, 0x00, 0x24};  
static uint8_t ip[4] = {
  192, 168, 0, 55};                       
static uint16_t port = 80;                                      

LiquidCrystal_I2C lcd(0x27, 20, 4);    //инициализация библиотек
RTC_DS1307 RTC;
DHT dht;
SimpleTimer timer;
ETHER_28J60 e; 

void setup() {
  Serial.begin(9600);
  Serial.println("Henhouse v0.1_2015");
  analogReference(INTERNAL);           //для повышения точности делаем опорное Напр. 1.1В
  dht.setup(dht_pin);                  // старт DHT
  Wire.begin();                        // старт I2C
  RTC.begin();                         // Старт часов
  lcd.init();                          // Старт дисплея
  lcd.backlight();                     // Включаем подсветку дисплея
  //RTC.adjust(DateTime(__DATE__, __TIME__));   //раскоментируйте для установки системмных даты и времени
  timer.setInterval(6000, getSensors); // Каждую минуту опрашиваем датчики.
  e.setup(mac, ip, port);
  pinMode(heater_pin, OUTPUT);
  pinMode(fan_pin, OUTPUT);
  pinMode(lamp_Pin, OUTPUT);
  pinMode(horn_pin, OUTPUT);
  pinMode(ledR_pin, OUTPUT);
}


void loop() {
  if (! RTC.isrunning()) {                      //Если часы остановились,
    //Serial.println("RTC stopped!!!"); //то пишем в сериал ошибку.
  }

  timer.run();

  // опрашиваем кнопки
  button_read(); //читаем кнопки
  if (button_enter) { //если нажата кнопка enter, переходим в меню
    delay(del);
    lcd.clear();
    menu();
  }
  if (button_minus) {           // если нажата минус на основном экнане, то настраиваем дату-время
    delay(del);                 
    dataTime_setup();
  }
  if (button_plus) {            // если нажата конпка "плюс", то ...
    delay(del);
    lcd.clear();
    //startLight();
  }

  // выводим данные на web-страничку
  ethernet();

  // печатаем на дисплей данные
  printlcd();

  // выводим индикацию на внешний блок
  indication();

  // управляем обогревом
  heater();

  // управляем вентиляцией
  fanCompute();

  // управляем светом
  startLight();

  // КОНЕЦ ГЛАВНОГО ЦИКЛА ПРОГРАММЫ
}


//функция проверки нажатия кнопки
void button_read(){
  int x; 
  x = analogRead (buttonRead_pin); 
  if (x < 60){
    button_minus = 1; //запоминаем значение кнопки
    return;
  }
  else if (x < 200){
    button_plus = 1; //запоминаем значение кнопки
    return;
  }
  else if (x < 400){ 
    button_enter = 1; //запоминаем значение кнопки
    return;
    //if (button_minus || button_plus || button_enter) beeper(50);
  }
  else {  // если ни одно условие не сработало, то значения кнопок обнуляем.
    button_minus = 0;
    button_plus = 0;
    button_enter = 0;
  }
}


// функция меню
void menu() {
  temp_setup();
  hum_setup ();
  gas_setup();
  //  TimeVentMin_setup();
  //  TimeVentMax_setup();
  //  MinTempAlarm_setup();
  //  MaxTempAlarm_setup();

}

// функция опроса датчиков
void getSensors(){
  delay(dht.getMinimumSamplingPeriod()); 
  humidity = dht.getHumidity();
  temperature = dht.getTemperature(); 
  lightlevel = analogRead(lsensor_pin);
  lightlevel = map(lightlevel, 0, 1023, 0, 99);
  gaslevel = analogRead(gsensor_pin);
  gaslevel = map(gaslevel, 0, 1023, 0, 99);
  waterlevel = analogRead(wsensor_pin);
  waterlevel = map(waterlevel, 0, 1023, 0, 99);
  tempOut = analogReadOversampled(tempOut_pin);
  Serial.println(temperature);
}


// функция обогревателя
void heater(){
  int setTemp = 22;
  EEPROM_read(1, setTemp);              // читаем из памяти заданную температуру
  if (temperature > setTemp){           // Если измеренная температура в помещении выше заданной
    digitalWrite (heater_pin, LOW);     // то обогрев отключаем
    lcd.setCursor(0, 3);
    lcd.print("H-OFF");                 // пишем на экран сообщение
  }
  if (temperature < (setTemp-histeresis)){ 
    digitalWrite (heater_pin, HIGH);
    lcd.setCursor(0, 3);
    lcd.print("H-ON ");
  }
}


// функция управления вентиляцией
void fanCompute(){
  int difference;        // разность внутренней и наружной температуры.
  int duration;          // вычисленная подходящая длительность вентиляции.
  int setTemp;            // заданная в меню темпертура в помещении
  int setHum;            // заданная в меню пороговая влажность
  int setGas;            // заданная в меню пороговая концентрация загазованности
  long startFanTime;     // время старта вентиляции в юникс-формате
  difference = constrain((temperature - tempOut), -10, 40); // вычисляем разницу температур и умещаем их в диапазон -10 - 40 град.
  duration = map(difference, -10, 40, 20, 1);  // вычисляем длительность вентиляции от 20 до 1 минуты
  EEPROM_read(1, setTemp);
  EEPROM_read(2, setHum);
  EEPROM_read(3, setGas);
  DateTime now = RTC.now();  
  if ((now.hour()==10 && now.minute()==0 && now.second()==1) || (now.hour()==20 && now.minute()==0 && now.second()==1)){ // безусловное включение вентиляции
    digitalWrite(fan_pin, HIGH);         // по часам. в 10:00 и 20:00 на оптимальное время.
    startFanTime = now.unixtime();
  }
  if (digitalRead(fan_pin) == HIGH && startFanTime > (now.unixtime() + duration)) digitalWrite(fan_pin, LOW); 

  if ((humidity > setHum) || ((gaslevel) > setGas)) digitalWrite(fan_pin, HIGH); // если превышен порог влажности или загазованности, то включаем вентиляцию.

  if (digitalRead(fan_pin) == HIGH){    // если включена вентиляция
    if ((humidity > setHum-humGasHiseresis) || ((gaslevel) > setGas-humGasHiseresis) || (temperature < setTemp - FanTempHisteresis)) digitalWrite(fan_pin, LOW);
    // если влажность или загазованость снижена на 10% или температура упала на 5 градусов, то вентиляцию выключаем.
  }
}


// функция внешней индикации
void indication(){
  if (temperature<15 || temperature>30 || humidity<40 || gaslevel>30 || waterlevel<15) digitalWrite(ledR_pin, HIGH);
  else digitalWrite(ledR_pin, LOW);
  if (temperature<10 || temperature>35 || gaslevel>50) digitalWrite(horn_pin, HIGH);
  else digitalWrite(horn_pin, LOW);
  digitalWrite(ledG_pin, !digitalRead(ledG_pin));
}


// функция печати на дислей
void printlcd(){
  DateTime now = RTC.now();  
  lcd.setCursor(8, 0);                              // печатаем время.
  if (now.hour() < 10) lcd.print(" ");
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  if (now.minute() < 10)lcd.print(0);
  lcd.print(now.minute(), DEC);
  lcd.setCursor(0, 1);                              // печатаем температуру в помещении
  lcd.print("T.in=");
  lcd.print(temperature);
  lcd.setCursor(8, 1);                              // печатаем температуру на улице
  lcd.print("T.ou=");
  lcd.print(tempOut);
  lcd.setCursor(16, 1);                              // печатаем разницу температур
  lcd.print("*");
  lcd.print(temperature-tempOut);
  lcd.setCursor(0, 2);                              // печатаем влажность
  lcd.print("Hum=");
  lcd.print(humidity);
  lcd.print("%");
  lcd.setCursor(8, 2);                              // печатаем загазованность
  lcd.print("Gaz=");
  lcd.print(gaslevel);
  lcd.print("%");
  lcd.setCursor(8, 2);                              // печатаем освещенность на улице
  lcd.print("Lig=");
  lcd.print(lightlevel);
  lcd.print("%");

}

// функция web-странички
void ethernet(){
  if (e.serviceRequest())                               	// Если есть запрос клиента
  {
    e.print("<H2>Henhouse 1.0</H2><br/><table border=\"1\">"); // Создаём текст ответа - табличку
    e.print("<tr><th>Parameter</th><th>Value</th></tr>");
    e.print("<tr><td>TempIn</td><td>"); 
    e.print(temperature); 
    e.print("<tr><td>TempOut</td><td>"); 
    e.print(tempOut); 
    e.print("</td></tr>");
    e.print("<tr><td>Humidity</td><td>"); 
    e.print(humidity); 
    e.print("</td></tr>");
    e.print("<tr><td>Water-level</td><td>"); 
    e.print(waterlevel); 
    e.print("</td></tr>");
    e.print("<tr><td>Gas-level</td><td>"); 
    e.print(gaslevel); 
    e.print("</td></tr>");
    e.print("</table>");
    // данные о включенном обогреве печатаются в функции heater()
    e.respond();  		// отправляем табличку клиенту
  }
}

// функция усреднений аналоговых значений
unsigned int analogReadOversampled(byte analogChannel)  {  //алгоритм усреднения показаний термометров
  unsigned int aSum = 0;   // сумма аналоговых выборок
  for (byte i = 0; i < 16; i++)
    aSum += (analogRead(analogChannel) / 9.31); // Суммируем 16 выборок температуры
  return aSum >> 4;   // сдвигаем вправо на 4 что равно делению на 16 без остатка
}

// функция установки температуры
void temp_setup(){
  int setTemp;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(4, 0);
  lcd.print("TEMP SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(1, setTemp);

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (button_minus) {
      EEPROM_write(1, setTemp + 1);
      if (setTemp > 30) {     //проверяем, если выше 40,
        EEPROM_write(1, 30);  //пишем в память 40
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(1, setTemp - 1);
      if (setTemp < 0) {     //проверяем, если выше 40,
        EEPROM_write(1, 0);  //пишем в память 40
      }
      lcd.clear();
    }
    EEPROM_read(1, setTemp);
    lcd.setCursor(2, 0);
    lcd.print("TEMP = ");
    lcd.print(setTemp);
    lcd.setCursor(0, 3);
    lcd.print("minus  NEXT  plus");
    delay(del);
  }
}


// функция установки порога влажности
void hum_setup(){
  int setHum;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(2, 0);
  lcd.print("HUMIDITY SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(2, setHum);

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (button_minus) {
      EEPROM_write(2, setHum + 1);
      if (setHum > 90) {     //проверяем, если выше 40,
        EEPROM_write(2, 90);  //пишем в память 40
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(2, setHum - 1);
      if (setHum < 30) {     //проверяем, если выше 40,
        EEPROM_write(2, 30);  //пишем в память 40
      }
      lcd.clear();
    }
    EEPROM_read(2, setHum);
    lcd.setCursor(2, 0);
    lcd.print("HUM = ");
    lcd.print(setHum);
    lcd.setCursor(0, 3);
    lcd.print("minus  NEXT  plus");
    delay(del);
  }

}

// функция установки порога загазованности 
void gas_setup(){
  int setGas;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(2, 0);
  lcd.print("GAS.CONT. SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(3, setGas);

    if (button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (button_minus) {
      EEPROM_write(3, setGas + 1);
      if (setGas > 90) {     //проверяем, если выше 40,
        EEPROM_write(3, 90);  //пишем в память 40
      }
      lcd.clear();
    }

    if (button_plus) {
      EEPROM_write(3, setGas - 1);
      if (setGas < 0) {     //проверяем, если выше 40,
        EEPROM_write(3, 0);  //пишем в память 40
      }
      lcd.clear();
    }
    EEPROM_read(3, setGas);
    lcd.setCursor(2, 0);
    lcd.print("GAS = ");
    lcd.print(setGas);
    lcd.setCursor(0, 3);
    lcd.print("minus  NEXT  plus");
    delay(del);
  }
}

// функция освещения
void startLight(){
  DateTime now = RTC.now();
  getSensors();
  if (lightlevel < lightThreshold && now.hour() < 23) digitalWrite(lamp_Pin, HIGH);
  if (lightlevel < lightThreshold && now.hour() > 7) digitalWrite(lamp_Pin, HIGH);
  else (digitalWrite (lamp_Pin, LOW));
}


// функция пищалки
//void beeper(int duration) {
//  tone(beeper_pin, 2000, duration);
//}


// функция установки часов
void dataTime_setup(){
  clock_setup();
  date_setup();
  year_setup();
}


void clock_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("CLOCK SETUP");
    lcd.setCursor(8, 1);
    if (now.hour() < 10) lcd.print(" ");
    lcd.print(now.hour(), DEC);
    lcd.print(":");
    if (now.minute() < 10)lcd.print(0);
    lcd.print(now.minute(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("Min+1  NEXT  Hour+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      if(now.minute() < 59) RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, 0));
      else RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), 0, 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      if(now.hour() < 23) RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), now.month(), now.day(), 0, now.minute(), 0));
      lcd.clear();
    }
    delay(del);
  }
}

void year_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("YEAR SETUP");
    lcd.setCursor(8, 1);
    lcd.print(now.year(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("YEAR-1  NEXT  YEAR+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      RTC.adjust(DateTime(now.year()-1, now.month(), now.day(), now.hour(), now.minute(), 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      RTC.adjust(DateTime(now.year()+1, now.month(), now.day(), now.hour(), now.minute(), 0));

      lcd.clear();
    }
    delay(del);
  }
}

void date_setup() {
  delay(del);
  lcd.clear();
  //delay (1000);
  //lcd.clear();
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      lcd.clear();
      break;
    }

    DateTime now = RTC.now();  //получам текущее время из часов
    button_read();
    lcd.setCursor(6, 0);
    lcd.print("DATE SETUP");
    lcd.setCursor(8, 1);
    if (now.day() < 10) lcd.print("0");
    lcd.print(now.day(), DEC);
    lcd.print(":");
    if (now.month() < 10)lcd.print(0);
    lcd.print(now.month(), DEC);
    lcd.setCursor(0, 2);
    lcd.print("____________________");
    lcd.setCursor(0, 3);
    lcd.print("DAY+1  NEXT  MON+1");

    if (button_enter) {  //если Ентер, то выходим
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }

    if (button_minus) {  //если Минус, то убавляем мощность на 5%
      delay(del);
      if(now.day() < 31) RTC.adjust(DateTime(now.year(), now.month(), now.day()+1, now.hour(), now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), now.month(), 0, now.hour(), now.minute(), 0));
      lcd.clear();
    }

    if (button_plus) {
      delay(del);
      if(now.month() < 12) RTC.adjust(DateTime(now.year(), now.month()+1, now.day(), now.hour(), now.minute(), 0));
      else RTC.adjust(DateTime(now.year(), 1, now.day(), now.hour(), now.minute(), 0));
      lcd.clear();
    }
    delay(del);
  }
}




 

bwn
Offline
Зарегистрирован: 25.08.2014

aleks3905 пишет:

SU-27-16 пишет:

:) ещё и тензодатчики.... чтобы вести статистику - заколосились удои или ещё нет :)

За урожаем смотреть будут IP видеокамеры.

По освещению: клубника в стадии рассады будет на свету 19 часов, а в вегитотивной стадии 16-17. Для обеспечения этих режимов использую электронный таймер "Robiton el-02", а светить будут светодиоды разных спектров.

 

Спасибо за код. Сейчас буду тестировать!!!

 

Ну а для этого дуина сама так и просится. Umka кстати все правильно пишет, неплохой способ избавится от охладителя.

bwn
Offline
Зарегистрирован: 25.08.2014

Umka, Надеюсь ТС не обидится за оффтоп, какой сенсор использовали для оценки качества воздуха? Я хочу поставить MQ-135, но смущает пыль (ее сами знаете вдоволь), есть опыт работы с подобным?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Он самый. Хороший сенсор, не смотря на смешную цену. Он с колпачком от пыли, но я что-нибудь этакое расковыряю. 

От комбикорма в помещении жуткое количество пыли всегда. То же самое и DHT22 касается.

bwn
Offline
Зарегистрирован: 25.08.2014

Благодарю за ответ и за идею)))

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Umka, Спосибо за код :). 

bwn, Со временем система будет дополнятся и модернизироватся. Хочу перевести всю нагрузку управлением системой на arduino uno, а если мощности будет не хватать, то задействую arduino mega. Планов по поводу проекта очень много, но хотелось по быстрей запустить выращивание (дети уже "завтраками" сыты). И постепенно, методом проб и ошибок довести всё до идеала.

Спасибо всем за участие и помощь! Как и обещал буду вести проект до "конца" с полным описанием и отчетом.

Сейчас накопилось достаточно информации для анализа и эксперементов, буду обрабатывать.

P.S. Всё только начинается!

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Уважаемый Umka, не могли бы Вы скинуть библиотеки используемые Вами?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Весь проект в облаках. 

https://drive.google.com/open?id=0B0vRuSZ7oRUeWWtBV2J0OG0yWG8&authuser=0

 

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

Спасибо бальшое. Ушел с головой :)

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Только учтите, что код на работоспособность не проверялся еще. Руки не дошли. Если поможете ошибки выловить, буду весьма признателен. А я сейчас платы к нему рисую.

123ksn
Offline
Зарегистрирован: 24.11.2014

Когда встанет задача измерять уровень воды в баке рекомендую схему http://radiokot.ru/forum/viewtopic.php?f=3&t=108460

А по клубнике рекомендую посмотреть информацию "Солнечный вегетарий А.В. Иванова". Одна ссылка для затравки http://insoltm.blogspot.com/2011/08/blog-post_5950.html

aleks3905
aleks3905 аватар
Offline
Зарегистрирован: 18.02.2015

123ksn, спасибо, очень любопытно и позновательно.

Только сад будет в подвальном помещении. А вот с уровнем питательного раствора (гидропоника) "колдовать" конечно планирую. 

123ksn
Offline
Зарегистрирован: 24.11.2014

aleks3905 пишет:

123ksn, спасибо, очень любопытно и позновательно.

Только сад будет в подвальном помещении. А вот с уровнем питательного раствора (гидропоника) "колдовать" конечно планирую. 

Так я потому и дал информацию, что подвал - самое хорошее место. СО2 не улетучивается, влажность, освещенность, температуру поддерживать легко. Ставите на улице солнечный коллектор, а в подвале еврокубик или два (в утеплителе) и с ранней весны до поздней осени Вы в клубнике почти бесплатно (по теплоте). Успехов!