#include <Wire.h> // Библиотека шины
#include <LiquidCrystal_I2C.h> // Библиотека дисплея
#include <dht11.h> // Библиотека датчика температуры и влажности воздуха
#include <OneWire.h> // Библиотека датчика температуры почвы
#include "Sodaq_DS3231.h" // Библиотека часов реального времени
#include <EEPROM.h> // Библиотека памяти
LiquidCrystal_I2C lcd(0x3f,20,4); // Установка адреса и размерности дисплея
int VlazhnVozd; // Переменная влажности воздуха
int TempVozd; // Переменная температуры воздуха
int VlazhPoch = 0; // влажность почвы
dht11 DHT; // переменная типа DHT для датчика температуры и влажности воздуха
int chk; // Переменная проверки датчика температуры и влажности воздуха
byte i; // для датчика температуры почвы
byte DataVozd[12]; // Данные для датчика температуры почвы
//byte AddrVozd[8] = {0x28, 0xFF, 0x63, 0xC1, 0x74, 0x16, 0x4, 0xF7}; // Адрес для датчика температуры почвы
byte AddrVozd[8] = {0x28, 0xFF, 0x32, 0xD1, 0x64, 0x15, 0x1, 0xB7}; // Адрес для датчика температуры почвы
int TempPochv; // Переменная температуры почвы
char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
int FlagNaborVoda = 0; // Флажок, определяющий, что вода в этот час уже набиралась
int FlagPoliva = 0; // Флажок, определяющий, что полив в этот час уже был
unsigned long Vremya = 0; // Переменная для определения времени подсветки дисплея
int MotorTest = 0; // Переменная для включения теста моторов
int Konts; // переменная для определения концевика
int Sett = 0; // Включаем нумерацию настроечных параметров
int nz = 0; // Переменная отсчета задержек для меню.
int memread = 0; // Ключ для чтения данных из EEPROM
int KluchPauza = 0; // Ключ для паузы
int NParam; // Переменная для выбора параметра по времени работы моторов
double izmer [20]; // массив для получения данных с аналогового датчика температуры воздуха
double temp; // Временная переменная для сортировки данных с аналогового датчика температуры воздуха
double temperatura; // Значение температуры с аналогового датчика температуры воздуха
int temperatura_out; // округленное значение температуры аналогового датчика температуры воздуха
double Volt; // Напряжение на выходе (для настройки) с аналогового датчика температуры воздуха
const int KolNactr = 15; // Количество элементов массивов настроек
// (количество настраиваемых параметров)
int Parametr[KolNactr]; // Массив для значений параметров настроек
/*
"""Настройки"""
0. длительность набора воды в поливочный бак (сек.)
1. час, в который надо включить набор воды (часов)
2. длительность набора воды в поливочный бак, достаточное, чтобы вода перелилась и начался полив (сек.)
3. час, в который надо поливать (часов)
4. час, в который надо поливать второй раз (часов) - не менее, чем через 2 часа после первого полива!
5. время открытия окна по тылу (секунд)
6. время закрытия окна по тылу (секунд)
7. время открытия окна по фасаду (секунд)
8. время закрытия окна по фасаду (секунд)
9. температура открытия окон (градусов)
10.температура закрытия окон (градусов)
11.температура включения подогрева почвы (градусов)
12.температура отключения подогрева почвы (градусов)
13.температура включения подогрева воздуха (градусов)
14.температура отключения подогрева воздуха (градусов)
*/
// Массив названий параметров, названия можно писать свои в количестве, указанном выше,
// длиной до 10 символов включительно. Язык английский.
String NameParametr[KolNactr] =
{
"VremNabora",
"ChasNabora",
"VremPoliva",
"ChasPoliva",
"ChPoliva_2",
"VrOtkrTyla",
"VrZakrTyla",
"VrOtkFasad",
"VrZakFasad",
"T_OtkrOkon",
"T_ZakrOkon",
"T_Pochv_on",
"T_Poch_off",
"T_Vozd_ on",
"T_Vozd_off"
};
// Массив для настроек часов:
String NameClockSet[] =
{
"year: ",
"month: ",
"date: ",
"day of week:",
"hour: ",
"minute: "
};
// """Переменные для пинов"
OneWire ds(2); // Устанока пина 2 для датчика температуры почвы
#define DHT11_PIN 3 // Установка пина 3 для датчика температуры и влажности воздуха
int const MotorTyl_1 = 4; // номер пина мотора открывания форточки тыла 1
int const MotorTyl_2 = 5; // номер пина мотора открывания форточки тыла 2
int const MotorFas_1 = 6; // номер пина мотора открывания форточки фасада 1
int const MotorFas_2 = 7; // номер пина мотора открывания форточки фасада 2
int const Left = 8; // Кнопка настроек влево
int const Esc = 9; // Кнопка настроек выход
int const Enter = 10; // Кнопка настроек ввод
int const Right = 11; // Кнопка настроек вправо
int const KontsTylOtkr = 22; // номер пина концевого выключателя открывания форточки тыла
int const KontsTylZakr = 24; // номер пина концевого выключателя закрывания форточки тыла
int const SensorVoda = 26; // номер пина сенсора уровня воды в поливочном баке
int const KontsFasOtkr = 28; // номер пина концевого выключателя открывания форточки фасада
int const KontsFasZakr = 30; // номер пина концевого выключателя закрывания форточки фасада
int const OtklObogr = 32; // номер пина ручного выключателя автоматического обогрева (теплого пола и обогревателя воздуха)
int const OtkrOkon = 34; // номер пина ручного выключателя ОТКРЫТИЯ окон и отключения автоматического управления окнами
int const ZakrOkon = 36; // номер пина ручного выключателя ЗАКРЫТИЯ окон и отключения автоматического управления окнами
int const KnopkaNabor = 38; // номер пина для кнопки ручного набора воды в поливочный бак
int const KnopkaPoliv = 40; // номер пина кнопки включения полива
int const Poliv_x2 = 42; // номер пина переключателя полива (1 или 2 раза)
int const Podsvetka = 44; // номер пина кнопки включения подсветки дисплея
int const Rele_1 = 46; // номер пина реле №1
int const ReleNasos_2 = 48; // номер пина реле №2 включения насоса
int const ReleTeplPol_3 = 50; // номер пина реле №3 включения теплого пола
int const ReleObogr_4 = 52; // номер пина реле №4 включения обогревателя воздуха
int const VlazhPochPin = 14; // пин датчика влажности почвы
int const Temper_A = 13; // Пин аналогового датчика температуры LM235Z
int FuncOkon (int Motor) // Функция управления моторами
{
if (Motor==MotorTyl_1)
{
Konts=KontsTylOtkr; // Задаем какой концевик должен сработать
NParam = Parametr[5]; // Время открытия окна тыла
}
if (Motor==MotorTyl_2)
{
Konts=KontsTylZakr;
NParam = Parametr[6]; // Время закрытия окна тыла
}
if (Motor==MotorFas_1)
{
Konts=KontsFasOtkr;
NParam = Parametr[7]; // Время открытия окна фасада
}
if (Motor==MotorFas_2)
{
Konts=KontsFasZakr;
NParam = Parametr[7]; // Время закрытия окна фасада
}
digitalWrite(Motor,0);
//Serial.print("Motor ");
//Serial.println(Motor);
int n = 0;
while ( n<(NParam*10)) // Стеклоподъемник работает не более отведенного времени (защита от несработки концевика)
{
//Serial.println(Konts);
delay (100);
++n;
if (digitalRead (Konts) == 1) // Если концевик сработал
{
digitalWrite(Motor,1); // Останавливаем мотор
break;
}
}
digitalWrite(Motor,1); // Останавливаем мотор
}
void setup() {
// """НАЗНАЧЕНИЕ ПИНОВ"""
pinMode (MotorTyl_1, OUTPUT); // пин мотора открывания форточки тыла 1 - выход
pinMode (MotorTyl_2, OUTPUT); // пин мотора открывания форточки тыла 2 - выход
pinMode (MotorFas_1, OUTPUT); // пин мотора открывания форточки фасада 1 - выход
pinMode (MotorFas_2, OUTPUT); // пин мотора открывания форточки фасада 2 - выход
pinMode (Left, INPUT); // Кнопка настроек влево
pinMode (Esc, INPUT); // Кнопка настроек выход
pinMode (Enter, INPUT); // Кнопка настроек ввод
pinMode (Right, INPUT); // Кнопка настроек вправо
pinMode (KontsTylOtkr, INPUT); // пин концевого выключателя открывания форточки тыла - вход
pinMode (KontsTylZakr, INPUT); // пин концевого выключателя закрывания форточки тыла - вход
pinMode (SensorVoda, INPUT); // пин сенсора уровня воды в поливочном баке - вход
pinMode (KontsFasOtkr, INPUT); // пин концевого выключателя открывания форточки фасада - вход
pinMode (KontsFasZakr, INPUT); // пин концевого выключателя закрывания форточки фасада - вход
pinMode (OtklObogr, INPUT); // пин ручного выключателя автоматического обогрева (теплого пола и обогревателя воздуха) - вход
pinMode (OtkrOkon, INPUT); // пин ручного выключателя ОТКРЫТИЯ окон и отключения автоматического управления окнами - вход
pinMode (ZakrOkon, INPUT); // пин ручного выключателя ЗАКРЫТИЯ окон и отключения автоматического управления окнами - вход
pinMode (KnopkaNabor, INPUT); // пин для кнопки ручного набора воды в поливочный бак - вход
pinMode (KnopkaPoliv, INPUT); // пин кнопки включения полива - вход
pinMode (Poliv_x2, INPUT); // пин переключателя полива (1 или 2 раза) - вход
pinMode (Podsvetka, INPUT); // пин кнопки включения подсветки дисплея - вход
pinMode (Rele_1, OUTPUT); // пин реле №1 - выход
pinMode (ReleNasos_2, OUTPUT); // пин реле №2 включения насоса - выход
pinMode (ReleTeplPol_3, OUTPUT); // пин реле №3 включения теплого пола - выход
pinMode (ReleObogr_4, OUTPUT); // пин реле №4 включения обогревателя воздуха - выход
digitalWrite (Rele_1,1); // Резервное реле отключено
digitalWrite (ReleNasos_2,1); // Насос отключен
digitalWrite (ReleTeplPol_3,1); // Подогрев почвы отключен
digitalWrite (ReleObogr_4,1); // Обогреватель воздуха отключен
digitalWrite (MotorTyl_1, 1); // Пины управления моторами отключены
digitalWrite (MotorTyl_2, 1);
digitalWrite (MotorFas_1, 1);
digitalWrite (MotorFas_2, 1);
// """ДИСПЛЕЙ"""
lcd.init(); // Инициализация дисплея
lcd.backlight(); // Подсветка дисплея
// данные самодельных символов для дисплея:
byte lcd_ch[8] = {0x00,0x00,0x11,0x11,0x0F,0x01,0x01,0x00};
byte lcd_z[8] = {0x00,0x00,0x0E,0x11,0x06,0x11,0x0E,0x00};
byte lcd_d[8] = {0x00,0x00,0x06,0x0A,0x0A,0x0A,0x1F,0x00};
byte lcd_v[8] = {0x00,0x00,0x1E,0x11,0x1E,0x11,0x1E,0x00};
byte lcd_gradus[8] = {0x00,0x10,0x06,0x09,0x08,0x09,0x06,0x00};
byte lcd_l[8] = {0x00,0x00,0x07,0x09,0x09,0x09,0x19,0x00};
byte lcd_g[8] = {0x00,0x00,0x15,0x15,0x0E,0x15,0x15,0x00};
byte lcd_p[8] = {0x1F,0x11,0x11,0x11,0x11,0x11,0x11,0x00};
// Создание самодельных символов для дисплея
lcd.createChar(0, lcd_ch); // буква ч
lcd.createChar(1, lcd_z); // буква з
lcd.createChar(2, lcd_d); // буква д
lcd.createChar(3, lcd_v); // буква в
lcd.createChar(4, lcd_gradus); // градус
lcd.createChar(5, lcd_l); // буква л
lcd.createChar(6, lcd_g); // буква ж
lcd.createChar(7, lcd_p); // буква п
Wire.begin();
rtc.begin();
Serial.begin(9600);
}
void loop()
{
if (KluchPauza == 0) // Пауза перед запуском программы
{
//Serial.println("pause");
delay (3000);
KluchPauza = 1;
}
if (memread == 0) // Оди раз считываем данные настроек из памяти и выводим неизменяемые символы на дисплей
{
//Serial.println("memread");
for (int i = 0; i < KolNactr; ++i) // Цикл считывания данных из EEPROM
{
Parametr[i] = EEPROM.read(i);
}
memread = 1;
// Выводим на дисплей неизменяемые символы.
lcd.setCursor(0, 0);
lcd.print("Bo");
lcd.write(byte(1));
lcd.write(byte(2));
lcd.print("yx:");
lcd.setCursor(0, 1);
lcd.print("t=");
lcd.setCursor(4, 1);
lcd.write(byte(4));
lcd.setCursor(6, 1);
lcd.write(byte(3));
lcd.write(byte(5));
lcd.print("a");
lcd.write(byte(6));
lcd.print(".=");
lcd.setCursor(15, 1);
lcd.print("%");
lcd.setCursor(0, 2);
lcd.write(byte(7));
lcd.print("o");
lcd.write(byte(0));
lcd.write(byte(3));
lcd.print("a:");
lcd.setCursor(13, 2);
lcd.write(byte(7));
lcd.print("o");
lcd.write(byte(2));
lcd.print(":");
lcd.setCursor(0, 3);
lcd.print("t=");
lcd.setCursor(4, 3);
lcd.write(byte(4));
lcd.setCursor(6, 3);
lcd.write(byte(3));
lcd.write(byte(5));
lcd.print("a");
lcd.write(byte(6));
lcd.print(".=");
lcd.setCursor(15, 3);
lcd.print("%");
}
if (digitalRead(Enter) == 1) // Если кнопка ввода нажата
{
Nastroyka(); // Переходим в меню настройки
}
DatchikVozd (); // Работаем с цифровым датчиком температуры и влажности воздуха
DatchikVozdAnalog(); // Работаем с аналоговым датчиком температуры и влажности воздуха
if (TempVozd==99) // Если цифровой датчик температуры завис, используем данные с резервного аналогового
{
lcd.setCursor(2, 1); // Выводим на дисплей, что работаем на резервном аналоговом датчике
lcd.print("!!");
TempVozd = temperatura_out;
lcd.setCursor(17, 1); // Выводим на дисплей, что работаем на резервном аналоговом датчике
lcd.print("A");
}
else
{
lcd.setCursor(2,1);
lcd.print(TempVozd);
lcd.setCursor(17, 1); // Выводим на дисплей, что работаем на цифровом датчике
lcd.print("D");
}
DatchikPoch (); // Работаем с датчиками температуры и влажности почвы
DateTime now = rtc.now(); // получение даты - времени
int timehour = now.hour(); // Переменная для считывания времени (часы)
int timemin = now.minute(); // Переменная для считывания времени (минуты)
lcd.setCursor(14,0); // Начинаем выводить данные на дисплей
if (timehour < 10)
{
lcd.print("0");
lcd.print(timehour);
}
else
{
lcd.print(timehour);
}
lcd.print(":");
lcd.setCursor(17,0);
if (timemin < 10)
{
lcd.print("0");
lcd.print(timemin);
}
else
{
lcd.print(timemin);
}
lcd.setCursor(2,3);
lcd.print(TempPochv);
lcd.setCursor(13,1);
lcd.print(VlazhnVozd);
lcd.setCursor(13,3);
lcd.print(VlazhPoch);
lcd.setCursor(18,1);
lcd.print(temperatura_out); //Вывели данные на дисплей
// ***Управление насосом:***
// 1. Набор воды (возможен только при неполном баке):
// 1.1 Вручную:
// 1.1.1 Набор воды вручную:
//Serial.println("1.1.1");
if (digitalRead(SensorVoda)==0 && digitalRead(KnopkaNabor)==1) // Если бак неполон и кнопка набора воды нажата
{
unsigned long Vremya_1 = millis();
Serial.println("Nabor voda ruchn");
NaborVoda (); // Процедура набора воды
Serial.print("Nabor voda ");
Serial.print((millis()-Vremya_1)/1000);
Serial.println("sek.");
Serial.print("SensorVoda ");
Serial.println(digitalRead(SensorVoda));
}
// 1.2 Автоматически (по времени):
//Serial.println("1.2");
if (FlagNaborVoda == 0 && digitalRead (SensorVoda) == 0)
{
if (timehour == Parametr[1])
{
Serial.println("Nabor voda auto");
NaborVoda (); // Процедура набора воды
FlagNaborVoda = 1; // Ставим флажок, что воду больше пока набирать не надо
}
}
if (timehour == (Parametr[1] + 1))
{
FlagNaborVoda = 0; // Прошло время, можно набирать снова
}
// Serial.print("Flag nabor Voda ");
// Serial.println(FlagNaborVoda);
// 2.Полив
// Serial.println("2");
if (timehour == Parametr[3] && FlagPoliva == 0)
{
Serial.println("Poliv avto");
Poliv (); // Процедура полива
FlagPoliva = 1; // Установим флажок, что больше пока поливать не надо
}
// 2.1 Полив вручную:
//Serial.println("2.1");
//Serial.println(Parametr[2]*1000);
//Serial.println(Parametr[2]);
if (digitalRead (SensorVoda) == 1 && digitalRead (KnopkaPoliv) == 1) // Если бак полон и кнопка полива нажата
{
Serial.print ("SensorVoda ");
Serial.println (digitalRead(SensorVoda));
Serial.print ("KnopkaPoliv ");
Serial.println (digitalRead(KnopkaPoliv));
Poliv (); // Процедура полива
Serial.print ("SensorVoda poliv end ");
Serial.println (digitalRead(SensorVoda));
Serial.print ("KnopkaPoliv poliv end ");
Serial.println (digitalRead(KnopkaPoliv));
}
if (timehour == (Parametr[3] + 1))
{
FlagPoliva = 0; // Можно опять поливать
}
// 3. Двойной полив:
//Serial.println("3");
// 3.1 Набираем воду:
//Serial.println("3.1");
if (digitalRead (Poliv_x2) == 1 && timehour == (Parametr[3] + 1))
{
if (FlagNaborVoda == 0 && digitalRead (SensorVoda) == 0)
{
Serial.println("Nabor x2");
NaborVoda (); // Процедура набора воды
FlagNaborVoda = 1; // Ставим флажок, что воду больше пока набирать не надо
}
}
if (timehour == (Parametr[3] + 2))
{
FlagNaborVoda = 0; // Прошло время, можно набирать снова
}
// 3.2 Поливаем:
//Serial.println("3.2");
if (timehour == Parametr[4] && FlagPoliva == 0)
{
Serial.println("Poliv x2");
Poliv (); // Процедура полива
FlagPoliva = 1; // Установим флажок, что больше пока поливать не надо
}
if (timehour == (Parametr[4] + 1))
{
FlagPoliva = 0; // Можно опять поливать
}
// 4. Форточки:
// 4.1 Автоматическое открытие - закрытие:
//Serial.println("4.1");
if (digitalRead(OtkrOkon) == 0 && digitalRead(ZakrOkon) == 0) // Если отключено ручное открытие-закрытие окон
{
lcd.setCursor(10,0); // установка курсора
lcd.print("A");
if (TempVozd >= Parametr[9] && digitalRead(KontsTylOtkr) == 0)
{
FuncOkon(MotorTyl_1);
}
if (TempVozd >= Parametr[9] && digitalRead(KontsFasOtkr) == 0)
{
FuncOkon(MotorFas_1);
}
if (TempVozd <= Parametr[10] && digitalRead(KontsTylZakr) == 0)
{
FuncOkon(MotorTyl_2);
}
if (TempVozd <= Parametr[10] && digitalRead(KontsFasZakr) == 0)
{
FuncOkon(MotorFas_2);
}
}
// 4.2 Ручное открытие окон и отключение автоматического открытия-закрытия:
//Serial.println("4.2");
if (digitalRead(OtkrOkon) == 1) // Если включено ручное открытие окон
{
lcd.setCursor(10,0); // установка курсора
lcd.print("P");
if (digitalRead(KontsTylOtkr) == 0)
{
FuncOkon(MotorTyl_1);
}
if (digitalRead(KontsFasOtkr) == 0)
{
FuncOkon(MotorFas_1);
}
}
if (digitalRead(ZakrOkon) == 1) // Если включено ручное закрытие окон
{
lcd.setCursor(10,0); // установка курсора
lcd.print("P");
if (digitalRead(KontsTylZakr) == 0)
{
FuncOkon(MotorTyl_2);
}
if (digitalRead(KontsFasZakr) == 0)
{
FuncOkon(MotorFas_2);
}
}
// 5.Подогрев почвы и воздуха:
//Serial.println("5");
if ( digitalRead (OtklObogr) == 1 ) // Если автоматика отключена
{
digitalWrite (ReleTeplPol_3, 1); // Выключаем реле теплого пола
digitalWrite (ReleObogr_4, 1); // Выключаем реле обогревателя воздуха
lcd.setCursor(10,2); // Отображаем Р на дисплее, символизируещее ручное управление, отключение автоматики
lcd.print("P");
lcd.setCursor(17,2); // Отображаем на дисплее отключение подогрева пола
lcd.print("OFF");
}
else // Если автоматика не отключена
{
lcd.setCursor(10,2); // Отображаем А на дисплее
lcd.print("A");
if ( TempPochv <= Parametr[11]) // Если температура почвы меньше заданной
{
digitalWrite (ReleTeplPol_3, 0); // Включаем реле теплого пола
lcd.setCursor(17,2); // Отображаем это на дисплее
lcd.print("ON ");
}
if ( TempPochv >= Parametr[12] ) // Если температура почвы больше заданной
{
digitalWrite (ReleTeplPol_3, 1); // Выключаем реле теплого пола
lcd.setCursor(17,2); // Отображаем это на дисплее
lcd.print("OFF");
}
if ( TempVozd <= Parametr[13] ) // Если температура почвы меньше заданной
{
digitalWrite (ReleObogr_4, 0); // Включаем реле обогревателя воздуха
}
if ( TempVozd >= Parametr[14] ) // Если температура почвы больше заданной
{
digitalWrite (ReleObogr_4, 1); // Выключаем реле обогревателя воздуха
}
}
// Кнопка включения подсветки дисплея
if ( (millis() - Vremya) > 15000 || millis() < Vremya)
{
lcd.noBacklight(); // Подсветка дисплея отключается
}
if ( digitalRead(Podsvetka) == 1)
{
lcd.backlight(); // Подсветка дисплея
Vremya = millis();
}
}
void NaborVoda () // Процедура набора воды
{
Serial.println("void NaborVoda");
digitalWrite (ReleNasos_2,0); // Включаем насос
int n = 0;
while ( n<Parametr[0]+300) // Насос работает не более отведенного времени (защита от несработки датчика уровня)
{
delay (1000);
++n;
if (digitalRead (SensorVoda) == 1) // Если датчик уровня воды сработал
{
break;
}
}
digitalWrite (ReleNasos_2,1); // Насос отключить
}
void Poliv () // Процедура полива
{
Serial.println("void Poliv");
digitalWrite (ReleNasos_2,0); // Включаем насос
Serial.print("Paramer 2: ");
Serial.println(Parametr[2]*1000);
Serial.println("Nasos ON");
for (int Poliv_delay = 0; Poliv_delay<=Parametr[2]; Poliv_delay++)
{
delay (1000);
Serial.print("Poliv_delay: ");
Serial.println(Poliv_delay);
}
digitalWrite (ReleNasos_2,1); // Насос отключить
Serial.println("Nasos OFF");
delay (2000);
}
void DatchikVozd () // Функция получения данных с датчика температуры и влажности воздуха
{
//Serial.println("void DatchikVozd");
chk = DHT.read(DHT11_PIN); // Считываем данные с датчика температуры и влажности воздуха
switch (chk) // Проверка данных на ошибки. Если они есть, присваиваем значения 99.
{
case DHTLIB_OK:
break;
default: TempVozd = 99;
VlazhnVozd = 99;
break;
}
if (TempVozd != 99) // Если с данными все в порядке, присваиваем переменным значения.
{
VlazhnVozd = DHT.humidity,1;
TempVozd = DHT.temperature,1;
//Serial.println(VlazhnVozd);
//Serial.println(" void DatchikVozd ");
//Serial.println(TempVozd);
}
}
void DatchikVozdAnalog() // Функция получения даных с аналогового датчика температуры
{
for (int i=0; i<20; i=i+1)
{
izmer[i]=analogRead(Temper_A);
delay(100);
}
for (int j=19; j>=0; j=j-1)
{
for (int i=0; i<j; i=i+1)
{
if(izmer[i]>izmer[i+1])
{
temp=izmer[i];
izmer[i]=izmer[i+1];
izmer[i+1]=temp;
}
}
}
temp=0;
for (int i=2; i<18; i=i+1)
{
temp=temp+izmer[i];
}
//Serial.println(izmer[5]);
temp=temp/16;
//Serial.println(temp);
Volt=temp*5.2/1024; // Здесь 5,2 - опорное напряжение. Нужно реальное писать, тогда датик покажет правильно
// Volt должно при 25 градусов быть около 2.98-3.00 вольта
//Serial.println(Volt);
temperatura=Volt*100-273.15;
temperatura_out=int(temperatura);
if((temperatura-temperatura_out) >= 0.5)
{
temperatura_out=temperatura_out+1;
}
//Serial.print("T=");
//Serial.print(temperatura);
//Serial.print(" T_d=");
// Serial.println(temperatura_out);
}
void DatchikPoch () // Функция получения данных с датчика температуры почвы
{ //Serial.println("void DatchikPoch");
byte present = 0;
ds.reset(); // Очищаем датчик почвы
ds.select(AddrVozd);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(AddrVozd); // выбираем датчик почвы
ds.write(0xBE); // Считываем данные с датчика почвы
for ( i = 0; i < 9; i++) // Записываем данные с датчика почвы
{
DataVozd[i] = ds.read();
}
int16_t raw = (DataVozd[1] << 8) | DataVozd[0]; // Извлекаем данные о температуре почвы
raw = raw & ~7; // Определяем точность для температуры почвы 0,5 градусов
//Serial.println(raw);
TempPochv = (int)raw / 16.0; // Пересчитываем в градусы Цельсия
//Serial.println(TempPochv);
VlazhPoch = analogRead(VlazhPochPin); // считывание данных с датчика влажности почвы
VlazhPoch = (1000-VlazhPoch)/8; // вычисление влажности почвы
}
void Nastroyka() // Функция выбора меню на дисплее
{
lcd.backlight(); // Подсветка дисплея
lcd.clear(); // Очистка дисплея
while (nz < 5) // Цикл ожидания, выполняется 1 раз при входе
{
delay (200);
++nz;
}
int Kluch_5 = 1;
int menu = 0;
while (Kluch_5 = 1)
{
lcd.setCursor(0, 0);
lcd.print("Set parametr");
lcd.setCursor(0, 1);
lcd.print("Set clock");
lcd.setCursor(0, 3);
lcd.print("Testmot.-butt.on top");
delay (100);
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
lcd.clear(); // Очистка дисплея
Kluch_5 = 0;
nz = 0;
memread = 0;
break;
}
if (menu == 0)
{
lcd.setCursor(15, 0);
lcd.print("<");
lcd.setCursor(15, 1);
lcd.print(" ");
}
else
{
lcd.setCursor(15, 1);
lcd.print("<");
lcd.setCursor(15, 0);
lcd.print(" ");
}
if (digitalRead(Right) == 1) // Если кнопка вправо нажата
{
menu = 1;
}
if (digitalRead(Left) == 1) // Если кнопка влево нажата
{
menu = 0;
}
if (digitalRead(Enter) == 1) // Если кнопка ввода нажата
{
if (menu == 1)
{
Timeset ();
}
else
{
Nastr_Parametr ();
}
}
if (digitalRead(Podsvetka) == 1)
{
TestMotor();
}
}
}
void Timeset () // Функция настройки часов
{
DateTime now = rtc.now(); //получение даты - времени
int Setyear = now.year();
int Setmonth = now.month();
int Setdate = now.date();
int SetdayOfWeek = now.dayOfWeek();
int Sethour = now.hour();
int Setmin = now.minute();
lcd.clear(); // Очистка дисплея
int Kluch_3 = 1; // Задаем значение, не позволяющее покинуть функцию без команды
while (Kluch_3 == 1) // Цикл выбора параметра
{
lcd.setCursor(0, 0);
lcd.print("Clock setting:");
while (nz < 5) // Цикл ожидания, выполняется 1 раз при входе
{
delay (100);
++nz;
}
delay (100); // Ожидание - выполняется каждый раз
if (digitalRead(Right) == 1) // Изменяем значение номера выбираемого параметра:
{
++Sett; // увеличиваем
}
if (digitalRead(Left) == 1)
{
--Sett; // уменьшаем
}
if (Sett < 0) // Ограничиваем выбор настроек заданным их количеством
{
Sett = 5;
}
if (Sett > 5)
{
Sett = 0;
}
lcd.setCursor(0, 1); // Вывод на экран названия настройки
lcd.print(NameClockSet[Sett]); // в соответствии с ее номером в массиве названий
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
lcd.clear(); // Очистка дисплея
Kluch_3 = 0;
memread = 0;
break;
}
if (digitalRead(Enter) == 1) // Если нажата кнопка выбора настроечного параметра
{
int Kluch_4 = 1; // Задаем значение, не позволяющее покинуть цикл без команды
nz = 0; // Обнуляем счетчик цикла ожидания
while (Kluch_4 == 1) // Цикл выбора значения параметра
{
lcd.setCursor(12, 1);
delay (100); // Ожидание, отвечает за скорость смены значений
if (Sett == 0)
{
lcd.print(Setyear);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Setyear;
if (Setyear > 2030)
{
Setyear = 2016;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Setyear;
if (Setyear < 2016)
{
Setyear = 2030;
}
}
}
if (Sett == 1)
{
lcd.print(" ");
if (Setmonth < 10)
{
lcd.print("0");
}
lcd.print(Setmonth);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Setmonth;
if (Setmonth > 12)
{
Setmonth = 1;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Setmonth;
if (Setmonth < 1)
{
Setmonth = 12;
}
}
}
if (Sett == 2)
{
lcd.print(" ");
if (Setdate < 10)
{
lcd.print("0");
}
lcd.print(Setdate);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Setdate;
if (Setdate > 31)
{
Setdate = 1;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Setdate;
if (Setdate < 1)
{
Setdate = 31;
}
}
}
if (Sett == 3)
{
lcd.print(" ");
lcd.print(weekDay[SetdayOfWeek]);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++SetdayOfWeek;
if (SetdayOfWeek > 6)
{
SetdayOfWeek = 0;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--SetdayOfWeek;
if (SetdayOfWeek < 0)
{
SetdayOfWeek = 6;
}
}
}
if (Sett == 4)
{
lcd.print(" ");
if (Sethour < 10)
{
lcd.print("0");
}
lcd.print(Sethour);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Sethour;
if (Sethour > 23)
{
Sethour = 0;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Sethour;
if (Sethour < 0)
{
Sethour = 23;
}
}
}
if (Sett == 5)
{
lcd.print(" ");
if (Setmin < 10)
{
lcd.print("0");
}
lcd.print(Setmin);
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Setmin;
if (Setmin > 59)
{
Setmin = 0;
}
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Setmin;
if (Setmin < 0)
{
Setmin = 59;
}
}
}
while (nz < 5) // Цикл ожидания, выполняется 1 раз
{
delay (100);
++nz;
}
delay (100); // Ожидание, отвечает за скорость смены значений
if (digitalRead(Enter) == 1) // Если в этом режиме нажата кнопка Ввод,
{ // Производим установку часов
DateTime dt(Setyear, Setmonth, Setdate, Sethour, Setmin, 0, SetdayOfWeek);
rtc.setDateTime(dt);
lcd.setCursor(11, 1);
lcd.print("+"); // и выводим значок +, подтверждение сохранения
}
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода, выходим в предыдущее меню
{ // выбора номера параметра,
lcd.setCursor(12, 1);
lcd.print(" "); // попутно стирая на дисплее значение.
Kluch_4 = 0;
nz = 0;
continue;
}
}
}
delay (200);
}
}
void Nastr_Parametr () // Функция настройки параметров с кнопок и сохранения их в EEPROM
{
lcd.clear(); // Очистка дисплея
int Kluch = 1; // Задаем значение, не позволяющее покинуть функцию без команды
int nastr = 0; // Включаем нумерацию настроечных параметров
int nastr_d = nastr+1;
int nz = 0; // Счетчик для циклов ожидания, выполняющихся 1 раз
while (Kluch = 1) // Цикл выбора параметра
{
while (nz < 5) // Цикл ожидания, выполняется 1 раз при входе
{
delay (100);
++nz;
}
delay (100); // Ожидание - выполняется каждый раз
if (digitalRead(Right) == 1) // Изменяем значение номера выбираемого параметра:
{
++nastr; // увеличиваем
}
if (digitalRead(Left) == 1)
{
--nastr; // уменьшаем
}
if (nastr < 0) // Ограничиваем выбор настроек заданным их количеством
{
nastr = KolNactr - 1;
}
if (nastr > KolNactr - 1)
{
nastr = 0;
}
nastr_d = nastr+1;
if (nastr == KolNactr - 1)
{
nastr_d = 0;
}
lcd.setCursor(0, 0); // Вывод на экран названия настройки
lcd.print(NameParametr[nastr]); // в соответствии с ее номером в массиве названий
lcd.setCursor(10, 0);
lcd.print("<");
lcd.setCursor(0, 1);
lcd.print(NameParametr[nastr_d]);
lcd.setCursor(12, 0);
if (Parametr[nastr] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr] >= 10 && Parametr[nastr] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr]); // выводим значение сохраненного параметра
lcd.setCursor(12, 1);
if (Parametr[nastr_d] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr_d] >= 10 && Parametr[nastr_d] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr_d]);
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода из режима выбора настроек
{
lcd.clear(); // Очистка дисплея
Kluch = 0;
nz = 0;
break;
}
if (digitalRead(Enter) == 1) // Если нажата кнопка выбора настроечного параметра
{
int Kluch_2 = 1; // Задаем значение, не позволяющее покинуть цикл без команды
nz = 0; // Обнуляем счетчик цикла ожидания
lcd.setCursor(10, 0);
lcd.print(" ");
lcd.setCursor(15, 0);
lcd.print("<");
while (Kluch_2 == 1) // Цикл выбора значения параметра
{
lcd.setCursor(12, 0);
if (Parametr[nastr] < 10) // Прописываем пустое место перед единицами
{
lcd.print(" ");
}
if (Parametr[nastr] >= 10 && Parametr[nastr] < 100) // Пустое место перед десятками
{
lcd.print(" ");
}
lcd.print(Parametr[nastr]); // выводим значение сохраненного параметра
while (nz < 5) // Цикл ожидания, выполняется 1 раз
{
delay (100);
++nz;
}
delay (100); // Ожидание, отвечает за скорость смены значений
if (digitalRead(Right) == 1) // Если кнопка вправо нажата, увеличиваем значение параметра
{
++Parametr[nastr];
}
if (digitalRead(Left) == 1) // То же для кнопки влево
{
--Parametr[nastr];
}
if (Parametr[nastr] < 1) // Задаем границы для значений параметров, в том числе
{ // обусловленные возможностями ячейки памяти (256)
Parametr[nastr] = 250;
}
if (Parametr[nastr] > 250)
{
Parametr[nastr] = 1;
}
if (digitalRead(Enter) == 1) // Если в этом режиме нажата кнопка Ввод,
{ // сохраняем значение параметра в EEPROM
EEPROM.write(nastr, Parametr[nastr]);
lcd.setCursor(15, 0);
lcd.print("+");
delay (500);
lcd.setCursor(15, 0);
lcd.print(" "); // Стираем значок
Kluch_2 = 0;
nz = 0;
memread = 0;
continue;
}
if (digitalRead(Esc) == 1) // Если нажата кнопка выхода, выходим в предыдущее меню
{ // выбора номера параметра,
lcd.setCursor(15, 0);
lcd.print(" "); // попутно стирая на дисплее значок
Kluch_2 = 0;
nz = 0;
continue;
}
}
}
delay (200);
}
}
void Kontsevik () // Для отображения положения концевиков
{
lcd.setCursor(3, 3);
lcd.print(digitalRead(KontsTylOtkr));
lcd.setCursor(8, 3);
lcd.print(digitalRead(KontsTylZakr));
lcd.setCursor(13, 3);
lcd.print(digitalRead(KontsFasOtkr));
lcd.setCursor(18, 3);
lcd.print(digitalRead(KontsFasZakr));
}
void TestMotor() // Тестовая программа для проверки и настройки моторов открывания окон
{
MotorTest = 1;
lcd.clear(); // Очистка дисплея
lcd.backlight(); // Подсветка дисплея
lcd.setCursor(0, 0); // Вывод на дисплей неизменяемых символов:
lcd.print("Motors test");
lcd.setCursor(0, 1);
lcd.print("Motors select:");
lcd.setCursor(0, 2);
lcd.print("Motors status:");
lcd.setCursor(0, 3);
lcd.print("TO:");
lcd.setCursor(5, 3);
lcd.print("TC:");
lcd.setCursor(10, 3);
lcd.print("FO:");
lcd.setCursor(15, 3);
lcd.print("FC:");
delay(500);
while ( MotorTest == 1)
{
lcd.setCursor(15, 1);
lcd.print("OFF ");
lcd.setCursor(15, 2);
lcd.print("STOP ");
Kontsevik ();
if ((digitalRead(Left) == 1) && (digitalRead(KontsTylOtkr) == 0)) // Нажата кнопка 1 и концевик открыт
{
lcd.setCursor(15, 1);
lcd.print("Tyl ");
lcd.setCursor(15, 2);
lcd.print("Open ");
Kontsevik ();
digitalWrite (MotorTyl_1, 0);
while ((digitalRead(Left) == 1) && (digitalRead(KontsTylOtkr) == 0))
{
Kontsevik ();
delay (100);
}
digitalWrite (MotorTyl_1, 1);
}
if ((digitalRead(Esc) == 1) && (digitalRead(KontsTylZakr) == 0)) // Нажата кнопка 2 и концевик открыт
{
lcd.setCursor(15, 1);
lcd.print("Tyl ");
lcd.setCursor(15, 2);
lcd.print("Close");
Kontsevik ();
digitalWrite (MotorTyl_2, 0);
while ((digitalRead(Esc) == 1) && (digitalRead(KontsTylZakr) == 0))
{
Kontsevik ();
delay (100);
}
digitalWrite (MotorTyl_2, 1);
}
if ((digitalRead(Enter) == 1) && (digitalRead(KontsFasOtkr) == 0)) // Нажата кнопка 3 и концевик открыт
{
lcd.setCursor(15, 1);
lcd.print("Fasad");
lcd.setCursor(15, 2);
lcd.print("Open ");
Kontsevik ();
digitalWrite (MotorFas_1, 0);
while ((digitalRead(Enter) == 1) && (digitalRead(KontsFasOtkr) == 0))
{
Kontsevik ();
delay (100);
}
digitalWrite (MotorFas_1, 1);
}
if ((digitalRead(Right) == 1) && (digitalRead(KontsFasZakr) == 0)) // Нажата кнопка 4 и концевик открыт
{
lcd.setCursor(15, 1);
lcd.print("Fasad");
lcd.setCursor(15, 2);
lcd.print("Close");
Kontsevik ();
digitalWrite (MotorFas_2, 0);
while ((digitalRead(Right) == 1) && (digitalRead(KontsFasZakr) == 0))
{
Kontsevik ();
delay (100);
}
digitalWrite (MotorFas_2, 1);
}
if (digitalRead(Podsvetka) == 1) // Нажата кнопка подсветки
{
delay (2000);
if (digitalRead(Podsvetka) == 1) // Все еще нажата кнопка подсветки
{
MotorTest = 0;
lcd.clear(); // Очистка дисплея
delay(1000);
break;
}
break;
}
}
delay (500);
}