ОК, продолжим лёгкий ликбез.
Надеюсь вы уже поняли что потери пропорциональны разнице температур.
И что котёл более эффективно ( экономично) работает на низкой температуре.
И что количество тепла производимого котлом
необходимо немножко больше чем оно теряется в окружающую среду.
И вот этим " немножко больше" мы можем управлять с помощью термоголовок на радиаторах
Теперь что такое тампература в комнате.
Там где стоят радиаторы температура под потолком будет выше чем у пола.
И будет сильная циркуляция воздуха.
Там где тёплый пол там температура под потолком будет ниже чем у пола
и практически отсутствует циркуляция воздуха.
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать
А у них то холодно то жарко.
А надо установившийся режим. Плавный, непрерывное регулирование.
И релейным отключением-включением котла на длительное время этого не добиться.
По поводу непрерывного регулирования согласен при условии, что у котла модулируемая горелка, мощность которой можно изменять в режиме нормальной работы. Однако у некоторых котлов с модулируемой горелкой ее мощность можно изменять только в режиме "сервиса", но никак не в рабочем режиме. А что по поводу датчика на столбе? Каково Ваше мнение по поводу его месторасположения?
Котёл сам разбирается со своей горелкой.
И сам снижает мощьность когда видит что температура стала слишком быстро расти.
Мы туда не залезем просто никак и нельзя этого делать
Я , например, просто ограничил максимальную мощьность как раз в сервисе.
До 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 <EEPROM.h> // для обращения к энергонезависимой памяти
#include <wdt.h> // библиотека сторожевого таймера
// адреса EEPROM, по которым хранятся задаваемые пользователем параметры:
// 0-часы начала ночного периода, 1-минуты начала ночного периода, 2-часы начала утреннего периода, 3 - минуты начала утреннего периода, 4-часы начала дневного периода,
// временные переменные для считывания адресов с подключенных датчиков
bytetemp_adres[8];
bytetemp_adres_datch_1[8]; // для считывания адреса 1-го подключенного датчика
bytetemp_adres_datch_2[8];
bytetemp_adres_datch_3[8];
bytekolvo_new_datch=0; // содержит кол-во новых подключенных датчиков
boolean status_schit_datch_new[3];
bytesss[8];
// для подпрограммы formirovanie_intervala().
unsigned intinterval_zapuska_dat_room=30000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с комнатного датчика. Он равен 30 сек.
unsigned longinterval_zapuska_dat_street=180000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с уличного датчика. Он равен 3 мин.
unsigned intinterval_wychoda_menu=15000; // интервал в милисекундах, через который будет осуществляться выход из подпрограммы программирования
unsigned longtime_snachala_progi; // содержит текущие данные о времени, прошедшем сначала запуска программы. Для формирования интеравала .
unsigned longtime_snach_progi_dat_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания комнатной температуры
unsigned longtime_snach_progi_dat_street=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания уличной температуры
unsigned longtime_snach_progi_wychoda_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала выхода из подпрограммы программирования
unsigned longtime_snach_progi_migania_dvoet=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания двоеточия
unsigned longtime_snach_progi_migania_sost_kotla=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания состояния котла
unsigned longtime_snach_progi_parametra_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания выбранного параметра меню
unsigned longtime_snach_progi_problem_datch_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала отсутствия ответа от комнатного датчика температуры
boolean miganie_parametra_programmirovaniya=true; // когда true светится выбранный параметр, false - вместо параметра пробелы.
// содержит предыдущие данные о времени, прошедшем с начала запуска программы для формирования мигания
// для работы с температурой
byteadres_dat_temp_room[8]; // для хранения адреса комнатаного датчика температуры
byteadres_dat_temp_street[8]; // для хранения адреса уличного датчика температуры
byteadres_dat_temp_water[8]; // для хранения адреса датчика температуры котловой воды
floattemperatura_room; // считанная с комнатного датчика температура
floattemperatura_street; // считанная с уличного датчика температура
floattemperatura_water; // считанная с датчика котловой воды температура
floattemperatura_room_pamyat[3]; // последние 3 считанных температуры (для проверки считанной температуры на наличие ошибок и исключения тактования)
bytetemperatura_room_ustanovka[3]; // в них считываются из EEPROM задаваемые пользователем температуры временных периодов: 0-ночь, 1-утро, 2-день.
floatgisteresis=0.2; // задаваемый пользователем гистерезис для определения температурных границ управления выходом
boolean proverka_temperatura_room_status; // содержит информацию о том, прошла ли считанная температура проверку на наличие грубых ошибок: true-да; false-нет.
floattemperatura_room_predyd=0, temperatura_street_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
// для работы со временем
boolCentury=false; // для часов. Пока не знаю??????????????????????
boolh12; // для часов. Пока не знаю??????????????????????
boolPM; // для часов. Пока не знаю??????????????????????
byteyear, month, date, hour, minute, second; // в них записываются полученные от часов данные о времени
bytehour_predyd=0, minute_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
bytenachalo_periodov[6]; // в них считываются из EEPROM часы и минуты начала периодов: 0-часы ночи, 1-минуты ночи, 2-часы утра, 3-минуты утра, 4-часы дня, 5-минуты дня.
byteperiod_time; // для храненения сведений о временном периоде (ночь-0, утро-1, день-2)
intsumma_minut[4]; // общие суммы минут: 0-текущего времени, 1-начала ночного периода, 2-начала утреннего периода, 3-начала дневного периода, для удобства сравнения
byteobnovl_peremen=0; // необходима для ежечасного считывания данных из EEPROM и их записи в соответствующие переменные
// для подпрограммы программирования
bytestatus_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
intnashat_knopka=1023; // содержит данные с аналогового входа 0
boolean status_wybora_delete=false; // содержит состояние необходимости удаления датчика температуры из EEPROM
boolean status_wybora_save=false; // содержит состояние необходимости сохранения измененных параметров
bytewybor_status_zapis_datch=1; // содержит число (1, 2 или 3), свидетельствующее о том, каким именно (комнатным, уличным или водяным) записывается новый датчик в EEPROM
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 минуты.
// подпрограмма определения выхода комнатной температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
// подпрограмма сравнения полученной с датчика температуры и хранящихся в памяти последних 3 показаний с границами заданной пользователем температуры и управление выходом.
// с целью исключения тактования и возможных краткосрочных незначительных измерений температуры (например открытие окна или двери, дуновение ветра) переключение выхода
// происходит только, если 3 последних показаний температуры также находятся за границами заданной пользователем температуры.
voidsravnenie_temp_room_upravl_wychod()
{
if(proverka_temperatura_room_status==true) // сначла проверяем прохождение проверки на наличие грубок ошибок. Если да, то переходим к сравнению.
{
// если считанная температура и последние 3 показания меньше нижней границы заданной пользователем температуры и на управляемом выходе 0, то данный выход переключается в 1 (котел включается).
// если считанная температура и последние 3 показания большее верхней границы заданной пользователем температуры и на управляемом выходе 1, то данный выход переключается в 0 (котел выключается).
// считываем данные из 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 градусов,
// подпрограмма программирования - установки времени, начала временных периодов(ночи, утра и дня), температуры временных периодов и записи (удаления) адресов датчиков температуры
voidprogrammirovanie()
{
// считываем из 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
// подпрограмма формирования изображения 5-й страницы на lcd (1 строка - текущие часы, минуты, число, месяц и год; 2 строка - сохранение, выход на 1 стр.)
// подпрограмма формирования изображения 6-й страницы на lcd (1 строка - комнатный, уличный и водяной датчики; 2 строка - новый датчик, выход на 1 стр.)
// подпрограмма формирования изображения 7-й страницы на lcd (1 строка - комнатный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
// подпрограмма формирования изображения 8-й страницы на lcd (1 строка - уличный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
// подпрограмма формирования изображения 9-й страницы на lcd (1 строка - датчик котловой воды, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
// вывод инфы на дисплей о подключении более 1 нового датчика и необходимости выключения и выключения устройства с 1 новым датчиком для его записи в EEPROM и присвоения ему статуса: комнатного, уличного и котловой воды
// подпрограмма проверки адресов подключенных датчиков температуры на их соответствие данным, содержащимся в EEPROM.
voidproverka_podkluch_datchikov_temp()
{
// считываем адреса датчиков, содержащиеся в EEPROM
read_eeprom_adres_datch();
// считываем адреса подключенных датчиков температуры
for(byteb=1; b<4; b++)
{
ds.reset();
ds.search(temp_adres);
for(bytei=0; i<8; i++)
{
switch(b)
{
case1:
temp_adres_datch_1[i]=temp_adres[i];
break;
case2:
temp_adres_datch_2[i]=temp_adres[i];
break;
case3:
temp_adres_datch_3[i]=temp_adres[i];
break;
}
}
}
ds.reset();
ds.search(sss); // нужна для исключения ошибок, так как командой search последний датчик считывывается два раза. Результат этой команды не используется
////////////////////////////////////
// Проверяем на отсутствие какого-либо датчика и исключения дальнейших ошибок от возможной записи в в несколько переменных одного и того же адреса
// Если в адресе 3 считанного датчика содержится адрес 2 считанного датчика, то записываем нули
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // 3 раза считываем температуру и записываемх их в переменные temperatura_pamyat[] для исключения ошибок при сравнении.
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" заданной пользователем температуры для последующего сравненния со считанной.
// проверяем достижение необходимого интервала для запуска подпрограммы считывания комнатной температуры
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // переход к подпрограмме считывания температуры с уличного датчика температуры. 3 - кол-во считываний
wyhod_temp_room_predel(); // переход к подпрограмме определения выхода температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
}
// проверяем достижение необходимого интервала для запуска подпрограммы считывания уличной температуры
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1); // переход к подпрограмме считывания температуры с уличного датчика температуры. 1 - кол-во считываний
}
proverka_temperatury_room(); // переход к подпрограмме проверки считанной температуры на наличие грубых ошибок
sravnenie_temp_room_upravl_wychod(); // переход к подпрограмме сравнения полученной с датчика температуры с установленными пользователем температурами с учетом времени и выполнение команд на включение или выключение котла
problem_datch_room(); // переход к подпрограмме определения отсутствия ответа от комнатного датчика в течение длительного времени
Допоборудование - ds18b20(вывод 2 )- 3 датчика (комнатный, уличный, на котловую воду), ds3231(выводы 5-SCL и 4-SDA) и lcd1602.
Функция - замеряет температуру в помещении и на основании ее сравнения с установленными пользователями включает или выключает нагрузку.
Принцип работы:
1) пользователем устанавливаются время начала временных периода - ночного, утреннего и дневного.
2) пользователем устанавливаются температуры каждого временного периода - ночью, утром и днем.
3) в основном цикле программы постоянно считываются данные с часов ds3231, которые заносятся в соответствующие переменные.
4) через устанавливаемый пользователем в тексте программы интервал (сейчас равен 30 с.) считывается температура с датчика (три замера, высчитывается среднеарифмитическая).
5) затем определяется текущий временной период (ночь, утро или день).
6) считанная температура проверяется на наличие ошибки, то есть сравнивается с последней сохранненной в памяти.
7) считанная температура сравнивается с установленной пользователем температурой текущего временного периода и при выходе температуры за границы включается ил выключатеся котел.
#include <EEPROM.h> // для обращения к энергонезависимой памяти
#include <wdt.h> // библиотека сторожевого таймера
// адреса EEPROM, по которым хранятся задаваемые пользователем параметры:
// 0-часы начала ночного периода, 1-минуты начала ночного периода, 2-часы начала утреннего периода, 3 - минуты начала утреннего периода, 4-часы начала дневного периода,
// временные переменные для считывания адресов с подключенных датчиков
bytetemp_adres[8];
bytetemp_adres_datch_1[8]; // для считывания адреса 1-го подключенного датчика
bytetemp_adres_datch_2[8];
bytetemp_adres_datch_3[8];
bytekolvo_new_datch=0; // содержит кол-во новых подключенных датчиков
boolean status_schit_datch_new[3];
bytesss[8];
// для подпрограммы formirovanie_intervala().
unsigned intinterval_zapuska_dat_room=30000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с комнатного датчика. Он равен 30 сек.
unsigned longinterval_zapuska_dat_street=180000; // интервал в милисекундах, через который будут запускаться подпрограмма по считыванию температуры с уличного датчика. Он равен 3 мин.
unsigned intinterval_wychoda_menu=15000; // интервал в милисекундах, через который будет осуществляться выход из подпрограммы программирования
unsigned longtime_snachala_progi; // содержит текущие данные о времени, прошедшем сначала запуска программы. Для формирования интеравала .
unsigned longtime_snach_progi_dat_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания комнатной температуры
unsigned longtime_snach_progi_dat_street=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала запуска для перехода к подпрограмме считывания уличной температуры
unsigned longtime_snach_progi_wychoda_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала выхода из подпрограммы программирования
unsigned longtime_snach_progi_migania_dvoet=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания двоеточия
unsigned longtime_snach_progi_migania_sost_kotla=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания состояния котла
unsigned longtime_snach_progi_parametra_menu=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала мигания выбранного параметра меню
unsigned longtime_snach_progi_problem_datch_room=0; // содержит предыдущие данные о времении, прошедшем с начала запуска проги для исчисления интервала отсутствия ответа от комнатного датчика температуры
boolean miganie_parametra_programmirovaniya=true; // когда true светится выбранный параметр, false - вместо параметра пробелы.
// содержит предыдущие данные о времени, прошедшем с начала запуска программы для формирования мигания
// для работы с температурой
byteadres_dat_temp_room[8]; // для хранения адреса комнатаного датчика температуры
byteadres_dat_temp_street[8]; // для хранения адреса уличного датчика температуры
byteadres_dat_temp_water[8]; // для хранения адреса датчика температуры котловой воды
floattemperatura_room; // считанная с комнатного датчика температура
floattemperatura_street; // считанная с уличного датчика температура
floattemperatura_water; // считанная с датчика котловой воды температура
floattemperatura_room_pamyat[3]; // последние 3 считанных температуры (для проверки считанной температуры на наличие ошибок и исключения тактования)
bytetemperatura_room_ustanovka[3]; // в них считываются из EEPROM задаваемые пользователем температуры временных периодов: 0-ночь, 1-утро, 2-день.
floatgisteresis=0.2; // задаваемый пользователем гистерезис для определения температурных границ управления выходом
boolean proverka_temperatura_room_status; // содержит информацию о том, прошла ли считанная температура проверку на наличие грубых ошибок: true-да; false-нет.
floattemperatura_room_predyd=0, temperatura_street_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
// для работы со временем
boolCentury=false; // для часов. Пока не знаю??????????????????????
boolh12; // для часов. Пока не знаю??????????????????????
boolPM; // для часов. Пока не знаю??????????????????????
byteyear, month, date, hour, minute, second; // в них записываются полученные от часов данные о времени
bytehour_predyd=0, minute_predyd=0; // используются для исключения постоянного вывода на lcd неизменнных данных
bytenachalo_periodov[6]; // в них считываются из EEPROM часы и минуты начала периодов: 0-часы ночи, 1-минуты ночи, 2-часы утра, 3-минуты утра, 4-часы дня, 5-минуты дня.
byteperiod_time; // для храненения сведений о временном периоде (ночь-0, утро-1, день-2)
intsumma_minut[4]; // общие суммы минут: 0-текущего времени, 1-начала ночного периода, 2-начала утреннего периода, 3-начала дневного периода, для удобства сравнения
byteobnovl_peremen=0; // необходима для ежечасного считывания данных из EEPROM и их записи в соответствующие переменные
// для подпрограммы программирования
bytestatus_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
intnashat_knopka=1023; // содержит данные с аналогового входа 0
boolean status_wybora_delete=false; // содержит состояние необходимости удаления датчика температуры из EEPROM
boolean status_wybora_save=false; // содержит состояние необходимости сохранения измененных параметров
bytewybor_status_zapis_datch=1; // содержит число (1, 2 или 3), свидетельствующее о том, каким именно (комнатным, уличным или водяным) записывается новый датчик в EEPROM
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 минуты.
// подпрограмма определения выхода комнатной температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
// подпрограмма сравнения полученной с датчика температуры и хранящихся в памяти последних 3 показаний с границами заданной пользователем температуры и управление выходом.
// с целью исключения тактования и возможных краткосрочных незначительных измерений температуры (например открытие окна или двери, дуновение ветра) переключение выхода
// происходит только, если 3 последних показаний температуры также находятся за границами заданной пользователем температуры.
voidsravnenie_temp_room_upravl_wychod()
{
if(proverka_temperatura_room_status==true) // сначла проверяем прохождение проверки на наличие грубок ошибок. Если да, то переходим к сравнению.
{
// если считанная температура и последние 3 показания меньше нижней границы заданной пользователем температуры и на управляемом выходе 0, то данный выход переключается в 1 (котел включается).
// если считанная температура и последние 3 показания большее верхней границы заданной пользователем температуры и на управляемом выходе 1, то данный выход переключается в 0 (котел выключается).
// считываем данные из 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 градусов,
// подпрограмма программирования - установки времени, начала временных периодов(ночи, утра и дня), температуры временных периодов и записи (удаления) адресов датчиков температуры
voidprogrammirovanie()
{
// считываем из 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
// подпрограмма формирования изображения 5-й страницы на lcd (1 строка - текущие часы, минуты, число, месяц и год; 2 строка - сохранение, выход на 1 стр.)
// подпрограмма формирования изображения 6-й страницы на lcd (1 строка - комнатный, уличный и водяной датчики; 2 строка - новый датчик, выход на 1 стр.)
// подпрограмма формирования изображения 7-й страницы на lcd (1 строка - комнатный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
// подпрограмма формирования изображения 8-й страницы на lcd (1 строка - уличный датчик, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
// подпрограмма формирования изображения 9-й страницы на lcd (1 строка - датчик котловой воды, удалить, выход на 1 стр.; 2 строка - адрес комнатного датчика)
lcd.print(" "); // создает мигание выбранного параметра путем выключения его изображения на 0,1 сек. через 0,2 сек.
}
else
{
lcd.print("Exit ");
}
}
// вывод инфы на дисплей о подключении более 1 нового датчика и необходимости выключения и выключения устройства с 1 новым датчиком для его записи в EEPROM и присвоения ему статуса: комнатного, уличного и котловой воды
// подпрограмма проверки адресов подключенных датчиков температуры на их соответствие данным, содержащимся в EEPROM.
voidproverka_podkluch_datchikov_temp()
{
// считываем адреса датчиков, содержащиеся в EEPROM
read_eeprom_adres_datch();
// считываем адреса подключенных датчиков температуры
for(byteb=1; b<4; b++)
{
ds.reset();
ds.search(temp_adres);
for(bytei=0; i<8; i++)
{
switch(b)
{
case1:
temp_adres_datch_1[i]=temp_adres[i];
break;
case2:
temp_adres_datch_2[i]=temp_adres[i];
break;
case3:
temp_adres_datch_3[i]=temp_adres[i];
break;
}
}
}
ds.reset();
ds.search(sss); // нужна для исключения ошибок, так как командой search последний датчик считывывается два раза. Результат этой команды не используется
////////////////////////////////////
// Проверяем на отсутствие какого-либо датчика и исключения дальнейших ошибок от возможной записи в в несколько переменных одного и того же адреса
// Если в адресе 3 считанного датчика содержится адрес 2 считанного датчика, то записываем нули
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // 3 раза считываем температуру и записываемх их в переменные temperatura_pamyat[] для исключения ошибок при сравнении.
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" заданной пользователем температуры для последующего сравненния со считанной.
// проверяем достижение необходимого интервала для запуска подпрограммы считывания комнатной температуры
temperatura_room=schit_datchik_temperatury(adres_dat_temp_room, 3); // переход к подпрограмме считывания температуры с уличного датчика температуры. 3 - кол-во считываний
wyhod_temp_room_predel(); // переход к подпрограмме определения выхода температуры за установленный пользователем предел более чем на 1 градус и гистерезис и включения звукого уведомления
}
// проверяем достижение необходимого интервала для запуска подпрограммы считывания уличной температуры
temperatura_street=schit_datchik_temperatury(adres_dat_temp_street, 1); // переход к подпрограмме считывания температуры с уличного датчика температуры. 1 - кол-во считываний
}
proverka_temperatury_room(); // переход к подпрограмме проверки считанной температуры на наличие грубых ошибок
sravnenie_temp_room_upravl_wychod(); // переход к подпрограмме сравнения полученной с датчика температуры с установленными пользователем температурами с учетом времени и выполнение команд на включение или выключение котла
problem_datch_room(); // переход к подпрограмме определения отсутствия ответа от комнатного датчика в течение длительного времени
Совет где повесить датчик.......
Мой совет не использовать температуру внутри для регулировки
Сам соседям лично выкидывал комнатные термостаты " втюханные" разными сантехниками.
А люди доверчивы, кнопочки жимкают, видиш, говорят: я тут температуру поставил, всё должно само работать А у них то холодно то жарко.
Была такая же фигня, пока не настроил реакцию комнатного термостата на 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...
Может кому-нибудь помогут результаты моей работы. Также прошу высказывать мысли по поводу оптимизации.
[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, подключение уличного датчика предусмотрено производителем, подходящий по параметрам я подобрал у китайцев.
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
а как её добавить стандартным вариантом не получается :(
1
#include <avr/wdt.h>
2
3
void
setup
() {
4
// put your setup code here, to run once:
5
}
6
7
void
loop
() {
8
// put your main code here, to run repeatedly:
9
}
В скетче вот что заметил - #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 - Вам за решение проблемы с запуском!
В итоге все работает, температуру показывает, сейчас буду подключать к котлу.