Хабрахабр

Дистанционное управление системой отопления

Интернет вещей (IoT, Internet of Things) является многообещающим направлением, как уверяют аналитики. Одним из главных трендов IoT является автоматизация жилья или, как любят выражаться маркетологи, создание «умного дома».

Оставим в покое словесные упражнения и рассмотрим конкретный проект.

Постановка задачи

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

Справедливо утверждение, что в средней полосе России отопление зимой это не вопрос комфорта, но выживания. Одной из таких задач для меня стала необходимость дистанционного мониторинга и управления системой отопления. Более чем за десятилетие опыта жизни в собственном доме я тоже убедился в справедливости этого закона. Согласно многократно подтвержденному эмпирическому закону, все неприятности случаются в самое неподходящее время.

В такой мороз нормально утепленный дом выстужается менее чем за сутки. Но если, например, отказ насоса водоснабжения в 30-ти градусный мороз еще как-то можно пережить, то выход из строя отопительного котла превращается в катастрофу.

Поэтому возможность дистанционного мониторинга состояния системы отопления и ее управления стала для меня актуальной задачей. Мне приходится часто отлучаться из дома на длительное время, в том числе и зимой.

Данный выбор обусловлен не только вопросами резервирования, но и оптимизации расходов на отопление. В моем доме система отопления имеет два котла, солярный (увы, газа нет и не предвидится) и электрический. Мощности этого котла вполне хватает для комфортной ночной температуры (18-19 градусов). По ночам, за исключением суровых морозов, работает электрокотел, так как в доме установлен двухтарифный электросчетчик. В таком режиме система отопления работает уже несколько лет и позволяет сделать вывод об экономичности данного варианта. Днем же в работу вступает солярный котел, поднимающий температуру до 22-23 градусов.

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

Техническое задание

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

Вот краткий перечень основных требований к проектируемому решению:

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

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

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

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

Метод обеспечения безопасности IoT

Начитавшись страшилок про последствия взлома умных домов, я решил подстраховаться и минимизировать возможность внешнего взлома. Кто-то скажет, дескать, кому нужно взламывать именно твой умный дом. Соглашусь, вероятность минимальна, но наблюдая регулярные попытки хакинга своих вебсерверов, я решил действовать по принципу: лучше переспать, чем недоесть. Шутка.

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

Ведь датчик воспринимает только ответ от сервера на свой запрос. Передача инициативы в обмене данными на сторону умного датчика позволяет практически полностью исключить его взлом посторонними лицами. Если нет желания поднимать в датчике этот протокол, то есть вариант с вычислением контрольных сумм с учетом параметров, априори неизвестных злоумышленнику. Теоретически можно перехватить такой запрос и подменить ответ, но эта угроза минимизируется, например, протоколом https. Но данный криптографический вопрос выходит за рамки рассматриваемой темы.

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

Сайт был написан с использованием адаптивной верстки, что позволяет комфортно работать со смартфона.
Для обмена информацией с сервером был выбран пятиминутный период. В качестве сервера было решено создать небольшой веб-сайт с базой MySQL, который развертывался на домене третьего уровня одного из моих сайтов.

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

Алгоритм работы

Работа умного датчика, получившего название метеомодуль, не содержит ничего необычного. В цикле опрашиваются датчики температуры и влажности. Это продолжается примерно 4,5 минуты. Затем происходит формирование GET-запроса к серверу и обрабатывается полученный ответ. В итоге период (главный цикл) получается длительностью примерно 5 минут. Здесь не требуется идеальная точность, на практике период оказался меньше на несколько секунд, что приводит к постепенному сдвигу. При идеальном пятиминутном периоде в сутки передавалось бы 288 отсчетов, реально их оказывается 289-290. Это совсем не сказывается на работе системы.

В силу обширного объема кода я не стал публиковать реализации используемых подпрограмм. Основной скетч программы с подробными комментариями приведен в листинге. В листинге оставлены диагностические сообщения для вывода в терминал.

Основной скетч программы

/*
* Sketch Meteo Control Mega2560
* ver. 13.0
* упрощенный алгоритм автоматики день - солярка, ночь - электрика. Начальный порог 21 градус, шаг - 0,5 градуса
* обмен с сервером по http 1.0
*/ // libs
#include <Wire.h>
#include "DHT.h" // wired connections
// подключение таймера через шину I2C, адрес на шине 104
#define DS3231_I2C_ADDRESS 104 // define
#define HYSTERESIS 0.5 // гистерезис порога температуры, градусы
#define LONG_CYCLE 9 // продолжительность цикла измерений, 9 - около 5 мин с учетом времени обмена с сервером #define SHORT_CYCLE 13 // продолжительность малого цикла измерений, 13 сек. с учетом времени сбора данных с датчиков малый цикл получается около 30 сек
#define DAY_BEGIN 6 // начало дневного тарифного периода
#define DAY_END 22 // конец дневного тарифного периода
#define MIN_INTERVAL 3000 // интервал чтения датчиков температуры 3 сек #define PIN_DHT_IN 23 // вход датчика температуры и влажности внутри AM2301 #define PIN_DHT_OUT 22 // вход датчика температуры и влажности снаружи AM2301 #define DHTTYPE DHT21 DHT dhtin(PIN_DHT_IN, DHTTYPE);
DHT dhtout(PIN_DHT_OUT, DHTTYPE); #define RELAY_E 25 // выход управления реле электрокотла
#define RELAY_D 24 // выход управления реле солярного котла #define LED_R 27 // LED RGB
#define LED_G 29 // LED RGB
#define LED_B 31 // LED RGB
#define LED 13 // внутренний светодиод #define LEAP_YEAR(_year) ((_year%4)==0) // для вычисления високосного года // vars
uint32_t workTime; // время работы котла с момента включения реле float hIn; // влажность внутри
float tIn; // температура внутри float hOut; // влажность снаружи
float tOut; // температура снаружи
float tModule; // температура внутри метеомодуля float tInSet; // установленное значение температуры внутри
float tOutSet; // установленное значение температуры снаружи. В текущей версии не используется. Параметр оставлен для развития byte seconds, minutes, hours, day, date, month, year;
byte del; // счетчик большого цикла, считает декрементом малые циклы
char weekDay[4]; byte tMSB, tLSB;
float temp3231; static byte monthDays[] = ;
uint32_t unixSeconds; // метка времени UNIX uint16_t timeWorkElectro; // время работы (сек) электрокотла между сеансами обмена с сервером
uint16_t timeWorkDiesel; // время работы (сек) солярного котла между сеансами обмена с сервером
uint32_t unixSecondsStartCycle; // метка времени UNIX начала цикла между сеансами обмена с сервером int modeWork; // режим работы метеомодуля, 0 - auto, 1 - ручное-выключено, 2 - ручное-электро, 3 - ручное-солярка, 4 - полуавтомат-электро, 5 - полуавтомат-солярка
byte typeBoiler; // тип рабочего котла, 0 - котлы не работают, 1 - электро, 2 - солярный char statusBoiler; // статус работающего котла для сервера
char unit = '1'; // id модуля
char mode; // метка режима работы метеомодуля для сервера String message; // строка для отправки на сервер char ans; // символ из буфера
String answerServer; // исходная строка ответа сервера
String tInSer; // строка от сервера = порог температуры внутри
String tOutSer; // строка от сервера = порог температуры снаружи
String timeSer; // строка от сервера = установка времени char datetime[15]; // массив для установки времени модуля void setup()
{ Serial.begin(115200); // выставляем скорость COM порта для терминала Serial.println("Start setup()"); Serial.println("Meteo Module. Ver.13.0 Unit Number: " + String(unit)); pinMode(LED, OUTPUT); //LED flash pinMode(LED_R, OUTPUT); //LED_R pinMode(LED_G, OUTPUT); //LED_G pinMode(LED_B, OUTPUT); //LED_B // инициализация внешнего таймера Wire.begin(); //set control register to output square wave on pin 3 at 1Hz Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address Wire.write(0x0E); Wire.write(B00000000); Wire.write(B10001000); Wire.endTransmission(); // устанавливаем порог температуры по умолчанию tInSet = 21; tOutSet = -15; // включаем наружний термометр pinMode(PIN_DHT_OUT, INPUT_PULLUP); dhtout.begin(); // включаем внутренний термометр pinMode(PIN_DHT_IN, INPUT_PULLUP); dhtin.begin(); // задаем пины управления котлами на выход pinMode(RELAY_E, OUTPUT); pinMode(RELAY_D, OUTPUT); modeWork = 0; // автоматический режим // котлы в состоянии выключено relayElectroSwitchOff(); relayDieselSwitchOff(); timeWorkElectro = 0; // сбрасываем время работы котлов timeWorkDiesel = 0; unixSecondsStartCycle = 0; // сбрасываем начальное время работы котлов typeBoiler = 0; Serial.println("All Boilers Off"); digitalWrite(LED_G, HIGH); // включаем зеленый цвет RGB-светодиода. Исходное состояние, котлы выключены //инициализация serial 1 is to esp8266 Serial1.begin(115200); //скорость передачи в модуль ESP8266 Serial1.setTimeout(1000); while (!Serial1); String startcommand = "AT+CWMODE=1"; // модуль ESP8266 в режиме клиента Serial1.println(startcommand); Serial.println(startcommand); delay(2000); del = 0; // сброс счетчика большого цикла
} void loop()
{ Serial.print("Start loop(). "); // диагностический вывод текущего времени get3231Date(); // получаем текущее время unixSeconds = timeUnix(seconds, minutes, hours, date, month, year); // UNIX-метка в секундах Serial.print("Current datetime: "); Serial.print(weekDay); Serial.print(", "); if (date < 10) Serial.print("0"); Serial.print(date, DEC); Serial.print("."); if (month < 10) Serial.print("0"); Serial.print(month, DEC); Serial.print("."); Serial.print(year, DEC); Serial.print(" - "); if (hours < 10) Serial.print("0"); Serial.print(hours, DEC); Serial.print(":"); if (minutes < 10) Serial.print("0"); Serial.print(minutes, DEC); Serial.print(":"); if (seconds < 10) Serial.print("0"); Serial.println(seconds, DEC); // сбор данных с датчиков Serial.println("Getting temperature and himidity"); getSensors(); // подготовка сообщения для отправки на сервер collectServerData(); // БЛОК ОБМЕНА С СЕРВЕРОМ И ИНИЦИАЛИЗАЦИИ // отправка данных на сервер и прием управляющей строки Serial.println("Send data to server"); connectServer(); // анализ управляющей строки и установка новых режимов controlServer(); // БЛОК УПРАВЛЕНИЯ КОТЛАМИ В ЗАВИСИМОСТИ ОТ УСТАНОВЛЕННОГО РЕЖИМА switch(modeWork){ case 0: // автоматический режим Serial.println("Current Mode: Auto"); autoMode(); break; case 1: // ручной режим Serial.println("Manual Mode"); manualMode1(); break; case 2: // ручной режим Serial.println("Manual Mode"); manualMode2(); break; case 3: // ручной режим Serial.println("Manual Mode"); manualMode3(); break; case 4: // полуавтоматический режим Serial.println("Semi Auto Mode Electro"); semiAutoMode4(); break; case 5: // полуавтоматический режим Serial.println("Semi Auto Mode Diesel"); semiAutoMode5(); break; } del = LONG_CYCLE; // устанавливаем счетчик большого цикла while (del > 0) { Serial.print("Start short cycle #"); Serial.println(del); // отображение номера малого цикла mDelay(SHORT_CYCLE); // сбор данных с датчиков Serial.println("Getting temperature and himidity"); getSensors(); del--; // декремент счетчика в большом цикле } }

Как я упоминал выше, в метеомодуле предусмотрено три режима работы:

  • автоматический
  • полуавтоматический
  • ручной

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

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

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

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

Он подразумевает не только выбор конкретного котла для работы, но и передачу управления им штатному выносному блоку. Ручной режим я практически не использую. Метеомодуль в таком режиме продолжает работать только как станция мониторинга температуры и влажности. Другими словами, котел будет управляться заданными температурными параметрами на этом блоке.

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

Полученный ответ парсится с помощью регулярных выражений. После отправки запроса метеомодуль ожидает ответ сервера в течение 20 секунд. В ответе сервера присутствует четыре параметра:

  • пороговое значение температуры внутри дома
  • пороговое значение температуры снаружи дома
  • заданный режим работы
  • время первоначальной установки для часов реального времени модуля

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

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

Ведь предыдущее значение уже было отправлено на сервер. После разбора ответа от сервера, обнуляются текущие счетчики времени работы котлов. При сбросе учитывается время паузы на ожидание ответа от сервера.

По этому параметру нельзя судит, скажем, о потребленной электроэнергии. Надо заметить, что передаваемое время работы котла имеет оценочное значение. Например, при достижении температуры в котле 80 градусов происходит его выключение, но продолжает работать циркулярный насос. Это связано с особенностями работы котлов отопления. Метеомодуль лишь измеряет суммарное время, которое потребовалось котлу для достижения температурного порога внутри дома. При снижении температуры теплоносителя до 60 градусов, котел снова включается в работу.

При снижении температуры более чем на 0,5 градуса, котел отопления вновь включается в работу. После достижения заданной температуры котел отключается, а метеомодуль продолжает с периодичностью 30 секунд считывать температурные показатели. Такая величина гистерезиса была подобрана опытным путем, с учетом инерционности работы системы отопления.

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

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

Реализация

Для воплощения идеи я использовал то, что оказалось под рукой. Было решено построить метеомодуль с применением модулей Arduino. В качестве процессорной платы была взята Mega 2560, оставшаяся от предыдущих экспериментов. Эта плата заведомо избыточна для данной задачи, но она была в наличии. К тому же к ней был шилд макетирования, на котором разместились почти все остальные модули. Это часы реального времени DS3231 и WiFi-модуль ESP8266(01). Был куплен блок коммутации с двумя реле для раздельного управления электрическим и солярным котлами.

Как известно, в таком блоке достаточно широкий выбор вторичного питающего напряжения. В качестве источника питания использован имевшийся компьютерный блок питания. К тому же эти блоки очень надежны, принимая во внимание непрерывный характер работы метеомодуля. Там есть +5В и, что особенно важно при работе с WiFi-модулем ESP8266, +3,3В.

Принципиальная схема не рисовалась в виду ее очевидности. На рисунке представлена схема коммутации плат. Зеленый цвет показывает, что котлы выключены, красный означает работу солярного котла, голубой – электрического. На рисунке есть RGB-светодиод для визуальной индикации режимов работы метеомодуля. Каюсь, был не прав, но шел на риск осознанно. У меня под рукой не оказалось резисторов на 220 Ом, поэтому RGB-светодиод был подключен напрямую к выходам платы, без токоограничивающих резисторов. За три года эксплуатации пока проблем не было. Ток потребления каждого вывода светодиода составляет всего 20 мА, выход платы позволяет подключать до 40 мА.

Первоначально для измерения температуры внутри дома использовал датчик DHT11, но у него очень плохая точность измерения и, по невыясненной причине, библиотека DTH.h некорректно работала при использовании в схеме двух разных типов датчиков. В качестве датчиков температуры были использованы DHT21 (AM2301). Но так как замена DHT11 в силу его чрезмерной погрешности была очевидна, то я не стал разбираться с проблемой библиотеки.

Цифры в квадратиках означают номера проводов, подключающие внешние устройства к основной плате.

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

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

Сервер управления

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

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

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

Гистограммы показывают время работы котлов. В качестве примера графиков приведены значения на 25 января 2018 года.

Страница установки параметров

За это время было всего два зависания, вызванных долговременным пропаданием канала к Интернет. Как я уже упоминал, это решение для мониторинга и управления системой отопления частного дома уже отработало три отопительных сезона. Причем зависал не весь метеомодуль, а только WiFi-модуль ESP8266.

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть