Удаленное управление отоплением с помощью arduino

Блог Евгения Николаенко

Контроль отопления и вентиляции на базе Arduino

Представляю мой новый проект — автоматическое управление отоплением и вентиляцией на базе Arduino Nano 3.0.

Довольно долго я бился над решением задачи создания оптимального микроклимата в ванной комнате, и наконец-то, благодаря знаниям, полученным в процессе изучения Arduino и различных датчиков температуры и влажности, мне это удалось! 🙂

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

А теперь предлагаю подробнее рассмотреть как все работает, включая программу (скетч) для Arduino!

Устройство системы

На передней панели системы управления отоплением и вентиляции находится двухстрочный дисплей LCD 1602 I2C, который отображает текущие значения температуры и влажности, а также позволяет просматривать меню установок прибора. Красная и зеленая кнопки — кнопки управления (оказалось вполне достаточно двух кнопок для изменения настроек и управления устройством). Красный светодиод загорается при включении отопления, а зеленый — при включении вентиляции. На левой стороне расположен датчик температуры и влажности DHT22 а также USB-порт модуля Arduino, который пришлось заклеить для лучшей сохранности.

Читайте также:  Расширительные бачки для отопления частного дома открытого типа

Система для управления отоплением и вентиляцией на базе Arduino. Вид сбоку

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

Система для управления отоплением и вентиляцией на базе Arduino. Вид сбоку

Система контроля микроклимата работает от сети 220 вольт и подключена к ближайшей розетке.

Система для управления отоплением и вентиляцией на базе Arduino.

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

Система для управления отоплением и вентиляцией на базе Arduino со снятой лицевой панелью

Внутри находится сборка из модуля ардуино нано 3.0, силовых реле с максимальным током до 10 ампер, и блоком питания на 9 вольт.

Система для управления отоплением и вентиляцией на базе Arduino. Вид изнутри

Панель управления подключена к основному модулю при помощи шлейфов.

Система для управления отоплением и вентиляцией на базе Arduino. Вид изнутри

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

Панель управления системы контроля микроклимата на базе Arduino

Управляющий модуль сконструирован на монтажной плате и имеет разъемы для подключения датчика влажности и температуры DHT22, панели управления, нагрузки (4 разъема), а также источника питания. Первый, второй и четвертый разъемы работают в режиме ключа (замыкают и размыкают цепь). Третий разъем обеспечивает выход с напряжением 5 вольт для управления дистанционной розеткой.

Главный модуль системы контроля микроклимата на базе Arduino

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

Главный модуль системы контроля микроклимата на базе Arduino. Монтажная плата

Корпус системы — обычная электрическая разветвительная коробка стандартного размера.

Корпус системы контроля микроклимата

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

Настенный конвектор, управляемый системой на базе Arduino

Розетка с дистанционным управлением системы контроля микроклимата на базе Arduino

Управляющая программа (скетч для ардуино)

Теперь, пожалуй, самое интересное 🙂 Предлагаю вашему вниманию полный скетч для управления отоплением и вентиляцией на базе Arduino. Скажу сразу, что скетч модернизировался после первого запуска системы целых 3 раза. И на то были определенные причины.

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

Решением данной ситуации стало изменение алгоритма программы таким образом, чтобы измерения проводились 5 раз подряд (в течение 10 секунд), а затем для всех показателей вычислялось среднее значение, на основании которого применялись правила включения/отключения нагрузки. Это позволило избавиться от таких «скачков» с выключением вытяжки или батареи!

Итак, скетч под этим спойлером:

Скетч занимает около 50% памяти ардуино и требует дополнительных библиотек для работы с датчиком DHT22 и экраном LCD через интерфейс I2C, найти которые можно на просторах интернета.

На момент написания статьи уже месяц система работает в штатном режиме, микроклимат в ванной стал практически идеальным, конечно пришлось несколько раз менять настройки включения и выключения вытяжки и батареи, но подобрав нужные параметры все стало просто идеально — и днем и ночью комфортные ощущения при нахождении в этом помещении! 🙂

Обновлено 05.11.2018

Зависание контроллера Arduino

Прошло пол года с момента начала активной эксплуатации устройства, и обнаружились некоторые проблемы, а именно, периодические зависания модуля ардуино. Начав разбираться, первым делом наткнулся на некий WatchDog, который способен автоматически перезагрузить систему при зависании микроконтроллера. Подумал — вот оно подходящее решение. Но как выяснилось, на моей китайской копии Arduino Nano 3.0 WatchDog работает неправильно из-за некорректной прошивки загрузчика. Для того чтобы это исправить, нужна «правильная» прошивка загрузчика, найти которую можно в интернете, и программатор, которым все это дело будет «зашиваться» внутрь чипа. Пока ждал программатор с Китая, решил поискать реальные причины зависания контроллера.

Просадка напряжения

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

Первым делом решил добавить 2 конденсатора по 1000 мкф в надежде, что они уменьшат просадку напряжения при срабатывании реле. Первый поставил параллельно выходу с блока питания (там кстати уже был свой конденсатор, но второй лишним не будет, подумал я), а второй — установил параллельно выходу +5V на плате ардуино, откуда как раз берется питание для реле. С этого же выхода питается и сам микроконтроллер. Складывается логичная ситуация — когда все реле включаются одновременно, микроконтроллеру не хватает напряжения и он зависает.

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

Доработка скетча Ардуино

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

Дело в том, что после обработки данных, полученных с датчиков, и включении/выключении какого-либо реле, происходил мгновенный переход к следующей обработке данных с датчиков, и включение/выключение следующего реле, и так далее. Фактически, все реле действительно могли включаться или отключаться одновременно, с задержкой менее 1 мсек, поскольку между обработкой данных для каждого реле отсутствовала пауза.

Исправив код этой процедуры, а именно, добавив искусственную задержку в 200 миллисекунд после включения/отключения какого-либо реле, я был крайне удивлен стабильной работой прибора. Зависания вовсе прекратились, и вот уже 2 месяца прибор работает стабильно. Теперь и WatchDog не нужен, хотя конечно он не помешает, на всякий случай.

В итоге можно сказать, что причиной зависания являлась несбалансированность нагрузки на источник питания при выполнении программного кода, а также низкое качество источника питания. Исправив программу, исчез и дисбаланс. Ниже представлен исправленный фрагмент кода процедуры DoAll(). Жирным текстом выделены те самые задержки по 200 мсек, которые были добавлены в программу и кардинально повысили стабильность работы микроконтроллера.

Обновлено 02.02.2019

Раздельное включение вентиляторов вытяжки

Зимой обнаружилось, что из одной из вытяжет стал капать конденсат, поэтому было решено отключать на зиму этот вентилятор. И чтобы не лазить каждый сезон с отверткой в развет коробку и уж тем более в само устройство, решил сделать все программно, поскольку каждый вентилятор управляется отдельным реле. Немного переработал скетч, добавив дополнительный экран настроек, на котором можно задействовать или отключить каждый вентилятор по отдельности Также уменьшил время одновременного нажатия кнопок для переключения между экранами настроек с 3 до 2 секунд. Свежий скетч можно скачать по ссылке ниже

Самодельный GSM термостат на Arduino для удаленного контроля системы отопления (котла) через SMS

Внимание! Статья периодически обновляется. По состоянию на ноябрь 2019 прибор модернизирован и упакован в корпус! Читайте внизу!

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

Версия прототипа на февраль 2019:

Идея сделать свой GSM термостат появилась не сразу, но после разочарования в готовых решениях. Читайте обзор WiFi термостата POER и доступных в продаже GSM/SMS-термостатов. Wi-Fi термостат оказался бесполезным в плане пресечения проблем с котлом (отключение электричества на долгий период, нежелание котла зажечься в -20 и т.п.), что приводит к заморозке воды в доме и затратам на ремонт, а готовые термостаты кажутся мне весьма неудобными при излишне завышенной цене (в среднем 7-10 тысяч). Создание своего GSM термостата позволяет за разумные деньги (до 3 тысяч рублей) сделать изделие, которое будет заточено под конкретные пожелания создателя и по возможностям будет превосходить готовые решения за 9 тысяч рублей. Первоначальная идея была взята из темы «Управление отоплением в загородном доме (GSM)«. Там же можете скачать готовые скетчи для девайса, однако, я настоятельно рекомендую разобраться в программировании для Arduino и написать свой скетч, отвечающий Вашим личным нуждам. Так Вы получите не только недорогой GSM термостат, но и новое хобби, которое увлечет Вас как минимум на несколько недель.

Итак, для создания термостата была выбрана платформа Arduino, как наиболее дружелюбная к тем, кто очень далек от электроники и программирования микроконтроллеров. Уже на второй неделе после того, как я узнал об Arduino, я смог сам сделать термометр с логгером на SD карту, а на третьей неделе у меня уже был немного работающий прототип GSM-термостата. Почему я назвал его «немного работающим» — да дело в том, что просто создать девайс (соеденить провода) — дело весьма быстрое и незамысловатое, но написать программное обеспечение, которое будет работать правильно при любых нестандартных ситуациях — вот это самое сложное. Ведь если не продумать все возможные варианты развития ситуации, прибор может войти в «вечный цикл» и перестать выполнять даже свои первостепенные задачи, такие как поддержание нужной температуры в доме, не говоря уже об управлении котлом с помощью SMS. Посмотрев несколько ардуино-скетчей по контролю климата в доме, я сначала порадовался, что не придется писать свой код, но потом, познакомившись поближе с ардуино и вникнув в суть имеющихся готовых программ по работе с GSM, ужаснулся. Использование подобных программ может нанести больше вреда, чем пользы.

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

Итак, вот список того, что, по моему мнению, должен делать нормальный термостат. К сожалению, по мере роста кода, я столкнулся с проблемой ограниченности ресурсов Arduino (32 килобайта на код и 2 килобайта на переменные — это очень мало). Не всё, что я могу сделать, может существовать в рамках одного проекта, но, тем не менее, делюсь идеями, а каждый сам решит, какие фичи ему более полезны и интересны.

  • Термостат должен показывать текущую температуру и установленную пользователем температуру, которую будет поддерживать котел.
  • Чтобы котел не включался/выключался каждые 5 секунд, используется гистерезис, который определяет границы допустимой температуры. Например, при желаемой температуре 20 градусов и гистерезисе 1 градус, котел будет включаться при температуре =21 градус. При остывании батарей, в интервале от 21 до 20 градусов котел будет выключен.
  • В случаях, когда термостат обесточен (или не работает по непонятным причинам), котел должен иметь возможность работать на нагрев. Это обеспечивается особым подкючением котла к реле, когда котлу разрешен нагрев тогда, когда на реле не подается ток с термостата. Когда же термостат подает ток на реле, котел прекращает нагрев. Таким образом, если термостат глюконёт и выключится или потеряет питание, котел все еще сможет выполнять свои функции, и вероятность заморозки дома уменьшается. Обратите внимание, существуют модули реле, которые по-разному отрабатывают входной сигнал. Логическая единица может включать реле или выключать его. На некоторых модулях есть джампер, который меняет логику, но на многих его нет (не путать с джампером внешнего питания реле). Таким образом, если Вы скачали чей-то скетч, но он действует «наоборот», значит у Вас релейный модуль с другой логикой (нужно править скетч).
  • Кроме гистерезиса, используется контроль по границам температуры, который позволяет удаленно понять, что с котлом что-то не так. Например, если желаемая температура 20 градусов, то при выходе реальной температуры за границы между установленными 17 и 25 градусами, термостат высылает SMS, что что-то не так. Границы подбираются экспериментально и с небольшим запасом такими, за пределы которых при нормальной работе котла температура в поещении не выходит.
  • Поскольку отопление газовое, неплохо было бы контроллировать утечку газа. Для этого используется датчик газа. Сам датчик передает значения от 0 до 1023, но для удобства я использую процентное значение от 0 до 99%. Также устанавливается значение, при превышении которого прибор отправит тревожное SMS. Учитывайте, что газовый датчик потребляет 120 мА и есть смысл отключать его при переходе на резервное питание в случае отключения электроэнергии, иначе он быстро высадит резервный аккумулятор. Также тем, кто экономит на электроэнергии, стоит иметь в виду, что добавление датчика газа в проект увеличит расход электроэнергии на 12.3 квтч в год — много это или мало — решайте сами. По моим наблюдениям, располагать его «где-то на столе» — практически бесполезно (вы задохнетесь или взорвете всё быстрее, чем он среагирует). Чтобы он реально поднял панику вовремя, надо обеспечить активное попадание в него газа, то есть располагать его сверху, над местом потенциальной протечки газа, что существенно усложняет монтаж и уменьшает мобильность термостата. Так что пока у меня есть сомнения на счет необходимости использования данного датчика. MQ-9 был достаточно чувствительным, но я его спалил, а вот MQ-2 весьма вяло реагирует как на природный, так и на сжиженный газ. В добавок, учитывайте, что показания этих датчиков сильно зависят от температуры окружающей среды. При холодном старте показания зашкаливают за 30% при том, что через несколько минут датчик нагревается и показания падают до 5%. Это не позволяет поставить достаточно низкий порог на отсылку тревожных СМС, а чтобы довести значение до 30%, нужно целенаправленно держать датчик над источником газа.
  • Модем не должен слать тревожные SMS каждые 10 секунд, иначе баланс быстро сойдет на ноль. Пока для решения этой проблемы я сделал триггер. После первого тревожного SMS отсылка последующих SMS не производится до сброса триггера специальной командой (перед этим следует вручную устранить проблему, вызвавшую отсылку тревожного SMS).
  • Кроме первого реле, управляющего котлом по температуре, есть еще три реле, которые включаются и выключаются вручную. Можном использовать одно следующим образом. Если котел заглючит и температура начнет падать, придет тревожное SMS. Если электричество при этом будет, можно удаленно второе реле, к которому будет заранее подключен электрический обогреватель. Таким образом, он сможет поддерживать положительную температуру в помещении с водой до того момента, как получится приехать и выяснить, почему котел встал (прецеденты уже были). Если будете так делать, убедитесь, что мощность обогревателя меньше допустимой разрешенной мощности реле (обычно они 250 вольт 10 ампер, но для надежности больше одного киловатта лучше не подключать).
  • Все настройки должны храниться в энергонезависимой памяти и восстанавливаться после отключения от сети или сбоев питания.
  • Для экономии денег на SMS при настройке прибора хорошо бы иметь альтернативный метод настройки при нахождении вблизи прибора. Пока я без проблем меняю все настройки через терминал при подключении к компу, но, когда прибор будет готов, это будет неудобно. Поэтому к пинам 0 и 1, когда компьютер уже не используется, можно подцепить Bluetooth модуль HC-05, и проводить все те же настройки с телефона через Bluetooth терминал. Не забываем, что HC-05 работает с уровнем 3.3 вольт, нужно подключать RX блютус модуля через делитель напряжения (10к и 4.7к резисторы — схемы смотрите в инете). Для андройда можно использовать бесплатный Serial Bluetooth Terminal. Связка со смартфоном работает отлично, таким образом, за изменение настроек при нахождении рядом с девайсом платить не придется.
  • Ну а когда настройки приходится менять удаленно, опять же ради экономии, девайс должен принимать несколько команд в одном SMS, но, при этом, комадны должны быть интуитивными и запоминающимися, чтобы не носить с собой справочник. Свой вариант предлагаю ниже.
  • Поскольку модем уже имеет встроенную возможность выходить в интернет через GPRS (без Wi-Fi), есть смысл вести лог ошибок и параметров прибора на удаленном сервере. Таким образом, выяснять статус можно удаленно и без оплаты SMS, если, конечно, на тарифе оплачен доступ в интернет. Реализация данного функционала вполне несложная (описана ниже).
  • Нужно позаботиться об источнике бесперебойного питания для термостата, чтобы при отключенном напряжении 220 вольт термостат мог высылать тревожные SMS о пропадании электричества и о недопустимом падении температуры, когда дом начнет остывать. Чтобы сильно не заморачиваться и не усложнять скетч, я пошел простым путем. Ардуино имеет несколько входов для питания. Если подключить несколько источников питания, она питается от источника с большим напряжением. Так, если использовать блок питания на 9 вольт в круглом разъеме питания и повер-банк в разъеме usb, ардуина будет питаться от блока питания, и переходить на повер-банк в случах отключения электроэнергии. Недостаток конструкции только в том, что повер-банк сам не заряжается после того, как разрядится, что не очень хорошо при регулярных сбоях в электроснабжении. То есть либо надо периодически подзаряжать его вручную, либо пустить на него отдельный внешний блок питания для автоматической подзарядки (зарядка от 5 вольт ардуины может прогнуть всю систему). Как вариант, «раздвоить» шнур блока питания, пустить 9 вольт напрямую на ардуину и 5 вольт через step-down converter на зарядку повербанка. Для проверки на отключения 220 вольт, чтобы выслать смс об отключении и включении, многие рекомендуют использовать реле на 220 вольт, или вообще мудрствуют с оптронами и прочими делами, но это в любом случае лишняя занятая розетка. Я сделал проще. У меня был Voltage Sensor (по сути это модуль из двух аккуратно оформленных резисторов). Суть в том, что на модуль подается от 0 до 25 вольт, а модуль преобразует это напряжение в годное для чтения analogRead(). Можно подпаяться напрямую к штекеру питания, но, точность здесь не принципиальна, и поскольку у меня внешнее питание 9 вольт, а резервное 5 вольт, я могу отследить эту разницу на пине VIN. В моем случае при питании от 220 вольт на VIN считывается 8.11 вольт (8.18 мультиметром), а при питании повер-банком 4.50 вольт (4.34 мультиметром). Так, простое условие if (voltage>6) позволяет понять, что напряжение 220 вольт присутствует, и не надо занимать лишнюю розетку и вообще баловаться с высоким напряжением!

Что хотелось бы, но еще не сделано:

  • Для разбирательств в проблемных случаях хорошо бы вести лог температур и действий термостата на MicroSD карту. С точки зрения железа и программирования проблем тут никаких нет, но проблема в ресурсах Arduino. Подключение одной только библиотеки SD сжирает чуть ли ни половину доступной памяти. Как вариант, библиотека SdFat, которая не столь требовательна к памяти, но и с ней мой код не влез в лимит 32 кб. На Arduino UNO это точно не выйдет, разве что переделывать всё на Arduino Mega. Так что эта задумка пока под вопросом.

Команды (посылаются через терминал или SMS, или со смартфона, подключенного по Bluetooth):

Для фильтрации рекламных SMS и прочих мессаг от чужих людей каждое управляющее SMS должно начинаться с пароля, который невозмжно встретить в случайном SMS. Фильтрация по номеру телефона распростанена в подобных проектах, но она может сыграть в Вами злую шутку (например, если в случае аварии нужно будет срочно получить информацию с места или выслать какие-то управляющие команды, а зарегистрированного в термостате телефона почему-то не будет под рукой (кончатся деньги, сядет батарейка, забудется дома — вариантов куча). Пароль же можно применить с любого телефона, и вероятность того, что его наберут посторонние люди «случайно» практически нулевая (если, конечно, пароль не банален, типа «Привет!». Предположим, для примера, что пароль установлен «#pass#». Дальшейшие команды вводятся одной строкой и разделяются знаком-разделителем. У меня это «,». Команды выполняются в указанной последовательности слева направо, регистр букв не имеет значения.

«T=x» устанавиливает автоматическое поддержание температуры на x градусов.

«H=x» устанавливает гистерезис для автоматического поддержания температуры.

«A=1/0» включает или выключает автоконтроль температуры на первом реле.

«TW=1/0» (или «W=1/0» или просто «W» для включения) включает или выключает SMS-предупреждения о выходе температуры за установленные границы.

«TH=x» верхний предел допустимой температуры.

«LL=x» нижний предел допустимой температуры.

«VW=1/0» (или «VW» для включения) разрешает или запрещает отправку тревожных смс при исчезновении электричества в сети.

«G=x» верхний предел уровня газа в помещении (в процентах). «G=0» отключает контроль утечки газа.

«R=xxxx» устанавливает значения четырех реле. 1=вкл, 0=выкл, -=оставить как есть. Пример: «R=-1-0» включает второе реле, выключает четвертое реле, остальные остаются без изменений. Допускаются сокращения, например «R=1» — включает первое реле, остальные без изменений.

«S» статус (высылает в SMS все то, что обычно видно на экране прибора — все данные). Того же можно добиться без отправки SMS, просто позвонив бесплатно на номер термостата (в этом случае данные высылаются только при звонке с админского телефона). Термостат сбросит вызов и отправит SMS со статусом на номер админа. На чужие звонки модем не ответит.

«I» — срочно выслать данные на сервер в интернете (не дожидаясь положенного по расписанию времени).

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

«LCD=1/0» включает или выключает подсветку LCD экрана. Так как при отсутствии людей в доме подсветка не нужна, ее можно выключить (потребление электричества в этом случае уменьшается на 0.5 ватт, что составляет примерно 4.4 квтч в год).

«AT=команда» — отправляет на модем указанную команду, например «#pass#AT=AT+CPOWD=1» — выключает модем. Список AT команд смотрите в документации к своему модему. Фича сделана, в основном, чтобы играться с модемом через терминал, но если приспичит, можно отправить команду и по SMS.

«GSMRST» — позволяет выключить и включить модем снова (на случай, если заглючит).

«RST» — перезагрузка ардуины (если заглючит).

«RSTDEF» — перезагрузка со сбросом всех параметров на прошитые в скетче по умолчанию (если дела совсем плохи).

«PW=newpass» — замена пароля.

«PH=+79991234567» — замена админского телефонного номера.

«SEP=&» — замена знака-разделителя команд. Сохраняется только до перезагрузки. Замена разделителя пригодится только если нужно передать значение, имеющее запятые в AT-командах модема.

«GA=1/0» — gsmAllow (разрешает/запрещает работу с GSM — прием/отправка смс, прием входящего звонка).

«SA=1/0» — smsAllow (разрешает/запрещает отправку любого смс).

«IA=1/0» — iLogAllow (разрешает/запрещает выход в интернет для отправки лога на сервер).

«LA=1/0» — LogAllow (разрешает/запрещает сбор данных о температуре для SMS-лога).

«CR=x» — clock refresh time (количество секунд для обновления часов на экране).

«TR=x» — temp refresh time (количество секунд для обновления значений датчиков).

«GR=x» — gsm refresh time (количество секунд, через которое проверяется состояние модема — если он выключился по какой-либо причине, будет произведена попытка его включения. Некоторые модемы могут выключаться в условиях плохой связи из-за недостатка тока от источника питания — рекомендуется не менее 2 ампер для питания модема в условиях низкого качества сигнала от вышки сотовой связи).

«IR=x» — iLog refresh time (количество секунд, через которое отправляется лог на сервер).

«LR=x» — Log refresh time (количество секунд, через которое обновляются данные температуры для SMS-лога).

«TA=x» — Корректировка температуры, получаемой с датчика. Поскольку разброс погрешности у далласовских датчиков весьма велик, каждый датчик нужно калибровать отдельно. Для этого к показываемой датчиком прибавляется или отнимается некоторое значение, для получения показаний, схожих с калиброванными показаниями. Здесь X — число, умноженое на 100, то есть 25 означает, что к показаниям датчика будет прибавляться 0.25 градусов, -150 означает, что от показаний датчика отбавится 1.5 градуса.

«DT=yyyymmddhhmmss» — установка даты и времени.

«PAR» — показать значения вышеуказанных параметров.

«LOG» — высылает лог температуры на SMS (чуть больше 30 значений последних температур через точку с запятой).

«LOG10» — высылает на SMS последние 10 температур из лога с датой и временем, когда они были зафиксированы.

«MINMAX» или «MAXMIN» — высылает на SMS текущее время, время последней перезагрузки прибора, время, с которого собирается статистика по минимальным и максимальным значениям, сами эти значения, и время, когда они были достигнуты.

«MINMAXRST» или «MAXMINRST» — сбрасывает максимальное и минимальное значения температуры на текущее значение температуры и начинает сбор статистики заново.

«HELP» — высылает все возможные команды в одном SMS (если память подводит):
S,T,H,A,W(TW),LH,LL,VW,R,G,I,LCD,PAR,LOG,LOG10,LOGRST,MINMAX,MINMAXRST,GA,SA,IA,LA,CR,TR,GR,IR,LR,DT,PW,PH,SEP,GSMRST,RST,RSTDEF

Ну и крутяцкая фича самодельного термостата в том, что все команды можно выслать в одном CMC для экономии, так как тупые «готовые» GSM-термостаты принимают по одной команде за раз, то есть для изменения пяти параметров нужно выслать 5 СМС. Здесь же все просто. Пример: держать температуру в помещении 21 градус, включить второе реле, разрешить прием тревожных СМС, запросить статус:

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

T=20.63; R=1111; A=1(21.00+0.30); W=1(10.00-30.00); VW=0; G=10/15; N=8; V=USB; DT=2019.10.15/10:44:48

Ну как-то так все и работает.

Отправка данных на интернет-сервер по GPRS.

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

Самая простая реализация следующая:

Если еще нет своего сайта, делаем сайт (можно на бесплатном хостинге, но обязательно с поддержкой PHP).

Делаем какой-нибудь скрипт, который сохраняет параметр из адресной строки в файл или в MySQL базу данных — второй способ более навороченный, но позволит в дальнейшем удобнее обрабатывать данные. Наипростейший пример («log.php»):

В результате получаете лог типа такого при проветривании помещения:

2019-02-14,09:54:20,23.25
2019-02-14,09:55:20,22.50
2019-02-14,09:56:19,22.00
2019-02-14,09:57:24,20.75
2019-02-14,09:58:25,20.25
2019-02-14,09:59:19,20.25
2019-02-14,10:00:19,20.25
2019-02-14,10:01:20,19.75
2019-02-14,10:02:19,19.50

В скетче периодически по таймеру делаем GET запрос на наш сервер с нужными данными. Например, если сейчас 21.75 градусов, делаем запрос: «http://server.com/log.php?t=21%2E75». Здесь %2E — это hex значение точки — все символы, которые недопустимы в параметрах урла, нужно заменить на hex значения перед отправкой.

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

AT+CGATT=1
AT+CGATT?
AT+SAPBR=3,1,»CONTYPE»,»GPRS»
AT+SAPBR=3,1,»APN»,»internet.beeline.ru» //internet.tele2.ru или internet.mts.ru
AT+SAPBR=3,1,»USER»,»»
AT+SAPBR=3,1,»PWD»,»»
AT+SAPBR=1,1
AT+HTTPINIT
AT+HTTPPARA=»CID»,1″
AT+HTTPPARA=»URL»,»http://server.com/log.php?t=some_data»
AT+HTTPACTION=0
AT+HTTPTERM
AT+SAPBR=0,1

Максимальное время ожидания подбирается экспериментальным путем. Большинству команд хватит 200-300мс, но AT+CGATT=1 может выполняться несколько секунд, AT+SAPBR=1,1 тоже долгая команда, AT+HTTPACTION=0 — это и есть отправка данных в интернет. Я поставил максимальное время ожидания 15 секунд, хотя обычно она проходит за 3-5 секунд (зависит от качества связи). В изначальной версии своего скетча я делал как в скетчах-примерах, которые можно найти в интернете: тупо отсылал команду модему и ждал от 0.3 до 10 секунд после каждой команды, надеясь на положительный результат. Иногда модем не укладывался в отложенные рамки, иногда выдавал ошибку, а скетч слал следующие команды, не дождавшись выполнения предыдущих, и получалась полная фигня. Результат отправки был хаотичным, иногда почти всегда, а иногда один успешный раз за 3-5 попыток, и занимало это по 20-30 секунд на попытку. Делать удлиненные задержки по несколько секунд для 10 команд — это тоже дичь, в таком случае ардуина только и будет, что ждать, особенно, если лог отправляется каждую минуту. В общем, в какой-то момент постоянные глюки начали меня злить, и я пошел искать, как делают нормальные люди. Есть библиотека GPRS_Shield_Arduino. Она жирненькая, так что в моем проекте не прижилась, но я подсмотрел там функцию sim900_wait_for_resp, немного ее изменив под свои нужды. Суть функции в том, что мы посылаем в модем AT-команду и вызываем эту функцию с двумя параметрами — какой должен прийти ответ при благоприятном исходе, и максимальное время, которое можно ожидать ответ. Если ответ приходит быстрее, функция сразу же завершается. Этим мы добиваемся двух целей: команды выполняются без фиксированной задержки максимально быстро, и мы знаем результат выполнения (OK или нет). Только когда я применил этот подход, почти все* попытки отправить данные на сервер стали успешными, и время отправки уменьшилось до 5-10 секунд.

Ну а имея данные на сервере в интернете, с ними уже можно делать что угодно — выводить на экране в удобном виде, строить графики, рассылать тревожные email’ы при выходе параметров за разумные границы и т.п. Я также думал об обратной связи — чтобы из интернета слать команды на модем, но пока не вижу в этом большой необходимости — это излишнее нагромождение в проекте, а у меня уже на это нет памяти — 31.8 кб из 32 занято. Да и если всё исправно работает, то и слать на термостат ничего не нужно. А я все же надеюсь, что термостат будет работать исправно 🙂 Если же кто-то планирует это сделать, у меня в мыслях два варианта:

  1. Каждый раз, когда термостат запрашивает log.php, пусть читает его вывод (команда AT+HTTPREAD). Можно сделать на сайте страницу для задания команд и настроить всё так, чтобы команды выводились файлом log.php. Термостат периодически всё равно запрашивает этот файл, заодно захватит и подготовленные для него команды. Этот подход имеет смысл только если термостат настроен на частую отправку лога в интернет, например, каждую минуту, иначе выполнения команд не дождешься…
  2. Другой способ — если при запросе log.php термостат высылает в параметрах кроме всего прочего и свой IP адрес. На модеме можно развернуть и небольшой HTTP сервер, а его IP будет вычленяться из log.php и выводиться на Вашем сайте (в случае динамического IP это особенно актуально). Далее Вы просто в браузере набираете IP термостата и уже на сгенерированной им HTML странице вводите команды, а ардуина их парсит и выполняет.

Еще один важный момент по отправке данных через GPRS. Поскольку трафик с термостата составит несколько десятков мегабайт в месяц, платить ежемесячно за анлим для термостата — как-то жирно. Вполне хватит пакета на 50-100 мегабайт. Но и тут опсосы схитрили, чтобы увеличить свои прибыли. Предположим, наш термостат делает один GET запрос на 1 килобайт в минуту, 60 запросов в час, 1440 запросов в сутки, 44640 запросов в месяц. Грубо говоря, модему нужно 45 мегабайт в месяц для выполнения своих обязанностей. Опсосы прекрасно понимают, что на этом много с нас не сдерешь, поэтому в предложении интернета мелким шрифтом пишут, что-то вроде «округление трафика в большую сторону до 100 кб». Что это для нас значит? Это значит, что открыв сессию, скачав 1 кб, и закрыв сессию, с нас «учтут» 100 кб трафика. Значит наши 45 мегабайт в месяц мистическим образом превращаются в 4.5 гигабайта. Нехило, да? А мегафон, помнится, в какое-то время округлял трафик до мегабайта! Что с этим можно сделать. Ну во-первых, поискать предложения интернета с наименьим округлением. В идеале, можно поискать предложения с неоплачиваемым минимумом трафика, но не знаю, остались ли еще такие. Если тарифицируемый минимум там больше килобайта, получится, что мы вообще как бы не будем платить за трафик. Если с этим не повезло, то код скетча придется поменять, так, чтобы модем не закрывал сессию после отправки каждого пакета. В нашем случае, AT+SAPBR=1,1 открывает сессию, а AT+SAPBR=0,1 закрывает сессию. Изменим код так, чтобы сессия открывалась один раз и никогда не закрывалась. Правда, нужно учесть, что опсос сам может разорвать сессию, так что перед отправкой данных нужно будет проверять, активна еще сессия или нет, и если ее разорвали, открывать заново. Проверяем командой AT+SAPBR=2,1, получаем ответ +SAPBR: 1,1,»наш IP», если вторая цифра 1, значит соединение установлено. Таким образом, если опсос не будет слишком часто разрывать сессию, мы заплатим примерно за тот трафик, который реально использовали.

* Выявленные проблемы. Во время поступления внешних данных на модем (входящий звонок, пришедшее смс), модем выдает в буфер данные, которые мешают нормальному парсингу ответов, которые в этот момент идут от команд при отправке данных на интернет-сервер. В результате, прибор «захлебывается» левой информацией и отправка не удается. Пока я не понял, как с этим бороться. Вроде бы и мелочь — вероятность, что кто-то позвонит в те самые 5-10 секунд, когда отправляются данные — весьма невелика, но, с другой стороны, именно непродуманность таких мелочей и отличают «быдлокод» от нормального кода. Куда более неприятно, что пока ардуина отправляет данные на сервер и парсит ответы модема, она пропускает звонки, а значит, и входящие смс. Короче, как-то «по-китайски» получилось. Если кто-то обошел эту проблему — пишите, какие есть варианты.

Остальное…

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

Теперь несколько слов о потенциальных проблемах, которые я обнаружил в скетчах, имеющихся в интернете.

Об использовании millis(); в качестве таймера.

Классический пример, который можно видеть чуть ли ни во всех скетчах, которые мне попались:

unsigned long currentTime;
unsigned long loopTime;
currentTime = millis();
if(currentTime >= (loopTime + 10000)) <
loopTime = currentTime;
/* какое-то важное действие, которое надо выполнять каждые 10 секунд */
>

Это часто работает при первоначальных проверках, но копнем глубже, прочитаем инструкцию:

millis() — Возвращает количество миллисекунд с момента начала выполнения текущей программы на плате Arduino. Это количество сбрасывается на ноль, в следствие переполнения значения, приблизительно через 50 дней.

Итак, предпложим, наш прибор каким-то чудом проработал 50 дней. Незадолго до этого значение loopTime + 10000 переходит через 4,294,967,295, и получает некоторое значение меньше 10000 в данном примере. А millis все еще находится на каком-то гигантском числе. Так вот, в каждый момент, пока millis не сбросится на 0, будет выполняться «какое-то важное действие» (в данном примере), которое по задумке должно было выполняться только раз в 10 секунд. И количество этих выполнений будет сравнимо с числом миллисекунд, которое прибавляется к loopTime (чем длиннее интервал и реже должно выполняться действие, тем больше раз оно в реальности выполнится). У меня нет желания ждать 50 дней, поэтому я накидал несложный скетч для проверки такой реализации в рамках unsigned char (0-255):

unsigned char ct =0; // типа замена таймера millis(); в рамках 0-255
unsigned char lt = 0; // текущее значение времени цикла

void setup() <
Serial.begin(9600);
>

void loop() <
if (ct>=byte(lt+10)) // выполняем каждые 10 единиц времени ct
<
Serial.println(» WIN!»);
lt=ct;
> else Serial.println();

И что Вы думаете, последний раз прога нормально отработала на ct=250, далее еще 5 раз выполнила наше действие «незапланированно», и только когда таймер, наконец, сбросился на 0, программа начала выполняться как и было задуманно (до следующего переполнения):


ct=238 lt=230 lt+10=240
ct=239 lt=230 lt+10=240
ct=240 lt=230 lt+10=240 WIN!
ct=241 lt=240 lt+10=250
ct=242 lt=240 lt+10=250
ct=243 lt=240 lt+10=250
ct=244 lt=240 lt+10=250
ct=245 lt=240 lt+10=250
ct=246 lt=240 lt+10=250
ct=247 lt=240 lt+10=250
ct=248 lt=240 lt+10=250
ct=249 lt=240 lt+10=250
ct=250 lt=240 lt+10=250 WIN!
ct=251 lt=250 lt+10=4 WIN!
ct=252 lt=251 lt+10=5 WIN!
ct=253 lt=252 lt+10=6 WIN!
ct=254 lt=253 lt+10=7 WIN!
ct=255 lt=254 lt+10=8 WIN!
ct=0 lt=255 lt+10=9
ct=1 lt=255 lt+10=9
ct=2 lt=255 lt+10=9
ct=3 lt=255 lt+10=9
ct=4 lt=255 lt+10=9
ct=5 lt=255 lt+10=9
ct=6 lt=255 lt+10=9
ct=7 lt=255 lt+10=9
ct=8 lt=255 lt+10=9
ct=9 lt=255 lt+10=9 WIN!
ct=10 lt=9 lt+10=19
ct=11 lt=9 lt+10=19

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

Варианты решения проблемы (как я их вижу):

  1. Не дожидаясь переполнения, обнулить нужные переменные самому. Например, выполнять «сброс» каждый месяц.
  2. Использовать RTC, ведь в серъезных проектах часы все равно не помешают (не зря же китайцы во всё подряд встраивают часы!). Но тут есть другая проблема — работа с RTC медленная и энергозатратная, поэтому польностью переложить всё на нее не получится. Я думаю, имеет смысл отсчитывать короткие интервалы времени через millis(), а уже остчитав, скажем, 1 секунду, получать точное значение с RTC и на основании этого значения принимать решение, что делать. Но тут еще надо поэкспериментировать. Но зато если повесить важные таймеры на DateTime.unixtime(), то ожидать переполнения в ближайшем будущем не стоит.

Об отсутствии проверок на текущее состояние оборудования.

Например типичное включение модема, которое можно видет в скетчах:

digitalWrite(GSM_PIN, HIGH);
delay(800);
digitalWrite(GSM_PIN, LOW);

Но эти же команды и выключают модем. Так что если по какой-то причине модем уже был включен, выполняя эти команды, мы его выключаем. Далее авторы скетчей беззаботно выполняют команды отправки SMS, даже не проверив, работает модем или нет. Имхо, вреда от такого оборудования будет больше, чем пользы — если Вы выключите модем, полагая, что вы его включаете, то вовсе останетесь без удаленного контроля.

Некоторые продвинутые программеры даже проверяют, зарегистрировался ли модем в сети, командой «AT+COPS?», и если модем возвращает «+COPS: 0», считают, что все OK, можно слать SMS. Только вот мой опыт показал, что модем может возвращать эту строку даже тогда, когда он не зарегистрирован в сети! Нужны альтернативные проверки.

Как я это себе представляю (на практике пока работает без проблем):

  • Посылаем AT-команду.
  • Если не приходит OK, считаем, что модем выключен, включаем модем, ждем секунд 5 и повторяем проверку AT-командой.
  • Если OK не приходит, считаем модем временно неисправным и включаем термостат для оффлайновой работы (котел все-таки надо регулировать). Будем повторять попытки включать модем каждые 10 минут.
  • Если приходит OK, считаем, что модем включен, но это не гарантирует наличие связи. Поиск сети может занять 20-30 секунд, после чего проверяем AT+COPS? (в идеале сравнить ответ с названием Вашего опсоса, потому что «+COPS: 0» без названия опсоса все равно оставляет Вас без связи. Как дополнительную проверку я использую «AT+CSQ», которая возвращает качество радиосвязи с опсосом от 0 до 31 (0 или 99 = связи нет). Если все это выдает нормальные значение, считаем, что связь есть.
  • Проводим проверки на работоспособность модема каждые 10 минут, на всякий случай. Мой GSM модуль прожорливый и может выключиться сам при некоторых условиях, например, при низком качестве связи, если в это время отправляется или принимается SMS, а если еще в это время и релехами начать щелкать, то шансы отрубить модем сильно увеличиваются. Конечно, сейчас я отлаживаю его по USB, а в идеале, когда все будет готово, нужно подключить блок питания на 2A, но и с ним никогда не знаешь когда отрубит, так что лучше подстраховаться.

О выводе SMS в сериал порт без сохранения.

Идея выводить смс с модема в сериал порт без сохранения на модеме и постоянно читать сериал ардуиной в loop вроде как работает, но только до того момента, как мы попытаемся общаться с модемом для каких-либо целей, помимо отлова «+CMT». Даже добавление простой проверки «модем еще жив?» требует отправлять в модем «АТ» и некоторое время читать вывод, ожидая «ОК». Понятно, что «АТ» выполняется быстро, и вероятность, что в эти пару десятков-сотен миллисекунд придет СМС — крайне мала. Но если мы используем долгие АТ команды, такие как установка GPRS соединения, отправка данных на сервер и чтение данных из интернета, время ожидания ответа от этих команд — уже несколько секунд. Если за это время придет SMS, насколько я понимаю, функция ожидания ответа от АТ команды просто проглотит +CMT, и SMS не будет обработана. Вот я и думаю, надежнее было бы установить в модеме сохнанение СМС на сим карту. Потом, когда модем нам будет не нужен, в loop прочитаем имеющиеся в памяти СМС, пропарсим, выполним указанные действия, удалим СМС. Конечно, это больше геммора в коде, но вероятность пропуска СМС во время взаимодействия с модемом должна сойти в ноль. Я пока что минимизировал общение с модемом и надеюсь на лучшее, но если кто-то активно использует AT-команды — имейте в виду ту ситуацию, которую я описал.

Статья будет дополняться и исправляться со временем. Если кто-то тоже работает над подобным проектом — делитесь своими мыслями в комментах. Также пишите о граблях, на которые уже пришлось наступить при подобных разработках.

Дополнение 2019-10-15:

После некоторого опыта использования, в новом сезоне внес в прошивку следующие изменения:

  • Переход с Arduino Uno на Robotdyn Mega+WiFi позволил избавиться от Bluetooth, требовавшего на телефоне установленного терминала. Теперь все настройки производятся с помощью телефона или компьютера по WiFi из любого браузера. При этом подключение к интернету не требуется, так как соединение происходит в режиме точки доступа. Теоретически, при наличии роутера, можно менять настройки и смотреть состояние прибора и удаленно через Интернет. Когда прибор настроен, WiFi модуль отключается физической кнопкой, чтобы не висел в эфире впустую. Я не любитель бессмысленного радиочастотного загрязнения, поэтому эта кнопка служит для отключения wi-fi радиомодуля, когда он не требуется. Если же требуется «бесплатная» локальная настройка термостата, этой же кнопкой wifi включается, и тогда загорается синий светодиод. Также состояние wifi дублируется на экране буковой “N”, если беспроводная сеть работает, и “n”, если нет. За буквой идет числовое значение мощности принимаемого сигнала GSM сети (в диапазоне от 0 до 31). Кнопка подключена через GPIO5 на ESP8266, которая программно управляет включением/выключением радиомодуля и зажигает/гасит светодиод, подвешенный на GPIO4, который, в свою очередь подключен и к 10-му пину на меге, так чтобы через этот пин мега могла узнать, когда wi-fi работает, а когда нет. Такая вот немного замудренная конструкция, так как MEGA и ESP хоть и на одной плате, но работают каждая сама по себе, соединяясь только через Serial3, который я оставил исключительно для трансляции полезных мне сообщений в готовом для показа виде без дополнительного парсинга.
  • Заданная температура теперь считается минимально допустимой, и именно при ней включается котел. До этого допустимый диапазон температур был от T-hyst до T+hyst, теперь стал от T до T+hyst. На мой взгляд, это более логично и интуитивно, так как позволяет задать минимальную допустимую температуру в помещении. Конечно, надо учитывать, что котел не сразу нагреет теплоноситель, так что температура успеет упасть еще немного до того, как батареи начнут греть, но всё равно это лучше, чем было раньше.
  • Изменен алгоритм отправки SMS-сообщений о выходе температуры за допустимые границы. Раньше границы рассчитывались автоматически при изменении желаемой температуры. Например, при нижней/верхней границе 5/8 при 20 градусах границы были 15-28, при переключении на 10 градусов становились 5-18. Всё это нормально работало, но вызывало нежелательное срабатывание триггера в момент переключения температур. Например, в вышеприведенном примере, когда в доме 20 градусов, триггер не срабатывает, но стоит перевести температуру на 10 градусов (когда нужно уезжать), и триггер срабатывает сразу же, так как новая граница 18 меньше реальных 20 градусов. В результате, приходилось либо дико завышать лимиты, либо отключать оповещение на один день, чтобы температура снизилась до допустимых границ, но нужно было и не забыть включить потом оповещения снова. Та же ситуация была при переводе температуры с 10 градусов на 20, только срабатывало оповещение по нижней температуре, так как реальные 10 градусов были меньше новой минимальной границы в 15 градусов. В новой версии прошивки границы задаются не относительными, а абсолютными значениями, например от 8 до 28 градусов, чтобы триггер не срабатывал впустую. При длительном отсутствии, конечно, можно установить более узкие границы, чтобы получить информацию о сбое в работе котла быстрее.
  • Также триггер временного выключения предупреждений о выходе температуры за разрешенные границы оказался излишним, так как, по сути, он просто дублировал состояние переменной, разрешающей такое информирование.

Дополнение 2019-11-03:

Вот и начался очередной холодный сезон, и снова встал вопрос о GSM термостате. Достав из шкафа пылившуюся все лето кучу электронных компонентов, набросанных кое-как в лотке, и соединенных быстросъемными перемычками, я пришел к выводу, что пора придать этому девайсу какой-то законченный вид, чтобы можно было перемещать его с места на место, не боясь, что какой-нибудь проводок вылетит, и прибор перестанет функционировать. Посмотрев, сколько стоят корпуса для самодельных приборов в местном радиомагазине, у меня слегка отпала челюсть, так что я пошел во всем известный гипермаркет, где можно найти много недорогих вещей. В кухонном отделе я присмотрел маленькую желтую разделочную доску из полипропилена рублей за 30, которую я планировал использовать как основу, и контейнер для еды подходящего мне размера, 0.9 литров (примерные размеры — 19х12х4см), рублей за 35, который должен был стать корпусом. Такие были только с крышками стремных цветов, но я выбрал зеленоватую как наименее «вырвиглазную» из тех, что там были. Зато такой «корпус» по цене чуть ли ни в десять раз дешевле тех, что продают в магазине радиотоваров.

Далее последовала игра под названием «попробуй запихни всю эту кучу компонентов в маленький контейнер». Было ясно, что придется строить в два этажа. Для удобства ремонта и апгрейда все компоненты делал на быстроразъемных соединениях. Также и крышку проще снимать, если всё, что на ней находится, можно отсоединить. На дне я разместил мегу, релейный модуль, RTC, Voltage Sensor и небольшую плату для спаивания проводов, а на верхней крышке – экран, модем и самодельный модуль, состоящий из кнопки и светодиода.

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

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

К отпиленной по размеру контейнера желтой разделочной доске компоненты крепил маленькими саморезами, а к верхней крышке – термоклеем, чтобы не портить внешний вид головками от болтов. Модем приклеил «вверх ногами», чтобы была возможность замены сим-карты снаружи без вскрытия контейнера. Для этого пришлось отпаять выпячивающийся держатель батарейки, но он мне и не нужен, так как я не использую встроенные в модем часы. Для удобства обслуживания девайса клемник для подключения кабеля котла вывел наружу, на заднюю стенку, тоже приклеив его термоклеем.

Следующий шаг – просверлить отверстий в контейнере для штекера питания, USB, кабелей от реле. Также сделал отверстие под термодатчик, чтобы вынести его за пределы корпуса в месте с наименьшим тепловыделением, так как такая куча оборудования нехило греется и может вносить нежелательные изменения в показания температуры, если установить датчик внутри корпуса. По той же причине не советую устанавливать датчик на верхней крышке, так как она всегда будет греться (в моем случае локальный разогрев крышки доходил до 30 градусов) . В моем случае датчик нашел свое идеальное пристанище снаружи, на боковой стороне контейнера, в «холодном» углу, где находится плата для спаивания проводов. Дополнение:показанная на первоначальных фотографиях реализация оказалась все же не совсем удачной, так как при длительной работе прибора даже боковые стенки контейнера нагревались, внося ошибку в определение температуры примерно в 2 градуса. Пришлось сделать «хобот», чтобы вынести датчик совсем за пределы корпуса, минимум на 1-2 см от стенок, так чтобы он обдувался со всех сторон и никакой своей частью не касался контейнера (кроме, конечно, проводов). Наиболее оптимальное расстояние датчика от корпуса можно будет определить позже экспериментальным путем (длина «хобота» намерено сделана с хорошим запасом, чтобы можно было при необходимости более точных замеров выдвинуть датчик дальше от корпуса, не прибегая к перепайке). Отчасти по той же причине добавил параметр «TA», позволяющий вносить корректировку в показываемую датчиком температуру (плюс-минус какое-то значение).

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

Ну и последний шаг – наклеить 4 подушечки из толстого двухстороннего скотча на нижнюю часть разделочной доски и хорошенько прижать ее к дну контейнера, чтобы при вставлении штекера питания или USB, вся сборка не отодвигалась от отверстий для штекеров. Можно использовать для фиксации и термоклей, но в случае необходимости вынуть сборку из контейнера для проведения ремонта или апгрейда, отдирать термоклей будет сложнее, чем скотч. Теперь контейнер можно закрывать: замена сим-карты, подключение питания и USB кабеля для программирования, а также кабеля для котла, будет производиться снаружи.

В результате, штуковина получилась немного «вырубленной топором», в стиле совковых приборов, но всё же более аккуратной, чем я изначально ожидал. Оказалось, что допустимы и горизонтальное, и вертикальное расположение. Но главное, после всех издевательств и пыток паяльником, ОНА ЖИВА, ЖИВААА.

Дополнение 2019-11-05:

Идея сделать лог температур меня не оставляла, но мудрить с логом на microSD я пока не решился, чтобы не усложнять конструкцию и не увеличивать вероятность сбоя, так как хардварные или софтварные проблемы при работе с картой памяти могут остановить и сам термостат, а это уже может вызвать кучу иных более серъезных проблем. В крайнем случае, у меня есть отдельный SD-логгер температур на ардуино. А в этом девайсе я пошел простым путем. Сделал массив int из 48 элементов для температур и еще один массив uint32_t для даты и времени (в меге памяти дофига, уже нет смысла экономить каждый байт), и переменную logRefresh, которая определяет, через сколько секунд будет обновляться лог, и собственно, всё. Число 48 взял из рассчета, что если сохранять лог один раз в час, то можно проследить ход событий на двое суток назад, а больше обычно и не требуется, так как за это время проблема либо решится сама собой, либо надо ехать и решать ее самостоятельно. Через заданный интервал все ячейки массива сдвигаются на одну вперед, последняя «удаляется», а в первую записывается текущая температура. Система простая, а значит надежная. Например, если logRefresh=3600 (обновление лога 1 раз в час) и в массиве лежат значения 227, 225, 224, 223, … значит в последнее обновление лога температура была 22.7 градусов, час назад 22.5, два часа назад 22.4, три часа назад 22.3 и так далее. Десятичные точки я специально отбрасываю, чтобы побольше значений уместилось в SMS. У меня в SMS влезает чуть больше 30 таких значений, что при ежечасном логгинге достаточно, чтобы посмотреть температуру чуть более чем за сутки. Если проблем с котлом обычно не наблюдается, можно увеличить интервал до трех часов, или даже снимать по одному значению за сутки, тогда SMS-лог можно будет посмотреть даже на месяц назад. Но мне интересно собирать лог каждый час, чтобы определить тенденцию снижения температуры при сбое котла, когда термостат вышлет тревожную SMS о снижении температуры в доме до критически низкого значения. Тогда можно запросить лог за последние часы и прикинуть, за сколько часов температура упала с нормального уровня до низкого, и сколько приблизительно еще есть времени в запасе до полной заморозки дома. Лог можно запросить простой командой «log», которая выводит только последние значения температур, но с указанием дня и времени, когда они были зафиксированы (влезает около 17 показаний за один день, или чуть меньше, если за разные дни). Есть еще команда «logall», при этом массив температур выводится без всяких бантиков и ленточек через точку с запятой — так в СМС влезает около 38 значений. Обрезка лога происходит только для запроса через SMS, а при просмотре через Serial или WiFi отображаются все 48 значений из массива без урезания, так как там нет ограничения длины сообщения в 160 символов. Очистка лога производится командой «logrst». Ручная очистка имеет смысл только при смене интервала, если планируется использовать команду «logall» в ближайшее время, иначе не определишь, какие значения были сохранены со старым интервалом, а какие с новым. Команда «log» выводит дату и время, когда сохранено значение температуры, поэтому если планируется использовать только ее, смена интервала не вызовет путаницу, так что и очистка не требуется.

По аналогии, сделал такой же лог для состояния первого реле, чтобы отслеживать циклы работы котла. Массив лога имеет всего 30 элементов (в SMS влезает не более 22 значений с указанием даты и времени события, по wifi можно посмотреть все 30). Прибор сохраняет состояние реле и дату/время каждый раз, когда реле включается или выключается (автоматически и вручную). Для просмотра истории переключений используется команда «rlog».

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

Также, не столько ради нужды, сколько ради интереса, сделал функцию отслеживания минимальной и максимальной температуры. Статистика высылается по запросу «minmax», или просто «mm». Now — текущее время, установленное на приборе. Boot — дата и время последней перезагрузки (в приборе установлен watchdog на всякий случай, да и вообще полезно узнать, перезагружался девайс втихаря или нет). MinMaxFrom — дата и время, с которого ведется учет минимальных и максимальных значений, сбрасывается по команде «minmaxrst». Ну и Max/Min — соответственно, значения максимальной и минимальной температуры, и дата/время, когда они были замечены. Разумеется, не обязательно отправлять SMS, когда находишься рядом с прибором — есть и бесплатная возможность проверки через Serial или через WiFi. В принципе, интересная игрушка, потому что мои метеостанции Oregon Scientific и Ea2, хоть и могут фиксировать минимальное и максимальное значение за некоторый период, но не запоминают, когда именно происходили эти события, и вообще не указывают за какой конкретно период собирались эти данные (если не помнишь, когда именно сбрасывал статистику последний раз).

Примеры общения с термостатом по Wi-Fi:

По SMS общение происходит так же, только за деньги 🙁 Кстати, благодаря статистике теперь видно, что температура гуляет в пределах 1.25 градусов, что намного приятнее, чем 2-3 градуса перепадов при использовании термостата Poer. Вынесенный наружу цифровой датчик Dallas значительно быстрее улавливает иизменения температуры в помещении, чем встроенная внутрь корпуса аналоговая термопара Поера. Также теперь можно оценить циклы работы/простоя котла. В примере на втором скриншоте видно, что котел работал примерно по 15 минут с последующим отдыхом около 60-70 минут, чтобы прогреть дом до 20-21 градусов при уличной температуре около 0 градусов.

Оцените статью