ОК, продолжим лёгкий ликбез.
Надеюсь вы уже поняли что потери пропорциональны разнице температур.
И что котёл более эффективно ( экономично) работает на низкой температуре.
И что количество тепла производимого котлом
необходимо немножко больше чем оно теряется в окружающую среду.
И вот этим " немножко больше" мы можем управлять с помощью термоголовок на радиаторах
Теперь что такое тампература в комнате.
Там где стоят радиаторы температура под потолком будет выше чем у пола.
И будет сильная циркуляция воздуха.
Там где тёплый пол там температура под потолком будет ниже чем у пола
и практически отсутствует циркуляция воздуха.
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать
А у них то холодно то жарко.
А надо установившийся режим. Плавный, непрерывное регулирование.
И релейным отключением-включением котла на длительное время этого не добиться.
По поводу непрерывного регулирования согласен при условии, что у котла модулируемая горелка, мощность которой можно изменять в режиме нормальной работы. Однако у некоторых котлов с модулируемой горелкой ее мощность можно изменять только в режиме "сервиса", но никак не в рабочем режиме. А что по поводу датчика на столбе? Каково Ваше мнение по поводу его месторасположения?
Котёл сам разбирается со своей горелкой.
И сам снижает мощьность когда видит что температура стала слишком быстро расти.
Мы туда не залезем просто никак и нельзя этого делать
Я , например, просто ограничил максимальную мощьность как раз в сервисе.
До 33 % от 28 килоВатт , меньше не было , 9.24 кВатт
Так как при самых лютых морозах (20 и ниже) больше 16 кубов в сутки ( и то при разгоне, потом 12) не видел.
А 16 куб Х 8 = 128 . 128 делим на 24= 5.3 средней . двойной запас.
А вот темературу регулировать без вмешательства во внутренности мы можем двумя способами:
Используя вход контактов комнатного термостата или поворачивая ручку температуры ( например сервой).
Ставьте на столб. Градусник. Будет точно показывать среднюю температуру по больнице.
Может кому-нибудь помогут результаты моей работы. Также прошу высказывать мысли по поводу оптимизации.
[code]
/* Программа "Комнатный термостат"
Допоборудование - ds18b20(вывод 2 )- 3 датчика (комнатный, уличный, на котловую воду), ds3231(выводы 5-SCL и 4-SDA) и lcd1602.
Функция - замеряет температуру в помещении и на основании ее сравнения с установленными пользователями включает или выключает нагрузку.
Принцип работы:
1) пользователем устанавливаются время начала временных периода - ночного, утреннего и дневного.
2) пользователем устанавливаются температуры каждого временного периода - ночью, утром и днем.
3) в основном цикле программы постоянно считываются данные с часов ds3231, которые заносятся в соответствующие переменные.
4) через устанавливаемый пользователем в тексте программы интервал (сейчас равен 30 с.) считывается температура с датчика (три замера, высчитывается среднеарифмитическая).
5) затем определяется текущий временной период (ночь, утро или день).
6) считанная температура проверяется на наличие ошибки, то есть сравнивается с последней сохранненной в памяти.
7) считанная температура сравнивается с установленной пользователем температурой текущего временного периода и при выходе температуры за границы включается ил выключатеся котел.
*/
////////////////////////////////////////////////////////////////
// подключение необходимых библиотек
#include <OneWire.h> // для протокола 1-Wire
#include <Wire.h> // для протокола I2C
#include <LiquidCrystal.h> // для lcd
#include <EEPROM.h> // для обращения к энергонезависимой памяти
#include <wdt.h> // библиотека сторожевого таймера
// адреса EEPROM, по которым хранятся задаваемые пользователем параметры:
// 0-часы начала ночного периода, 1-минуты начала ночного периода, 2-часы начала утреннего периода, 3 - минуты начала утреннего периода, 4-часы начала дневного периода,
// 5-минуты начала дневного периода, 6-температура ночного периода, 7-температура утреннего периода, 8-температура дневного периода.
// 10-17 - адрес комнатного датчика температуры, 20-27 - адрес уличного датчика температуры, 30-37 - адрес датчика температуры котловой воды
////////////////////////////////////////////////////////////////
// определяем вывод для протокола 1-Wire
OneWire ds(2); // для Uno (провод припаянн на 2 вывод
// определяем вывод, который будет управлять включением/выключением котла по результатам сравнения температур
byte relekotla=3; // то же для Uno.
// определяем вывод для lcd
//LiquidCrystal lcd(RS, E, DB4, DB5, DB6, DB7)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // LCD для Uno - Keypad Schild
////////////////////////////////////////////////////////////////
// формируем 3 знака (маленькая, средняя и большая стрелки вверх), которые будут отражаться на lcd
// и свидетельствовать, что на выходе управления установлен HIGH, то есть котел включен на обогрев.
enum {symbol_height=8};
byte znak_lcd_plamya[symbol_height]= // знак в виде пламени. Если нужен другой, то закомментировать.
{
B00010,
B00110,
B01100,
B11100,
B11110,
B01111,
B01110,
B00100,
};
byte znak_lcd_gradus[symbol_height]= // знак градус.
{
B00100,
B01010,
B00100,
B00000,
B00000,
B00000,
B00000,
B00000,
};
byte znak_lcd_D_Rus[symbol_height]= // буква "Д".
{
B01111,
B00101,
B00101,
B00101,
B01001,
B10001,
B11111,
B10001,
};
byte znak_lcd_b_Rus[symbol_height]= // буква "ь".
{
B00000,
B00000,
B10000,
B10000,
B11110,
B10001,
B11110,
B00000,
};
byte znak_lcd_n_Rus[symbol_height]= // буква "н" .
{
B00000,
B00000,
B10001,
B10001,
B11111,
B10001,
B10001,
B00000,
};
byte znak_lcd_ch_Rus[symbol_height]= // буква "ч" .
{
B00000,
B00000,
B10001,
B10001,
B01111,
B00001,
B00001,
B00000,
};
byte znak_lcd_u_Rus[symbol_height]= // буква "У" .
{
B10001,
B10001,
B10001,
B01010,
B00100,
B01000,
B10000,
B00000,
};
byte znak_lcd_t_Rus[symbol_height]= // буква "т" .
{
B00000,
B00000,
B11111,
B00100,
B00100,
B00100,
B00100,
B00000,
};
/*
byte znak_lcd_l_Rus[symbol_height]= // буква "л" .
{
B00000,
B00000,
B01111,
B00101,
B00101,
B10101,
B01001,
B00000,
};
byte znak_lcd_CH_Rus[symbol_height]= // буква "Ч" .
{
B10001,
B10001,
B10001,
B01111,
B00001,
B00001,
B00001,
B00000,
};
byte znak_lcd_bl_Rus[symbol_height]= // буква "ы" .
{
B00000,
B00000,
B10001,
B10001,
B11101,
B10011,
B11101,
B00000,
};
*/
////////////////////////////////////////////////////////////////
// объявляем переменные
// временные переменные для считывания адресов с подключенных датчиков
byte temp_adres[8];
byte temp_adres_datch_1[8]; // для считывания адреса 1-го подключенного датчика
byte temp_adres_datch_2[8];
byte temp_adres_datch_3[8];
byte kolvo_new_datch=0; // содержит кол-во новых подключенных датчиков
boolean status_schit_datch_new[3];
byte sss[8];
// для подпрограммы formirovanie_intervala().
unsigned int interval_zapuska_dat_room=30000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с комнатного датчика. Он равен 30 сек.
unsigned long interval_zapuska_dat_street=180000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с уличного датчика. Он равен 3 мин.
unsigned int interval_wychoda_menu=15000; // интервал в милисекундах, через который будет осуществляться выход из подпрограммы программирования
unsigned long time_snachala_progi; // содержит текущие данные о времени, прошедшем сначала запуска программы. Для формирования интеравала .
unsigned long time_snach_progi_dat_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания комнатной температуры
unsigned long time_snach_progi_dat_street=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания уличной температуры
unsigned long time_snach_progi_wychoda_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала выхода из подпрограммы программирования
unsigned long time_snach_progi_migania_dvoet=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания двоеточия
unsigned long time_snach_progi_migania_sost_kotla=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания состояния котла
unsigned long time_snach_progi_parametra_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания выбранного параметра меню
unsigned long time_snach_progi_problem_datch_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала отсутствия ответа от комнатного датчика температуры
unsigned long time_snach_progi_wychod_predel_temp=0;
boolean miganie_parametra_programmirovaniya=true; // когда true светится выбранный параметр, false - вместо параметра пробелы.
// содержит предыдущие данные о времени, прошедшем с начала запуска программы для формирования мигания
// для работы с температурой
byte adres_dat_temp_room[8]; // для хранения адреса комнатаного датчика температуры
byte adres_dat_temp_street[8]; // для хранения адреса уличного датчика температуры
byte adres_dat_temp_water[8]; // для хранения адреса датчика температуры котловой воды
float temperatura_room; // считанная с комнатного датчика температура
float temperatura_street; // считанная с уличного датчика температура
float temperatura_water; // считанная с датчика котловой воды температура
float temperatura_room_pamyat[3]; // последние 3 считанных температуры (для проверки считанной температуры на наличие ошибок и исключения тактования)
byte temperatura_room_ustanovka[3]; // в них считываются из EEPROM задаваемые пользователем температуры временных периодов: 0-ночь, 1-утро, 2-день.
float gisteresis=0.2; // задаваемый пользователем гистерезис для определения температурных границ управления выходом
boolean proverka_temperatura_room_status; // содержит информацию о том, прошла ли считанная температура проверку на наличие грубых ошибок: true-да; false-нет.
float temperatura_room_predyd=0, temperatura_street_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
// для работы со временем
bool Century=false; // для часов. Пока не знаю??????????????????????
bool h12; // для часов. Пока не знаю??????????????????????
bool PM; // для часов. Пока не знаю??????????????????????
byte year, month, date, hour, minute, second; // в них записываются полученные от часов данные о времени
byte hour_predyd=0, minute_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
byte nachalo_periodov[6]; // в них считываются из EEPROM часы и минуты начала периодов: 0-часы ночи, 1-минуты ночи, 2-часы утра, 3-минуты утра, 4-часы дня, 5-минуты дня.
byte period_time; // для храненения сведений о временном периоде (ночь-0, утро-1, день-2)
int summa_minut[4]; // общие суммы минут: 0-текущего времени, 1-начала ночного периода, 2-начала утреннего периода, 3-начала дневного периода, для удобства сравнения
byte obnovl_peremen=0; // необходима для ежечасного считывания данных из EEPROM и их записи в соответствующие переменные
// для подпрограммы программирования
byte status_programmirovaniya=1; // содержит число на основании которого устанавливается тот или иной параметр
boolean knopka_verch=false; // содержит состояние кнопки "ВВЕРХ", по умолчанию false
boolean knopka_vniz=false; // содержит состояние кнопки "ВНИЗ", по умолчанию false
boolean knopka_pravo=false; // содержит состояние кнопки "ПРАВО" по умолчанию false
boolean knopka_levo=false; // содержит состояние кнопки "ЛЕВО", по умолчанию false
boolean knopka_select=false; // содержит состояние кнопки select, по умолчанию false
int nashat_knopka=1023; // содержит данные с аналогового входа 0
boolean status_wybora_delete=false; // содержит состояние необходимости удаления датчика температуры из EEPROM
boolean status_wybora_save=false; // содержит состояние необходимости сохранения измененных параметров
byte wybor_status_zapis_datch=1; // содержит число (1, 2 или 3), свидетельствующее о том, каким именно (комнатным, уличным или водяным) записывается новый датчик в EEPROM
///////////////////////////////////////////////////////////////
// подпрограмма формирования задаваемого интервала между обращениями к подпрограммам считывания температуры с датчика и получения времени с часов.
unsigned long formirovanie_intervala(unsigned long time_snachala_progi_time_pred)
{
time_snachala_progi=millis(); // получаем количество милисекунд с начала выполнения программы
// Проверяем, не проскочил ли счетчик прошедшего времени через 0, если предыдущие показания не достигли максимума.
// Если проскочил то к обоим сравниваемым переменным добавляем число из tempintervalzapuska и 100, чтобы вторая переменная также перескочила через 0.
if (time_snachala_progi_time_pred>time_snachala_progi) // если текущие сведения о прошедшем времени меньше предыдущих данных, то это свидетельствует о том, что счетчик перескочил через 0.
{
time_snachala_progi_time_pred=time_snachala_progi_time_pred+185000; // 185000 необходимо для максимального интервала 3 минуты.
time_snachala_progi=time_snachala_progi+185000;
}
unsigned long time_interval=time_snachala_progi-time_snachala_progi_time_pred; // высчитываем пройденный интервал
return time_interval;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания температуры с датчика.
float schit_datchik_temperatury(byte time_adres_dat_temp[], byte i)
{
float time_temperatura[i]; // объявляем переменные для временного хранения температуры из 3 последовательных замеров
for(byte cikl=0; cikl<i; cikl++)
{
ds.reset();
ds.write(0xCC); // игнорируем адреса всех датчиков для следующей команды
ds.write(0x44); // запуск преобразования температуры всеми датчиками.
delay(200);
ds.reset();
ds.select(time_adres_dat_temp); // следующая команда предназначется только комнатному датчику
ds.write(0xBE); // чтение двух байт с данными температуры из памяти датчика
byte data[2];
data[0]=ds.read(); // присваивание переменной data[0] данных первого байта, полученного от датчика
data[1]=ds.read(); // присваивание переменной data[1] данных второго байта, полученного от датчика
time_temperatura[cikl]=((data[1] << 8)|data[0])/16.0; // высчитываем температуру и заносим во временную переменную
}
float temperatura;
switch(i)
{
case 1:
temperatura=time_temperatura[0];
break;
case 3:
temperatura=(time_temperatura[0]+time_temperatura[1]+time_temperatura[2])/3;
break;
}
return temperatura;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма получения времени с часов ds3231 и их присваивание переменным.
void poluchenie_wremeni()
{
// считываем данные с часов
byte tempBuffer;
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x00));
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
tempBuffer = Wire.read();
h12 = tempBuffer & 0b01000000;
if (h12)
{
PM = tempBuffer & 0b00100000;
hour = bcdToDec(tempBuffer & 0b00011111);
}
else
{
hour = bcdToDec(tempBuffer & 0b00111111);
}
byte DoW = Wire.read();
date = bcdToDec(Wire.read());
month = bcdToDec(Wire.read() & 0b01111111);
year = bcdToDec(Wire.read());
// Ежечасно сохраняем в переменные содержащиеся в EEPROM установленные: время начала временных периодов и их температуры, адреса датчиков температур
if(minute!=24)
{
obnovl_peremen==0; // обнуляем переменную, если минуты не равны 24.
}
if(minute==24 && obnovl_peremen==0) //
{
nachal_ustanovki();
obnovl_peremen++; // для исключения обращения к подпрограмме nachal_ustanovki() более одного раза когда минуты равны 24.
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма записи времени в часы ds3231.
void zapis_wremeni()
{
byte time_hour=hour;
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x02));
Wire.endTransmission();
Wire.requestFrom(0x68, 1);
h12 = (Wire.read() & 0b01000000);
if (h12)
{
if(time_hour > 12)
{
time_hour = decToBcd(time_hour-12) | 0b01100000;
}
else
{
time_hour = decToBcd(time_hour) & 0b11011111;
}
}
else
{
time_hour = decToBcd(time_hour) & 0b10111111;
}
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x00));
Wire.write(0x00);
Wire.write(decToBcd(minute));
Wire.write(time_hour);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x04));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма преобразования данных полученных с часов
byte bcdToDec(byte val)
{
return ((val/16*10) + (val%16));
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма преобразования данных для записи в часы
byte decToBcd(byte val)
{
return ((val/10*16) + (val%10));
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM часов и минут начала временных режимов
void read_eeprom_time_periodov()
{
for(byte z=0; z<6; z++)
{
nachalo_periodov[z]=EEPROM.read(z);
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM установленных температур
void read_eeprom_ustan_temper()
{
for(byte z=6; z<9; z++)
{
nachalo_periodov[z]=EEPROM.read(z);
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM адресов датчиков температур
void read_eeprom_adres_datch()
{
for(byte z=0; z<8; z++)
{
adres_dat_temp_room[z]=EEPROM.read(z+10); // адрес комнатного датчика
adres_dat_temp_street[z]=EEPROM.read(z+20); // адрес уличного датчика
adres_dat_temp_water[z]=EEPROM.read(z+30); // адрес датчика котловой воды
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма определения временного периода (ночного, утреннего или дневного).
void opredelenie_perioda_wremeni()
{
// перевод часов и минут в минуты для удобства последующего сравнения
summa_minut[0]=hour*60+minute; // для последующего сравнения часы и минуты текущего времени, полученных с часов, переводим в общее количество минут
summa_minut[1]=nachalo_periodov[0]*60+nachalo_periodov[1]; // общая сумма минут начала ночного периода
summa_minut[2]=nachalo_periodov[2]*60+nachalo_periodov[3]; // общая сумма минут начала утреннего периода
summa_minut[3]=nachalo_periodov[4]*60+nachalo_periodov[5]; // общая сумма минут начала дневного периода
// определениe ночного периода и сохранение в переменной period_time значения 0, что означает ночь.
if(summa_minut[0]>=summa_minut[1] || summa_minut[0]<summa_minut[2])
{
period_time=0;
}
// определениe утреннего периода и сохранение в переменной period_time значения 1, что означает утро.
if(summa_minut[0]>=summa_minut[2] && summa_minut[0]<summa_minut[3])
{
period_time=1;
}
// определениe дневного периода и сохранение в переменной period_time значения 2, что означает день.
if(summa_minut[0]>=summa_minut[3] && summa_minut[0]<summa_minut[1])
{
period_time=2;
}
}
//////////////////////////////////////////////////////////////////////////////
// подпрограмма грубой проверки считанной температуры
/*
Считанная температура сверяется с последней записанной в память температурой (защита от грубых ошибок).
Если разница более чем на 3 градуса как в большую так и в меньшую сторону, то запускаем повторное считывание температуры,
иначе статусу проверки присваиваем true и завершается подпрограмма.
Если повторно считанная температура также более чем на 3 градуса как в большую так и в меньшую сторону, то статусу проверки
выставляем false, иначе true и возвращаемся в основное тело проги.
*/
void proverka_temperatury_room()
{
if(temperatura_room>=temperatura_room_pamyat[2]-3 && temperatura_room<=temperatura_room_pamyat[2]+3)
{
proverka_temperatura_room_status=true;
}
else
{
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3);
if(temperatura_room>=temperatura_room_pamyat[2]-3 && temperatura_room<=temperatura_room_pamyat[2]+3)
{
proverka_temperatura_room_status=true;
}
else
{
proverka_temperatura_room_status=false;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма определения выхода комнатной температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
void wyhod_temp_room_predel()
{
byte schetchik_wyhoda_temp_room_predel;
if(temperatura_room<18 || temperatura_room>26)
{
schetchik_wyhoda_temp_room_predel++;
}
switch(schetchik_wyhoda_temp_room_predel)
{
case 1:
time_snach_progi_wychod_predel_temp=millis();
break;
case 10:
if(formirovanie_intervala(time_snach_progi_wychod_predel_temp)-time_snachala_progi<360000)
{
// здесь указать, что будет выполняться, если в течение 6 минут комнатная температура выходила за пределы
schetchik_wyhoda_temp_room_predel=0;
time_snach_progi_wychod_predel_temp=time_snachala_progi;
}
else
{
schetchik_wyhoda_temp_room_predel=0;
time_snach_progi_wychod_predel_temp=time_snachala_progi;
}
break;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма определения отсутствия в течение длительного времени данных от комнатного датчика температуры, то есть наличия проблем с ним.
void problem_datch_room()
{
time_snach_progi_problem_datch_room;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма сравнения полученной с датчика температуры и хранящихся в памяти последних 3 показаний с границами заданной пользователем температуры и управление выходом.
// с целью исключения тактования и возможных краткосрочных незначительных измерений температуры (например открытие окна или двери, дуновение ветра) переключение выхода
// происходит только, если 3 последних показаний температуры также находятся за границами заданной пользователем температуры.
void sravnenie_temp_room_upravl_wychod()
{
if(proverka_temperatura_room_status==true) // сначла проверяем прохождение проверки на наличие грубок ошибок. Если да, то переходим к сравнению.
{
// если считанная температура и последние 3 показания меньше нижней границы заданной пользователем температуры и на управляемом выходе 0, то данный выход переключается в 1 (котел включается).
if(digitalRead(relekotla)==LOW)
{
if(temperatura_room<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[0]<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[1]<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[2]<temperatura_room_ustanovka[period_time]-gisteresis)
{
digitalWrite(relekotla, HIGH);
}
}
// если считанная температура и последние 3 показания большее верхней границы заданной пользователем температуры и на управляемом выходе 1, то данный выход переключается в 0 (котел выключается).
if(digitalRead(relekotla)==HIGH)
{
if(temperatura_room>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[0]>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[1]>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[2]>temperatura_room_ustanovka[period_time]+gisteresis)
{
digitalWrite(relekotla, LOW);
}
}
// сдвиг хранящейся темпрературы. При этом считанную температуру записываем в самую последнюю переменную
temperatura_room_pamyat[0]=temperatura_room_pamyat[1];
temperatura_room_pamyat[1]=temperatura_room_pamyat[2];
temperatura_room_pamyat[2]=temperatura_room;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма первоначальных установок начала временных периодов и температур
/* Если при считывании из EEPROM задаваемые пользователем время начала периодов и температуры выходят за рамки
установленных программой пределов,то устанавливаются заложенные программой данные.
*/
void nachal_ustanovki()
{
// считываем данные из EEPROM установленные данные (часы и минуты начала временных периодов и температуры)
read_eeprom_time_periodov();
read_eeprom_ustan_temper();
read_eeprom_adres_datch();
// Часы и минуты начала временных периодов проверяем на наличие ошибок(не соответствие временному интервалу) и при необходимости записываем в соответствующие переменные.
if(nachalo_periodov[0]<18 || nachalo_periodov[0]>23) // Если считанные из EEPROM часы начала ночи меньше 18 или больше 23, тогда в память и переменную записывам 21.
{
EEPROM.write(0, 21);
delay(100);
nachalo_periodov[0]=21;
}
if(nachalo_periodov[1]<0 || nachalo_periodov[1]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 30.
{
EEPROM.write(1, 30);
delay(100);
nachalo_periodov[1]=30;
}
if(nachalo_periodov[2]>10 || nachalo_periodov[2]<3) // Если считанные из EEPROM часы начала утра меньше 3 или больше 10 часов, тогда в память и переменную записывам 6.
{
EEPROM.write(2, 6);
delay(100);
nachalo_periodov[2]=6;
}
if(nachalo_periodov[3]<0 || nachalo_periodov[3]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 0.
{
EEPROM.write(3, 0);
delay(100);
nachalo_periodov[3]=0;
}
if(nachalo_periodov[4]>12 || nachalo_periodov[4]<6) // Если считанные из EEPROM часы начала дня меньше 6 или больше 12 часов, тогда в память и переменную записывам 9.
{
EEPROM.write(4, 9);
delay(100);
nachalo_periodov[4]=9;
}
if(nachalo_periodov[5]<0 || nachalo_periodov[5]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 0.
{
EEPROM.write(5, 0);
delay(100);
nachalo_periodov[5]=0;
}
// Температуры проверям на соответствие периоду 10-35 градусов и при необходимости записываем в соответствующие переменные.
if(temperatura_room_ustanovka[0]>35 || temperatura_room_ustanovka[0]<10) // если считанная из EEPROM температура ночного периода меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 19.
EEPROM.write(6, 19);
delay(100);
temperatura_room_ustanovka[0]=19;
}
if(temperatura_room_ustanovka[1]>35 || temperatura_room_ustanovka[1]<10) // если считанная из EEPROM температура утреннего периода меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 23.
EEPROM.write(7, 23);
delay(100);
temperatura_room_ustanovka[1]=23;
}
if(temperatura_room_ustanovka[2]>35 || temperatura_room_ustanovka[2]<10) // если считанная из EEPROM температура дневного период меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 21.
EEPROM.write(8, 21);
delay(100);
temperatura_room_ustanovka[2]=21;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "Ночь"
void wywod_na_lcd_slova_Noch()
{
lcd.print("Ho");
lcd.write(6);
lcd.write(4);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "Утро"
void wywod_na_lcd_slova_Utro()
{
lcd.write(7);
lcd.write(8);
lcd.print("po");
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "День"
void wywod_na_lcd_slova_Den()
{
lcd.write(3);
lcd.print("e");
lcd.write(5);
lcd.write(4);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd температуры со значком градуса
void wywod_na_lcd_temper(float wywod_temper)
{
if(wywod_temper<10)
{
lcd.print(" ");
}
lcd.print(wywod_temper, 1);
lcd.write(2);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd времени-часов
void wywod_na_lcd_hour(byte wywod_hour)
{
if(wywod_hour<10)
{
lcd.print(" ");
}
lcd.print(wywod_hour);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd времени-минут
void wywod_na_lcd_min(byte wywod_minute)
{
if(wywod_minute<10)
{
lcd.print("0");
}
lcd.print(wywod_minute);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода текущих данных на lcd дисплей при переходе из основной программы
// с целью исключения повтороного вывода на дисплей информации, которая не изенилась с прошлого обращения к подпрограмме, производиться ее сравнение
void wywod_na_lcd_tekusch()
{
// формируем сначала вывод информации, которая меняется относительно редко (часы, минуты, температура)
//////////////// верхняя строка lcd
// вывод текущего времени
if(hour!=hour_predyd)
{
lcd.setCursor(0, 0);
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов
hour_predyd=hour;
}
if(minute!=minute_predyd)
{
lcd.setCursor(3, 0);
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - минут
minute_predyd=minute;
}
// вывод комнатной температуры и значка градус
if(temperatura_room!=temperatura_room_predyd)
{
lcd.setCursor(11, 0);
wywod_na_lcd_temper(temperatura_room); // переход к подпрограмме вывода на lcd температуры со значком градуса
lcd.setCursor(15, 0); // обрезаем второй знак после запятой и ставим вместо него значок градуса
lcd.write(2);
temperatura_room_predyd=temperatura_room;
}
//////////////// нижняя строка lcd
// вывод уличной температуры
if(temperatura_street!=temperatura_street_predyd)
{
lcd.setCursor(7, 1);
lcd.print("Out");
lcd.setCursor(11, 1);
if(temperatura_street>=0)
{
lcd.print(" ");
}
lcd.print(temperatura_street, 1);
lcd.setCursor(15, 1);
lcd.write(2);
temperatura_street_predyd=temperatura_street;
//
}
// формирование мигающего двоеточия между часами и минутами (0,75 сек. светятся, 0,45 не светятся)
unsigned long miganie_dvoet=formirovanie_intervala(time_snach_progi_migania_dvoet);
lcd.setCursor(2, 0);
if(miganie_dvoet<750) // 0,75 сек знаки светятся
{
lcd.print(":");
}
else
{
lcd.print(" ");
}
if(miganie_dvoet>1200)
{
time_snach_progi_migania_dvoet=time_snachala_progi;
}
// последовательный вывод названия временного периода и, если котел включен, то сведения об этом
// первые 0,5 сек. ничего нет
unsigned long miganie_sost_kotla=formirovanie_intervala(time_snach_progi_migania_sost_kotla);
lcd.setCursor(6, 0);
// первые 0,5 сек. ничего нет
if(miganie_sost_kotla<500)
{
lcd.print(" ");
}
// вывод первой буквы названия режима
if(miganie_sost_kotla>500 && miganie_sost_kotla<=1250)
{
switch(period_time)
{
case 0:
lcd.print("H");
break;
case 1:
lcd.write(7);
break;
case 2:
lcd.write(3);
break;
}
lcd.print(" ");
}
// вывод 1-й и 2-й букв названия режима
if(miganie_sost_kotla>1250 && miganie_sost_kotla<=2000)
{
switch(period_time)
{
case 0:
lcd.print("Ho");
break;
case 1:
lcd.write(7);
lcd.write(8);
break;
case 2:
lcd.write(3);
lcd.print("e");
break;
}
lcd.print(" ");
}
// вывод 1-й, 2-й и 3-й букв названия режима
if(miganie_sost_kotla>2000 && miganie_sost_kotla<=2750)
{
switch (period_time)
{
case 0:
lcd.print("Ho");
lcd.write(6);
break;
case 1:
lcd.write(7);
lcd.write(8);
lcd.print("p");
break;
case 2:
lcd.write(3);
lcd.print("e");
lcd.write(5);
break;
}
lcd.print(" ");
}
// вывод всего слова названия режима
if(miganie_sost_kotla>2750 && miganie_sost_kotla<=3500)
{
switch (period_time)
{
case 0:
lcd.print("Ho");
lcd.write(6);
lcd.write(4);
break;
case 1:
lcd.write(7);
lcd.write(8);
lcd.print("po");
break;
case 2:
lcd.write(3);
lcd.print("e");
lcd.write(5);
lcd.write(4);
break;
}
}
// Если на выходе котла 0, то обнуляем временной интервал для повторного вывода временного периода
if(miganie_sost_kotla>3500 && digitalRead(relekotla)==LOW)
{
time_snach_progi_migania_sost_kotla=time_snachala_progi;
miganie_sost_kotla=formirovanie_intervala(time_snach_progi_migania_sost_kotla);
}
// 0,5 сек. ничего нет
if(miganie_sost_kotla>3500 && miganie_sost_kotla<=4000)
{
lcd.print(" ");
}
// далее, если на выход котла 1, то выводим значки пламени
if(miganie_sost_kotla>4000 && miganie_sost_kotla<=4750)
{
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем два значка пламени
if(miganie_sost_kotla>4750 && miganie_sost_kotla<=5500)
{
lcd.write(1);
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем три значка пламени
if(miganie_sost_kotla>5500 && miganie_sost_kotla<=6250)
{
lcd.write(1);
lcd.write(1);
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем четыре значка пламени
if(miganie_sost_kotla>6250 && miganie_sost_kotla<=7000)
{
lcd.write(1);
lcd.write(1);
lcd.write(1);
lcd.write(1);
}
// обнуляем временной показатель
if(miganie_sost_kotla>7000)
{
time_snach_progi_migania_sost_kotla=time_snachala_progi;
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма формирования интервала мигания выбранного для изменения параметра при нахождении в меню программирования
void miganie_parametra_lcd()
{
unsigned long miganie_parametra=formirovanie_intervala(time_snach_progi_parametra_menu);
if(miganie_parametra<=750)
{
miganie_parametra_programmirovaniya=true;
}
else
{
miganie_parametra_programmirovaniya=false;
}
if(miganie_parametra>1200)
{
time_snach_progi_parametra_menu=time_snachala_progi;
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма программирования - установки времени, начала временных периодов(ночи, утра и дня), температуры временных периодов и записи (удаления) адресов датчиков температуры
void programmirovanie()
{
// считываем из EEPROM часы и минуты начала временных периодов, установленных температур и адреса датчиков, а также текущие дату и время
read_eeprom_time_periodov();
read_eeprom_ustan_temper();
read_eeprom_adres_datch();
poluchenie_wremeni(); // переход к подпрограмме считывания времени с часов
time_snach_progi_wychoda_menu=millis(); // для формирования интервала с нуля.
time_snach_progi_parametra_menu=time_snach_progi_wychoda_menu; // для формирования интервала мигания выбранного для изменения параметра
lcd.clear();
delay(1000);
// создаем циклический опрос нажатия кнопок, вывод изображения данных на lcd
cikl_programm:
wdt_reset();
if(formirovanie_intervala(time_snach_progi_wychoda_menu)>interval_wychoda_menu || status_programmirovaniya==0)
{
goto na_wychod; // если интервал достиг задаваемого программистом и не нажата ни одна кнопка, то осуществляется выход из подпрограммы программирования
}
opredel_nashat_knopok(); // переход к подпрограмме определения нажатия кнопок
nashata_knopka_pravo(); // переход к подпрограмме и выполнение действий при нажатии кнопки право
nashata_knopka_levo(); // переход к подпрограмме и выполнение действий при нажатии кнопки лево
nashata_knopka_verch(); // переход к подпрограмме и выполнение действий при нажатии кнопки верх
nashata_knopka_vniz(); // переход к подпрограмме и выполнение действий при нажатии кнопки вниз
nashata_knopka_select(); // переход к подпрограмме и выполнение действий при нажатии кнопки select
miganie_parametra_lcd(); // переход к подпрограмме определения продожительности мигания выбранного в меню параметра
opredel_stranizy_lcd(); // переход к подпрограмме, которая определяет, какую из двух страниц выводить на lcd
goto cikl_programm;
// завершение цикла опроса кнопок и т.д.
na_wychod:
status_programmirovaniya=1;
lcd.clear();
// первоначальный вывод на lcd текущих данных
lcd.setCursor(0, 0);
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов
lcd.setCursor(3, 0);
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - минут
lcd.setCursor(11, 0);
wywod_na_lcd_temper(temperatura_room); // переход к подпрограмме вывода на lcd температуры со значком градуса
lcd.setCursor(15, 0); // обрезаем второй знак после запятой и ставим вместо него значок градуса
lcd.write(2);
lcd.setCursor(7, 1);
lcd.print("Out");
lcd.setCursor(10, 1);
if(temperatura_street>=0)
{
lcd.print(" ");
}
wywod_na_lcd_temper(temperatura_street);
}
//////////////////////////////////////////////////////////////////////////////
// подпрограмма определения нажатия кнопок
void opredel_nashat_knopok()
{
int temp_temp=1023;
temp_temp=analogRead(0); // считываем данные
//определяем нажатие кнопки "ВВЕРХ" (показатель 99)
if(temp_temp>50 && temp_temp<150)
{
knopka_verch=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ВНИЗ" (показатель 255)
if(temp_temp>200 && temp_temp<300)
{
knopka_vniz=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ПРАВО" (показатель 0)
if(temp_temp<30)
{
knopka_pravo=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ЛЕВО" (показатель 409)
if(temp_temp>350 && temp_temp<500)
{
knopka_levo=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
// определяем нажатие кнопки Select (показатель 639)
if(temp_temp>550 && temp_temp<750)
{
knopka_select=true;
time_snach_progi_wychoda_menu=millis();
}
temp_temp=1023;
delay(200);
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка право
void nashata_knopka_pravo()
{
if(knopka_pravo==true)
{
knopka_pravo=false;
// на 1-й странице
if(status_programmirovaniya>=1 && status_programmirovaniya<=6)
{
if(status_programmirovaniya==6)
{
status_programmirovaniya=1;
}
else
{
status_programmirovaniya++;
}
}
// на 2-й странице
if(status_programmirovaniya>=11 && status_programmirovaniya<=15)
{
if(status_programmirovaniya==15)
{
status_programmirovaniya=11;
}
else
{
status_programmirovaniya++;
}
}
// на 3-й странице
if(status_programmirovaniya>=21 && status_programmirovaniya<=25)
{
if(status_programmirovaniya==25)
{
status_programmirovaniya=21;
}
else
{
status_programmirovaniya++;
}
}
// на 4-й странице
if(status_programmirovaniya>=31 && status_programmirovaniya<=35)
{
if(status_programmirovaniya==35)
{
status_programmirovaniya=31;
}
else
{
status_programmirovaniya++;
}
}
// на 5-й странице
if(status_programmirovaniya>=41 && status_programmirovaniya<=47)
{
if(status_programmirovaniya==47)
{
status_programmirovaniya=41;
}
else
{
status_programmirovaniya++;
}
}
// на 6-й странице
if(status_programmirovaniya>=51 && status_programmirovaniya<=55)
{
if(status_programmirovaniya==55)
{
status_programmirovaniya=51;
}
else
{
status_programmirovaniya++;
}
}
// на 7-й странице
if(status_programmirovaniya==61 || status_programmirovaniya==62)
{
if(status_programmirovaniya==62)
{
status_programmirovaniya=61;
}
else
{
status_programmirovaniya++;
}
}
// на 8-й странице
if(status_programmirovaniya==71 || status_programmirovaniya==72)
{
if(status_programmirovaniya==72)
{
status_programmirovaniya=71;
}
else
{
status_programmirovaniya++;
}
}
// на 9-й странице
if(status_programmirovaniya==81 || status_programmirovaniya==82)
{
if(status_programmirovaniya==82)
{
status_programmirovaniya=81;
}
else
{
status_programmirovaniya++;
}
}
// на 11-й странице
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
if(status_programmirovaniya==103)
{
status_programmirovaniya=101;
}
else
{
status_programmirovaniya++;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка лево
void nashata_knopka_levo()
{
if(knopka_levo==true)
{
knopka_levo=false;
// на 1-й странице
if(status_programmirovaniya>=1 && status_programmirovaniya<=6)
{
if(status_programmirovaniya==1)
{
status_programmirovaniya=6;
}
else
{
status_programmirovaniya--;
}
}
// на 2-й странице
if(status_programmirovaniya>=11 && status_programmirovaniya<=15)
{
if(status_programmirovaniya==11)
{
status_programmirovaniya=15;
}
else
{
status_programmirovaniya--;
}
}
// на 3-й странице
if(status_programmirovaniya>=21 && status_programmirovaniya<=25)
{
if(status_programmirovaniya==21)
{
status_programmirovaniya=25;
}
else
{
status_programmirovaniya--;
}
}
// на 4-й странице
if(status_programmirovaniya>=31 && status_programmirovaniya<=35)
{
if(status_programmirovaniya==31)
{
status_programmirovaniya=35;
}
else
{
status_programmirovaniya--;
}
}
// на 5-й странице
if(status_programmirovaniya>=41 && status_programmirovaniya<=47)
{
if(status_programmirovaniya==41)
{
status_programmirovaniya=47;
}
else
{
status_programmirovaniya--;
}
}
// на 6-й странице
if(status_programmirovaniya>=51 && status_programmirovaniya<=55)
{
if(status_programmirovaniya==51)
{
status_programmirovaniya=55;
}
else
{
status_programmirovaniya--;
}
}
// на 7-й странице
if(status_programmirovaniya==61 || status_programmirovaniya==62)
{
if(status_programmirovaniya==61)
{
status_programmirovaniya=62;
}
else
{
status_programmirovaniya--;
}
}
// на 8-й странице
if(status_programmirovaniya==71 || status_programmirovaniya==72)
{
if(status_programmirovaniya==71)
{
status_programmirovaniya=72;
}
else
{
status_programmirovaniya--;
}
}
// на 9-й странице
if(status_programmirovaniya==81 || status_programmirovaniya==82)
{
if(status_programmirovaniya==81)
{
status_programmirovaniya=82;
}
else
{
status_programmirovaniya--;
}
}
// на 11-й странице
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
if(status_programmirovaniya==101)
{
status_programmirovaniya=103;
}
else
{
status_programmirovaniya--;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка верх
void nashata_knopka_verch()
{
if(knopka_verch==true)
{
knopka_verch=false;
if(status_programmirovaniya==14 || status_programmirovaniya==24 || status_programmirovaniya==34 || status_programmirovaniya==46 || status_programmirovaniya==102)
{
if(status_wybora_save==false)
{
status_wybora_save=true;
}
else
{
status_wybora_save=false;
}
}
switch(status_programmirovaniya)
{
// увеличиваем часы начала ночного периода
case 11:
if(nachalo_periodov[0]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[0]=0;
}
else
{
nachalo_periodov[0]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала ночного периода
case 12:
if(nachalo_periodov[1]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[1]=0;
}
else
{
nachalo_periodov[1]++; // увеличиваем показатель
}
break;
// увеличиваем температуру ночного периода
case 13:
if(temperatura_room_ustanovka[0]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[0]=10;
}
else
{
temperatura_room_ustanovka[0]++; // увеличиваем показатель
}
break;
// увеличиваем часы начала утреннего периода
case 21:
if(nachalo_periodov[2]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[2]=0;
}
else
{
nachalo_periodov[2]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала утреннего периода
case 22:
if(nachalo_periodov[3]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[3]=0;
}
else
{
nachalo_periodov[3]++; // увеличиваем показатель
}
break;
// увеличиваем температуру утреннего периода
case 23:
if(temperatura_room_ustanovka[1]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[1]=10;
}
else
{
temperatura_room_ustanovka[1]++; // увеличиваем показатель
}
break;
// увеличиваем часы начала дневного периода
case 31:
if(nachalo_periodov[4]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[4]=0;
}
else
{
nachalo_periodov[4]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала утреннего периода
case 32:
if(nachalo_periodov[5]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[5]=0;
}
else
{
nachalo_periodov[5]++; // увеличиваем показатель
}
break;
// увеличиваем температуру утреннего периода
case 33:
if(temperatura_room_ustanovka[2]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[2]=10;
}
else
{
temperatura_room_ustanovka[2]++; // увеличиваем показатель
}
break;
// увеличиваем часы текущего времени
case 41:
if(hour==23) // часы должны быть в пределах от 0 до 24.
{
hour=0;
}
else
{
hour++; // увеличиваем показатель
}
break;
// увеличиваем минуты текущего времени
case 42:
if(minute==59) // минуты должны быть в пределах от 0 по 59.
{
minute=0;
}
else
{
minute++; // увеличиваем показатель
}
break;
// увеличиваем текущую дату
case 43:
if(date==31) // число должно быть в пределах от 1 до 31.
{
date=1;
}
else
{
date++; // увеличиваем показатель
}
break;
// увеличиваем текущий месяц
case 44:
if(month==12)
{
month=1;
}
else
{
month++; // увеличиваем показатель
}
break;
// увеличиваем текущий год
case 45:
if(year==99) // год не может быть больше 99.
{
year=0;
}
else
{
year++; // увеличиваем показатель
}
break;
// изменяем присваемый подключенныому датчику статус - комнатный, уличный или водяной
case 101:
if(wybor_status_zapis_datch==3)
{
wybor_status_zapis_datch=1;
}
else
{
wybor_status_zapis_datch++;
}
break;
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка вниз
void nashata_knopka_vniz()
{
if(knopka_vniz==true)
{
knopka_vniz=false;
if(status_programmirovaniya==14 || status_programmirovaniya==24 || status_programmirovaniya==34 || status_programmirovaniya==46 || status_programmirovaniya==102)
{
if(status_wybora_save==false)
{
status_wybora_save=true;
}
else
{
status_wybora_save=false;
}
}
switch(status_programmirovaniya)
{
// уменьшаем часы начала ночного периода
case 11:
if(nachalo_periodov[0]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[0]=23;
}
else
{
nachalo_periodov[0]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала ночного периода
case 12:
if(nachalo_periodov[1]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[1]=59;
}
else
{
nachalo_periodov[1]--; // увеличиваем показатель
}
break;
// уменьшаем температуру ночного периода
case 13:
if(temperatura_room_ustanovka[0]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[0]=35;
}
else
{
temperatura_room_ustanovka[0]--; // увеличиваем показатель
}
break;
// уменьшаем часы начала утреннего периода
case 21:
if(nachalo_periodov[2]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[2]=23;
}
else
{
nachalo_periodov[2]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала утреннего периода
case 22:
if(nachalo_periodov[3]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[3]=59;
}
else
{
nachalo_periodov[3]--; // увеличиваем показатель
}
break;
// уменьшаем температуру утреннего периода
case 23:
if(temperatura_room_ustanovka[1]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[1]=35;
}
else
{
temperatura_room_ustanovka[1]--; // увеличиваем показатель
}
break;
// уменьшаем часы начала дневного периода
case 31:
if(nachalo_periodov[4]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[4]=23;
}
else
{
nachalo_periodov[4]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала утреннего периода
case 32:
if(nachalo_periodov[5]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[5]=59;
}
else
{
nachalo_periodov[5]--; // увеличиваем показатель
}
break;
// уменьшаем температуру утреннего периода
case 33:
if(temperatura_room_ustanovka[2]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[2]=35;
}
else
{
temperatura_room_ustanovka[2]--; // увеличиваем показатель
}
break;
// уменьшаем часы текущего времени
case 41:
if(hour==0) // часы должны быть в пределах от 0 до 24.
{
hour=23;
}
else
{
hour--; // увеличиваем показатель
}
break;
// уменьшаем минуты текущего времени
case 42:
if(minute==0) // минуты должны быть в пределах от 0 по 59.
{
minute=59;
}
else
{
minute--; // увеличиваем показатель
}
break;
// уменьшаем текущую дату
case 43:
if(date==1) // число должно быть в пределах от 1 до 31.
{
date=31;
}
else
{
date--; // увеличиваем показатель
}
break;
// уменьшаем текущий месяц
case 44:
if(month==1)
{
month=12;
}
else
{
month--; // увеличиваем показатель
}
break;
// уменьшаем текущий год
case 45:
if(year==0) // год не может быть больше 99.
{
year=99;
}
else
{
year--; // увеличиваем показатель
}
break;
// изменяем присваемый подключенныому датчику статус - комнатный, уличный или водяной
case 101:
if(wybor_status_zapis_datch==1)
{
wybor_status_zapis_datch=3;
}
else
{
wybor_status_zapis_datch--;
}
break;
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка select
void nashata_knopka_select()
{
if(knopka_select==true)
{
knopka_select=false; // для исключения учитывания факта нажатой кнопки при переходах из меню в подменю и обратно
switch(status_programmirovaniya)
{
// переходы в подменю или выход из меню
case 1:
status_programmirovaniya=11; // переход в подменю установок параметров ночного режима
break;
case 2:
status_programmirovaniya=21; // переход в подменю установок параметров утреннего режима
break;
case 3:
status_programmirovaniya=31; // переход в подменю установок параметров дневного режима
break;
case 4:
status_programmirovaniya=41; // переход в подменю установок текущих даты и времени
break;
case 5:
status_programmirovaniya=51; // переход в подменю датчики
break;
case 6:
status_programmirovaniya=0; // команда на выход
break;
// сохранение параметров ночного периода, при условии выбора Yes
case 14:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(0, nachalo_periodov[0]);
delay(100);
EEPROM.write(1, nachalo_periodov[1]);
delay(100);
EEPROM.write(6, temperatura_room_ustanovka[0]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю ночного периода в основное меню
case 15:
status_programmirovaniya=1;
break;
// сохранение параметров утреннего периода, при условии выбора Yes
case 24:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(2, nachalo_periodov[2]);
delay(100);
EEPROM.write(3, nachalo_periodov[3]);
delay(100);
EEPROM.write(7, temperatura_room_ustanovka[1]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю утреннего периода в основное меню
case 25:
status_programmirovaniya=1;
break;
// сохранение параметров дневного периода, при условии выбора Yes
case 34:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(4, nachalo_periodov[4]);
delay(100);
EEPROM.write(5, nachalo_periodov[5]);
delay(100);
EEPROM.write(8, temperatura_room_ustanovka[8]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю дневного периода в основное меню
case 35:
status_programmirovaniya=1;
break;
// сохранение текущих даты и времени, при условии выбора Yes
case 46:
if(status_wybora_save==true)
{
status_wybora_save=false;
zapis_wremeni();
}
status_programmirovaniya=1;
break;
// выход из подменю часов в основное меню
case 47:
status_programmirovaniya=1;
break;
// переход из подменю датчики в подменю комнантный датчик
case 51:
status_programmirovaniya=62;
break;
// переход из подменю датчики в подменю уличный датчик
case 52:
status_programmirovaniya=72;
break;
// переход из подменю датчики в подменю водяной датчик
case 53:
status_programmirovaniya=82;
break;
// переход из подменю датчики в подменю новый датчик
case 54:
proverka_podkluch_datchikov_temp(); // сначала переход в подпрограмму определения новых подключенных датчиков
status_programmirovaniya=91; // переход в подменю новый датчик
break;
// переход из подменю датчики в основное меню
case 55:
status_programmirovaniya=1;
break;
// удаление комнатного датчика
case 61:
for(byte h1=0; h1<8; h1++)
{
EEPROM.write(h1+10, 255);
adres_dat_temp_room[h1]=255;
delay(100);
}
break;
// переход из подменю уличный датчик в основное меню
case 62:
status_programmirovaniya=51;
break;
// удаление уличного датчика
case 71:
for(byte h2=0; h2<8; h2++)
{
EEPROM.write(h2+20, 255);
adres_dat_temp_street[h2]=255;
delay(100);
}
break;
// переход из подменю уличный датчик в основное меню
case 72:
status_programmirovaniya=51;
break;
// удаление водяного датчика
case 81:
for(byte h3=0; h3<8; h3++)
{
EEPROM.write(h3+30, 255);
adres_dat_temp_water[h3]=255;
delay(100);
}
break;
// переход из подменю водяной датчик в основное меню
case 82:
status_programmirovaniya=51;
break;
// переход из подменю новый датчик в подменю датчики
case 91:
status_programmirovaniya=51;
break;
// сохранение выбранного статуса датчику температуры и запись его адреса в EEPROM, при условии выбора Yes
case 102:
if(status_wybora_save==true)
{
status_wybora_save=false;
for(byte x1=0; x1<8; x1++)
{
if(status_schit_datch_new[0]==true)
{
temp_adres[x1]=temp_adres_datch_1[x1];
}
if(status_schit_datch_new[1]==true)
{
temp_adres[x1]=temp_adres_datch_2[x1];
}
if(status_schit_datch_new[2]==true)
{
temp_adres[x1]=temp_adres_datch_3[x1];
}
EEPROM.write(x1+wybor_status_zapis_datch*10, temp_adres[x1]);
delay(100);
}
}
status_programmirovaniya=51;
break;
// переход из записи нового датчика в подменю датчики
case 103:
status_programmirovaniya=51;
break;
}
}
}
//////////////////////////////////////////////////////////
// подпрограмма определения выводимой на lcd страницы с учетом нажатых кнопок "ПРАВО", "ЛЕВО" и "Select"
void opredel_stranizy_lcd()
{
if(status_programmirovaniya>0 && status_programmirovaniya<7)
{
straniza_programmirovaniya_1();
}
if(status_programmirovaniya>10 && status_programmirovaniya<16)
{
straniza_programmirovaniya_2();
}
if(status_programmirovaniya>20 && status_programmirovaniya<26)
{
straniza_programmirovaniya_3();
}
if(status_programmirovaniya>30 && status_programmirovaniya<36)
{
straniza_programmirovaniya_4();
}
if(status_programmirovaniya>40 && status_programmirovaniya<48)
{
straniza_programmirovaniya_5();
}
if(status_programmirovaniya>50 && status_programmirovaniya<56)
{
straniza_programmirovaniya_6();
}
if(status_programmirovaniya>60 && status_programmirovaniya<63)
{
straniza_programmirovaniya_7();
}
if(status_programmirovaniya>70 && status_programmirovaniya<73)
{
straniza_programmirovaniya_8();
}
if(status_programmirovaniya>80 && status_programmirovaniya<83)
{
straniza_programmirovaniya_9();
}
if(status_programmirovaniya>90 && status_programmirovaniya<92)
{
straniza_programmirovaniya_10();
}
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
straniza_programmirovaniya_11();
}
}
////////////////////////////////////////
// подпрограмма формирования изображения 1-й страницы на lcd (1 строка - ночь, день, утро; 2 строка - часы, датчики, выход из программирования)
void straniza_programmirovaniya_1()
{
// 1 строка
// с 0 позиции - Ночь
lcd.setCursor(0, 0);
if(status_programmirovaniya==1 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Noch(); // переход к подпрограмме вывода слова "Ночь"
}
lcd.print(" ");
// с 6 позиции - Утро
lcd.setCursor(6, 0);
if(status_programmirovaniya==2 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Utro(); // переход к подпрограмме вывода слова "Утро"
}
lcd.print(" ");
// с 12 позиции - День
lcd.setCursor(12, 0);
if(status_programmirovaniya==3 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Den(); // переход к подпрограмме вывода слова "День"
}
// 2 строка
// с 0 позиции - Часы
lcd.setCursor(0, 1);
if(status_programmirovaniya==4 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Time ");
}
// с 6 позиции - Датчики
lcd.setCursor(6, 1);
if(status_programmirovaniya==5 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.write(3);
lcd.print("a");
lcd.write(8);
lcd.write(6);
lcd.print(" ");
}
// с 12 позиции - Выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==6 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 2-й страницы на lcd (1 строка - ночь, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_2()
{
// 1 строка
// с 0 позиции - Ночь
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Noch(); // переход к подпрограмме вывода слова "Ночь"
lcd.print(" ");
// с 5 позиции - часы начала ночного периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==11 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[0]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала ночного периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==12 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[1]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура ночного периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==13 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[0]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==14 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==15 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 3-й страницы на lcd (1 строка - утро, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_3()
{
// 1 строка
// с 0 позиции - Утро
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Utro(); // переход к подпрограмме вывода слова "Утро"
lcd.print(" ");
// с 5 позиции - часы начала утреннего периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==21 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[2]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала утреннего периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==22 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[3]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура утреннего периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==23 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[1]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==24 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==25 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 4-й страницы на lcd (1 строка - день, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_4()
{
// 1 строка
// с 0 позиции - День
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Den(); // переход к подпрограмме вывода слова "День"
lcd.print(" ");
// с 5 позиции - часы и минуты начала дневного периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==31 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[4]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала утреннего периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==32 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[5]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура дневного периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==33 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[2]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==34 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==35 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 5-й страницы на lcd (1 строка - текущие часы, минуты, число, месяц и год; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_5()
{
// 1 строка
// с 0 позиции - часы
lcd.setCursor(0, 0);
if(status_programmirovaniya==41 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов и минут через двоеточие
}
lcd.print(":");
lcd.setCursor(3, 0);
if(status_programmirovaniya==42 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - часов и минут через двоеточие
}
lcd.print(" ");
// с 6 позиции - текущее число
lcd.setCursor(6, 0);
if(status_programmirovaniya==43 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(date<10)
{
lcd.print(" ");
}
lcd.print(date);
}
lcd.print("-");
// с 9 позиции - текущий месяц
lcd.setCursor(9, 0);
if(status_programmirovaniya==44 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(month<10)
{
lcd.print("0");
}
lcd.print(month);
}
lcd.print("-20");
// с 14 позиции - текущий год
lcd.setCursor(14, 0);
if(status_programmirovaniya==45 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(year<10)
{
lcd.print("0");
}
lcd.print(year);
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==46 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==47 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 6-й страницы на lcd (1 строка - комнатный, уличный и водяной датчики; 2 строка - новый датчик, выход на 1 стр.)
void straniza_programmirovaniya_6()
{
// 1 строка
// с 0 позиции - комнатный датчик D-room
lcd.setCursor(0, 0);
if(status_programmirovaniya==51 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Room");
}
lcd.setCursor(4, 0);
lcd.print(" ");
// с 5 позиции - уличный
lcd.setCursor(5, 0);
if(status_programmirovaniya==52 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Stret ");
}
// с 11 позиции - водяной
lcd.setCursor(11, 0);
if(status_programmirovaniya==53 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Water");
}
// 1 строка
// с позиции 0 - новый датчик - New
lcd.setCursor(0, 1);
if(status_programmirovaniya==54 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("New ");
}
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==55 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 7-й страницы на lcd (1 строка - комнатный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_7()
{
// 1 строка
// с 0 позиции - комнатный датчик Room
lcd.setCursor(0, 0);
lcd.print("Room ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==61 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==62 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f1=0; f1<8; f1++)
{
lcd.print(adres_dat_temp_room[f1], HEX);
}
lcd.print(" ");
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 8-й страницы на lcd (1 строка - уличный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_8()
{
// 1 строка
// с 0 позиции - уличный датчик Stret
lcd.setCursor(0, 0);
lcd.print("Stret ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==71 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==72 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f2=0; f2<8; f2++)
{
lcd.print(adres_dat_temp_street[f2], HEX);
}
lcd.print(" ");
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 9-й страницы на lcd (1 строка - датчик котловой воды, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_9()
{
// 1 строка
// с 0 позиции - уличный датчик Stret
lcd.setCursor(0, 0);
lcd.print("Water ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==81 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==82 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f3=0; f3<8; f3++)
{
lcd.print(adres_dat_temp_water[f3], HEX);
}
lcd.print(" ");
}
//////////////////////////////////////////////////////////
// подпрограмма формирования страницы 10-й страницы на lcd (1 строка - надпись, что новых датчиков нет или их больше одного. 2 строка - выход)
void straniza_programmirovaniya_10()
{
if(kolvo_new_datch==0)
{
lcd.setCursor(0, 0);
lcd.print("No new datchik ");
lcd.setCursor(0, 1);
if(status_programmirovaniya==91 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
// вывод инфы на дисплей о подключении более 1 нового датчика и необходимости выключения и выключения устройства с 1 новым датчиком для его записи в EEPROM и присвоения ему статуса: комнатного, уличного и котловой воды
if(kolvo_new_datch>1)
{
lcd.setCursor(0, 0);
lcd.print("New datch > 1 ");
lcd.setCursor(0,1);
if(status_programmirovaniya==91 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
if(kolvo_new_datch==1)
{
status_programmirovaniya=101;
}
}
//////////////////////////////////////////////////////////
// подпрограмма формирования страницы 11-й страницы на lcd (1 строка - надпись, что новых датчиков нет или их больше одного. 2 строка - выход)
void straniza_programmirovaniya_11()
{
// 1 строка
lcd.setCursor(0, 0);
lcd.print("NewDat Vid:");
lcd.setCursor(11, 0);
if(status_programmirovaniya==101 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
switch(wybor_status_zapis_datch)
{
case 1:
lcd.print("Room ");
break;
case 2:
lcd.print("Stret");
break;
case 3:
lcd.print("Water");
break;
}
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==102 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==103 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма проверки адресов подключенных датчиков температуры на их соответствие данным, содержащимся в EEPROM.
void proverka_podkluch_datchikov_temp()
{
// считываем адреса датчиков, содержащиеся в EEPROM
read_eeprom_adres_datch();
// считываем адреса подключенных датчиков температуры
for(byte b=1; b<4; b++)
{
ds.reset();
ds.search(temp_adres);
for(byte i=0; i<8; i++)
{
switch(b)
{
case 1:
temp_adres_datch_1[i]=temp_adres[i];
break;
case 2:
temp_adres_datch_2[i]=temp_adres[i];
break;
case 3:
temp_adres_datch_3[i]=temp_adres[i];
break;
}
}
}
ds.reset();
ds.search(sss); // нужна для исключения ошибок, так как командой search последний датчик считывывается два раза. Результат этой команды не используется
////////////////////////////////////
// Проверяем на отсутствие какого-либо датчика и исключения дальнейших ошибок от возможной записи в в несколько переменных одного и того же адреса
// Если в адресе 3 считанного датчика содержится адрес 2 считанного датчика, то записываем нули
if(temp_adres_datch_3[0]==temp_adres_datch_2[0] && temp_adres_datch_3[1]==temp_adres_datch_2[1] && temp_adres_datch_3[2]==temp_adres_datch_2[2] && temp_adres_datch_3[3]==temp_adres_datch_2[3] &&
temp_adres_datch_3[4]==temp_adres_datch_2[4] && temp_adres_datch_3[5]==temp_adres_datch_2[5] && temp_adres_datch_3[6]==temp_adres_datch_2[6] && temp_adres_datch_3[7]==temp_adres_datch_2[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_3[qwerty]=0;
}
}
// Если в адресе 3 считанного датчика содержится адрес 1 считанного датчика, то записываем нули
if(temp_adres_datch_3[0]==temp_adres_datch_1[0] && temp_adres_datch_3[1]==temp_adres_datch_1[1] && temp_adres_datch_3[2]==temp_adres_datch_1[2] && temp_adres_datch_3[3]==temp_adres_datch_1[3] &&
temp_adres_datch_3[4]==temp_adres_datch_1[4] && temp_adres_datch_3[5]==temp_adres_datch_1[5] && temp_adres_datch_3[6]==temp_adres_datch_1[6] && temp_adres_datch_3[7]==temp_adres_datch_1[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_3[qwerty]=0;
}
}
// Если в адресе 2 считанного датчика содержится адрес 1 считанного датчика, то записываем нули
if(temp_adres_datch_2[0]==temp_adres_datch_1[0] && temp_adres_datch_2[1]==temp_adres_datch_1[1] && temp_adres_datch_2[2]==temp_adres_datch_1[2] && temp_adres_datch_2[3]==temp_adres_datch_1[3] &&
temp_adres_datch_2[4]==temp_adres_datch_1[4] && temp_adres_datch_2[5]==temp_adres_datch_1[5] && temp_adres_datch_2[6]==temp_adres_datch_1[6] && temp_adres_datch_2[7]==temp_adres_datch_1[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_2[qwerty]=0;
}
}
kolvo_new_datch=0;
// сравниваем считанные адреса подключенных датчиков и содержащиеся в памяти
// датчик с адресом temp_adres_datch_1
if(temp_adres_datch_1[0]==0x28)
{
if(temp_adres_datch_1[0]==adres_dat_temp_room[0] && temp_adres_datch_1[1]==adres_dat_temp_room[1] && temp_adres_datch_1[2]==adres_dat_temp_room[2] && temp_adres_datch_1[3]==adres_dat_temp_room[3] &&
temp_adres_datch_1[4]==adres_dat_temp_room[4] && temp_adres_datch_1[5]==adres_dat_temp_room[5] && temp_adres_datch_1[6]==adres_dat_temp_room[6] && temp_adres_datch_1[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[0]=false;
}
else
{
if(temp_adres_datch_1[0]==adres_dat_temp_street[0] && temp_adres_datch_1[1]==adres_dat_temp_street[1] && temp_adres_datch_1[2]==adres_dat_temp_street[2] && temp_adres_datch_1[3]==adres_dat_temp_street[3] &&
temp_adres_datch_1[4]==adres_dat_temp_street[4] && temp_adres_datch_1[5]==adres_dat_temp_street[5] && temp_adres_datch_1[6]==adres_dat_temp_street[6] && temp_adres_datch_1[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[0]=false;
}
else
{
if(temp_adres_datch_1[0]==adres_dat_temp_water[0] && temp_adres_datch_1[1]==adres_dat_temp_water[1] && temp_adres_datch_1[2]==adres_dat_temp_water[2] && temp_adres_datch_1[3]==adres_dat_temp_water[3] &&
temp_adres_datch_1[4]==adres_dat_temp_water[4] && temp_adres_datch_1[5]==adres_dat_temp_water[5] && temp_adres_datch_1[6]==adres_dat_temp_water[6] && temp_adres_datch_1[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[0]=false;
}
else
{
status_schit_datch_new[0]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[0]=false;
}
// датчик с адресом temp_adres_datch_2
if(temp_adres_datch_2[0]==0x28)
{
if(temp_adres_datch_2[0]==adres_dat_temp_room[0] && temp_adres_datch_2[1]==adres_dat_temp_room[1] && temp_adres_datch_2[2]==adres_dat_temp_room[2] && temp_adres_datch_2[3]==adres_dat_temp_room[3] &&
temp_adres_datch_2[4]==adres_dat_temp_room[4] && temp_adres_datch_2[5]==adres_dat_temp_room[5] && temp_adres_datch_2[6]==adres_dat_temp_room[6] && temp_adres_datch_2[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[1]=false;
}
else
{
if(temp_adres_datch_2[0]==adres_dat_temp_street[0] && temp_adres_datch_2[1]==adres_dat_temp_street[1] && temp_adres_datch_2[2]==adres_dat_temp_street[2] && temp_adres_datch_2[3]==adres_dat_temp_street[3] &&
temp_adres_datch_2[4]==adres_dat_temp_street[4] && temp_adres_datch_2[5]==adres_dat_temp_street[5] && temp_adres_datch_2[6]==adres_dat_temp_street[6] && temp_adres_datch_2[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[1]=false;
}
else
{
if(temp_adres_datch_2[0]==adres_dat_temp_water[0] && temp_adres_datch_2[1]==adres_dat_temp_water[1] && temp_adres_datch_2[2]==adres_dat_temp_water[2] && temp_adres_datch_2[3]==adres_dat_temp_water[3] &&
temp_adres_datch_2[4]==adres_dat_temp_water[4] && temp_adres_datch_2[5]==adres_dat_temp_water[5] && temp_adres_datch_2[6]==adres_dat_temp_water[6] && temp_adres_datch_2[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[1]=false;
}
else
{
status_schit_datch_new[1]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[1]=false;
}
// датчик с адресом temp_adres_datch_3
if(temp_adres_datch_3[0]==0x28)
{
if(temp_adres_datch_3[0]==adres_dat_temp_room[0] && temp_adres_datch_3[1]==adres_dat_temp_room[1] && temp_adres_datch_3[2]==adres_dat_temp_room[2] && temp_adres_datch_3[3]==adres_dat_temp_room[3] &&
temp_adres_datch_3[4]==adres_dat_temp_room[4] && temp_adres_datch_3[5]==adres_dat_temp_room[5] && temp_adres_datch_3[6]==adres_dat_temp_room[6] && temp_adres_datch_3[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[2]=false;
}
else
{
if(temp_adres_datch_3[0]==adres_dat_temp_street[0] && temp_adres_datch_3[1]==adres_dat_temp_street[1] && temp_adres_datch_3[2]==adres_dat_temp_street[2] && temp_adres_datch_3[3]==adres_dat_temp_street[3] &&
temp_adres_datch_3[4]==adres_dat_temp_street[4] && temp_adres_datch_3[5]==adres_dat_temp_street[5] && temp_adres_datch_3[6]==adres_dat_temp_street[6] && temp_adres_datch_3[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[2]=false;
}
else
{
if(temp_adres_datch_3[0]==adres_dat_temp_water[0] && temp_adres_datch_3[1]==adres_dat_temp_water[1] && temp_adres_datch_3[2]==adres_dat_temp_water[2] && temp_adres_datch_3[3]==adres_dat_temp_water[3] &&
temp_adres_datch_3[4]==adres_dat_temp_water[4] && temp_adres_datch_3[5]==adres_dat_temp_water[5] && temp_adres_datch_3[6]==adres_dat_temp_water[6] && temp_adres_datch_3[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[2]=false;
}
else
{
status_schit_datch_new[2]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[2]=false;
}
}
/////////////////////////////////////////////////////////////////////////////
void setup()
{
wdt_disable(); // останавливаем таймер перезагрузки
Wire.begin(); // старт интерфейса I2C (выводы 4 и 5 для UNO). Необходим для часов.
// инициализация выхода управления реле котла
pinMode(relekotla, OUTPUT); // вывод, предназначенный для управления котлом, устанавливаем как выход
digitalWrite(relekotla, LOW); // устанавливаем на выходе управления котлом 0
lcd.begin(16, 2); // включаем lcd
lcd.createChar(1, znak_lcd_plamya); // региструем индивидуальный знак в виде пламени
lcd.createChar(2, znak_lcd_gradus); // региструем индивидуальный знак в виде градуса
lcd.createChar(3, znak_lcd_D_Rus);
lcd.createChar(4, znak_lcd_b_Rus);
lcd.createChar(5, znak_lcd_n_Rus);
lcd.createChar(6, znak_lcd_ch_Rus);
lcd.createChar(7, znak_lcd_u_Rus);
lcd.createChar(8, znak_lcd_t_Rus);
poluchenie_wremeni(); // считываем время с часов
opredelenie_perioda_wremeni(); // для моментального отражения на Lcd временного периода после включения и не ждать истечения задаваемого интервала
nachal_ustanovki(); // переход к подпрограмме считывания данных из EEPROM и их проверке
lcd.clear();
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3);
for(byte rrr=0; rrr<3; rrr++)
{
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // 3 раза считываем температуру и записываемх их в переменные temperatura_pamyat[] для исключения ошибок при сравнении.
temperatura_room_pamyat[rrr]=temperatura_room;
}
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1);
lcd.clear();
wdt_enable(WDTO_8S); // запускае таймер перезагрузки с длительностью 8 сек.
}
///////////////////////////////////////////////////////////////////
void loop()
{
nashat_knopka=analogRead(0); // постоянно считываем данные с аналогового входа
// определяем факт нажатия кнопки Select (показатель 639) в течение 3 секунд для перехода к подпрограмме программирования
if(nashat_knopka>550&&nashat_knopka<750)
{
nashat_knopka=1023; // для исключения ошибок присваиваем переменной значение, равное состоянию, когда ни одна из кнопок не нажата
delay(3000); // необходиая длительность удержания кнопки Select для перехода в режим программирования
nashat_knopka=analogRead(0);
if(nashat_knopka>550&&nashat_knopka<750)
{
nashat_knopka=1023; // для исключения ошибок присваиваем переменной значение, равное состоянию, когда ни одна из кнопок не нажата
programmirovanie();
}
}
wywod_na_lcd_tekusch(); // переход к подпрограмме вывода текущих данных на дисплей.
//////
poluchenie_wremeni(); // переход к подпрограмме считывания времени с ds3231
opredelenie_perioda_wremeni(); // переход к подпрограмме определения временного периода (ночного, утреннего или дневного) и присваивания переменной "temperatura_sravnenia" заданной пользователем температуры для последующего сравненния со считанной.
// проверяем достижение необходимого интервала для запуска подпрограммы считывания комнатной температуры
if(formirovanie_intervala(time_snach_progi_dat_room)>interval_zapuska_dat_room)
{
time_snach_progi_dat_room=time_snachala_progi;
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // переход к подпрограмме считывания температуры с уличного датчика температуры. 3 - кол-во считываний
wyhod_temp_room_predel(); // переход к подпрограмме определения выхода температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
}
// проверяем достижение необходимого интервала для запуска подпрограммы считывания уличной температуры
if(formirovanie_intervala(time_snach_progi_dat_street)>interval_zapuska_dat_street)
{
time_snach_progi_dat_street=time_snachala_progi;
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1); // переход к подпрограмме считывания температуры с уличного датчика температуры. 1 - кол-во считываний
}
proverka_temperatury_room(); // переход к подпрограмме проверки считанной температуры на наличие грубых ошибок
sravnenie_temp_room_upravl_wychod(); // переход к подпрограмме сравнения полученной с датчика температуры с установленными пользователем температурами с учетом времени и выполнение команд на включение или выключение котла
problem_datch_room(); // переход к подпрограмме определения отсутствия ответа от комнатного датчика в течение длительного времени
wdt_reset(); // обнуляем таймер перезагрузки
}
[/code]
[code]
/* Программа "Комнатный термостат"
Допоборудование - ds18b20(вывод 2 )- 3 датчика (комнатный, уличный, на котловую воду), ds3231(выводы 5-SCL и 4-SDA) и lcd1602.
Функция - замеряет температуру в помещении и на основании ее сравнения с установленными пользователями включает или выключает нагрузку.
Принцип работы:
1) пользователем устанавливаются время начала временных периода - ночного, утреннего и дневного.
2) пользователем устанавливаются температуры каждого временного периода - ночью, утром и днем.
3) в основном цикле программы постоянно считываются данные с часов ds3231, которые заносятся в соответствующие переменные.
4) через устанавливаемый пользователем в тексте программы интервал (сейчас равен 30 с.) считывается температура с датчика (три замера, высчитывается среднеарифмитическая).
5) затем определяется текущий временной период (ночь, утро или день).
6) считанная температура проверяется на наличие ошибки, то есть сравнивается с последней сохранненной в памяти.
7) считанная температура сравнивается с установленной пользователем температурой текущего временного периода и при выходе температуры за границы включается ил выключатеся котел.
*/
////////////////////////////////////////////////////////////////
// подключение необходимых библиотек
#include <OneWire.h> // для протокола 1-Wire
#include <Wire.h> // для протокола I2C
#include <LiquidCrystal.h> // для lcd
#include <EEPROM.h> // для обращения к энергонезависимой памяти
#include <wdt.h> // библиотека сторожевого таймера
// адреса EEPROM, по которым хранятся задаваемые пользователем параметры:
// 0-часы начала ночного периода, 1-минуты начала ночного периода, 2-часы начала утреннего периода, 3 - минуты начала утреннего периода, 4-часы начала дневного периода,
// 5-минуты начала дневного периода, 6-температура ночного периода, 7-температура утреннего периода, 8-температура дневного периода.
// 10-17 - адрес комнатного датчика температуры, 20-27 - адрес уличного датчика температуры, 30-37 - адрес датчика температуры котловой воды
////////////////////////////////////////////////////////////////
// определяем вывод для протокола 1-Wire
OneWire ds(2); // для Uno (провод припаянн на 2 вывод
// определяем вывод, который будет управлять включением/выключением котла по результатам сравнения температур
byte relekotla=3; // то же для Uno.
// определяем вывод для lcd
//LiquidCrystal lcd(RS, E, DB4, DB5, DB6, DB7)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // LCD для Uno - Keypad Schild
////////////////////////////////////////////////////////////////
// формируем 3 знака (маленькая, средняя и большая стрелки вверх), которые будут отражаться на lcd
// и свидетельствовать, что на выходе управления установлен HIGH, то есть котел включен на обогрев.
enum {symbol_height=8};
byte znak_lcd_plamya[symbol_height]= // знак в виде пламени. Если нужен другой, то закомментировать.
{
B00010,
B00110,
B01100,
B11100,
B11110,
B01111,
B01110,
B00100,
};
byte znak_lcd_gradus[symbol_height]= // знак градус.
{
B00100,
B01010,
B00100,
B00000,
B00000,
B00000,
B00000,
B00000,
};
byte znak_lcd_D_Rus[symbol_height]= // буква "Д".
{
B01111,
B00101,
B00101,
B00101,
B01001,
B10001,
B11111,
B10001,
};
byte znak_lcd_b_Rus[symbol_height]= // буква "ь".
{
B00000,
B00000,
B10000,
B10000,
B11110,
B10001,
B11110,
B00000,
};
byte znak_lcd_n_Rus[symbol_height]= // буква "н" .
{
B00000,
B00000,
B10001,
B10001,
B11111,
B10001,
B10001,
B00000,
};
byte znak_lcd_ch_Rus[symbol_height]= // буква "ч" .
{
B00000,
B00000,
B10001,
B10001,
B01111,
B00001,
B00001,
B00000,
};
byte znak_lcd_u_Rus[symbol_height]= // буква "У" .
{
B10001,
B10001,
B10001,
B01010,
B00100,
B01000,
B10000,
B00000,
};
byte znak_lcd_t_Rus[symbol_height]= // буква "т" .
{
B00000,
B00000,
B11111,
B00100,
B00100,
B00100,
B00100,
B00000,
};
/*
byte znak_lcd_l_Rus[symbol_height]= // буква "л" .
{
B00000,
B00000,
B01111,
B00101,
B00101,
B10101,
B01001,
B00000,
};
byte znak_lcd_CH_Rus[symbol_height]= // буква "Ч" .
{
B10001,
B10001,
B10001,
B01111,
B00001,
B00001,
B00001,
B00000,
};
byte znak_lcd_bl_Rus[symbol_height]= // буква "ы" .
{
B00000,
B00000,
B10001,
B10001,
B11101,
B10011,
B11101,
B00000,
};
*/
////////////////////////////////////////////////////////////////
// объявляем переменные
// временные переменные для считывания адресов с подключенных датчиков
byte temp_adres[8];
byte temp_adres_datch_1[8]; // для считывания адреса 1-го подключенного датчика
byte temp_adres_datch_2[8];
byte temp_adres_datch_3[8];
byte kolvo_new_datch=0; // содержит кол-во новых подключенных датчиков
boolean status_schit_datch_new[3];
byte sss[8];
// для подпрограммы formirovanie_intervala().
unsigned int interval_zapuska_dat_room=30000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с комнатного датчика. Он равен 30 сек.
unsigned long interval_zapuska_dat_street=180000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с уличного датчика. Он равен 3 мин.
unsigned int interval_wychoda_menu=15000; // интервал в милисекундах, через который будет осуществляться выход из подпрограммы программирования
unsigned long time_snachala_progi; // содержит текущие данные о времени, прошедшем сначала запуска программы. Для формирования интеравала .
unsigned long time_snach_progi_dat_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания комнатной температуры
unsigned long time_snach_progi_dat_street=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания уличной температуры
unsigned long time_snach_progi_wychoda_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала выхода из подпрограммы программирования
unsigned long time_snach_progi_migania_dvoet=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания двоеточия
unsigned long time_snach_progi_migania_sost_kotla=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания состояния котла
unsigned long time_snach_progi_parametra_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания выбранного параметра меню
unsigned long time_snach_progi_problem_datch_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала отсутствия ответа от комнатного датчика температуры
unsigned long time_snach_progi_wychod_predel_temp=0;
boolean miganie_parametra_programmirovaniya=true; // когда true светится выбранный параметр, false - вместо параметра пробелы.
// содержит предыдущие данные о времени, прошедшем с начала запуска программы для формирования мигания
// для работы с температурой
byte adres_dat_temp_room[8]; // для хранения адреса комнатаного датчика температуры
byte adres_dat_temp_street[8]; // для хранения адреса уличного датчика температуры
byte adres_dat_temp_water[8]; // для хранения адреса датчика температуры котловой воды
float temperatura_room; // считанная с комнатного датчика температура
float temperatura_street; // считанная с уличного датчика температура
float temperatura_water; // считанная с датчика котловой воды температура
float temperatura_room_pamyat[3]; // последние 3 считанных температуры (для проверки считанной температуры на наличие ошибок и исключения тактования)
byte temperatura_room_ustanovka[3]; // в них считываются из EEPROM задаваемые пользователем температуры временных периодов: 0-ночь, 1-утро, 2-день.
float gisteresis=0.2; // задаваемый пользователем гистерезис для определения температурных границ управления выходом
boolean proverka_temperatura_room_status; // содержит информацию о том, прошла ли считанная температура проверку на наличие грубых ошибок: true-да; false-нет.
float temperatura_room_predyd=0, temperatura_street_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
// для работы со временем
bool Century=false; // для часов. Пока не знаю??????????????????????
bool h12; // для часов. Пока не знаю??????????????????????
bool PM; // для часов. Пока не знаю??????????????????????
byte year, month, date, hour, minute, second; // в них записываются полученные от часов данные о времени
byte hour_predyd=0, minute_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
byte nachalo_periodov[6]; // в них считываются из EEPROM часы и минуты начала периодов: 0-часы ночи, 1-минуты ночи, 2-часы утра, 3-минуты утра, 4-часы дня, 5-минуты дня.
byte period_time; // для храненения сведений о временном периоде (ночь-0, утро-1, день-2)
int summa_minut[4]; // общие суммы минут: 0-текущего времени, 1-начала ночного периода, 2-начала утреннего периода, 3-начала дневного периода, для удобства сравнения
byte obnovl_peremen=0; // необходима для ежечасного считывания данных из EEPROM и их записи в соответствующие переменные
// для подпрограммы программирования
byte status_programmirovaniya=1; // содержит число на основании которого устанавливается тот или иной параметр
boolean knopka_verch=false; // содержит состояние кнопки "ВВЕРХ", по умолчанию false
boolean knopka_vniz=false; // содержит состояние кнопки "ВНИЗ", по умолчанию false
boolean knopka_pravo=false; // содержит состояние кнопки "ПРАВО" по умолчанию false
boolean knopka_levo=false; // содержит состояние кнопки "ЛЕВО", по умолчанию false
boolean knopka_select=false; // содержит состояние кнопки select, по умолчанию false
int nashat_knopka=1023; // содержит данные с аналогового входа 0
boolean status_wybora_delete=false; // содержит состояние необходимости удаления датчика температуры из EEPROM
boolean status_wybora_save=false; // содержит состояние необходимости сохранения измененных параметров
byte wybor_status_zapis_datch=1; // содержит число (1, 2 или 3), свидетельствующее о том, каким именно (комнатным, уличным или водяным) записывается новый датчик в EEPROM
///////////////////////////////////////////////////////////////
// подпрограмма формирования задаваемого интервала между обращениями к подпрограммам считывания температуры с датчика и получения времени с часов.
unsigned long formirovanie_intervala(unsigned long time_snachala_progi_time_pred)
{
time_snachala_progi=millis(); // получаем количество милисекунд с начала выполнения программы
// Проверяем, не проскочил ли счетчик прошедшего времени через 0, если предыдущие показания не достигли максимума.
// Если проскочил то к обоим сравниваемым переменным добавляем число из tempintervalzapuska и 100, чтобы вторая переменная также перескочила через 0.
if (time_snachala_progi_time_pred>time_snachala_progi) // если текущие сведения о прошедшем времени меньше предыдущих данных, то это свидетельствует о том, что счетчик перескочил через 0.
{
time_snachala_progi_time_pred=time_snachala_progi_time_pred+185000; // 185000 необходимо для максимального интервала 3 минуты.
time_snachala_progi=time_snachala_progi+185000;
}
unsigned long time_interval=time_snachala_progi-time_snachala_progi_time_pred; // высчитываем пройденный интервал
return time_interval;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания температуры с датчика.
float schit_datchik_temperatury(byte time_adres_dat_temp[], byte i)
{
float time_temperatura[i]; // объявляем переменные для временного хранения температуры из 3 последовательных замеров
for(byte cikl=0; cikl<i; cikl++)
{
ds.reset();
ds.write(0xCC); // игнорируем адреса всех датчиков для следующей команды
ds.write(0x44); // запуск преобразования температуры всеми датчиками.
delay(200);
ds.reset();
ds.select(time_adres_dat_temp); // следующая команда предназначется только комнатному датчику
ds.write(0xBE); // чтение двух байт с данными температуры из памяти датчика
byte data[2];
data[0]=ds.read(); // присваивание переменной data[0] данных первого байта, полученного от датчика
data[1]=ds.read(); // присваивание переменной data[1] данных второго байта, полученного от датчика
time_temperatura[cikl]=((data[1] << 8)|data[0])/16.0; // высчитываем температуру и заносим во временную переменную
}
float temperatura;
switch(i)
{
case 1:
temperatura=time_temperatura[0];
break;
case 3:
temperatura=(time_temperatura[0]+time_temperatura[1]+time_temperatura[2])/3;
break;
}
return temperatura;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма получения времени с часов ds3231 и их присваивание переменным.
void poluchenie_wremeni()
{
// считываем данные с часов
byte tempBuffer;
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x00));
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
tempBuffer = Wire.read();
h12 = tempBuffer & 0b01000000;
if (h12)
{
PM = tempBuffer & 0b00100000;
hour = bcdToDec(tempBuffer & 0b00011111);
}
else
{
hour = bcdToDec(tempBuffer & 0b00111111);
}
byte DoW = Wire.read();
date = bcdToDec(Wire.read());
month = bcdToDec(Wire.read() & 0b01111111);
year = bcdToDec(Wire.read());
// Ежечасно сохраняем в переменные содержащиеся в EEPROM установленные: время начала временных периодов и их температуры, адреса датчиков температур
if(minute!=24)
{
obnovl_peremen==0; // обнуляем переменную, если минуты не равны 24.
}
if(minute==24 && obnovl_peremen==0) //
{
nachal_ustanovki();
obnovl_peremen++; // для исключения обращения к подпрограмме nachal_ustanovki() более одного раза когда минуты равны 24.
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма записи времени в часы ds3231.
void zapis_wremeni()
{
byte time_hour=hour;
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x02));
Wire.endTransmission();
Wire.requestFrom(0x68, 1);
h12 = (Wire.read() & 0b01000000);
if (h12)
{
if(time_hour > 12)
{
time_hour = decToBcd(time_hour-12) | 0b01100000;
}
else
{
time_hour = decToBcd(time_hour) & 0b11011111;
}
}
else
{
time_hour = decToBcd(time_hour) & 0b10111111;
}
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x00));
Wire.write(0x00);
Wire.write(decToBcd(minute));
Wire.write(time_hour);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(uint8_t(0x04));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма преобразования данных полученных с часов
byte bcdToDec(byte val)
{
return ((val/16*10) + (val%16));
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма преобразования данных для записи в часы
byte decToBcd(byte val)
{
return ((val/10*16) + (val%10));
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM часов и минут начала временных режимов
void read_eeprom_time_periodov()
{
for(byte z=0; z<6; z++)
{
nachalo_periodov[z]=EEPROM.read(z);
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM установленных температур
void read_eeprom_ustan_temper()
{
for(byte z=6; z<9; z++)
{
nachalo_periodov[z]=EEPROM.read(z);
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма считывания из EEPROM адресов датчиков температур
void read_eeprom_adres_datch()
{
for(byte z=0; z<8; z++)
{
adres_dat_temp_room[z]=EEPROM.read(z+10); // адрес комнатного датчика
adres_dat_temp_street[z]=EEPROM.read(z+20); // адрес уличного датчика
adres_dat_temp_water[z]=EEPROM.read(z+30); // адрес датчика котловой воды
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма определения временного периода (ночного, утреннего или дневного).
void opredelenie_perioda_wremeni()
{
// перевод часов и минут в минуты для удобства последующего сравнения
summa_minut[0]=hour*60+minute; // для последующего сравнения часы и минуты текущего времени, полученных с часов, переводим в общее количество минут
summa_minut[1]=nachalo_periodov[0]*60+nachalo_periodov[1]; // общая сумма минут начала ночного периода
summa_minut[2]=nachalo_periodov[2]*60+nachalo_periodov[3]; // общая сумма минут начала утреннего периода
summa_minut[3]=nachalo_periodov[4]*60+nachalo_periodov[5]; // общая сумма минут начала дневного периода
// определениe ночного периода и сохранение в переменной period_time значения 0, что означает ночь.
if(summa_minut[0]>=summa_minut[1] || summa_minut[0]<summa_minut[2])
{
period_time=0;
}
// определениe утреннего периода и сохранение в переменной period_time значения 1, что означает утро.
if(summa_minut[0]>=summa_minut[2] && summa_minut[0]<summa_minut[3])
{
period_time=1;
}
// определениe дневного периода и сохранение в переменной period_time значения 2, что означает день.
if(summa_minut[0]>=summa_minut[3] && summa_minut[0]<summa_minut[1])
{
period_time=2;
}
}
//////////////////////////////////////////////////////////////////////////////
// подпрограмма грубой проверки считанной температуры
/*
Считанная температура сверяется с последней записанной в память температурой (защита от грубых ошибок).
Если разница более чем на 3 градуса как в большую так и в меньшую сторону, то запускаем повторное считывание температуры,
иначе статусу проверки присваиваем true и завершается подпрограмма.
Если повторно считанная температура также более чем на 3 градуса как в большую так и в меньшую сторону, то статусу проверки
выставляем false, иначе true и возвращаемся в основное тело проги.
*/
void proverka_temperatury_room()
{
if(temperatura_room>=temperatura_room_pamyat[2]-3 && temperatura_room<=temperatura_room_pamyat[2]+3)
{
proverka_temperatura_room_status=true;
}
else
{
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3);
if(temperatura_room>=temperatura_room_pamyat[2]-3 && temperatura_room<=temperatura_room_pamyat[2]+3)
{
proverka_temperatura_room_status=true;
}
else
{
proverka_temperatura_room_status=false;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма определения выхода комнатной температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
void wyhod_temp_room_predel()
{
byte schetchik_wyhoda_temp_room_predel;
if(temperatura_room<18 || temperatura_room>26)
{
schetchik_wyhoda_temp_room_predel++;
}
switch(schetchik_wyhoda_temp_room_predel)
{
case 1:
time_snach_progi_wychod_predel_temp=millis();
break;
case 10:
if(formirovanie_intervala(time_snach_progi_wychod_predel_temp)-time_snachala_progi<360000)
{
// здесь указать, что будет выполняться, если в течение 6 минут комнатная температура выходила за пределы
schetchik_wyhoda_temp_room_predel=0;
time_snach_progi_wychod_predel_temp=time_snachala_progi;
}
else
{
schetchik_wyhoda_temp_room_predel=0;
time_snach_progi_wychod_predel_temp=time_snachala_progi;
}
break;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма определения отсутствия в течение длительного времени данных от комнатного датчика температуры, то есть наличия проблем с ним.
void problem_datch_room()
{
time_snach_progi_problem_datch_room;
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма сравнения полученной с датчика температуры и хранящихся в памяти последних 3 показаний с границами заданной пользователем температуры и управление выходом.
// с целью исключения тактования и возможных краткосрочных незначительных измерений температуры (например открытие окна или двери, дуновение ветра) переключение выхода
// происходит только, если 3 последних показаний температуры также находятся за границами заданной пользователем температуры.
void sravnenie_temp_room_upravl_wychod()
{
if(proverka_temperatura_room_status==true) // сначла проверяем прохождение проверки на наличие грубок ошибок. Если да, то переходим к сравнению.
{
// если считанная температура и последние 3 показания меньше нижней границы заданной пользователем температуры и на управляемом выходе 0, то данный выход переключается в 1 (котел включается).
if(digitalRead(relekotla)==LOW)
{
if(temperatura_room<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[0]<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[1]<temperatura_room_ustanovka[period_time]-gisteresis && temperatura_room_pamyat[2]<temperatura_room_ustanovka[period_time]-gisteresis)
{
digitalWrite(relekotla, HIGH);
}
}
// если считанная температура и последние 3 показания большее верхней границы заданной пользователем температуры и на управляемом выходе 1, то данный выход переключается в 0 (котел выключается).
if(digitalRead(relekotla)==HIGH)
{
if(temperatura_room>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[0]>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[1]>temperatura_room_ustanovka[period_time]+gisteresis && temperatura_room_pamyat[2]>temperatura_room_ustanovka[period_time]+gisteresis)
{
digitalWrite(relekotla, LOW);
}
}
// сдвиг хранящейся темпрературы. При этом считанную температуру записываем в самую последнюю переменную
temperatura_room_pamyat[0]=temperatura_room_pamyat[1];
temperatura_room_pamyat[1]=temperatura_room_pamyat[2];
temperatura_room_pamyat[2]=temperatura_room;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма первоначальных установок начала временных периодов и температур
/* Если при считывании из EEPROM задаваемые пользователем время начала периодов и температуры выходят за рамки
установленных программой пределов,то устанавливаются заложенные программой данные.
*/
void nachal_ustanovki()
{
// считываем данные из EEPROM установленные данные (часы и минуты начала временных периодов и температуры)
read_eeprom_time_periodov();
read_eeprom_ustan_temper();
read_eeprom_adres_datch();
// Часы и минуты начала временных периодов проверяем на наличие ошибок(не соответствие временному интервалу) и при необходимости записываем в соответствующие переменные.
if(nachalo_periodov[0]<18 || nachalo_periodov[0]>23) // Если считанные из EEPROM часы начала ночи меньше 18 или больше 23, тогда в память и переменную записывам 21.
{
EEPROM.write(0, 21);
delay(100);
nachalo_periodov[0]=21;
}
if(nachalo_periodov[1]<0 || nachalo_periodov[1]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 30.
{
EEPROM.write(1, 30);
delay(100);
nachalo_periodov[1]=30;
}
if(nachalo_periodov[2]>10 || nachalo_periodov[2]<3) // Если считанные из EEPROM часы начала утра меньше 3 или больше 10 часов, тогда в память и переменную записывам 6.
{
EEPROM.write(2, 6);
delay(100);
nachalo_periodov[2]=6;
}
if(nachalo_periodov[3]<0 || nachalo_periodov[3]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 0.
{
EEPROM.write(3, 0);
delay(100);
nachalo_periodov[3]=0;
}
if(nachalo_periodov[4]>12 || nachalo_periodov[4]<6) // Если считанные из EEPROM часы начала дня меньше 6 или больше 12 часов, тогда в память и переменную записывам 9.
{
EEPROM.write(4, 9);
delay(100);
nachalo_periodov[4]=9;
}
if(nachalo_periodov[5]<0 || nachalo_periodov[5]>59) // Если считанные из EEPROM минуты меньше 0 или больше 59, тогда в память и переменную записывам 0.
{
EEPROM.write(5, 0);
delay(100);
nachalo_periodov[5]=0;
}
// Температуры проверям на соответствие периоду 10-35 градусов и при необходимости записываем в соответствующие переменные.
if(temperatura_room_ustanovka[0]>35 || temperatura_room_ustanovka[0]<10) // если считанная из EEPROM температура ночного периода меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 19.
EEPROM.write(6, 19);
delay(100);
temperatura_room_ustanovka[0]=19;
}
if(temperatura_room_ustanovka[1]>35 || temperatura_room_ustanovka[1]<10) // если считанная из EEPROM температура утреннего периода меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 23.
EEPROM.write(7, 23);
delay(100);
temperatura_room_ustanovka[1]=23;
}
if(temperatura_room_ustanovka[2]>35 || temperatura_room_ustanovka[2]<10) // если считанная из EEPROM температура дневного период меньше 10 или выше 35 градусов,
{ // тогда в память и переменную записывам 21.
EEPROM.write(8, 21);
delay(100);
temperatura_room_ustanovka[2]=21;
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "Ночь"
void wywod_na_lcd_slova_Noch()
{
lcd.print("Ho");
lcd.write(6);
lcd.write(4);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "Утро"
void wywod_na_lcd_slova_Utro()
{
lcd.write(7);
lcd.write(8);
lcd.print("po");
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd слова "День"
void wywod_na_lcd_slova_Den()
{
lcd.write(3);
lcd.print("e");
lcd.write(5);
lcd.write(4);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd температуры со значком градуса
void wywod_na_lcd_temper(float wywod_temper)
{
if(wywod_temper<10)
{
lcd.print(" ");
}
lcd.print(wywod_temper, 1);
lcd.write(2);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd времени-часов
void wywod_na_lcd_hour(byte wywod_hour)
{
if(wywod_hour<10)
{
lcd.print(" ");
}
lcd.print(wywod_hour);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода на lcd времени-минут
void wywod_na_lcd_min(byte wywod_minute)
{
if(wywod_minute<10)
{
lcd.print("0");
}
lcd.print(wywod_minute);
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма вывода текущих данных на lcd дисплей при переходе из основной программы
// с целью исключения повтороного вывода на дисплей информации, которая не изенилась с прошлого обращения к подпрограмме, производиться ее сравнение
void wywod_na_lcd_tekusch()
{
// формируем сначала вывод информации, которая меняется относительно редко (часы, минуты, температура)
//////////////// верхняя строка lcd
// вывод текущего времени
if(hour!=hour_predyd)
{
lcd.setCursor(0, 0);
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов
hour_predyd=hour;
}
if(minute!=minute_predyd)
{
lcd.setCursor(3, 0);
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - минут
minute_predyd=minute;
}
// вывод комнатной температуры и значка градус
if(temperatura_room!=temperatura_room_predyd)
{
lcd.setCursor(11, 0);
wywod_na_lcd_temper(temperatura_room); // переход к подпрограмме вывода на lcd температуры со значком градуса
lcd.setCursor(15, 0); // обрезаем второй знак после запятой и ставим вместо него значок градуса
lcd.write(2);
temperatura_room_predyd=temperatura_room;
}
//////////////// нижняя строка lcd
// вывод уличной температуры
if(temperatura_street!=temperatura_street_predyd)
{
lcd.setCursor(7, 1);
lcd.print("Out");
lcd.setCursor(11, 1);
if(temperatura_street>=0)
{
lcd.print(" ");
}
lcd.print(temperatura_street, 1);
lcd.setCursor(15, 1);
lcd.write(2);
temperatura_street_predyd=temperatura_street;
//
}
// формирование мигающего двоеточия между часами и минутами (0,75 сек. светятся, 0,45 не светятся)
unsigned long miganie_dvoet=formirovanie_intervala(time_snach_progi_migania_dvoet);
lcd.setCursor(2, 0);
if(miganie_dvoet<750) // 0,75 сек знаки светятся
{
lcd.print(":");
}
else
{
lcd.print(" ");
}
if(miganie_dvoet>1200)
{
time_snach_progi_migania_dvoet=time_snachala_progi;
}
// последовательный вывод названия временного периода и, если котел включен, то сведения об этом
// первые 0,5 сек. ничего нет
unsigned long miganie_sost_kotla=formirovanie_intervala(time_snach_progi_migania_sost_kotla);
lcd.setCursor(6, 0);
// первые 0,5 сек. ничего нет
if(miganie_sost_kotla<500)
{
lcd.print(" ");
}
// вывод первой буквы названия режима
if(miganie_sost_kotla>500 && miganie_sost_kotla<=1250)
{
switch(period_time)
{
case 0:
lcd.print("H");
break;
case 1:
lcd.write(7);
break;
case 2:
lcd.write(3);
break;
}
lcd.print(" ");
}
// вывод 1-й и 2-й букв названия режима
if(miganie_sost_kotla>1250 && miganie_sost_kotla<=2000)
{
switch(period_time)
{
case 0:
lcd.print("Ho");
break;
case 1:
lcd.write(7);
lcd.write(8);
break;
case 2:
lcd.write(3);
lcd.print("e");
break;
}
lcd.print(" ");
}
// вывод 1-й, 2-й и 3-й букв названия режима
if(miganie_sost_kotla>2000 && miganie_sost_kotla<=2750)
{
switch (period_time)
{
case 0:
lcd.print("Ho");
lcd.write(6);
break;
case 1:
lcd.write(7);
lcd.write(8);
lcd.print("p");
break;
case 2:
lcd.write(3);
lcd.print("e");
lcd.write(5);
break;
}
lcd.print(" ");
}
// вывод всего слова названия режима
if(miganie_sost_kotla>2750 && miganie_sost_kotla<=3500)
{
switch (period_time)
{
case 0:
lcd.print("Ho");
lcd.write(6);
lcd.write(4);
break;
case 1:
lcd.write(7);
lcd.write(8);
lcd.print("po");
break;
case 2:
lcd.write(3);
lcd.print("e");
lcd.write(5);
lcd.write(4);
break;
}
}
// Если на выходе котла 0, то обнуляем временной интервал для повторного вывода временного периода
if(miganie_sost_kotla>3500 && digitalRead(relekotla)==LOW)
{
time_snach_progi_migania_sost_kotla=time_snachala_progi;
miganie_sost_kotla=formirovanie_intervala(time_snach_progi_migania_sost_kotla);
}
// 0,5 сек. ничего нет
if(miganie_sost_kotla>3500 && miganie_sost_kotla<=4000)
{
lcd.print(" ");
}
// далее, если на выход котла 1, то выводим значки пламени
if(miganie_sost_kotla>4000 && miganie_sost_kotla<=4750)
{
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем два значка пламени
if(miganie_sost_kotla>4750 && miganie_sost_kotla<=5500)
{
lcd.write(1);
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем три значка пламени
if(miganie_sost_kotla>5500 && miganie_sost_kotla<=6250)
{
lcd.write(1);
lcd.write(1);
lcd.write(1);
lcd.print(" ");
}
// следующие 0,75 сек. рисуем четыре значка пламени
if(miganie_sost_kotla>6250 && miganie_sost_kotla<=7000)
{
lcd.write(1);
lcd.write(1);
lcd.write(1);
lcd.write(1);
}
// обнуляем временной показатель
if(miganie_sost_kotla>7000)
{
time_snach_progi_migania_sost_kotla=time_snachala_progi;
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма формирования интервала мигания выбранного для изменения параметра при нахождении в меню программирования
void miganie_parametra_lcd()
{
unsigned long miganie_parametra=formirovanie_intervala(time_snach_progi_parametra_menu);
if(miganie_parametra<=750)
{
miganie_parametra_programmirovaniya=true;
}
else
{
miganie_parametra_programmirovaniya=false;
}
if(miganie_parametra>1200)
{
time_snach_progi_parametra_menu=time_snachala_progi;
}
}
////////////////////////////////////////////////////////////////////////////
// подпрограмма программирования - установки времени, начала временных периодов(ночи, утра и дня), температуры временных периодов и записи (удаления) адресов датчиков температуры
void programmirovanie()
{
// считываем из EEPROM часы и минуты начала временных периодов, установленных температур и адреса датчиков, а также текущие дату и время
read_eeprom_time_periodov();
read_eeprom_ustan_temper();
read_eeprom_adres_datch();
poluchenie_wremeni(); // переход к подпрограмме считывания времени с часов
time_snach_progi_wychoda_menu=millis(); // для формирования интервала с нуля.
time_snach_progi_parametra_menu=time_snach_progi_wychoda_menu; // для формирования интервала мигания выбранного для изменения параметра
lcd.clear();
delay(1000);
// создаем циклический опрос нажатия кнопок, вывод изображения данных на lcd
cikl_programm:
wdt_reset();
if(formirovanie_intervala(time_snach_progi_wychoda_menu)>interval_wychoda_menu || status_programmirovaniya==0)
{
goto na_wychod; // если интервал достиг задаваемого программистом и не нажата ни одна кнопка, то осуществляется выход из подпрограммы программирования
}
opredel_nashat_knopok(); // переход к подпрограмме определения нажатия кнопок
nashata_knopka_pravo(); // переход к подпрограмме и выполнение действий при нажатии кнопки право
nashata_knopka_levo(); // переход к подпрограмме и выполнение действий при нажатии кнопки лево
nashata_knopka_verch(); // переход к подпрограмме и выполнение действий при нажатии кнопки верх
nashata_knopka_vniz(); // переход к подпрограмме и выполнение действий при нажатии кнопки вниз
nashata_knopka_select(); // переход к подпрограмме и выполнение действий при нажатии кнопки select
miganie_parametra_lcd(); // переход к подпрограмме определения продожительности мигания выбранного в меню параметра
opredel_stranizy_lcd(); // переход к подпрограмме, которая определяет, какую из двух страниц выводить на lcd
goto cikl_programm;
// завершение цикла опроса кнопок и т.д.
na_wychod:
status_programmirovaniya=1;
lcd.clear();
// первоначальный вывод на lcd текущих данных
lcd.setCursor(0, 0);
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов
lcd.setCursor(3, 0);
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - минут
lcd.setCursor(11, 0);
wywod_na_lcd_temper(temperatura_room); // переход к подпрограмме вывода на lcd температуры со значком градуса
lcd.setCursor(15, 0); // обрезаем второй знак после запятой и ставим вместо него значок градуса
lcd.write(2);
lcd.setCursor(7, 1);
lcd.print("Out");
lcd.setCursor(10, 1);
if(temperatura_street>=0)
{
lcd.print(" ");
}
wywod_na_lcd_temper(temperatura_street);
}
//////////////////////////////////////////////////////////////////////////////
// подпрограмма определения нажатия кнопок
void opredel_nashat_knopok()
{
int temp_temp=1023;
temp_temp=analogRead(0); // считываем данные
//определяем нажатие кнопки "ВВЕРХ" (показатель 99)
if(temp_temp>50 && temp_temp<150)
{
knopka_verch=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ВНИЗ" (показатель 255)
if(temp_temp>200 && temp_temp<300)
{
knopka_vniz=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ПРАВО" (показатель 0)
if(temp_temp<30)
{
knopka_pravo=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
//определяем нажатие кнопки "ЛЕВО" (показатель 409)
if(temp_temp>350 && temp_temp<500)
{
knopka_levo=true;
time_snach_progi_wychoda_menu=millis(); // для обнуления интервала бездействия и выхода из режима программирования
}
// определяем нажатие кнопки Select (показатель 639)
if(temp_temp>550 && temp_temp<750)
{
knopka_select=true;
time_snach_progi_wychoda_menu=millis();
}
temp_temp=1023;
delay(200);
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка право
void nashata_knopka_pravo()
{
if(knopka_pravo==true)
{
knopka_pravo=false;
// на 1-й странице
if(status_programmirovaniya>=1 && status_programmirovaniya<=6)
{
if(status_programmirovaniya==6)
{
status_programmirovaniya=1;
}
else
{
status_programmirovaniya++;
}
}
// на 2-й странице
if(status_programmirovaniya>=11 && status_programmirovaniya<=15)
{
if(status_programmirovaniya==15)
{
status_programmirovaniya=11;
}
else
{
status_programmirovaniya++;
}
}
// на 3-й странице
if(status_programmirovaniya>=21 && status_programmirovaniya<=25)
{
if(status_programmirovaniya==25)
{
status_programmirovaniya=21;
}
else
{
status_programmirovaniya++;
}
}
// на 4-й странице
if(status_programmirovaniya>=31 && status_programmirovaniya<=35)
{
if(status_programmirovaniya==35)
{
status_programmirovaniya=31;
}
else
{
status_programmirovaniya++;
}
}
// на 5-й странице
if(status_programmirovaniya>=41 && status_programmirovaniya<=47)
{
if(status_programmirovaniya==47)
{
status_programmirovaniya=41;
}
else
{
status_programmirovaniya++;
}
}
// на 6-й странице
if(status_programmirovaniya>=51 && status_programmirovaniya<=55)
{
if(status_programmirovaniya==55)
{
status_programmirovaniya=51;
}
else
{
status_programmirovaniya++;
}
}
// на 7-й странице
if(status_programmirovaniya==61 || status_programmirovaniya==62)
{
if(status_programmirovaniya==62)
{
status_programmirovaniya=61;
}
else
{
status_programmirovaniya++;
}
}
// на 8-й странице
if(status_programmirovaniya==71 || status_programmirovaniya==72)
{
if(status_programmirovaniya==72)
{
status_programmirovaniya=71;
}
else
{
status_programmirovaniya++;
}
}
// на 9-й странице
if(status_programmirovaniya==81 || status_programmirovaniya==82)
{
if(status_programmirovaniya==82)
{
status_programmirovaniya=81;
}
else
{
status_programmirovaniya++;
}
}
// на 11-й странице
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
if(status_programmirovaniya==103)
{
status_programmirovaniya=101;
}
else
{
status_programmirovaniya++;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка лево
void nashata_knopka_levo()
{
if(knopka_levo==true)
{
knopka_levo=false;
// на 1-й странице
if(status_programmirovaniya>=1 && status_programmirovaniya<=6)
{
if(status_programmirovaniya==1)
{
status_programmirovaniya=6;
}
else
{
status_programmirovaniya--;
}
}
// на 2-й странице
if(status_programmirovaniya>=11 && status_programmirovaniya<=15)
{
if(status_programmirovaniya==11)
{
status_programmirovaniya=15;
}
else
{
status_programmirovaniya--;
}
}
// на 3-й странице
if(status_programmirovaniya>=21 && status_programmirovaniya<=25)
{
if(status_programmirovaniya==21)
{
status_programmirovaniya=25;
}
else
{
status_programmirovaniya--;
}
}
// на 4-й странице
if(status_programmirovaniya>=31 && status_programmirovaniya<=35)
{
if(status_programmirovaniya==31)
{
status_programmirovaniya=35;
}
else
{
status_programmirovaniya--;
}
}
// на 5-й странице
if(status_programmirovaniya>=41 && status_programmirovaniya<=47)
{
if(status_programmirovaniya==41)
{
status_programmirovaniya=47;
}
else
{
status_programmirovaniya--;
}
}
// на 6-й странице
if(status_programmirovaniya>=51 && status_programmirovaniya<=55)
{
if(status_programmirovaniya==51)
{
status_programmirovaniya=55;
}
else
{
status_programmirovaniya--;
}
}
// на 7-й странице
if(status_programmirovaniya==61 || status_programmirovaniya==62)
{
if(status_programmirovaniya==61)
{
status_programmirovaniya=62;
}
else
{
status_programmirovaniya--;
}
}
// на 8-й странице
if(status_programmirovaniya==71 || status_programmirovaniya==72)
{
if(status_programmirovaniya==71)
{
status_programmirovaniya=72;
}
else
{
status_programmirovaniya--;
}
}
// на 9-й странице
if(status_programmirovaniya==81 || status_programmirovaniya==82)
{
if(status_programmirovaniya==81)
{
status_programmirovaniya=82;
}
else
{
status_programmirovaniya--;
}
}
// на 11-й странице
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
if(status_programmirovaniya==101)
{
status_programmirovaniya=103;
}
else
{
status_programmirovaniya--;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка верх
void nashata_knopka_verch()
{
if(knopka_verch==true)
{
knopka_verch=false;
if(status_programmirovaniya==14 || status_programmirovaniya==24 || status_programmirovaniya==34 || status_programmirovaniya==46 || status_programmirovaniya==102)
{
if(status_wybora_save==false)
{
status_wybora_save=true;
}
else
{
status_wybora_save=false;
}
}
switch(status_programmirovaniya)
{
// увеличиваем часы начала ночного периода
case 11:
if(nachalo_periodov[0]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[0]=0;
}
else
{
nachalo_periodov[0]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала ночного периода
case 12:
if(nachalo_periodov[1]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[1]=0;
}
else
{
nachalo_periodov[1]++; // увеличиваем показатель
}
break;
// увеличиваем температуру ночного периода
case 13:
if(temperatura_room_ustanovka[0]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[0]=10;
}
else
{
temperatura_room_ustanovka[0]++; // увеличиваем показатель
}
break;
// увеличиваем часы начала утреннего периода
case 21:
if(nachalo_periodov[2]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[2]=0;
}
else
{
nachalo_periodov[2]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала утреннего периода
case 22:
if(nachalo_periodov[3]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[3]=0;
}
else
{
nachalo_periodov[3]++; // увеличиваем показатель
}
break;
// увеличиваем температуру утреннего периода
case 23:
if(temperatura_room_ustanovka[1]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[1]=10;
}
else
{
temperatura_room_ustanovka[1]++; // увеличиваем показатель
}
break;
// увеличиваем часы начала дневного периода
case 31:
if(nachalo_periodov[4]==23) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[4]=0;
}
else
{
nachalo_periodov[4]++; // увеличиваем показатель
}
break;
// увеличиваем минуты начала утреннего периода
case 32:
if(nachalo_periodov[5]==59) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[5]=0;
}
else
{
nachalo_periodov[5]++; // увеличиваем показатель
}
break;
// увеличиваем температуру утреннего периода
case 33:
if(temperatura_room_ustanovka[2]==35) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[2]=10;
}
else
{
temperatura_room_ustanovka[2]++; // увеличиваем показатель
}
break;
// увеличиваем часы текущего времени
case 41:
if(hour==23) // часы должны быть в пределах от 0 до 24.
{
hour=0;
}
else
{
hour++; // увеличиваем показатель
}
break;
// увеличиваем минуты текущего времени
case 42:
if(minute==59) // минуты должны быть в пределах от 0 по 59.
{
minute=0;
}
else
{
minute++; // увеличиваем показатель
}
break;
// увеличиваем текущую дату
case 43:
if(date==31) // число должно быть в пределах от 1 до 31.
{
date=1;
}
else
{
date++; // увеличиваем показатель
}
break;
// увеличиваем текущий месяц
case 44:
if(month==12)
{
month=1;
}
else
{
month++; // увеличиваем показатель
}
break;
// увеличиваем текущий год
case 45:
if(year==99) // год не может быть больше 99.
{
year=0;
}
else
{
year++; // увеличиваем показатель
}
break;
// изменяем присваемый подключенныому датчику статус - комнатный, уличный или водяной
case 101:
if(wybor_status_zapis_datch==3)
{
wybor_status_zapis_datch=1;
}
else
{
wybor_status_zapis_datch++;
}
break;
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка вниз
void nashata_knopka_vniz()
{
if(knopka_vniz==true)
{
knopka_vniz=false;
if(status_programmirovaniya==14 || status_programmirovaniya==24 || status_programmirovaniya==34 || status_programmirovaniya==46 || status_programmirovaniya==102)
{
if(status_wybora_save==false)
{
status_wybora_save=true;
}
else
{
status_wybora_save=false;
}
}
switch(status_programmirovaniya)
{
// уменьшаем часы начала ночного периода
case 11:
if(nachalo_periodov[0]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[0]=23;
}
else
{
nachalo_periodov[0]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала ночного периода
case 12:
if(nachalo_periodov[1]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[1]=59;
}
else
{
nachalo_periodov[1]--; // увеличиваем показатель
}
break;
// уменьшаем температуру ночного периода
case 13:
if(temperatura_room_ustanovka[0]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[0]=35;
}
else
{
temperatura_room_ustanovka[0]--; // увеличиваем показатель
}
break;
// уменьшаем часы начала утреннего периода
case 21:
if(nachalo_periodov[2]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[2]=23;
}
else
{
nachalo_periodov[2]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала утреннего периода
case 22:
if(nachalo_periodov[3]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[3]=59;
}
else
{
nachalo_periodov[3]--; // увеличиваем показатель
}
break;
// уменьшаем температуру утреннего периода
case 23:
if(temperatura_room_ustanovka[1]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[1]=35;
}
else
{
temperatura_room_ustanovka[1]--; // увеличиваем показатель
}
break;
// уменьшаем часы начала дневного периода
case 31:
if(nachalo_periodov[4]==0) // часы должны быть в пределах от 0 до 24.
{
nachalo_periodov[4]=23;
}
else
{
nachalo_periodov[4]--; // увеличиваем показатель
}
break;
// уменьшаем минуты начала утреннего периода
case 32:
if(nachalo_periodov[5]==0) // минуты должны быть в пределах от 0 по 59.
{
nachalo_periodov[5]=59;
}
else
{
nachalo_periodov[5]--; // увеличиваем показатель
}
break;
// уменьшаем температуру утреннего периода
case 33:
if(temperatura_room_ustanovka[2]==10) // температура должна быть в пределах от 10 до 35.
{
temperatura_room_ustanovka[2]=35;
}
else
{
temperatura_room_ustanovka[2]--; // увеличиваем показатель
}
break;
// уменьшаем часы текущего времени
case 41:
if(hour==0) // часы должны быть в пределах от 0 до 24.
{
hour=23;
}
else
{
hour--; // увеличиваем показатель
}
break;
// уменьшаем минуты текущего времени
case 42:
if(minute==0) // минуты должны быть в пределах от 0 по 59.
{
minute=59;
}
else
{
minute--; // увеличиваем показатель
}
break;
// уменьшаем текущую дату
case 43:
if(date==1) // число должно быть в пределах от 1 до 31.
{
date=31;
}
else
{
date--; // увеличиваем показатель
}
break;
// уменьшаем текущий месяц
case 44:
if(month==1)
{
month=12;
}
else
{
month--; // увеличиваем показатель
}
break;
// уменьшаем текущий год
case 45:
if(year==0) // год не может быть больше 99.
{
year=99;
}
else
{
year--; // увеличиваем показатель
}
break;
// изменяем присваемый подключенныому датчику статус - комнатный, уличный или водяной
case 101:
if(wybor_status_zapis_datch==1)
{
wybor_status_zapis_datch=3;
}
else
{
wybor_status_zapis_datch--;
}
break;
}
}
}
/////////////////////////////////////////////////////////////////////////
// подпрограмма выполнения действий, если нажата кнопка select
void nashata_knopka_select()
{
if(knopka_select==true)
{
knopka_select=false; // для исключения учитывания факта нажатой кнопки при переходах из меню в подменю и обратно
switch(status_programmirovaniya)
{
// переходы в подменю или выход из меню
case 1:
status_programmirovaniya=11; // переход в подменю установок параметров ночного режима
break;
case 2:
status_programmirovaniya=21; // переход в подменю установок параметров утреннего режима
break;
case 3:
status_programmirovaniya=31; // переход в подменю установок параметров дневного режима
break;
case 4:
status_programmirovaniya=41; // переход в подменю установок текущих даты и времени
break;
case 5:
status_programmirovaniya=51; // переход в подменю датчики
break;
case 6:
status_programmirovaniya=0; // команда на выход
break;
// сохранение параметров ночного периода, при условии выбора Yes
case 14:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(0, nachalo_periodov[0]);
delay(100);
EEPROM.write(1, nachalo_periodov[1]);
delay(100);
EEPROM.write(6, temperatura_room_ustanovka[0]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю ночного периода в основное меню
case 15:
status_programmirovaniya=1;
break;
// сохранение параметров утреннего периода, при условии выбора Yes
case 24:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(2, nachalo_periodov[2]);
delay(100);
EEPROM.write(3, nachalo_periodov[3]);
delay(100);
EEPROM.write(7, temperatura_room_ustanovka[1]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю утреннего периода в основное меню
case 25:
status_programmirovaniya=1;
break;
// сохранение параметров дневного периода, при условии выбора Yes
case 34:
if(status_wybora_save==true)
{
status_wybora_save=false;
EEPROM.write(4, nachalo_periodov[4]);
delay(100);
EEPROM.write(5, nachalo_periodov[5]);
delay(100);
EEPROM.write(8, temperatura_room_ustanovka[8]);
delay(100);
}
status_programmirovaniya=1;
break;
// выход из подменю дневного периода в основное меню
case 35:
status_programmirovaniya=1;
break;
// сохранение текущих даты и времени, при условии выбора Yes
case 46:
if(status_wybora_save==true)
{
status_wybora_save=false;
zapis_wremeni();
}
status_programmirovaniya=1;
break;
// выход из подменю часов в основное меню
case 47:
status_programmirovaniya=1;
break;
// переход из подменю датчики в подменю комнантный датчик
case 51:
status_programmirovaniya=62;
break;
// переход из подменю датчики в подменю уличный датчик
case 52:
status_programmirovaniya=72;
break;
// переход из подменю датчики в подменю водяной датчик
case 53:
status_programmirovaniya=82;
break;
// переход из подменю датчики в подменю новый датчик
case 54:
proverka_podkluch_datchikov_temp(); // сначала переход в подпрограмму определения новых подключенных датчиков
status_programmirovaniya=91; // переход в подменю новый датчик
break;
// переход из подменю датчики в основное меню
case 55:
status_programmirovaniya=1;
break;
// удаление комнатного датчика
case 61:
for(byte h1=0; h1<8; h1++)
{
EEPROM.write(h1+10, 255);
adres_dat_temp_room[h1]=255;
delay(100);
}
break;
// переход из подменю уличный датчик в основное меню
case 62:
status_programmirovaniya=51;
break;
// удаление уличного датчика
case 71:
for(byte h2=0; h2<8; h2++)
{
EEPROM.write(h2+20, 255);
adres_dat_temp_street[h2]=255;
delay(100);
}
break;
// переход из подменю уличный датчик в основное меню
case 72:
status_programmirovaniya=51;
break;
// удаление водяного датчика
case 81:
for(byte h3=0; h3<8; h3++)
{
EEPROM.write(h3+30, 255);
adres_dat_temp_water[h3]=255;
delay(100);
}
break;
// переход из подменю водяной датчик в основное меню
case 82:
status_programmirovaniya=51;
break;
// переход из подменю новый датчик в подменю датчики
case 91:
status_programmirovaniya=51;
break;
// сохранение выбранного статуса датчику температуры и запись его адреса в EEPROM, при условии выбора Yes
case 102:
if(status_wybora_save==true)
{
status_wybora_save=false;
for(byte x1=0; x1<8; x1++)
{
if(status_schit_datch_new[0]==true)
{
temp_adres[x1]=temp_adres_datch_1[x1];
}
if(status_schit_datch_new[1]==true)
{
temp_adres[x1]=temp_adres_datch_2[x1];
}
if(status_schit_datch_new[2]==true)
{
temp_adres[x1]=temp_adres_datch_3[x1];
}
EEPROM.write(x1+wybor_status_zapis_datch*10, temp_adres[x1]);
delay(100);
}
}
status_programmirovaniya=51;
break;
// переход из записи нового датчика в подменю датчики
case 103:
status_programmirovaniya=51;
break;
}
}
}
//////////////////////////////////////////////////////////
// подпрограмма определения выводимой на lcd страницы с учетом нажатых кнопок "ПРАВО", "ЛЕВО" и "Select"
void opredel_stranizy_lcd()
{
if(status_programmirovaniya>0 && status_programmirovaniya<7)
{
straniza_programmirovaniya_1();
}
if(status_programmirovaniya>10 && status_programmirovaniya<16)
{
straniza_programmirovaniya_2();
}
if(status_programmirovaniya>20 && status_programmirovaniya<26)
{
straniza_programmirovaniya_3();
}
if(status_programmirovaniya>30 && status_programmirovaniya<36)
{
straniza_programmirovaniya_4();
}
if(status_programmirovaniya>40 && status_programmirovaniya<48)
{
straniza_programmirovaniya_5();
}
if(status_programmirovaniya>50 && status_programmirovaniya<56)
{
straniza_programmirovaniya_6();
}
if(status_programmirovaniya>60 && status_programmirovaniya<63)
{
straniza_programmirovaniya_7();
}
if(status_programmirovaniya>70 && status_programmirovaniya<73)
{
straniza_programmirovaniya_8();
}
if(status_programmirovaniya>80 && status_programmirovaniya<83)
{
straniza_programmirovaniya_9();
}
if(status_programmirovaniya>90 && status_programmirovaniya<92)
{
straniza_programmirovaniya_10();
}
if(status_programmirovaniya>100 && status_programmirovaniya<104)
{
straniza_programmirovaniya_11();
}
}
////////////////////////////////////////
// подпрограмма формирования изображения 1-й страницы на lcd (1 строка - ночь, день, утро; 2 строка - часы, датчики, выход из программирования)
void straniza_programmirovaniya_1()
{
// 1 строка
// с 0 позиции - Ночь
lcd.setCursor(0, 0);
if(status_programmirovaniya==1 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Noch(); // переход к подпрограмме вывода слова "Ночь"
}
lcd.print(" ");
// с 6 позиции - Утро
lcd.setCursor(6, 0);
if(status_programmirovaniya==2 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Utro(); // переход к подпрограмме вывода слова "Утро"
}
lcd.print(" ");
// с 12 позиции - День
lcd.setCursor(12, 0);
if(status_programmirovaniya==3 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_slova_Den(); // переход к подпрограмме вывода слова "День"
}
// 2 строка
// с 0 позиции - Часы
lcd.setCursor(0, 1);
if(status_programmirovaniya==4 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Time ");
}
// с 6 позиции - Датчики
lcd.setCursor(6, 1);
if(status_programmirovaniya==5 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.write(3);
lcd.print("a");
lcd.write(8);
lcd.write(6);
lcd.print(" ");
}
// с 12 позиции - Выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==6 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 2-й страницы на lcd (1 строка - ночь, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_2()
{
// 1 строка
// с 0 позиции - Ночь
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Noch(); // переход к подпрограмме вывода слова "Ночь"
lcd.print(" ");
// с 5 позиции - часы начала ночного периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==11 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[0]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала ночного периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==12 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[1]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура ночного периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==13 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[0]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==14 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==15 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 3-й страницы на lcd (1 строка - утро, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_3()
{
// 1 строка
// с 0 позиции - Утро
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Utro(); // переход к подпрограмме вывода слова "Утро"
lcd.print(" ");
// с 5 позиции - часы начала утреннего периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==21 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[2]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала утреннего периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==22 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[3]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура утреннего периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==23 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[1]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==24 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==25 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 4-й страницы на lcd (1 строка - день, часы, минуты, температура; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_4()
{
// 1 строка
// с 0 позиции - День
lcd.setCursor(0, 0);
wywod_na_lcd_slova_Den(); // переход к подпрограмме вывода слова "День"
lcd.print(" ");
// с 5 позиции - часы и минуты начала дневного периода
lcd.setCursor(5, 0);
if(status_programmirovaniya==31 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(nachalo_periodov[4]); // переход к подпрограмме вывода времени начала периода - часов
}
lcd.print(":");
// с 8 позиции - минуты начала утреннего периода
lcd.setCursor(8, 0);
if(status_programmirovaniya==32 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(nachalo_periodov[5]); // переход к подпрограмме вывода времени начала периода - минут
}
lcd.print(" ");
// с 11 позиции - температура дневного периода
lcd.setCursor(11, 0);
if(status_programmirovaniya==33 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_temper(temperatura_room_ustanovka[2]); // переход к подпрограмме вывода температуры
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==34 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==35 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 5-й страницы на lcd (1 строка - текущие часы, минуты, число, месяц и год; 2 строка - сохранение, выход на 1 стр.)
void straniza_programmirovaniya_5()
{
// 1 строка
// с 0 позиции - часы
lcd.setCursor(0, 0);
if(status_programmirovaniya==41 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_hour(hour); // переход к подпрограмме вывода на lcd текущего времени - часов и минут через двоеточие
}
lcd.print(":");
lcd.setCursor(3, 0);
if(status_programmirovaniya==42 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
wywod_na_lcd_min(minute); // переход к подпрограмме вывода на lcd текущего времени - часов и минут через двоеточие
}
lcd.print(" ");
// с 6 позиции - текущее число
lcd.setCursor(6, 0);
if(status_programmirovaniya==43 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(date<10)
{
lcd.print(" ");
}
lcd.print(date);
}
lcd.print("-");
// с 9 позиции - текущий месяц
lcd.setCursor(9, 0);
if(status_programmirovaniya==44 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(month<10)
{
lcd.print("0");
}
lcd.print(month);
}
lcd.print("-20");
// с 14 позиции - текущий год
lcd.setCursor(14, 0);
if(status_programmirovaniya==45 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(year<10)
{
lcd.print("0");
}
lcd.print(year);
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==46 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==47 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 6-й страницы на lcd (1 строка - комнатный, уличный и водяной датчики; 2 строка - новый датчик, выход на 1 стр.)
void straniza_programmirovaniya_6()
{
// 1 строка
// с 0 позиции - комнатный датчик D-room
lcd.setCursor(0, 0);
if(status_programmirovaniya==51 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Room");
}
lcd.setCursor(4, 0);
lcd.print(" ");
// с 5 позиции - уличный
lcd.setCursor(5, 0);
if(status_programmirovaniya==52 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Stret ");
}
// с 11 позиции - водяной
lcd.setCursor(11, 0);
if(status_programmirovaniya==53 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Water");
}
// 1 строка
// с позиции 0 - новый датчик - New
lcd.setCursor(0, 1);
if(status_programmirovaniya==54 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("New ");
}
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==55 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 7-й страницы на lcd (1 строка - комнатный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_7()
{
// 1 строка
// с 0 позиции - комнатный датчик Room
lcd.setCursor(0, 0);
lcd.print("Room ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==61 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==62 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f1=0; f1<8; f1++)
{
lcd.print(adres_dat_temp_room[f1], HEX);
}
lcd.print(" ");
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 8-й страницы на lcd (1 строка - уличный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_8()
{
// 1 строка
// с 0 позиции - уличный датчик Stret
lcd.setCursor(0, 0);
lcd.print("Stret ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==71 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==72 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f2=0; f2<8; f2++)
{
lcd.print(adres_dat_temp_street[f2], HEX);
}
lcd.print(" ");
}
/////////////////////////////////////////////////////////////
// подпрограмма формирования изображения 9-й страницы на lcd (1 строка - датчик котловой воды, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
void straniza_programmirovaniya_9()
{
// 1 строка
// с 0 позиции - уличный датчик Stret
lcd.setCursor(0, 0);
lcd.print("Water ");
// с 6 позиции
lcd.setCursor(6, 0);
if(status_programmirovaniya==81 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Delet ");
}
// с позиции 12 - выход
lcd.setCursor(12, 0);
if(status_programmirovaniya==82 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
// 2 строка
// с позиции 0 - адрес датчика
lcd.setCursor(0, 1);
for(byte f3=0; f3<8; f3++)
{
lcd.print(adres_dat_temp_water[f3], HEX);
}
lcd.print(" ");
}
//////////////////////////////////////////////////////////
// подпрограмма формирования страницы 10-й страницы на lcd (1 строка - надпись, что новых датчиков нет или их больше одного. 2 строка - выход)
void straniza_programmirovaniya_10()
{
if(kolvo_new_datch==0)
{
lcd.setCursor(0, 0);
lcd.print("No new datchik ");
lcd.setCursor(0, 1);
if(status_programmirovaniya==91 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
// вывод инфы на дисплей о подключении более 1 нового датчика и необходимости выключения и выключения устройства с 1 новым датчиком для его записи в EEPROM и присвоения ему статуса: комнатного, уличного и котловой воды
if(kolvo_new_datch>1)
{
lcd.setCursor(0, 0);
lcd.print("New datch > 1 ");
lcd.setCursor(0,1);
if(status_programmirovaniya==91 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
if(kolvo_new_datch==1)
{
status_programmirovaniya=101;
}
}
//////////////////////////////////////////////////////////
// подпрограмма формирования страницы 11-й страницы на lcd (1 строка - надпись, что новых датчиков нет или их больше одного. 2 строка - выход)
void straniza_programmirovaniya_11()
{
// 1 строка
lcd.setCursor(0, 0);
lcd.print("NewDat Vid:");
lcd.setCursor(11, 0);
if(status_programmirovaniya==101 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
switch(wybor_status_zapis_datch)
{
case 1:
lcd.print("Room ");
break;
case 2:
lcd.print("Stret");
break;
case 3:
lcd.print("Water");
break;
}
}
// 2 строка
// с позиции 0 - "Save" сохранить
lcd.setCursor(0, 1);
lcd.print("Save ");
// с позиции 5 меняющиеся "Yes" или "No"
lcd.setCursor(5, 1);
if(status_programmirovaniya==102 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
if(status_wybora_save==true)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
lcd.print(" ");
// с позиции 12 - выход
lcd.setCursor(12, 1);
if(status_programmirovaniya==103 && miganie_parametra_programmirovaniya==false)
{
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit");
}
}
/////////////////////////////////////////////////////////////////////////////
// подпрограмма проверки адресов подключенных датчиков температуры на их соответствие данным, содержащимся в EEPROM.
void proverka_podkluch_datchikov_temp()
{
// считываем адреса датчиков, содержащиеся в EEPROM
read_eeprom_adres_datch();
// считываем адреса подключенных датчиков температуры
for(byte b=1; b<4; b++)
{
ds.reset();
ds.search(temp_adres);
for(byte i=0; i<8; i++)
{
switch(b)
{
case 1:
temp_adres_datch_1[i]=temp_adres[i];
break;
case 2:
temp_adres_datch_2[i]=temp_adres[i];
break;
case 3:
temp_adres_datch_3[i]=temp_adres[i];
break;
}
}
}
ds.reset();
ds.search(sss); // нужна для исключения ошибок, так как командой search последний датчик считывывается два раза. Результат этой команды не используется
////////////////////////////////////
// Проверяем на отсутствие какого-либо датчика и исключения дальнейших ошибок от возможной записи в в несколько переменных одного и того же адреса
// Если в адресе 3 считанного датчика содержится адрес 2 считанного датчика, то записываем нули
if(temp_adres_datch_3[0]==temp_adres_datch_2[0] && temp_adres_datch_3[1]==temp_adres_datch_2[1] && temp_adres_datch_3[2]==temp_adres_datch_2[2] && temp_adres_datch_3[3]==temp_adres_datch_2[3] &&
temp_adres_datch_3[4]==temp_adres_datch_2[4] && temp_adres_datch_3[5]==temp_adres_datch_2[5] && temp_adres_datch_3[6]==temp_adres_datch_2[6] && temp_adres_datch_3[7]==temp_adres_datch_2[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_3[qwerty]=0;
}
}
// Если в адресе 3 считанного датчика содержится адрес 1 считанного датчика, то записываем нули
if(temp_adres_datch_3[0]==temp_adres_datch_1[0] && temp_adres_datch_3[1]==temp_adres_datch_1[1] && temp_adres_datch_3[2]==temp_adres_datch_1[2] && temp_adres_datch_3[3]==temp_adres_datch_1[3] &&
temp_adres_datch_3[4]==temp_adres_datch_1[4] && temp_adres_datch_3[5]==temp_adres_datch_1[5] && temp_adres_datch_3[6]==temp_adres_datch_1[6] && temp_adres_datch_3[7]==temp_adres_datch_1[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_3[qwerty]=0;
}
}
// Если в адресе 2 считанного датчика содержится адрес 1 считанного датчика, то записываем нули
if(temp_adres_datch_2[0]==temp_adres_datch_1[0] && temp_adres_datch_2[1]==temp_adres_datch_1[1] && temp_adres_datch_2[2]==temp_adres_datch_1[2] && temp_adres_datch_2[3]==temp_adres_datch_1[3] &&
temp_adres_datch_2[4]==temp_adres_datch_1[4] && temp_adres_datch_2[5]==temp_adres_datch_1[5] && temp_adres_datch_2[6]==temp_adres_datch_1[6] && temp_adres_datch_2[7]==temp_adres_datch_1[7])
{
for(byte qwerty=0; qwerty<8; qwerty++)
{
temp_adres_datch_2[qwerty]=0;
}
}
kolvo_new_datch=0;
// сравниваем считанные адреса подключенных датчиков и содержащиеся в памяти
// датчик с адресом temp_adres_datch_1
if(temp_adres_datch_1[0]==0x28)
{
if(temp_adres_datch_1[0]==adres_dat_temp_room[0] && temp_adres_datch_1[1]==adres_dat_temp_room[1] && temp_adres_datch_1[2]==adres_dat_temp_room[2] && temp_adres_datch_1[3]==adres_dat_temp_room[3] &&
temp_adres_datch_1[4]==adres_dat_temp_room[4] && temp_adres_datch_1[5]==adres_dat_temp_room[5] && temp_adres_datch_1[6]==adres_dat_temp_room[6] && temp_adres_datch_1[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[0]=false;
}
else
{
if(temp_adres_datch_1[0]==adres_dat_temp_street[0] && temp_adres_datch_1[1]==adres_dat_temp_street[1] && temp_adres_datch_1[2]==adres_dat_temp_street[2] && temp_adres_datch_1[3]==adres_dat_temp_street[3] &&
temp_adres_datch_1[4]==adres_dat_temp_street[4] && temp_adres_datch_1[5]==adres_dat_temp_street[5] && temp_adres_datch_1[6]==adres_dat_temp_street[6] && temp_adres_datch_1[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[0]=false;
}
else
{
if(temp_adres_datch_1[0]==adres_dat_temp_water[0] && temp_adres_datch_1[1]==adres_dat_temp_water[1] && temp_adres_datch_1[2]==adres_dat_temp_water[2] && temp_adres_datch_1[3]==adres_dat_temp_water[3] &&
temp_adres_datch_1[4]==adres_dat_temp_water[4] && temp_adres_datch_1[5]==adres_dat_temp_water[5] && temp_adres_datch_1[6]==adres_dat_temp_water[6] && temp_adres_datch_1[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[0]=false;
}
else
{
status_schit_datch_new[0]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[0]=false;
}
// датчик с адресом temp_adres_datch_2
if(temp_adres_datch_2[0]==0x28)
{
if(temp_adres_datch_2[0]==adres_dat_temp_room[0] && temp_adres_datch_2[1]==adres_dat_temp_room[1] && temp_adres_datch_2[2]==adres_dat_temp_room[2] && temp_adres_datch_2[3]==adres_dat_temp_room[3] &&
temp_adres_datch_2[4]==adres_dat_temp_room[4] && temp_adres_datch_2[5]==adres_dat_temp_room[5] && temp_adres_datch_2[6]==adres_dat_temp_room[6] && temp_adres_datch_2[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[1]=false;
}
else
{
if(temp_adres_datch_2[0]==adres_dat_temp_street[0] && temp_adres_datch_2[1]==adres_dat_temp_street[1] && temp_adres_datch_2[2]==adres_dat_temp_street[2] && temp_adres_datch_2[3]==adres_dat_temp_street[3] &&
temp_adres_datch_2[4]==adres_dat_temp_street[4] && temp_adres_datch_2[5]==adres_dat_temp_street[5] && temp_adres_datch_2[6]==adres_dat_temp_street[6] && temp_adres_datch_2[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[1]=false;
}
else
{
if(temp_adres_datch_2[0]==adres_dat_temp_water[0] && temp_adres_datch_2[1]==adres_dat_temp_water[1] && temp_adres_datch_2[2]==adres_dat_temp_water[2] && temp_adres_datch_2[3]==adres_dat_temp_water[3] &&
temp_adres_datch_2[4]==adres_dat_temp_water[4] && temp_adres_datch_2[5]==adres_dat_temp_water[5] && temp_adres_datch_2[6]==adres_dat_temp_water[6] && temp_adres_datch_2[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[1]=false;
}
else
{
status_schit_datch_new[1]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[1]=false;
}
// датчик с адресом temp_adres_datch_3
if(temp_adres_datch_3[0]==0x28)
{
if(temp_adres_datch_3[0]==adres_dat_temp_room[0] && temp_adres_datch_3[1]==adres_dat_temp_room[1] && temp_adres_datch_3[2]==adres_dat_temp_room[2] && temp_adres_datch_3[3]==adres_dat_temp_room[3] &&
temp_adres_datch_3[4]==adres_dat_temp_room[4] && temp_adres_datch_3[5]==adres_dat_temp_room[5] && temp_adres_datch_3[6]==adres_dat_temp_room[6] && temp_adres_datch_3[7]==adres_dat_temp_room[7])
{
status_schit_datch_new[2]=false;
}
else
{
if(temp_adres_datch_3[0]==adres_dat_temp_street[0] && temp_adres_datch_3[1]==adres_dat_temp_street[1] && temp_adres_datch_3[2]==adres_dat_temp_street[2] && temp_adres_datch_3[3]==adres_dat_temp_street[3] &&
temp_adres_datch_3[4]==adres_dat_temp_street[4] && temp_adres_datch_3[5]==adres_dat_temp_street[5] && temp_adres_datch_3[6]==adres_dat_temp_street[6] && temp_adres_datch_3[7]==adres_dat_temp_street[7])
{
status_schit_datch_new[2]=false;
}
else
{
if(temp_adres_datch_3[0]==adres_dat_temp_water[0] && temp_adres_datch_3[1]==adres_dat_temp_water[1] && temp_adres_datch_3[2]==adres_dat_temp_water[2] && temp_adres_datch_3[3]==adres_dat_temp_water[3] &&
temp_adres_datch_3[4]==adres_dat_temp_water[4] && temp_adres_datch_3[5]==adres_dat_temp_water[5] && temp_adres_datch_3[6]==adres_dat_temp_water[6] && temp_adres_datch_3[7]==adres_dat_temp_water[7])
{
status_schit_datch_new[2]=false;
}
else
{
status_schit_datch_new[2]=true;
kolvo_new_datch++;
}
}
}
}
else
{
status_schit_datch_new[2]=false;
}
}
/////////////////////////////////////////////////////////////////////////////
void setup()
{
wdt_disable(); // останавливаем таймер перезагрузки
Wire.begin(); // старт интерфейса I2C (выводы 4 и 5 для UNO). Необходим для часов.
// инициализация выхода управления реле котла
pinMode(relekotla, OUTPUT); // вывод, предназначенный для управления котлом, устанавливаем как выход
digitalWrite(relekotla, LOW); // устанавливаем на выходе управления котлом 0
lcd.begin(16, 2); // включаем lcd
lcd.createChar(1, znak_lcd_plamya); // региструем индивидуальный знак в виде пламени
lcd.createChar(2, znak_lcd_gradus); // региструем индивидуальный знак в виде градуса
lcd.createChar(3, znak_lcd_D_Rus);
lcd.createChar(4, znak_lcd_b_Rus);
lcd.createChar(5, znak_lcd_n_Rus);
lcd.createChar(6, znak_lcd_ch_Rus);
lcd.createChar(7, znak_lcd_u_Rus);
lcd.createChar(8, znak_lcd_t_Rus);
poluchenie_wremeni(); // считываем время с часов
opredelenie_perioda_wremeni(); // для моментального отражения на Lcd временного периода после включения и не ждать истечения задаваемого интервала
nachal_ustanovki(); // переход к подпрограмме считывания данных из EEPROM и их проверке
lcd.clear();
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3);
for(byte rrr=0; rrr<3; rrr++)
{
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // 3 раза считываем температуру и записываемх их в переменные temperatura_pamyat[] для исключения ошибок при сравнении.
temperatura_room_pamyat[rrr]=temperatura_room;
}
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1);
lcd.clear();
wdt_enable(WDTO_8S); // запускае таймер перезагрузки с длительностью 8 сек.
}
///////////////////////////////////////////////////////////////////
void loop()
{
nashat_knopka=analogRead(0); // постоянно считываем данные с аналогового входа
// определяем факт нажатия кнопки Select (показатель 639) в течение 3 секунд для перехода к подпрограмме программирования
if(nashat_knopka>550&&nashat_knopka<750)
{
nashat_knopka=1023; // для исключения ошибок присваиваем переменной значение, равное состоянию, когда ни одна из кнопок не нажата
delay(3000); // необходиая длительность удержания кнопки Select для перехода в режим программирования
nashat_knopka=analogRead(0);
if(nashat_knopka>550&&nashat_knopka<750)
{
nashat_knopka=1023; // для исключения ошибок присваиваем переменной значение, равное состоянию, когда ни одна из кнопок не нажата
programmirovanie();
}
}
wywod_na_lcd_tekusch(); // переход к подпрограмме вывода текущих данных на дисплей.
//////
poluchenie_wremeni(); // переход к подпрограмме считывания времени с ds3231
opredelenie_perioda_wremeni(); // переход к подпрограмме определения временного периода (ночного, утреннего или дневного) и присваивания переменной "temperatura_sravnenia" заданной пользователем температуры для последующего сравненния со считанной.
// проверяем достижение необходимого интервала для запуска подпрограммы считывания комнатной температуры
if(formirovanie_intervala(time_snach_progi_dat_room)>interval_zapuska_dat_room)
{
time_snach_progi_dat_room=time_snachala_progi;
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // переход к подпрограмме считывания температуры с уличного датчика температуры. 3 - кол-во считываний
wyhod_temp_room_predel(); // переход к подпрограмме определения выхода температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
}
// проверяем достижение необходимого интервала для запуска подпрограммы считывания уличной температуры
if(formirovanie_intervala(time_snach_progi_dat_street)>interval_zapuska_dat_street)
{
time_snach_progi_dat_street=time_snachala_progi;
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1); // переход к подпрограмме считывания температуры с уличного датчика температуры. 1 - кол-во считываний
}
proverka_temperatury_room(); // переход к подпрограмме проверки считанной температуры на наличие грубых ошибок
sravnenie_temp_room_upravl_wychod(); // переход к подпрограмме сравнения полученной с датчика температуры с установленными пользователем температурами с учетом времени и выполнение команд на включение или выключение котла
problem_datch_room(); // переход к подпрограмме определения отсутствия ответа от комнатного датчика в течение длительного времени
wdt_reset(); // обнуляем таймер перезагрузки
}
[/code]
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать А у них то холодно то жарко.
Была такая же фигня, пока не настроил реакцию комнатного термостата на 0,5С, по умолчанию было 1,5С, во всем помещении температура с разницей 0,5С, что в общем то комфортно, суть в том, чтобы выбрать правильное место для датчика или брать средние/приоритные показания, если этих датчиков несколько.
Алгоритм с температрой улицы и носителя скорее для мини-котельни на несколько домов/квартир и явно не для обычных бытовых котлов, сам производитель начинает работу с термостатом от 55С носителя, повышая со временем, если термостат не реагирует. Расход газа и эл. с термостатом на малой температуре к сожалению не могу сравнить, но малая пост.температура носителя и высокая с термостатом имеют очень существенную разницу в пользу последнего.
Сам сейчас собираю термостат с интеграцией в УД, из наличия градусник DHT11, пробую подобрать к нему гистерезис, но чувствую надо брать другой с десятичными показаниями для этих дел.
Изначально свою программу писал с учетом двух датчиков в одном помещении. Потом отказался от этой затеи, поскольку вероятность выхода из строя одного из двух датчиков выше, чем у одного, и пока не продумал алгоритм работы скетча при данной ситуации.
Думаю, что не стоит управлять термостатом из УД или центрального блока (ЦБ). Если такая возможность будет прописана в самой программе, то этим могут воспользоваться сторонние лица. Котел не тот прибор, чтобы в его работу кто-то иной вмешивался. Максимум термостат все необходимые параметры может отправлять в УД или ЦБ и то не на основании получаемых запросов.
Сам сейчас собираю термостат с интеграцией в УД, из наличия градусник DHT11, пробую подобрать к нему гистерезис, но чувствую надо брать другой с десятичными показаниями для этих дел.
И это правильно. Насколько я понял, беда недорогих комнатных термостатов - как раз большой гистерезис, от этого и температура в помещении здорово плавает. У меня в доме в результате годового тест-драйва получилась комбинированная система - комнатный термостат (собственно, из топика) плюс уличный датчик, прикрученный к котлу. Подобрал подходящую кривую регулирования, ничего подкручивать не приходится. Котёл Baxi Mainfour 240F, подключение уличного датчика предусмотрено производителем, подходящий по параметрам я подобрал у китайцев.
Котёл Baxi Mainfour 240F, подключение уличного датчика предусмотрено производителем, подходящий по параметрам я подобрал у китайцев.
Здравствуйте! Я совсем новичок, но заинтересовался Ардуино и делаю самые первые шаги. У меня котел Baxi Ecofour 24, искал информацию по термостату и уличному датчику, а наткнулся на Ваш проект. К моему котлу все подключается, если верить инструкции. Если не сочтете за наглость, напишите, пожалуйста, какие компоненты мне необходимо купить, чтобы повторить Ваш проект.
Премного благодарен! Пошел изучать все это дело. Если будут вопросы ( а они будут ), то отпишусь.
Ну вот и сразу первый вопрос - с помощью чего Вы заливали Вашу программу? Простите за ламерские вопросы, но я сегодня только первый день читаю про Ардуино.
Человек в первую очередь ощущает температуру твердых тел вокруг себя, а только вторично - температуру воздуха.
В домах, где стены холодные (температурой до +20°C - то есть ниже темп.воздуха), а возух должен обогреть и самого человека и твердые тела вокруг, можно чувствовать холод даже при температуре воздуха в +25°C. Ведь холодные стены на расстоянии "высасывают" излучаемое телом человека тепло. И оно постоянно уходит "в никуда". А человек, в этом случае, выступает постоянным "нагревательным прибором", не айс..
извиняюсь за некропост.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
Ну вот и сразу первый вопрос - с помощью чего Вы заливали Вашу программу? Простите за ламерские вопросы, но я сегодня только первый день читаю про Ардуино.
На сайте разработчика www.arduino.cc в разделе 'download' скачайте 'Arduino software' - с помошью этого софта всё и делается.
Благодарю! С этим я уже разобрался. :) Сейчас активно изучаю Ваш скетч, чтобы понять, что куда подключается. После понимания этого набросаю схему подключений и выложу на Ваш суд. Возможно, пригодится таким же новичкам, как и я, для повторения Вашего проекта.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
таки, "да"... мне, тоже, про тёплые твёрдые тела не понравилось - чувствую себя комфортно исключительно рядом с тёплым и мягким телом противоположного пола.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
Аргументы будут? Собственные утверждения, доводы, факты, расчеты? Или ограничимся утверждением кг/ам?
Ради эксперимента можете попробовать прислониться в жару к бетонной стене которая назодится в тени.
Даже не надо прислоняться, при хорошем морозе на улице просто подойти к окну и почувствовать холод, это вашу тепловую энергию вытягивает через излучение.
...вокруг нас [С] твёрдые тела - это уже некомфортно.
Процесс превращения энергии излучения во внутреннюю энергию поглощающего тела называется поглощением. Большинство твердых и жидких тел излучают энергию всех длин волн в интервале от 0 до ∞, то есть имеют сплошной спектр излучения. Газы испускают энергию только в определенных интервалах длин волн (селективный спектр излучения). Твердые тела излучают и поглощают энергию поверхностью, а газы — объемом.
...вокруг нас [С] твёрдые тела - это уже некомфортно.
Процесс превращения энергии излучения во внутреннюю энергию поглощающего тела называется поглощением. Большинство твердых и жидких тел излучают энергию всех длин волн в интервале от 0 до ∞, то есть имеют сплошной спектр излучения. Газы испускают энергию только в определенных интервалах длин волн (селективный спектр излучения). Твердые тела излучают и поглощают энергию поверхностью, а газы — объемом.
ты график читал или смотрел? - написано "твёрдых тел вокруг нас[С]"
не википедию мне цитируй, а объясни, с какого будуна вокруг нас тела твёрдые?
Объясняю - стены, пол и крыша в доме сторятся из твердых материалов во избежании обрушения. Мебель производится в основном из дерева и пластика, поэтому коэффициент теплообмена у них ввиду более низкой плотности гораздо ниже.
Объясняю - стены, пол и крыша в доме сторятся из твердых материалов во избежании обрушения. Мебель производится в основном из дерева и пластика, поэтому коэффициент теплообмена у них ввиду более низкой плотности гораздо ниже.
в твоём доме мягкая мебедь из дерева и пластика потому, что нет опасности обрушения стола на табурет, а потолка нет вообще?
Аналоговый пин может быть настроен как цифровой (точнее, он и есть цифровой, но внутри чипа к нему подключен АЦП и он используется при необходимости после соответствующей инициализации). Подробности - в даташите на чип.
В общем - в данном случае A1 используется как цифровой пин.
В общем - в данном случае A1 используется как цифровой пин.
Премного благодарен за разъяснения! Просто столкнулся с тем, что у меня DS18B20 показывает только какие-то буквы nan, хотя отдельно работает как положено.
И еще вопрос - выходы реле (их в общей сложности 3, средний, понятно, общий) Вы как подключали к котлу?
vlad219i , до окончания зимы создана дешёвая схема управления газовым котлом с НЕ электронным управлением
а как ты сказал "Когда контакт замкнут - котлу разрешено зажигать горелку, когда разомкнут - запрещено)."
Надо ? поделюсь...
....если у тибя схема котла и отопления такая же
vlad219i , до окончания зимы создана дешёвая схема управления газовым котлом с НЕ электронным управлением
а как ты сказал "Когда контакт замкнут - котлу разрешено зажигать горелку, когда разомкнут - запрещено)."
Надо ? поделюсь...
....если у тибя схема котла и отопления такая же
Прочёл все слова, но не понял смысла. Если это предложение - то мне ни к чему, у меня всё работает как задумано...
Vlad219i, а из-за чего может показывать температуру в виде букв "nan"? Схему проверил, все в порядке. Датчик отдельно тоже работает нормально. Как только подключаешь по схеме, вместо температуры показывает вот это "nan".
Vlad219i, а из-за чего может показывать температуру в виде букв "nan"? Схему проверил, все в порядке. Датчик отдельно тоже работает нормально. Как только подключаешь по схеме, вместо температуры показывает вот это "nan".
Мне такая ошибка не встречалась.
Подтяжка есть (резистор 4,7к на +5в с A1)?
"Датчик отдельно работает нормально" - как проверяли?
Проверял просто. Взял этот же датчик, подключил тремя проводами. Залил скетч из примеров. Все в норме, температуру показывает.
Стало быть, остаётся только проверить, одинаковые ли библиотеки используются в примере и в этом скетче. Ну и в случае если нет - копать в этом направлении.
ОК, продолжим лёгкий ликбез.
Надеюсь вы уже поняли что потери пропорциональны разнице температур.
И что котёл более эффективно ( экономично) работает на низкой температуре.
И что количество тепла производимого котлом
необходимо немножко больше чем оно теряется в окружающую среду.
И вот этим " немножко больше" мы можем управлять с помощью термоголовок на радиаторах
Теперь что такое тампература в комнате.
Там где стоят радиаторы температура под потолком будет выше чем у пола.
И будет сильная циркуляция воздуха.
Там где тёплый пол там температура под потолком будет ниже чем у пола
и практически отсутствует циркуляция воздуха.
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать
А у них то холодно то жарко.
А надо установившийся режим. Плавный, непрерывное регулирование.
И релейным отключением-включением котла на длительное время этого не добиться.
По поводу непрерывного регулирования согласен при условии, что у котла модулируемая горелка, мощность которой можно изменять в режиме нормальной работы. Однако у некоторых котлов с модулируемой горелкой ее мощность можно изменять только в режиме "сервиса", но никак не в рабочем режиме. А что по поводу датчика на столбе? Каково Ваше мнение по поводу его месторасположения?
Котёл сам разбирается со своей горелкой.
И сам снижает мощьность когда видит что температура стала слишком быстро расти.
Мы туда не залезем просто никак и нельзя этого делать
Я , например, просто ограничил максимальную мощьность как раз в сервисе.
До 33 % от 28 килоВатт , меньше не было , 9.24 кВатт
Так как при самых лютых морозах (20 и ниже) больше 16 кубов в сутки ( и то при разгоне, потом 12) не видел.
А 16 куб Х 8 = 128 . 128 делим на 24= 5.3 средней . двойной запас.
А вот темературу регулировать без вмешательства во внутренности мы можем двумя способами:
Используя вход контактов комнатного термостата или поворачивая ручку температуры ( например сервой).
Ставьте на столб. Градусник. Будет точно показывать среднюю температуру по больнице.
Купите http://www.banggood.com/GM300-Digital-Laser-Point-Infrared-Thermometer-Temperature-Meter-Gun-p-85756.html
Увидите очень много интересного по температуре пола, потолка, стёкол и углов дома.
И столба.... :)
Спасибо.
http://www.banggood.com/GM320-Non-Contact-Laser-LCD-Display-Digital-IR-I...
Может кому-нибудь помогут результаты моей работы. Также прошу высказывать мысли по поводу оптимизации.
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать
А у них то холодно то жарко.
Была такая же фигня, пока не настроил реакцию комнатного термостата на 0,5С, по умолчанию было 1,5С, во всем помещении температура с разницей 0,5С, что в общем то комфортно, суть в том, чтобы выбрать правильное место для датчика или брать средние/приоритные показания, если этих датчиков несколько.
Алгоритм с температрой улицы и носителя скорее для мини-котельни на несколько домов/квартир и явно не для обычных бытовых котлов, сам производитель начинает работу с термостатом от 55С носителя, повышая со временем, если термостат не реагирует. Расход газа и эл. с термостатом на малой температуре к сожалению не могу сравнить, но малая пост.температура носителя и высокая с термостатом имеют очень существенную разницу в пользу последнего.
Сам сейчас собираю термостат с интеграцией в УД, из наличия градусник DHT11, пробую подобрать к нему гистерезис, но чувствую надо брать другой с десятичными показаниями для этих дел.
Изначально свою программу писал с учетом двух датчиков в одном помещении. Потом отказался от этой затеи, поскольку вероятность выхода из строя одного из двух датчиков выше, чем у одного, и пока не продумал алгоритм работы скетча при данной ситуации.
Думаю, что не стоит управлять термостатом из УД или центрального блока (ЦБ). Если такая возможность будет прописана в самой программе, то этим могут воспользоваться сторонние лица. Котел не тот прибор, чтобы в его работу кто-то иной вмешивался. Максимум термостат все необходимые параметры может отправлять в УД или ЦБ и то не на основании получаемых запросов.
Сам сейчас собираю термостат с интеграцией в УД, из наличия градусник DHT11, пробую подобрать к нему гистерезис, но чувствую надо брать другой с десятичными показаниями для этих дел.
И это правильно. Насколько я понял, беда недорогих комнатных термостатов - как раз большой гистерезис, от этого и температура в помещении здорово плавает. У меня в доме в результате годового тест-драйва получилась комбинированная система - комнатный термостат (собственно, из топика) плюс уличный датчик, прикрученный к котлу. Подобрал подходящую кривую регулирования, ничего подкручивать не приходится. Котёл Baxi Mainfour 240F, подключение уличного датчика предусмотрено производителем, подходящий по параметрам я подобрал у китайцев.
DHT11 - все его ругают.....
http://electronics-lab.ru/blog/mcu/46.html
Котёл Baxi Mainfour 240F, подключение уличного датчика предусмотрено производителем, подходящий по параметрам я подобрал у китайцев.
Здравствуйте! Я совсем новичок, но заинтересовался Ардуино и делаю самые первые шаги. У меня котел Baxi Ecofour 24, искал информацию по термостату и уличному датчику, а наткнулся на Ваш проект. К моему котлу все подключается, если верить инструкции. Если не сочтете за наглость, напишите, пожалуйста, какие компоненты мне необходимо купить, чтобы повторить Ваш проект.
какие компоненты мне необходимо купить, чтобы повторить Ваш проект.
Премного благодарен! Пошел изучать все это дело. Если будут вопросы ( а они будут ), то отпишусь.
Ну вот и сразу первый вопрос - с помощью чего Вы заливали Вашу программу? Простите за ламерские вопросы, но я сегодня только первый день читаю про Ардуино.
Человек в первую очередь ощущает температуру твердых тел вокруг себя, а только вторично - температуру воздуха.
В домах, где стены холодные (температурой до +20°C - то есть ниже темп.воздуха), а возух должен обогреть и самого человека и твердые тела вокруг, можно чувствовать холод даже при температуре воздуха в +25°C. Ведь холодные стены на расстоянии "высасывают" излучаемое телом человека тепло. И оно постоянно уходит "в никуда". А человек, в этом случае, выступает постоянным "нагревательным прибором", не айс..
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
Ну вот и сразу первый вопрос - с помощью чего Вы заливали Вашу программу? Простите за ламерские вопросы, но я сегодня только первый день читаю про Ардуино.
На сайте разработчика www.arduino.cc в разделе 'download' скачайте 'Arduino software' - с помошью этого софта всё и делается.
Благодарю! С этим я уже разобрался. :) Сейчас активно изучаю Ваш скетч, чтобы понять, что куда подключается. После понимания этого набросаю схему подключений и выложу на Ваш суд. Возможно, пригодится таким же новичкам, как и я, для повторения Вашего проекта.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
таки, "да"... мне, тоже, про тёплые твёрдые тела не понравилось - чувствую себя комфортно исключительно рядом с тёплым и мягким телом противоположного пола.
извиняюсь за некропост.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
Аргументы будут? Собственные утверждения, доводы, факты, расчеты? Или ограничимся утверждением кг/ам?
Ради эксперимента можете попробовать прислониться в жару к бетонной стене которая назодится в тени.
Аргументы будут?
у меня вопрос: почему тела твёрдые?
Аргументы будут?
у меня вопрос: почему тела твёрдые?
По утрам?
По утрам?
...вокруг нас [С] твёрдые тела - это уже некомфортно.
извиняюсь за некропост.
уважаемый ДжолиБибер, Вы хоть сами понимаете, что процитировали явно имбецильный текст и график тоже из разряда альтернативно одаренных.
Аргументы будут? Собственные утверждения, доводы, факты, расчеты? Или ограничимся утверждением кг/ам?
Ради эксперимента можете попробовать прислониться в жару к бетонной стене которая назодится в тени.
Даже не надо прислоняться, при хорошем морозе на улице просто подойти к окну и почувствовать холод, это вашу тепловую энергию вытягивает через излучение.
...вокруг нас [С] твёрдые тела - это уже некомфортно.
Процесс превращения энергии излучения во внутреннюю энергию поглощающего тела называется поглощением. Большинство твердых и жидких тел излучают энергию всех длин волн в интервале от 0 до ∞, то есть имеют сплошной спектр излучения. Газы испускают энергию только в определенных интервалах длин волн (селективный спектр излучения). Твердые тела излучают и поглощают энергию поверхностью, а газы — объемом.
...вокруг нас [С] твёрдые тела - это уже некомфортно.
Процесс превращения энергии излучения во внутреннюю энергию поглощающего тела называется поглощением. Большинство твердых и жидких тел излучают энергию всех длин волн в интервале от 0 до ∞, то есть имеют сплошной спектр излучения. Газы испускают энергию только в определенных интервалах длин волн (селективный спектр излучения). Твердые тела излучают и поглощают энергию поверхностью, а газы — объемом.
ты график читал или смотрел? - написано "твёрдых тел вокруг нас[С]"
не википедию мне цитируй, а объясни, с какого будуна вокруг нас тела твёрдые?
Объясняю - стены, пол и крыша в доме сторятся из твердых материалов во избежании обрушения. Мебель производится в основном из дерева и пластика, поэтому коэффициент теплообмена у них ввиду более низкой плотности гораздо ниже.
Объясняю - стены, пол и крыша в доме сторятся из твердых материалов во избежании обрушения. Мебель производится в основном из дерева и пластика, поэтому коэффициент теплообмена у них ввиду более низкой плотности гораздо ниже.
в твоём доме мягкая мебедь из дерева и пластика потому, что нет опасности обрушения стола на табурет, а потолка нет вообще?
ТС а Вы не думали об использования в термостате Эффективной температуры (ощущаемой)?
ТС а Вы не думали об использования в термостате Эффективной температуры (ощущаемой)?
Нет, не думал. И не собираюсь.
Как и обещал. Если я все правильно понял, то схема подключения выглядит так. Надеюсь, если что, vlad219i меня поправит.
Помогите пж с библиотекой wdt.h (сколько не искал так и не нашел извените) использую arduino 1.06 zip архив
Я нашёл тут :
arduino-1.6.7\hardware\tools\avr\avr\include\avr
И здесь :
arduino-1.7.8\hardware\tools\avr\avr\include\avr
а как её добавить стандартным вариантом не получается :(
В скетче вот что заметил - #define ONE_WIRE_BUS A1.
А разве этот датчик (DS18B20) может работать по аналоговым пинам?
Неверная постановка вопроса.
Аналоговый пин может быть настроен как цифровой (точнее, он и есть цифровой, но внутри чипа к нему подключен АЦП и он используется при необходимости после соответствующей инициализации). Подробности - в даташите на чип.
В общем - в данном случае A1 используется как цифровой пин.
В общем - в данном случае A1 используется как цифровой пин.
Премного благодарен за разъяснения! Просто столкнулся с тем, что у меня DS18B20 показывает только какие-то буквы nan, хотя отдельно работает как положено.
И еще вопрос - выходы реле (их в общей сложности 3, средний, понятно, общий) Вы как подключали к котлу?
И еще вопрос - выходы реле (их в общей сложности 3, средний, понятно, общий) Вы как подключали к котлу?
Замыкающий контакт реле - штатно, ко входу комнатного термостата котла (когда контакт замкнут - котлу разрешено зажигать горелку, когда разомкнут - запрещено).
vlad219i , до окончания зимы создана дешёвая схема управления газовым котлом с НЕ электронным управлением
а как ты сказал "Когда контакт замкнут - котлу разрешено зажигать горелку, когда разомкнут - запрещено)."
Надо ? поделюсь...
....если у тибя схема котла и отопления такая же
vlad219i , до окончания зимы создана дешёвая схема управления газовым котлом с НЕ электронным управлением
а как ты сказал "Когда контакт замкнут - котлу разрешено зажигать горелку, когда разомкнут - запрещено)."
Надо ? поделюсь...
....если у тибя схема котла и отопления такая же
Прочёл все слова, но не понял смысла. Если это предложение - то мне ни к чему, у меня всё работает как задумано...
Vlad219i, а из-за чего может показывать температуру в виде букв "nan"? Схему проверил, все в порядке. Датчик отдельно тоже работает нормально. Как только подключаешь по схеме, вместо температуры показывает вот это "nan".
Vlad219i, а из-за чего может показывать температуру в виде букв "nan"? Схему проверил, все в порядке. Датчик отдельно тоже работает нормально. Как только подключаешь по схеме, вместо температуры показывает вот это "nan".
Мне такая ошибка не встречалась.
Подтяжка есть (резистор 4,7к на +5в с A1)?
"Датчик отдельно работает нормально" - как проверяли?
Да, резистор стоит.
Проверял просто. Взял этот же датчик, подключил тремя проводами. Залил скетч из примеров. Все в норме, температуру показывает.
Да, резистор стоит.
Проверял просто. Взял этот же датчик, подключил тремя проводами. Залил скетч из примеров. Все в норме, температуру показывает.
Стало быть, остаётся только проверить, одинаковые ли библиотеки используются в примере и в этом скетче. Ну и в случае если нет - копать в этом направлении.
Добрый вечер! Перепробовал кучу библиотек, пайку проверил, датчик рабочий. Все равно температуру показывает вот так:
Подскажите, куда копнуть?
Сделайте холодный старт, зажмите энкодер при включении ардуино
Вы меня спасли!!!! Премного благодарен!!! Все запустилось и показывает.
Спасибо за спасённый мозг - у меня вариантов не осталось, что ещё это может быть. :-)
Как всё просто, а...
vlad219i, это вам спасибо большое за отличный скетч, отличная реализация использования энкодера, памяти, меню...
На базе вашего примера сделал управление тт котлом и бойлером коственого нагрева.
Управление турбиной, насосами, заслонкой+ с помощью esp8266 рулю всем этим по вайфаю)
Это было первое мое знакомство с ардуино, спасибо еще раз)
vlad219i - Вам огромаднейшее спасибо за отличную идею и, не менее отличную реализацию!
klbsss - Вам за решение проблемы с запуском!
В итоге все работает, температуру показывает, сейчас буду подключать к котлу.