Суточный термостат для газового котла

R2PM
Offline
Зарегистрирован: 28.12.2015

bagotu пишет:

это к этому:

dwk26111974 пишет:

 

#include <hd44780.h>
0003 #include <hd44780ioClass/hd44780_I2Cexp.h>

Выдает ошибку..а какую библиотеку использовали?

LCD к градуснику не причем.

надо внимательно просмотреть и прозвонить цепи. бывает.

может отвалилось чего...

только что всё проверил - всё так - может среда должна быть другая, например 1.0.1

bagotu
Offline
Зарегистрирован: 15.10.2016

[/quote]

только что всё проверил - всё так - может среда должна быть другая, например 1.0.1

[/quote]

первая же работает.

может его на ногу А2 подвесить и в скетче подправить. (нога пустая)

R2PM
Offline
Зарегистрирован: 28.12.2015

bagotu пишет:

только что всё проверил - всё так - может среда должна быть другая, например 1.0.1

[/quote]

первая же работает.

может его на ногу А2 подвесить и в скетче подправить. (нога пустая)

[/quote]

пробую

R2PM
Offline
Зарегистрирован: 28.12.2015

Всё запустил!!! на А2 не пошёл, вернул на А1 заработал!!!

При каких условиях вкл реле???

bagotu
Offline
Зарегистрирован: 15.10.2016

Мистика )))
Реле управляется низким уровнем. При Т в комнате = заданной

vlad219i
Offline
Зарегистрирован: 05.03.2014

Обратите внимание - в скетче есть задержка включения реле, чтобы оно не слишком часто котёл дёргало. Это я к тому, что стОит немного подождать перед тем, как писать, что реле не включается. :-))

R2PM
Offline
Зарегистрирован: 28.12.2015

vlad219i пишет:

Обратите внимание - в скетче есть задержка включения реле, чтобы оно не слишком часто котёл дёргало. Это я к тому, что стОит немного подождать перед тем, как писать, что реле не включается. :-))

Спасибо за проет!!!!!

Уже давно заметил, сейчас всё в порядке!!! РАБОТАЕТ!!!!

Виктор R2PM

 

bagotu
Offline
Зарегистрирован: 15.10.2016

Больше человеческое спасибо за проэкт!
Есть мысли прикрутить сюда модуль wi-fi для связи с внешним миром?

vlad219i
Offline
Зарегистрирован: 05.03.2014

wi-fi - нет, rf24 - да, мысли есть, а вот времени на это развлечение пока нет. :-)

 

Slaiterx
Offline
Зарегистрирован: 05.05.2016

а как добавить датчиков температуры хочу один на улицу выкинуть а второй на котел поставить чисто для мониторинга у меня дисплей 20х4 места для вывода предостаточно

UNIVERSE
Offline
Зарегистрирован: 26.10.2015
gurol
Offline
Зарегистрирован: 06.12.2016

Третий сезон работает самодельный контроллер отопления, реализованный на меге 2560. К этому контроллеру подключены: - газовый котел АОГВК-35 с клапаном ХОнивелл, который позволяет подключить удаленный термостат; - 4 циркулящионных насоса для гидрострелки, теплотрассы, теплого пола и радиаторов; - 6 датчиков темпратуры (DS18b20); - 5 реле для управления газовым клапаном и насосами. Информация о температуре выводится на LCD 1620, еще имеется 5 кнопок (2 для управления меню дисплея и 3- для выбора режима работы термостата. В контроллере реализована погодозависимая регулировка температуры воды в котле. На контроллере реализован сервер, есть возможность выводить информацию в локальную сеть. Из наблюдений за работой СВОЕЙ системы отопления могу сказать, что: - управление котлом по времени суток наиболее целесообразно в конце весны и в начале осени; - в управлении котлом кроме наружной температуры необходимо учитывать и скорость ветра (особенно актуально в Ростовской области, где зимой дуют сильные и холодные восточные ветры).

demonik-13
Offline
Зарегистрирован: 22.12.2016

День добрый.

Первый вариант кода работает отлично. Со вторым появляется ошибка при компиляции, уже и переустанавливал среду и все библиотеки, ошибка одна и та же: 

Arduino: 1.6.13 (Windows XP), Плата:"Arduino/Genuino Uno"
 

 

                
 
Andrej_SL
Offline
Зарегистрирован: 25.12.2016

стр. 2 сообщение №85

Или вот здесь почитайте https://forum.pjrc.com/threads/24589-Another-library-fails-to-compile%E2..., нужно установить патч

Tarantull
Offline
Зарегистрирован: 09.01.2017

Добрый день vlad219i, очень хорошая статья. Не смог найти схему подключения в вашем Посте. 

demonik-13
Offline
Зарегистрирован: 22.12.2016

Andrej_SL пишет:

стр. 2 сообщение №85

Или вот здесь почитайте https://forum.pjrc.com/threads/24589-Another-library-fails-to-compile%E2..., нужно установить патч

Долго не мог добраться до термостата, всё праздники да праздники. Этот пост читал уже давно. Вобщем много танцев, много бубнов разных племён и ничего. И вот решил перенести с работы всё домой. И о чудо! На вин7 с первого раза, чистая установка последней среды и библиотек напрямую с поиска, всё компилится и всё работает. А ноут на работе остался загадкой, жаль там винду нельзя перебить, думаю проблема в ней.

vlad219i
Offline
Зарегистрирован: 05.03.2014

Tarantull пишет:

Добрый день vlad219i, очень хорошая статья. Не смог найти схему подключения в вашем Посте. 

Её там и нет. Подключение железа описано в самом начале скетча в дефайнах, там всё прозрачно.

 

Tarantull
Offline
Зарегистрирован: 09.01.2017

Спасибо.

Aloe_Weider
Offline
Зарегистрирован: 09.01.2017

Добрый день vlad219i ваш проэкт очень интерестный но если можно было бы сделать LED 16:2 подключение по I2С То вобще было бы шикарно, я бы сам сделал только я рукажоп начинающий и могу создать код только мигающего светодиода =)

Slaiterx
Offline
Зарегистрирован: 05.05.2016

странициы две назад есть код для I2C

 

Aloe_Weider
Offline
Зарегистрирован: 09.01.2017

СПС

Staryjdub
Offline
Зарегистрирован: 08.04.2016

Доброго времени суток! По поводу библиотек к скетчу на 4ой странице. Не могу найти hd44780.h, RealTimeClockDS1307.h, EEPROM.h, TimerOne.h ... Гопода помогите найти - ткните носом!!!! И какая версия компилятора?

olezhan36
Offline
Зарегистрирован: 29.02.2016

спасибо автору за скетч. Все работает на 5.

Было бы здорово сделать термостат многоканальным. Т.е. отдельно управлять радиаторами, теплым полом и бойлером косвенного нагрева.

У бойлера, например свои температуры, свой гистерезис

001// Термостат, до пяти датчиков DS18B20.
002// 
003 
004//  v 0.2.1 beta
005 
006#include <EEPROM.h>
007#include <OneWire.h>
008#include <DallasTemperature.h>
009#include <LiquidCrystal.h>
010  
011OneWire  oneWire(15); // A1 вход датчиков 18b20
012DallasTemperature ds(&oneWire);
013LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
014 
015 
016const byte OUT[5] = {13, 12, 11, 3, 2}; // номера выходов
017  
018byte pos;
019byte tempOUTon[5];  // массив с температурой включения выхода
020float tempSensor[5]; // массив куда читается температура
021float Hysteresis = 0.5; // гистерезис
022byte qty; // количество градусников на шине.
023 
024// адреса градусников.
025DeviceAddress sensor1 = {0x28, 0xFF, 0x08, 0x26, 0x34, 0x16, 0x04, 0x68};
026DeviceAddress sensor2 = {0x28, 0xFF, 0x01, 0x4D, 0x34, 0x16, 0x04, 0x9F};
027DeviceAddress sensor3 = {0x28, 0xFF, 0x75, 0x2D, 0x34, 0x16, 0x03, 0xFE};
028DeviceAddress sensor4 = {0x28, 0xFF, 0x084, 0x4D, 0x34, 0x16, 0x04, 0x86};
029DeviceAddress sensor5 = {0x28, 0xFF, 0x4D, 0x28, 0x34, 0x16, 0x03, 0xC5};
030 
031byte gradus[8] = {
032  0b00110,
033  0b01001,
034  0b01001,
035  0b00110,
036  0b00000,
037  0b00000,
038  0b00000,
039  0b00000
040};
041byte on[8] = {
042  0b00110,
043  0b01111,
044  0b11111,
045  0b11111,
046  0b11111,
047  0b11111,
048  0b11110,
049  0b01100
050};
051 
052void readSet(){
053  for (byte i = 0; i < qty; i++) tempOUTon[i] = EEPROM.read(i);
054}
055  
056void outOff(){ // выключает выходы
057  for (byte i = 0; i < qty; i++) digitalWrite(OUT[i], LOW);
058}
059 
060void erorr(){ // останавливает работу программы и сигнализирует ошибку
061  outOff(); // выключаем выходы   
062  lcd.clear();
063  lcd.print("sensor error");
064   while(1){ // крутим бесконечный цикл
065      analogWrite(10, 100);
066      delay(500);
067      analogWrite(10, 255);
068      delay(500);
069  }
070}
071////
072 
073byte key(){ //// для кнопок ЛСДшилда
074  int val = analogRead(0);
075    if (val < 50) return 5;
076    else if (val < 150) return 3;
077    else if (val < 350) return 4;
078    else if (val < 500) return 2;
079    else if (val < 800) return 1;
080    else return 0; 
081}
082//// 
083 
084void setMenu(byte pos){ // установка температуры  
085 outOff();
086 lcd.clear();
087   
088  while(1){ // крутим бесконечный цикл     
089    byte KEY = key(); // читаем состояние кнопок
090     
091    lcd.setCursor(2, 0); // выводим на экран
092    lcd.print("Out:");
093    lcd.print(pos+1);
094    lcd.setCursor(9, 0);
095    lcd.print("Pin:");
096    lcd.print(OUT[pos]);
097    lcd.print("    ");
098      
099    lcd.setCursor(0, 1);  
100    lcd.print(" PinON: ");
101    lcd.print(tempOUTon[pos]);
102    lcd.write(1);
103    lcd.print("C <>");
104     
105     if (key() == 4
106     {TimeOUTon[pos]--;   // изменяем значение
107        if (TimeOUTon[pos] > 125) tempOUTon[pos] = 0;
108      EEPROM.write(
109     }
110     if (key() == 3 && pos != 0) pos--;
111   
112    if (KEY == 2) { // если нажата кнопка
113      tempOUTon[pos]--;   // изменяем значение
114        if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
115      EEPROM.write(pos, tempOUTon[pos]); // сохраняем в еепром
116     }
117     else if (KEY == 5){
118       tempOUTon[pos]++;
119         if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
120       EEPROM.write(pos, tempOUTon[pos]);   
121     }
122  
123   delay(200);
124  }/////  
125}//
126 
127void getTemp(){ // читаем температуру и заполняем массив
128   ds.requestTemperatures();   
129    
130   tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода
131   tempSensor[1] = ds.getTempC(sensor2);
132   tempSensor[2] = ds.getTempC(sensor3);
133   tempSensor[3] = ds.getTempC(sensor4);
134   tempSensor[4] = ds.getTempC(sensor5);
135}
136 
137void sensorTest(){  // ищим датчики на шине, если количество изменилось, останавливаем работу
138   ds.begin();
139   if(ds.getDeviceCount() != qty) erorr();
140}
141 
142void setup() {
143 //  Serial.begin(9600);
144  ds.begin();  
145  qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников,
146                             // можно и лучше количество указать руками.
147   
148  for (int i = 0; i < qty; i++) pinMode(OUT[i], OUTPUT); 
149  for (int i = 0; i < qty; i++) digitalWrite(OUT[i], LOW);
150   
151  lcd.createChar(1, gradus);
152  lcd.createChar(2, on);
153  lcd.begin(16, 2);
154  lcd.clear();
155   
156  readSet();  // читаем настройки из еепром  
157}
158 
159void loop() {  
160  if (key() == 1) setMenu(pos); // если нажата селект, уходим в настройки
161   
162  else if (key() == 4 && pos < qty-1) pos++; // крутим позицию
163  else if (key() == 3 && pos != 0) pos--;
164   
165   
166    sensorTest(); // тест наличия градусников на шине
167    getTemp(); // читаем температуру с датчиков 
168    
169  //// сверяем температуру и управляем выходами
170  for (int i = 0; i < qty; i++)
171        {if (tempSensor[i] > (tempOUTon[i]+Hysteresis))
172          if ( digitalRead(OUT[i]) == HIGH ) // если горелка включена
173              digitalWrite(OUT[i], LOW);
174              
175          
176    if (tempSensor[i] < tempOUTon[i])
177           if ( digitalRead(OUT[i]) == LOW ) // если горелка выключена
178              digitalWrite(OUT[i], HIGH);
179  }         
180 
181  /////// вывод инфы на экран
182  lcd.setCursor(0, 0);
183  lcd.print(pos+1);
184  lcd.print(". ");
185  lcd.print(tempSensor[pos], 1);  // показываем температуру с датчика
186  lcd.write(1);
187  lcd.print("C  ");
188  lcd.setCursor(2, 1);
189  lcd.print(tempOUTon[pos]); // показываем установленную температуру
190  lcd.write(1);
191  lcd.print("C  ");   
192   
193  lcd.setCursor(11, 0);  // рисуем статус выхода 
194    for (int i = 0; i < qty; i++){
195      if (digitalRead(OUT[i])) lcd.write(2);
196      else lcd.print(" ");
197    }
198  lcd.setCursor(11, 1); // рисуем номера выходов  
199    for (int i = 0; i < qty; i++) lcd.print(i+1);
200 
201// delay(500); // необязательная задержка
202}

и свой график расхода воды.

Ниже код для 5-ти канального термостата (скаченый из http://arrduinolab.blogspot.ru/2014/10/5-ds18b20.html), но функции суточной коррекции температуры там нет.

Задача-слепить из двух один.

С энкодером, наверное не получится , а с LCD Shield должно (кнопок больше и свободных пинов). Там 5 свободных цифровых выходов. 4 канала под реле, а 5-й можно на зуммер оставить.

Сам могу как и многие лишь моргать светодиодами.

Допилить кто может? можно за небольшое вознаграждение.

Tolchoks
Offline
Зарегистрирован: 27.05.2016

trembo пишет:

vlad219i пишет:

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

Вкратце - я ж говорю, меня устраивает. Вариант с уличным датчиком наверняка во сто крат правильнее и экономичнее, но в моём случае room thermostat'а мне хватает за глаза. Елозить установкой температуры теплоносителя больше не приходится, ну и, к примеру, котёл реже включается, если солнце через окна подогревает дом, - дык этого я и добивался. :-)

Или вы меня не понимаете или заблуждаетесь.

1. Уличный датчик- тот же самый DS18B20, он не стОит  несуразных денег.

2. Протокол нас не интересует- лезть в газовый котёл  так глубоко даже опасно. Единственное ЛЕГАЛЬНОЕ место куда можно подключаться как раз и есть те самые контакты комнатного термостата.

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

У меня два года у соседа работала Ардуина с блоком реле и ЖКИ шилдом на котле Junkrs Eurostar который по своей природе на минимуме регулятора не мог выдавать меньше 45-50 градусов, а его тёплый пол при этом становился горячим пока не сработают клапана на рейке, потом они отключались и когда снова включались - пол уже был ледяной. И так всё время колебания: холодный-горячий

Ардуина выключала котёл при 32 и снова включала при 28 (условно) Все клапана пола были НАВСЕГДА открыты! Регулировка вручную  температура-гистерезис, стабильная температура в доме, сосед был доволен.

У меня у самого дома котёл с погодником- Junkers Cerapur, как лет 8 назад отрегулировал наклон графика так и работает. Клапана тёплого пола тоже сняты навсегда за ненадобностью

 

у нас уличный датчик стоит данфосс - как часы все работает!

Slaiterx
Offline
Зарегистрирован: 05.05.2016

а где взять библиотеку вачдог таймер

 

demonik-13
Offline
Зарегистрирован: 22.12.2016

Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.

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

Slaiterx пишет:

а где взять библиотеку вачдог таймер

 

Э, он как бы уже на борту. Надо включить или выключить, ну и сбрасывать своевременно.

Slaiterx
Offline
Зарегистрирован: 05.05.2016

имелось в виду библиотека из этого скетча немогу найтиhttp://arduino.ru/forum/proekty/sutochnyi-termostat-dlya-gazovogo-kotla?page=2#comment-151943

dwk26111974
Offline
Зарегистрирован: 11.07.2016

День добрый. Было бы очень интересно получить и воплотить термостат на 2 модуля. Просьба вышлите на ЭП

dwk26111974@gmail.com Заранее благодарен.

Rukey
Offline
Зарегистрирован: 19.05.2016

Здравствуйте. Реализовал для загородного дома контроллер и добавил к нему модем siemens mc35i, подключаемый через com порт, для управления изменением температуры и получения уведомления о снижении ниже уровня, а также получания статуса. Огромное спасибо автору проекта vlad219i.

vlad219i
Offline
Зарегистрирован: 05.03.2014

Rukey пишет:

Реализовал для загородного дома контроллер и добавил к нему модем siemens mc35i

ЗдОрово, это как раз то, до чего у меня руки не дошли пока. :-)

Поинтересуюсь - для управления и получения статуса используются смс или интернет-подключение? Лет 10 назад я делал нечто похожее (дачная двусторонняя сигналка), там использовал СМС-команды.

Первую фотку удалось открыть только по прямой ссылке, остальные - не видно никак, а жаль.

 
Rukey
Offline
Зарегистрирован: 19.05.2016
 
 
 
 
 
 
 
Прошу прощения, яндекс диск подвел.
 
Управление SMS.
olezhan36
Offline
Зарегистрирован: 29.02.2016

demonik-13 пишет:

Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.

Два модуля-это два разных канала,  с независимым термостатированием??

Если да, то мне очень нужно.

Rukey скажите где брать такие корпуса??? Они идеальны. Я так понимаю, держатели под каждый модуль вы приклеиваете самостоятельно. И по сути это конструктор. Откройте для меня тайну, плиз!!

demonik-13
Offline
Зарегистрирован: 22.12.2016

olezhan36 пишет:

demonik-13 пишет:

Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.

Два модуля-это два разных канала,  с независимым термостатированием??

Если да, то мне очень нужно.

Rukey скажите где брать такие корпуса??? Они идеальны. Я так понимаю, держатели под каждый модуль вы приклеиваете самостоятельно. И по сути это конструктор. Откройте для меня тайну, плиз!!

 

Нет, это значит что модуль с экраном и датчиком висит в комнате, а в котёл засунул вторую ардуинку нано с релюшкой и они общаются через РФ-ку. Хотя собрать ещё один модуль для второго помещения и отправлять команду на тот-же адрес РФ-ки в котле и всё. Код одинаков, только адреса радиомодуей выставить.

balbes323
Offline
Зарегистрирован: 06.12.2016

Доброй ночи, товарищи! Вот сваял, поставил, все работает, автору респект, все устраивает. Немного допилил под свои задачи, три месяца, полет нормальный. Ежедневный отчет по GSM приходит исправно. Управляется по GSM тоже ок. Можно даже позвонить туда и оттуда и полноценно поговорить. Но вот сижу и думаю... Хата моя стоит за 300 км от меня, хорошо, что в скетче автора не используется адрес датчика DS, заменить сможет любой электрик. А если адрес датчика прописан и он накрылся? тогда брать ноут и новый датчик и ехать менять, т.к. без скетча никто ничего не сможет сделать. Далее, возникла идея прикрутить еще датчик на улицу. Тут уже адрес нужен и ремонтопригодность сводится к 1 человеку, который это сделал. Вот сижу и думаю, ведь можно и без адресов опросить все датчики на шине, но как контроллер узнает, какой из них какой, если адреса не прописаны? Но если это реализовать, то обслуживание и ремонт наших термостатов упростится в разы. Может, у кого есть идеи по этому поводу?

vlad219i
Offline
Зарегистрирован: 05.03.2014

balbes323 пишет:

Далее, возникла идея прикрутить еще датчик на улицу. Тут уже адрес нужен и ремонтопригодность сводится к 1 человеку, который это сделал. Вот сижу и думаю, ведь можно и без адресов опросить все датчики на шине, но как контроллер узнает, какой из них какой, если адреса не прописаны?

Никак не узнает.

Я в подобном случае каждый датчик на отдельный пин вешал и адрес датчика не использовал.

 

balbes323
Offline
Зарегистрирован: 06.12.2016

Тоже думал над этим вариантом, только у 328 пинов маловато, придется мегу ставить.

vlad219i
Offline
Зарегистрирован: 05.03.2014

Думаю, что мега тут - слишком жирно. LCD можно подключить по i2c, порты расширить 75hc595 (заодно светодиодов для индикации добавить). Ну это так - навскидку...

У меня умный дом немного по-другому организован. База на меге + LCD + LAN-шилд + датчики уличной температуры-давления-влажности + RF24, а уже через RF24 опрашиваются дополнительные модули (контроллер насоса, термостат и тд и тп). Все данные собираются-обрабатываются в меге и отправляются через мобильный инет на сервак, где и ведутся логи и генерятся странички с удобочитаемыми отчётами. Таким образом, из любой точки с интернетом есть доступ к инфе по дому.

balbes323
Offline
Зарегистрирован: 06.12.2016

Вот код и аппарат)))

 

balbes323
Offline
Зарегистрирован: 06.12.2016

только это не умный дом, а термостат.

vlad219i
Offline
Зарегистрирован: 05.03.2014

Красиво. Стимпанк... :-)

 

Rukey
Offline
Зарегистрирован: 19.05.2016

olezhan36 пишет:

demonik-13 пишет:

Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.

Два модуля-это два разных канала,  с независимым термостатированием??

Если да, то мне очень нужно.

Rukey скажите где брать такие корпуса??? Они идеальны. Я так понимаю, держатели под каждый модуль вы приклеиваете самостоятельно. И по сути это конструктор. Откройте для меня тайну, плиз!!

 

Спасибо. Корпус проектировал в инвенторе, печатал на 3д принтере. Территориально работаю в Москве, могу распечатать. Ну если проблема, можно файлы выложить для самостоятельной печати, если из другого города есть где распечатать.

olezhan36
Offline
Зарегистрирован: 29.02.2016

У меня при вращении энкодера значения на экране только увеличиваются. Независимо от направления вращения.

энкодер с фиксацией положения https://ru.aliexpress.com/item/Rotary-Encoder-Module-Brick-Sensor-Development-for-Arduino/32452759168.html?spm=2114.13010608.0.0.1YTNVw

В чем может быть причина? 

контакты "clk" "DT" вешаю на А4 и А5 соответственно. Пробовал менять местами-результат тот же.

olezhan36
Offline
Зарегистрирован: 29.02.2016

olezhan36 пишет:

 

контакты "clk" "DT" вешаю на А4 и А5 соответственно. Пробовал менять местами-результат тот же.

Ошибся-туда часы. Энкодер на 2 и3 пины.

vlad219i
Offline
Зарегистрирован: 05.03.2014

От 2 и 3 пина на землю параллельно энкодеру по керамическому конденсатору (примерно 0,01мкФ) подключите - должно помочь.

olezhan36
Offline
Зарегистрирован: 29.02.2016

Вот плод моих ночных бдений в свободное от работы и семьи время.

Сразу скажу, чтоб потом помидорами не закидали, что язык я специально не изучал, а с программированием до этого сталкивался еще в школе. Так что может быть скетч написан не идеально и м.б. косячки. Работу скетча  проверял только на макетке. В бою не тестировал.

За основу были взяты 3 скетча:

1.  скетч автора этой темы

2.https://www.youtube.com/watch?v=mFtgO3kWA4g

3.http://cxem.net/arduino/arduino166.php для работы со сдвиговым регистром.

vlad219i написал отличный скетч, но бывает так (как у меня), что система отопления состоит не только из одного котла. Например, у меня есть котел, к которому через гидрострелку подключены радиаторы, теплый пол, бойлер косвенного нагрева. Есть 3 насоса+насос рециркуляции ГВС. И всем этим хозяйством нужно управлять. Вот я и решил немного допилить скетч vlad219i.

Изменения:

-изменение температуры термостатирования перенесено в меню

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

-реле основное вкл/выкл котел, замыкает  и размыкает контакты термостата котла на плате.

-3 свободных аналоговых входа использованы для подключения сдвигового регистра 74HC595. Т.о. имеем 8 цифровых выходов, к которым подключены реле для управления  8 каналами. По каждому из каналов скетч работает как у vlad219i-задается температура и поддерживается, сохранено время миниманальной паузы между включениями/выключениями. Таймеры сохранены.

Когда по каждому из 8 каналов нет запроса на тепло, то выключается основное реле и котел гаснет.

Таким образом можно регулировать температуру в 8-ми комнатах отдельно, да ещё и по расписанию. Если конечно есть исполнительные устройсва в этих комнатах.

Я планирую управлять температурой в комнатах (один датчик на все комнаты) с помощью вкл/выкл насоса радиаторов. Аналогично для теплого пола и бойлера косвенного нагрева.

Цель-экономия газа. Скетч позволит мне снижать температуру в комнатах в ночное время или во время пребывания на работе, отключать теплый пол теплый пол на ночь, не греть бойлер когда это не нужно и разогревать его максимально в пиковые часы.

Будет ли экономия существенной я узнаю только следующей зимой. А пока это только мечты...

0001/*
0002Суточный термостат для котла Baxi Mainfour 240F
0003 >Encoder control
0004 >DS18B20 thermal sensor
0005 >LCD1602 parallel
0006 >DS1307 RTC
0007 */
0008  
0009//#include <avr\eeprom.h>
0010#include <Wire.h> // i2c (для RTC)
0011#include <RealTimeClockDS1307.h> // RTC
0012#include <EEPROMex.h> // EE
0013#include <LiquidCrystal.h> // LCD 16*2
0014#include <TimerOne.h> // прерывания по таймеру1
0015  
0016#include <OneWire.h> // 1wire для DS18B20
0017#include <DallasTemperature.h> // DS18B20
0018 
0019#define ONE_WIRE_BUS A1
0020OneWire oneWire(ONE_WIRE_BUS);
0021DallasTemperature DS18B20(&oneWire);
0022DeviceAddress DS18B20Address;
0023  
0024#define encoderA    2 // энкодер - поворот вправо (об землю)
0025#define encoderB    3 // энкодер - поворот влево (об землю)
0026#define encoderK    13 // энкодер - кнопка (об землю)
0027#define BeepPin     12 // пищалка
0028#define BeepToneNo  2000 // тон звука "No", герц
0029#define BeepToneYes 4000 // тон звука "Yes", герц
0030#define BeepToneNoDuration 200 // длительность звука "No", мс
0031#define BeepToneYesDuration 200 // длительность звука "Yes", мс
0032#define RelayMain  11  // нога, к которой подключено реле, которое вык/вкл котел
0033#define RelayOn LOW // полярность сигнала включения реле (HIGH/LOW)
0034#define qtyChannal 8  //количество каналов/датчиков
0035int channalOn;  //количество включенных реле (каналов, температура которых ниже заданной).
0036// LCD connection RS, E, D4, D5, D6, D7
0037// R/W - to ground
0038LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
0039 
0040//для регистра 74HС595
0041#define clock 16
0042#define data 17
0043#define latch 14
0044boolean Relay[8];
0045 
0046 
0047  
0048byte block1[8] = {
0049  0x06,0x09,0x09,0x06,0x00,0x04,0x0E,0x1F }; // значок градуса с пламенем снизу
0050byte block2[8] = {
0051  0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00 }; // значок градуса
0052 
0053#define serialenabled // раскомментировать для выдачи в порт отладочной инфы
0054  
0055#define TstatTimerMax 180 //минимальная пауза между включениями горелки, сек
0056unsigned int TstatTimer[qtyChannal]  ; //таймер паузы между включениями/выключениями, начальная установка 20 сек для устаканивания системы после сброса
0057 
0058float DS18B20Temperature[qtyChannal] ; //времянка
0059float Temperature[qtyChannal] ; //вычисленная температура с коррекцией
0060float DS18B20TempTmp[qtyChannal]; //сырая температура от датчиков
0061byte DS18B20iteration = 0; //счётчик измерений температуры для усреднения
0062  
0063float TstatTemp[qtyChannal] ; //температура термостатирования, может изменяться настройками
0064float TstatTempOld[qtyChannal];
0065float TemperatureCorr[qtyChannal]; //коррекция температуры, может изменяться настройками
0066float Hysteresis[qtyChannal] ; // гистерезис термостата, может изменяться настройками
0067float HysteresisOld[qtyChannal];
0068float AlarmTemp[qtyChannal] ; // температура для замерзательного орала
0069  
0070 
0071int Hours = 0; // времянка часов RTC для отображения и установки
0072int Minutes = 0; // времянка минут RTC для отображения и установки
0073int Seconds;
0074boolean PrintYesNo = false; // показывать ли после времени Yes/No (косвенно - указание на режим установка/отображение)
0075boolean SetH = false; // выделение часов при отображении
0076boolean SetM = false; // выделение минут при отображении
0077boolean SetYesNo = false; // выделение Yes/No при установке часов
0078  
0079boolean blink500ms = false; // мигающий бит, инвертируется каждые 500мс
0080boolean plus1sec = false; // ежесекундно взводится
0081  
0082boolean BeepEnabled = true;
0083int channel=0;   //номер канала
0084  
0085byte MenuTimeoutTimer;
0086  
0087 // адреса градусников.
0088DeviceAddress sensor []{
0089 {0x28, 0xFF, 0x08, 0x26, 0x34, 0x16, 0x04, 0x68},
0090 {0x28, 0xFF, 0x01, 0x4D, 0x34, 0x16, 0x04, 0x9F},
0091 {0x28, 0xFF, 0x75, 0x2D, 0x34, 0x16, 0x03, 0xFE},
0092 {0x28, 0xFF, 0x84, 0x4D, 0x34, 0x16, 0x04, 0x86},
0093 {0x28, 0xFF, 0x4D, 0x28, 0x34, 0x16, 0x03, 0xC5},
0094 {0x28, 0xFF, 0xF7, 0x4D, 0x34, 0x16, 0x04, 0xA5},
0095 {0x28, 0xFF, 0x8C, 0x30, 0x34, 0x16, 0x04, 0x8D},
0096 {0x28, 0xFF, 0xFC, 0x49, 0x34, 0x16, 0x04, 0xDB},
0097 {0x28, 0xFF, 0xAB, 0x30, 0x34, 0x16, 0x03, 0xA7},
0098 {0x28, 0xFF, 0x67, 0x40, 0x34, 0x16, 0x04, 0x8F},
0099};
0100// структура для суточных таймеров (8 байт)
0101struct buffer_template {
0102  byte Hours;
0103  byte Minutes;
0104  float Temperature;
0105  boolean Enabled;
0106  boolean Activated;
0107};
0108buffer_template Timer[4][qtyChannal] = {0, 0, 23.0, false, false}; //объявление 4-х суточных таймеров для каждого из 9 каналов и их начальные значения
0109  
0110 
0111// encoder vars
0112static boolean rotating=false;      // debounce management
0113boolean A_set = false;            
0114boolean B_set = false;
0115boolean encoderR = false;
0116boolean encoderL = false;
0117  
0118// EEPROM
0119EEMEM float TstatTempEE[qtyChannal]; //EE температура термостатирования
0120EEMEM float TemperatureCorrEE[qtyChannal]; // EE коррекция температуры
0121EEMEM float HysteresisEE[qtyChannal]; // EE гистерезис
0122EEMEM boolean BeepEnabledEE; // EE признак разрешения звука
0123EEMEM float AlarmTempEE[qtyChannal]; // EE значение недопустимого снижения температуры
0124EEMEM buffer_template TimerEE[4][qtyChannal]; // EE структуры для 4 суточных таймеров
0125  
0126// ===== SETUP ========================================================================
0127void setup() {
0128   
0129  
0130#ifdef serialenabled
0131  Serial.begin(9600);
0132#endif
0133// задаем начальные значения
0134for (int j=0; j<qtyChannal; j++){
0135  TstatTimer[j]=20  ; //таймер паузы между включениями/выключениями, начальная установка 20 сек для устаканивания системы после сброса
0136  DS18B20Temperature[j]=0 ; //времянка
0137  Temperature[j]=0 ; //вычисленная температура с коррекцией
0138}
0139  pinMode(RelayMain, OUTPUT);
0140  digitalWrite(RelayMain, HIGH);
0141  lcd.begin(16, 2);
0142  lcd.createChar(1, block1);
0143  lcd.createChar(2, block2);
0144  pinMode(encoderA, INPUT);
0145  digitalWrite(encoderA, HIGH);
0146  pinMode(encoderB, INPUT);
0147  digitalWrite(encoderB, HIGH);
0148  pinMode(encoderK, INPUT);
0149  digitalWrite(encoderK, HIGH);
0150  attachInterrupt(0, doEncoderA, CHANGE);   // encoder pin on interrupt 0 (pin 2)
0151  attachInterrupt(1, doEncoderB, CHANGE);  // encoder pin on interrupt 1 (pin 3)
0152  Timer1.initialize(500000); // Timer0 interrupt - set a timer of length 500000 microseconds
0153  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
0154  EEPROM.setMaxAllowedWrites(32767);
0155  //для сдвигового регистра
0156  pinMode(clock, OUTPUT);
0157  pinMode(data, OUTPUT);
0158  pinMode(latch, OUTPUT);
0159  digitalWrite(latch, HIGH);
0160 cleanreg();  
0161  if ((digitalRead(encoderK)) == 0)
0162  { // если первая запись однокристалки (зажата кнопка при включении питания)- записать начальные значения в EE
0163    lcd.setCursor(0, 0); //инфо на LCD
0164    lcd.print(F("Cold start..."));
0165    for (int j=0; j<qtyChannal; j++){
0166    for (int i=0; i<4; i++)
0167    {
0168           Timer[i][j].Hours = Timer[i][j].Minutes = 0;
0169           Timer[i][j].Temperature = 23.0;
0170           Timer[i][j].Enabled = Timer[i][j].Activated = false;
0171      EEPROM.updateBlock(int(&TimerEE[i][j]), Timer[i][j]);
0172      
0173    }
0174      //присвоение начальных значений
0175   
0176  TstatTemp[j]=25 ; //температура термостатирования, может изменяться настройками
0177  TemperatureCorr[j]=0; //коррекция температуры, может изменяться настройками
0178  Hysteresis[j]=0.5 ; // гистерезис термостата, может изменяться настройками
0179  AlarmTemp[j]=20 ; // температура для замерзательного орала 
0180    //запись начальных значений в еепром
0181    EEPROM.updateFloat(int(&TstatTempEE[j]), TstatTemp[j]);
0182    EEPROM.updateByte(int(&BeepEnabledEE), BeepEnabled);
0183    EEPROM.updateFloat(int(&TemperatureCorrEE[j]), TemperatureCorr[j]);
0184    EEPROM.updateFloat(int(&HysteresisEE[j]), Hysteresis[j]);
0185    EEPROM.updateFloat(int(&AlarmTempEE[j]), AlarmTemp[j]);
0186    }
0187    tone(BeepPin,2000,50);
0188    delay(50);
0189    tone(BeepPin,3000,50);
0190    delay(50);
0191    tone(BeepPin,4000,50);
0192    delay(1000);
0193  }
0194  lcd.clear();
0195  lcd.setCursor(0, 0); //инфо на LCD
0196  lcd.print(F("Read settings..."));
0197 //чтение еепром
0198  BeepEnabled = EEPROM.readByte(int(&BeepEnabledEE));
0199  for (int j=0; j<qtyChannal; j++) {
0200  TstatTemp[j] = EEPROM.readFloat(int(&TstatTempEE[j]));
0201  TemperatureCorr[j] = EEPROM.readFloat(int(&TemperatureCorrEE[j]));
0202  Hysteresis[j] = EEPROM.readFloat(int(&HysteresisEE[j]));
0203  AlarmTemp[j] = EEPROM.readFloat(int(&AlarmTempEE[j]));
0204  
0205  
0206  for (int i=0; i<4; i++)
0207  {
0208    EEPROM.readBlock(int(&TimerEE[i][j]), Timer[i][j]);
0209     
0210  }
0211  }
0212  DS18B20.begin();
0213  
0214  tone(BeepPin,4000,50);
0215  delay(100);
0216  tone(BeepPin,4000,50);
0217  delay(1000);
0218  lcd.clear();
0219  RTC.start();
0220  
0221}
0222// ===== MAIN CYCLE ===================================================================
0223void loop() {
0224  lcd.setCursor(6, 0);//инфо на LCD
0225  lcd.print(F("ch"));
0226  lcd.print(channel);
0227  lcd.setCursor(9, 0);
0228  if ((Temperature[channel] < AlarmTemp[channel])&(blink500ms)) {
0229    lcd.print(F("*"));
0230  }
0231  else {
0232    lcd.print(F(" "));
0233  }
0234  lcd.print(F("t="));
0235  if (Temperature[channel] < 10) {
0236    lcd.print(F(" "));
0237  }
0238  lcd.print(Temperature[channel],1);
0239  lcd.write(0x02); // значок градуса
0240  
0241  // если таймер включен - надпись светится, если сработал - мигает, обрабатываем все 4 таймера
0242  lcd.setCursor(0, 1); //инфо на LCD
0243  for (int i=0;i<4;i++){
0244    if ((Timer[i][channel].Enabled)&!((Timer[i][channel].Activated)&(blink500ms))) {
0245      lcd.print(F("T"));
0246      lcd.print(i+1);
0247    }
0248    else {
0249      lcd.print(F("  "));
0250    }
0251  }
0252  
0253  lcd.setCursor(9, 1); //инфо на LCD
0254  lcd.print(F("s="));
0255  lcd.print(TstatTemp[channel],1);
0256  if ( Relay[channel] == RelayOn ) {
0257    lcd.write(0x01); // значок градуса с пламенем
0258  }
0259  else {
0260    lcd.write(0x02); // значок градуса
0261  }
0262  
0263  // печатаем текущее время
0264  PrintYesNo = false;
0265  PrintRTC(0,0);
0266  Termostat();// термостатирование каждого канала в отдельности
0267   
0268  //вкл и выключение котла
0269  channalOn=qtyChannal;   //количество вкл каналов=количеству каналов
0270 for (int j=0; j<qtyChannal; j++){
0271    if (Relay[j]==!RelayOn) //если канал выключен
0272      channalOn-=1;
0273    }
0274  if (channalOn==0) {  //если нет включенных реле (нет запроса на тепло ни по одному из каналов)
0275  if ( digitalRead(RelayMain) == RelayOn)  //если котел включен
0276  digitalWrite(RelayMain, !RelayOn);    //выключить котел
0277  }
0278  
0279  if (channalOn>0) {  //если есть включенные реле (есть запроса на тепло хотя бы по одному из каналов)
0280  if ( digitalRead(RelayMain) == !RelayOn)  //если котел выключен
0281  digitalWrite(RelayMain, RelayOn);    //включить котел
0282  }
0283  
0284  // если прошла 1 секунда - делаем ежесекундные дела
0285  if (plus1sec) {
0286    plus1sec = false; // сбрасываем до следующей секунды
0287    // обновляем часы
0288    RTC.readClock();
0289    Hours=RTC.getHours();
0290    Minutes=RTC.getMinutes();
0291    Seconds=RTC.getSeconds();
0292 
0293    getTemp(); // читаем температуру с датчиков 
0294     
0295  
0296    // проверка таймеров и изменение температуры термостатирования при совпадении (активации таймера)
0297     for (int j=0; j<qtyChannal; j++){
0298    for (int i=0;i<4;i++)
0299    {
0300      if ((Hours == Timer[i][j].Hours)&(Minutes == Timer[i][j].Minutes)&(Timer[i][j].Enabled)&(Seconds == 0)) { // время T совпадает с RTC
0301      Timer[0][j].Activated = Timer[1][j].Activated = Timer[2][j].Activated = Timer[3][j].Activated = false;
0302        Timer[i][j].Activated = true;
0303        TstatTemp[j] = Timer[i][j].Temperature;
0304        EEPROM.updateFloat(int(&TstatTempEE[j]), TstatTemp[j]);
0305        if (BeepEnabled) {
0306          tone(BeepPin,4000,5);
0307        }
0308        break; // это чтобы статус Activated остался взведённым
0309      }
0310    }
0311   }
0312    // дебаг-инфо - в терминал
0313     
0314#ifdef serialenabled
0315Serial.print(F("iteration ="));
0316Serial.print (DS18B20iteration);
0317Serial.print(F("  channalOn="));
0318Serial.print (channalOn);
0319if (digitalRead(RelayMain) == RelayOn) Serial.println(F("  MAIN Relay ON    "));
0320else Serial.println(F("  MAIN Relay Of "));
0321    for (int j=0; j<qtyChannal; j++){
0322    Serial.print(F("sensor"));
0323    Serial.print(j,1);
0324    Serial.print(F(" Temp="));
0325    Serial.print(Temperature[j], 1);
0326    Serial.print(F(" TstatTemp="));
0327    Serial.print(TstatTemp[j], 1);
0328    Serial.print(F(" Hyster="));
0329    Serial.print(Hysteresis[j], 1);
0330    Serial.print(F("  ("));
0331    Serial.print(DS18B20Temperature[j], 1);
0332    Serial.print(F("   "));
0333    Serial.print(DS18B20TempTmp[j], 1);
0334    Serial.print(F(",corr "));
0335    Serial.print(TemperatureCorr[j], 1);
0336    Serial.print(F("),Timer="));
0337    Serial.print(TstatTimer[j]);
0338    
0339   if (Relay[j]==RelayOn) Serial.println(F(" ON    "));
0340   else Serial.println(F(" OF   "));
0341    }
0342    Serial.println(F("     "));
0343    
0344 
0345#endif
0346  
0347  for (int j=0; j<qtyChannal; j++){
0348    if (Temperature[j] < AlarmTemp[j])
0349      tone(BeepPin,4000,5);
0350    }
0351   
0352}
0353  // обработка поворота энкодера на изменение канала))
0354  rotating = true// reset the debouncer
0355  if ((encoderR)|(encoderL)) {
0356    if (encoderR) {
0357      channel += 1;
0358    }
0359    else
0360    {
0361      channel -= 1;
0362    }
0363    if ( channel > qtyChannal-1) {      // количество каналов, т.к считаем с нуля
0364          channel = 0;
0365        }
0366        if ( channel < 0 ) {
0367          channel = qtyChannal-1;
0368        }
0369    encoderR = false;
0370    encoderL = false;
0371    
0372  }
0373  // ================ по нажатию кнопки энкодера - меню настроек ====================
0374  if(digitalRead(encoderK) == 0) {
0375    MenuTimeoutTimer = 10; //таймер таймаута, секунд
0376    lcd.clear();
0377    lcd.setCursor(0, 0); //инфо на LCD
0378    lcd.print(F("< SETUP >  CH"));
0379    lcd.print(channel);
0380    if (BeepEnabled) {
0381      tone(BeepPin,4000,50);
0382    }
0383    delay(200);
0384    int menuitem = 0;
0385    
0386    
0387    do {              //обработка пунктов меню (по выбранному каналу)
0388      rotating = true// reset the debouncer
0389      if ((encoderR)|(encoderL)) {
0390        MenuTimeoutTimer = 10; //таймер таймаута, секунд
0391        if (encoderR) {
0392          menuitem += 1;
0393        }
0394        else  {
0395          menuitem -= 1;
0396        }
0397        if ( menuitem > 10 ) {
0398          menuitem = 0;
0399        } // границы пунктов меню
0400        if ( menuitem < 0 ) {
0401          menuitem = 10;
0402        }
0403        encoderR = false;
0404        encoderL = false;
0405      }
0406  
0407      // индикация пункта меню (номер пункта - в menuitem)
0408      lcd.setCursor(0, 1); //инфо на LCD
0409      switch(menuitem)
0410      {
0411      case 0:
0412        lcd.print(F("0.T-ON Relay   "));
0413        break;
0414      case 1:
0415        lcd.print(F("1.TIMER1 SET    "));
0416        break;
0417      case 2:
0418        lcd.print(F("2.TIMER2 SET    "));
0419        break;
0420      case 3:
0421        lcd.print(F("3.TIMER3 SET    "));
0422        break;    
0423      case 4:
0424        lcd.print(F("4.TIMER4 SET    "));
0425        break;    
0426      case 5:
0427        lcd.print(F("5.CLOCK SET     "));
0428        break;
0429      case 6:
0430        lcd.print(F("6.HYSTERESIS SET"));
0431        break;
0432      case 7:
0433        lcd.print(F("7.T-CORRECT SET "));
0434        break;
0435      case 8:
0436        lcd.print(F("8.SOUND SET     "));
0437        break;
0438      case 9:
0439        lcd.print(F("9.T-ALARM SET   "));
0440        break;
0441      case 10:
0442         lcd.print(F("10.BACK          "));
0443        break;        
0444      }
0445      if (MenuTimeoutTimer == 0) {
0446        menuitem = 10;
0447      }
0448  
0449    }
0450    while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0451    // если нажата кнопка энкодера или таймаут - обработка пункта меню (номер пункта - в menuitem)
0452    if (BeepEnabled) {
0453      tone(BeepPin,4000,50);
0454    }
0455    switch(menuitem)
0456    {
0457      // ====== пункт 0 - выход
0458    case 10:
0459      if (BeepEnabled) {
0460        tone(BeepPin,BeepToneNo,BeepToneNoDuration);
0461      } //звук "NO"
0462      break; // case 0 out
0463  
0464      // ====== пункт 1 - установка Timer1
0465    case 1:
0466      TimerXSetup(0);
0467      break; // case 1 out
0468  
0469      // ====== пункт 2 - установка Timer2
0470    case 2:
0471      TimerXSetup(1);
0472      break; // case 2 out
0473  
0474      // ====== пункт 3 - установка Timer3
0475    case 3:
0476      TimerXSetup(2);
0477      break; // case 3 out
0478  
0479      // ====== пункт 4 - установка Timer4
0480    case 4:
0481      TimerXSetup(3);
0482      break; // case 4 out
0483  
0484      // ====== пункт 5 - установка RTC
0485    case 5:
0486      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0487      lcd.clear();
0488      lcd.setCursor(0, 0); //инфо на LCD
0489      lcd.print(F("SETUP CLOCK"));
0490      delay(200);
0491      RTC.readClock();
0492      Hours=RTC.getHours();
0493      Minutes=RTC.getMinutes();
0494      SetYesNo = false;
0495      PrintYesNo = true;
0496      SetTime(0,1); // в позиции 0,1 - запрос ввода времени
0497      if (MenuTimeoutTimer != 0) {
0498        if (SetYesNo)
0499        {
0500          if (BeepEnabled) {
0501            tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0502          }
0503          RTC.setHours(Hours);
0504          RTC.setMinutes(Minutes);
0505          RTC.setSeconds(0);
0506          RTC.setClock();
0507          RTC.start();
0508        }
0509        else
0510        {
0511          if (BeepEnabled) {
0512            tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0513          }
0514        }
0515      }
0516      else {
0517        if (BeepEnabled) {
0518          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0519        }
0520      }
0521      break; // case 5 out
0522  
0523      // ====== пункт 6 - установка гистерезиса
0524    case 6:
0525      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0526      HysteresisOld[channel] = Hysteresis[channel];
0527      lcd.clear();
0528      lcd.setCursor(0, 0); //инфо на LCD
0529      lcd.print(F("SETUP HYSTERESIS"));
0530      delay(200);
0531      do {
0532        lcd.setCursor(0,1);
0533        if (blink500ms) {
0534          lcd.print("   ");
0535        }
0536        else {
0537          lcd.print(Hysteresis[channel], 1);
0538          lcd.write(0x02); // значок градуса
0539        }
0540        rotating = true// reset the debouncer
0541        if (encoderR) {
0542          Hysteresis[channel] += 0.1;
0543          encoderR = false;
0544        }
0545        if (encoderL) {
0546          Hysteresis[channel] -= 0.1;
0547          encoderL = false;
0548        }
0549        Hysteresis[channel] = constrain(Hysteresis[channel], 0.1, 20); // крайние значения
0550      }
0551      while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0552      if (MenuTimeoutTimer != 0) {
0553        EEPROM.updateFloat(int(&HysteresisEE[channel]), Hysteresis[channel]); // запись в ЕЕПРОМ
0554        if (BeepEnabled) {
0555          tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0556        }
0557      }
0558      else {
0559        Hysteresis[channel] = HysteresisOld[channel];
0560        if (BeepEnabled) {
0561          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0562        }
0563      }
0564      break; // case 6 out
0565  
0566      // ====== пункт 7 - установка коррекции температуры
0567    case 7:
0568      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0569      lcd.clear();
0570      lcd.setCursor(0, 0); //инфо на LCD
0571      lcd.print(F("SETUP T-CORRECT "));
0572      delay(200);
0573      do {
0574        lcd.setCursor(0,1);
0575        if (blink500ms) {
0576          lcd.print(F("    "));
0577        }
0578        else {
0579          if (TemperatureCorr[channel] >= 0) {
0580            lcd.print(F("+"));
0581          }
0582  
0583          lcd.print(TemperatureCorr[channel], 1);
0584          lcd.write(0x02); // значок градуса
0585        }
0586        rotating = true// reset the debouncer
0587        if (encoderR) {
0588          TemperatureCorr[channel] += 0.1;
0589          encoderR = false;
0590        }
0591        if (encoderL) {
0592          TemperatureCorr[channel] -= 0.1;
0593          encoderL = false;
0594        }
0595        TemperatureCorr[channel] = constrain(TemperatureCorr[channel], -8, 8); // крайние значения
0596      }
0597      while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0598  
0599      if (MenuTimeoutTimer != 0) {
0600        EEPROM.updateFloat(int(&TemperatureCorrEE[channel]), TemperatureCorr[channel]); // запись в ЕЕПРОМ
0601        if (BeepEnabled) {
0602          tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0603        }
0604      }
0605      else {
0606        TemperatureCorr[channel] = EEPROM.readFloat(int(&TemperatureCorrEE[channel]));
0607        if (BeepEnabled) {
0608          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0609        }
0610      }
0611      break; // case 7 out    
0612  
0613      // ====== пункт 8 - вкл/выкл звука
0614    case 8:
0615      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0616      lcd.clear();
0617      lcd.setCursor(0, 0); //инфо на LCD
0618      lcd.print(F("SOUND SET       "));
0619      delay(200);
0620      do {
0621        lcd.setCursor(0,1);
0622        if (BeepEnabled) {
0623          lcd.print(F("BEEP ON         "));
0624        }    
0625        else {
0626          lcd.print(F("BEEP OFF        "));
0627        }
0628  
0629        rotating = true// reset the debouncer
0630        if ((encoderR)|(encoderL)) {
0631          BeepEnabled = !BeepEnabled;
0632          encoderR = false;
0633          encoderL = false;
0634        }
0635      }
0636      while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0637  
0638      if (MenuTimeoutTimer != 0) {
0639        if (BeepEnabled) {
0640          tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0641        }
0642        EEPROM.updateByte(int(&BeepEnabledEE), BeepEnabled);
0643      }
0644      if (MenuTimeoutTimer == 0) {
0645        BeepEnabled = EEPROM.readByte(int(&BeepEnabledEE));
0646      }
0647      break; // case 8 out
0648  
0649      // ====== пункт 9 - установка предупреждалки о холоде
0650    case 9:
0651      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0652      lcd.clear();
0653      lcd.setCursor(0, 0); //инфо на LCD
0654      lcd.print(F("ALARM-TEMP SET  "));
0655      delay(200);
0656      do {
0657        lcd.setCursor(0,1);
0658        if (blink500ms) {
0659          lcd.print(F("    "));
0660        }
0661        else {
0662          if (AlarmTemp[channel] >= 0) {
0663            lcd.print(F("+"));
0664          }
0665  
0666          lcd.print(AlarmTemp[channel], 0);
0667          lcd.write(0x02); // значок градуса
0668        }
0669        rotating = true// reset the debouncer
0670        if (encoderR) {
0671          AlarmTemp[channel] += 1;
0672          encoderR = false;
0673        }
0674        if (encoderL) {
0675          AlarmTemp[channel] -= 1;
0676          encoderL = false;
0677        }
0678        AlarmTemp[channel] = constrain(AlarmTemp[channel], 15, 30); // крайние значения
0679      }
0680      while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0681  
0682      if (MenuTimeoutTimer != 0) {
0683        EEPROM.updateFloat(int(&AlarmTempEE[channel]), AlarmTemp[channel]); // запись в ЕЕПРОМ
0684        if (BeepEnabled) {
0685          tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0686        }
0687      }
0688      else {
0689        AlarmTemp[channel] = EEPROM.readFloat(int(&AlarmTempEE[channel]));
0690        if (BeepEnabled) {
0691          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0692        }
0693      }
0694      break; // case 9 out
0695       
0696      // ====== пункт 10 - установка температуры термостатирования
0697   case 0:
0698      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0699      TstatTempOld[channel]=TstatTemp[channel];
0700      lcd.clear();
0701      lcd.setCursor(0, 0); //инфо на LCD
0702      lcd.print(F("SETUP T-ON Raley"));
0703      delay(200);
0704      do {
0705        lcd.setCursor(0,1);
0706        if (blink500ms) {
0707          lcd.print("   ");
0708        }
0709        else {
0710          lcd.print(TstatTemp[channel], 1);
0711          lcd.write(0x02); // значок градуса
0712        }
0713        rotating = true// reset the debouncer
0714        if (encoderR) {
0715         TstatTemp[channel] += 1;
0716          encoderR = false;
0717        }
0718        if (encoderL) {
0719         TstatTemp[channel] -= 1;
0720          encoderL = false;
0721        }
0722        TstatTemp[channel] = constrain(TstatTemp[channel], 1, 80); // крайние значения
0723      }
0724      while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0725      if (MenuTimeoutTimer != 0) {
0726        EEPROM.updateFloat(int(&TstatTempEE[channel]), TstatTemp[channel]); // запись в ЕЕПРОМ
0727        if (BeepEnabled) {
0728          tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
0729        }
0730      }
0731      else {
0732       TstatTemp[channel] = TstatTempOld[channel];
0733        if (BeepEnabled) {
0734          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
0735        }
0736      }
0737      break; // case 10 out
0738    }
0739  
0740    delay(200);
0741    lcd.clear();
0742  }
0743}
0744   
0745// ===== SUBROUTINES ==================================================================
0746 //функция очистки сдвигового регистра
0747 void cleanreg(){
0748  for(int i=0; i<8; i++)
0749  Relay[i]=!RelayOn;
0750  digitalWrite(latch, LOW);
0751  shiftOut(data, clock, LSBFIRST, 0);
0752  digitalWrite(latch, HIGH);
0753  }
0754// ========================================
0755//функция управления сдвиговым регистром
0756 void sendpin(int pin, boolean state){
0757   
0758  Relay[pin]=state;
0759    
0760  byte value = 0;
0761  byte add = 1;
0762  for(int i=0; i<8; i++){
0763    if(Relay[i]==HIGH) value+=add;
0764    add*=2;
0765  }
0766  digitalWrite(latch, LOW);
0767  shiftOut(data, clock, MSBFIRST, value);
0768  digitalWrite(latch, HIGH);
0769}
0770// ========================================
0771 void getTemp(){   // измеряем температуру  на всех каналах
0772   DS18B20.requestTemperatures();   
0773  for (int j=0; j<qtyChannal; j++){
0774   DS18B20TempTmp[j] = DS18B20.getTempC(sensor[j]);
0775   DS18B20Temperature[j] += DS18B20TempTmp[j]; // суммируем для усреднения
0776    }
0777    DS18B20iteration ++;
0778      if (DS18B20iteration == 10)
0779      {
0780        DS18B20iteration = 0;
0781        for (int j=0; j<qtyChannal; j++){
0782          Temperature[j] = (DS18B20Temperature[j] / 10) + TemperatureCorr[j]; //усреднённая + коррекция
0783          DS18B20Temperature[j] = 0;
0784          }
0785     }
0786   }
0787   // ========================================
0788   void Termostat() {//термостатирование
0789   for (int j=0; j<8; j++){
0790    
0791    if ( TstatTimer[j] == 0 )       //если пауза между вкл/выкл реле превысила TstatTimerMax;
0792    {
0793      if ( Temperature[j] > ( TstatTemp[j] + Hysteresis[j] ) ) // если температра канала > температура заданная+гистерезис
0794    {
0795       if ( Relay[j]==RelayOn ) // если реле включено -
0796      {
0797        sendpin(j, !RelayOn); // выключить реле;
0798        TstatTimer[j] = TstatTimerMax; // реле держать выключённым не менее заданного в TstatTimerMax времени
0799      }
0800    }
0801    if (Temperature[j] < TstatTemp[j])       //если температура канала меньше заданной
0802    {
0803      if (  Relay[j]==!RelayOn ) // если реле выключено
0804      {
0805        sendpin(j, RelayOn); // включить реле
0806        TstatTimer[j] = TstatTimerMax; // реле держать включённым не менее заданного в TstatTimerMax времени
0807      }
0808    }
0809    }
0810   }
0811   }
0812// ========================================
0813void SetTime(char x, char y)
0814{
0815  // ========= set hours
0816  SetH = true;
0817  do {
0818    PrintRTC(x,y);
0819    rotating = true// reset the debouncer
0820    if (encoderR) {
0821      Hours += 1;
0822      if(Hours > 23) {
0823        Hours = 0;
0824      };
0825      encoderR = false;
0826    }
0827    if (encoderL) {
0828      Hours -= 1;
0829      if(Hours < 0) {
0830        Hours = 23;
0831      };
0832      encoderL = false;
0833    }
0834  }
0835  while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0836  if (BeepEnabled) {
0837    tone(BeepPin,4000,50); //звук "YES"
0838  }
0839  SetH = false;
0840  delay(200);
0841  // ========= set minutes
0842  SetM = true;
0843  do {
0844    PrintRTC(0,1);
0845    rotating = true// reset the debouncer
0846    if (encoderR) {
0847      Minutes += 1;
0848      if(Minutes > 59) {
0849        Minutes = 0;
0850      };
0851      encoderR = false;
0852    }
0853    if (encoderL) {
0854      Minutes -= 1;
0855      if(Minutes < 0) {
0856        Minutes = 59;
0857      };
0858      encoderL = false;
0859    }
0860  }
0861  while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0862  if (BeepEnabled) {
0863    tone(BeepPin,4000,50); //звук "YES"
0864  }
0865  if (PrintYesNo) {
0866    SetM = false;
0867    delay(200);
0868    // ========= set yes-no
0869    SetYesNo = false;
0870    do {
0871      PrintRTC(0,1);
0872      rotating = true// reset the debouncer
0873      if ((encoderR)||(encoderL)) {
0874        SetYesNo = !SetYesNo;
0875        encoderR = false;
0876        encoderL = false;
0877      }
0878    }
0879    while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
0880    delay(200);
0881  }
0882  
0883}
0884  
0885// ========================================
0886void PrintRTC(char x, char y)
0887{
0888  lcd.setCursor(x,y);
0889  if (SetH&&blink500ms) {
0890    lcd.print(F("  "));
0891  }
0892  else {
0893    if (Hours < 10) {
0894      lcd.print(F("0"));
0895    }  
0896    lcd.print(Hours);
0897  }
0898  
0899  // мигающее двоеточие, если не в режиме установки времени
0900  if (!(SetH||SetM||PrintYesNo||blink500ms))
0901  {
0902    lcd.print(F(" "));
0903  }
0904  else {
0905    lcd.print(F(":"));
0906  }
0907  
0908  if (SetM&&blink500ms) {
0909    lcd.print(F("  "));
0910  }
0911  else {
0912    if (Minutes < 10) {
0913      lcd.print(F("0"));
0914    }  
0915    lcd.print(Minutes);
0916  }
0917  lcd.print(F(" "));
0918  
0919  if (PrintYesNo) {
0920    lcd.print(F("["));
0921    if (!(SetH||SetM||blink500ms))
0922    {
0923      lcd.print(F("   "));
0924    }
0925    else {
0926      if (SetYesNo)
0927      {
0928        lcd.print(F("YES"));
0929      }
0930      else {
0931        lcd.print(F("NO "));
0932      }
0933    }
0934    lcd.print(F("]"));
0935  }
0936  
0937}
0938  
0939// ============================ Encoder interrupts =============================
0940// Interrupt on A changing state
0941void doEncoderA(){
0942  if ( rotating ) {
0943    delay (1) ;  // wait a little until the bouncing is done
0944  }
0945  // Test transition, did things really change?
0946  if( digitalRead(encoderA) != A_set ) {  // debounce once more
0947    A_set = !A_set;
0948    // adjust counter + if A leads B
0949    if ( A_set && !B_set )
0950    {
0951      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0952      if (BeepEnabled) {
0953        tone(BeepPin,4000,5);
0954      }
0955      encoderR = true;
0956      rotating = false// no more debouncing until loop() hits again
0957    }
0958  }
0959}
0960// Interrupt on B changing state, same as A above
0961void doEncoderB(){
0962  if ( rotating ) {
0963    delay (1);
0964  }
0965  if( digitalRead(encoderB) != B_set ) {
0966    B_set = !B_set;
0967    //  adjust counter - 1 if B leads A
0968    if( B_set && !A_set ) {
0969      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0970      if (BeepEnabled) {
0971        tone(BeepPin,4000,5);
0972      }
0973      encoderL = true;
0974      rotating = false;
0975    }
0976  }
0977}
0978// ============================ Timer0 interrupt =============================
0979// run every 500ms
0980void timerIsr()
0981{
0982  blink500ms = !blink500ms; // инверсия мерцающего бита
0983  if(blink500ms) {
0984    plus1sec = true; // ежесекундно взводится
0985    for (int j=0; j<qtyChannal; j++) {
0986    if (TstatTimer[j] != 0) {
0987      TstatTimer[j] --; // ежесекундный декремент этого таймера
0988    }
0989    }
0990    if (MenuTimeoutTimer != 0) {
0991      MenuTimeoutTimer --; // ежесекундный декремент этого таймера
0992    }
0993   
0994}
0995}
0996//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0997void TimerXSetup(int X) {
0998      MenuTimeoutTimer = 10; //таймер таймаута, секунд
0999      lcd.clear();
1000      lcd.setCursor(0, 0); //инфо на LCD
1001      lcd.print(F("SETUP TIMER"));
1002      lcd.print(X+1);  // выводим номер таймера на LCD
1003      delay(200);
1004      Hours=Timer[X][channel].Hours;
1005      Minutes=Timer[X][channel].Minutes;
1006      SetYesNo = false;
1007      PrintYesNo = true;
1008      SetTime(0,1); // в позиции 0,1 - запрос ввода времени
1009      if (MenuTimeoutTimer != 0) {
1010        if (SetYesNo) // если при установке времени выбрано "Yes"
1011        {
1012          if (BeepEnabled) {
1013            tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
1014          }
1015          Timer[X][channel].Hours = Hours;
1016          Timer[X][channel].Minutes = Minutes;
1017          Timer[X][channel].Enabled = true;
1018          EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
1019  
1020          MenuTimeoutTimer = 10; //таймер таймаута, секунд
1021          lcd.clear();
1022          lcd.setCursor(0, 0); //инфо на LCD
1023          lcd.print(F("Timer"));
1024          lcd.print(X+1);
1025          lcd.print(F(" Temp. Set"));
1026          delay(200);
1027          do {
1028            lcd.setCursor(0,1);
1029            if (blink500ms) {
1030              lcd.print(F("     "));
1031            }
1032            else {
1033              lcd.print(Timer[X][channel].Temperature, 1);
1034              lcd.write(0x02); // значок градуса
1035            }
1036            rotating = true// reset the debouncer
1037            if (encoderR) {
1038              Timer[X][channel].Temperature += 0.1;
1039              encoderR = false;
1040            }
1041            if (encoderL) {
1042              Timer[X][channel].Temperature -= 0.1;
1043              encoderL = false;
1044            }
1045            Timer[X][channel].Temperature = constrain(Timer[X][channel].Temperature, 10, 80); // крайние значения
1046          }
1047          while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
1048  
1049          if (MenuTimeoutTimer != 0) { // если после выбора температуры нажата кнопка энкодера
1050          EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
1051            if (BeepEnabled) {
1052              tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
1053            }
1054          }
1055          else { // если не нажата - используем старую температуру
1056          EEPROM.readBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
1057            if (BeepEnabled) {
1058              tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
1059            }
1060          }     
1061  
1062        }
1063        else // если при установке времени выбрано "No"
1064        {
1065          if (BeepEnabled) {
1066            tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
1067          }
1068          EEPROM.readBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
1069          Timer[X][channel].Enabled = false;
1070          EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
1071        }
1072      }
1073      else {
1074        if (BeepEnabled) {
1075          tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
1076        }
1077      }
1078}
1079//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~````

 

Ahtme
Offline
Зарегистрирован: 08.03.2017

leshak пишет:

А вообще, лично бы я пострелся ставить что-то что может самостоятельно "зажигать гас". Я бы ставил только больше/меньше. Причем, как правильно заметил JollyBiber нужен еще контроль что "горении идет".

Если погасло (не важно по каким причинам), все перекрывать, слать SMS хозяину, и... по хорошему, еще бы и себя обесточить.

А уж он пусть приходить и разбирается "чего погасло". И запуск только "в ручном режиме".

А если уж хочется все-таки "запуск", то только сертифицированное что-то. Оно потому столько и стоит, что учтена куча всяких нюансов, используются промышленные версии камней, проведены испытания "наработки на отказ.." и т.д. и т.п.  (ну по крайней мере в идеале так должно быть. если это не так, то хоть мучать угрызения совести потом не будут. что жаба задавила).

А меня задавила. Имелся работающий котёл (примерно 13 лет эксплуатации). Имелась в нем одна доработка  - заглушен контур ГВ, так как оказался самой не надёжной частью и требовал замены уплотнительных резинок. С заглушеным контуром ГВ проработал примерно 9 лет. А осенью 16го автоматика стала выдавать ошибки бредовые. Вызвал ремонтника профессионала, который с ходу сказал, что так долго не живут, мало того, что заказать такую же автоматику не получится, так и железо-то наверняка всё покрыто накипью и прочими отложениями, и насос та уже стаскался... короче есть у них на складе новые котлы из старой партии, и потому они его могут мне продать всего за 750 евросов...

И тут меня жаба и задавила. Я сам занимаюсь установкой и настройкой готового оборудования и автоматики отопления и ГВС в частных и многоквартирных домах. А тут ещё ради интереса прошлой весной собрал на Ардуино простой термостат с управлением сервоприводом трехходового клапана.

В общем как про 750 евро услышал, у меня сразу мысль родилась, попробовать Ардуино подружить с моим котлом. И так как я в схемотекнике не опытен был, и до этого паял только лампочки на новогодней гирлянде, поэтому прект ещё не закончил. Но много сделано, котёл запускается, датчик ионизаци простой как две копейки собрал сам, температуру нагнали - выключили клапана. Сбой электричества, свет пропал - даже при горящем котле - клапана закрылись. И так уже два месяца работает черновой вариант.

Ардуино - 6 евро. Остальное выпаяно из старой автоматики и старого же компьютерного монитора с кинескопом. Бонусом тернеровка серого вещества, новые знания и бесценный опыт.

И никакого привлечения военокосмического комплекса с нанотехнологиями не надо. Просто надо понимать, с чем имеешь дело.

А ещё... Хотел сказать по поводу диферамб в сторону наружнего датчика и погодозависимых графиков...

Во всех автоматиках, по крайней мере, что у нас в Эстонии продают, предусмотрен вход для подключения комнатного датчика. Именно с таким датчиком система работает более эффективно (читай экономно) и комфортней для потребителя. Устанавливать датчик конечно надо с учетом конкретного помещения и ньюансов там не мало.

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

pev0270
Offline
Зарегистрирован: 02.11.2015

Ahtme пишет:

1. А осенью 16го автоматика стала выдавать ошибки бредовые.

2. Я сам занимаюсь установкой и настройкой готового оборудования и автоматики отопления и ГВС в частных и многоквартирных домах. А тут ещё ради интереса прошлой весной собрал на Ардуино простой термостат с управлением сервоприводом трехходового клапана.

3. И так как я в схемотекнике не опытен был, и до этого паял только лампочки на новогодней гирлянде, поэтому прект ещё не закончил. Но много сделано, котёл запускается, датчик ионизаци простой как две копейки собрал сам, температуру нагнали - выключили клапана. Сбой электричества, свет пропал - даже при горящем котле - клапана закрылись. И так уже два месяца работает черновой вариант.

4. Ардуино - 6 евро. Остальное выпаяно из старой автоматики и старого же компьютерного монитора с кинескопом. Бонусом тернеровка серого вещества, новые знания и бесценный опыт.

5. А ещё... Хотел сказать по поводу диферамб в сторону наружнего датчика и погодозависимых графиков...

Во всех автоматиках, по крайней мере, что у нас в Эстонии продают, предусмотрен вход для подключения комнатного датчика. Именно с таким датчиком система работает более эффективно (читай экономно) и комфортней для потребителя. Устанавливать датчик конечно надо с учетом конкретного помещения и ньюансов там не мало.

6. Утверждать, что погодозависимого управления по графику достаточно для системы отопления дома - можно. Но утверждение, что это лучше управления по температуре внутреннего воздуха противоречит практике.

1. Автоматика показывает ошибки, а вы ее на помойку и все напрямую подключили... однако... (храни вас Господь)

2. Это хорошо когда разбираешься в теме. Вон хирург Леонид Рогозов сам себе аппендикс вырезал, но у него была делема жизнь или смерть. Вы тоже по этому пути собрались? Напишите в своем посте большими буквами "так делать нельзя" все делаете на свой страх и риск...

3. В схеммотехнике придется разбираться и в программировании тоже, ибо просто при пропадании электричества закрыть газ это мало...

4. Да-да 6 евро это стоимость кристала для любителей сделать что то своими руками. В нашем случае все делают устройство которое заставляет котел работать так как нам кажется правильно. Причем мы не лезем в защиту котла, а тупо используем контакты выведенные производителем для наружного таймера. При выходе из строя нашего изделия котел будет работать как и прежде в штатном режиме... Это единственно правильное решение, ибо 97% тех кто делает что то на ардуино, не знает (да это и не нужно) как работает автоматика того же котла...

5. Посмотрел температуру в Эстонии по зимним месяцам, смешно стало... Эффективно и экономно не одно и тоже... (читай п.6)

6. Зачем греть воду до максимума когда за окном +5? Проблема регулировки по температуре помещения это черезмерно горячие батареи, как следствие сухой воздух в помещении, как следствие статическое напряжение на всем... Ну и еще много чего можно сказать в зависимости от строения и степени его утепления и т.д.

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

uragan
Offline
Зарегистрирован: 23.02.2015

По п. 6 не понятно. Как связана сухость воздуха в помещении с температурой батарей, если в помещении нормальная температура?

pev0270
Offline
Зарегистрирован: 02.11.2015

uragan пишет:

Как связана сухость воздуха в помещении с температурой батарей, если в помещении нормальная температура?

На прямую. В отопительный сезон горячие батареи сушат воздух, проветривание помещения в мороз также сушит воздух. Так что температура в помещении ни при чем. А чем больше температура батареи тем интенсивнее происходит "осушение". Как то так...

В п. 6 можно еще указать что при инерционной системе при регулировании по температуре в помещении могут окна начать "плакать"... своего рода увлажнение... :)

Просто нельзя утверждать что по температуре в помещении регулировка самая-самая... (и она подтверждена практикой в конкретной климатической зоне) Очень много разных факторов влияют на комфорт в помещении в период отопления.