Хабрахабр

Опыт применения GSM модуля в домашней автоматизации

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

То, что получилось в итоге, можно увидеть на фото. image
Мой план заключался в том, чтобы создать простое и дешевое устройство, оснащенное двумя датчиками температуры, датчиком влажности, GSM модулем, а также твердотельным реле и розеткой для подключения нагрузки. На фото его можно увидеть под прозрачным колпачком слева от основного модуля. В качестве датчика температуры и влажности был выбран климатический сенсор BME280, его канал давления не используется. В качестве колпачка используется китайская пластиковая пробирка с двумя отверстиями для вентиляции. Такое расположение уменьшает влияние тепловыделения внутри корпуса на показания датчика. Он расположен внутри металлического зонда, с корпусом соединен кабелем через обычный аудио разъем для наушников. Второй датчик температуры выносной, сделан на DS18B20. Основной объем корпуса занимает твердотельное реле (я выбрал помощнее) и преобразователь из 220В в 5В для питания схемы. Зонд предназначен для измерения температуры непосредственно отопительной системы. OLED дисплей на базе контроллера SH1106 отображает показания датчиков, а также показывает, включена ли нагрузка. Розетка для подключения нагрузки смонтирована на задней стороне корпуса, на фото она не видна. 3В 8МГц. Для управления всей системой используется модуль Arduino Pro Mini в версии 3. Я не большой фанат этой платформы, но обилие библиотек, в том числе заботливо выпиленных автором, делает ее оптимальным выбором, когда нужно быстро сделать что то простое.

Как показала практика, помехи от этого уменьшаются не сильно. GSM модуль SIM800L размещен в отдельном металлическом корпусе для уменьшения создаваемых им помех на остальные части схемы. Но об этом подробнее мы поговорим позже. А радикально их уменьшает выносная антенна, подключенная экранированным кабелем к коаксиальному разъему, на фото выше она на переднем плане.

image

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

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

Первое, что важно сделать правильно, — вставить сим-карту

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

Чтобы хорошо работать, нужно хорошо питаться

Требования к питанию у GSM модуля достаточно специфические. Он сделан на базе микросхемы, разработанной для кнопочных мобильных телефонов, и рассчитан на питание непосредственно от литиевого аккумулятора. Поэтому, 5В для него много, а 3.3В — мало. К тому же, в режиме передачи на максимальной мощности он способен потреблять ток до 2А. Если источник питания не способен обеспечить нужный ток, GSM модуль может перезагрузиться при попытке регистрации в сети и продолжить перезагружаться в бесконечном цикле. Периоды пикового потребления обычно длятся меньше секунды, поэтому есть соблазн применить слаботочный стабилизатор с накопителем энергии для периодов пиковой нагрузки. В качестве такого накопителя можно применить литиевый аккумулятор. При этом важно обеспечить возможность его отключения и важно не забыть ей воспользоваться, иначе отключение устройства от сети закончится глубоким разрядом аккумулятора и его необратимым повреждением. Другой вариант — это поставить вместо аккумулятора ионистор (суперконденсатор). Он не боится глубокого разряда. Но у него тоже есть проблемы с надежностью. Одна ячейка ионистора обычно рассчитана на напряжение от 2.5 до 3В. Ионисторы, рассчитанные на большее напряжение, состоят из нескольких ячеек (обычно из 2-х). При этом, однако, дисбаланс напряжения на ячейках может закончится пробоем ячейки. Такой дисбаланс легко получить за счет разницы в емкости ячеек или разницы в токе утечки. Следует также учитывать параметр внутреннего сопротивления ионистора. Ионисторы с большим внутренним сопротивлением на больших токах бесполезны, а ионисторы с малым сопротивлением стоят не дешевле аккумулятора. После того, как у меня ионистор скоропостижно скончался из-за дисбаланса ячеек, я просто применил преобразователь из 220В в 5В достаточной мощности. Чтобы понизить напряжение до нужного GSM модулю, я поставил между преобразователем и модулем обычный кремниевый диод. На таком диоде обычно падает 0.7В, так что модулю достаются необходимые 4.3В. После диода полезно поставить электролитический конденсатор большой емкости. Он сгладит провалы напряжения при внезапном включении передатчика.

От передающей антенны лучше держаться подальше

Даже после того, как я обеспечил GSM модулю требуемое питание, симптом перезагрузки периодически проявлялся, но на этот раз перезагружалась Arduino. Наблюдение за ее питанием при помощи осциллографа показало, что питание тут непричем. Судя по всему помеху создавал передатчик модуля, поскольку проблема возникала тем чаще, чем хуже были условия приема сигнала базовой станции. Столь радикальный эффект помех от передающей антенны вполне объясним, если вспомнить, что передатчик модуля способен выдать в антенну 2 ватта. Такая мощность может за 5 минут вскипятить миллилитр воды или нагреть ваше ухо на несколько градусов. Для борьбы с этой проблемой были опробованы разные методы. Для начала я подключил внешнюю антенну, которая располагалась снаружи корпуса и соединялась с модулем коротким коаксиальным кабелем. Однако, ожидаемого эффекта это не дало. Тогда я расположил модуль в отдельном металлическом корпусе, к которому снаружи крепилась антенна. Стало лучше, но не сильно. Радикально улучшил ситуацию только вынос антенны на некоторое расстояние от устройства за счет ее подключение коаксиальным кабелем достаточной длины.

Типичная антенна — это 'четвертьволновой штырь', то есть половинка от дипольной антенны. Почему так происходит, легко понять из физических соображений. У правильной штыревой антенны второй половиной является либо поверхность земли, либо корпус прибора, либо специальные проводящие 'противовесы'. Но, чтобы создать электрическое поле, половинки диполя недостаточно, нужна вторая половинка, тогда между отрицательно и положительно заряженными элементами антенны возникнет электрическое поле. Как же она работает? Но для маркетологов все это слишком сложно, поэтому нам обычно продают только половинку от нормальной антенны. То, что он экранирован, ничего не меняет. Очень просто — второй половинкой является кабель, которым подключена антенна. При этом помеха легко наводится на проходящие по соседству провода несмотря на то, что кабель казалось бы экранирован. Внешняя поверхность его оплетки играет роль второй половинки дипольной антенны. Если экран большой (по сравнению с длиной волны), то он работает, как вторая половина излучателя, а если маленький, то излучают прочие провода, которые подведены к этому модулю, совершенно не важно, какие. Ну а если кабеля нет, например мы спрятали модуль в металлический экран, из которого торчит антенна? Следующий рисунок иллюстрирует вышесказанное (плюсы и минусы показаны для наглядности, в реальности заряд элементов антенны меняет знак с частотой несущей).

image

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

Какая длина является достаточной? Мораль заключается в том, что единственный надежный способ защититься от помех, создаваемых передающей антенной, — унести ее подальше от остальной электроники, подключив коаксиальным кабелем достаточной длины. Это и есть минимальное расстояние на которое следует отнести антенну, но чем дальше, тем лучше. Расстояние естественно соизмерять с длиной волны, в данном случае это максимум 30 см.

Не все последовательные порты одинаково полезны

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

Казалось бы, что в этом плохого, так многие делают. Суть проблемы в том, что программная реализация последовательного порта запрещает прерывания на все время передачи или приема очередного символа. Это конечно тоже не слишком хорошо. Например, реализация протокола 1-Wire для чтения термометров Dallas Semiconductor тоже запрещает прерывания на время передачи одного бита, то есть на 65 микросекунд. Если запрос на прерывание приходит, когда они запрещены, он будет обработан только после того, как прерывания разрешат снова. Если в системе есть другие обработчики прерываний, они не смогут обеспечить время реакции на прерывание меньше этих 65 микросекунд. Если следующий символ придет, пока не обработано прерывание от предыдущего, тот будет потерян. Например, аппаратный последовательный порт использует прерывания для того, чтобы положить в буфер приемника очередной принятый символ. В случае программной реализации последовательного порта все хуже. Это значит, что работать со скоростью больше 115200 бит в секунду аппаратный последовательный порт не сможет. Это ограничивает нас скоростью 9600 бит в секунду. Для его работы нужно, чтобы время реакции на прерывание было меньше времени передачи одного бита.

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

Асинхронному протоколу — асинхронный обработчик

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

Асинхронный обработчик предъявляет только необходимый минимум требований к ответам модуля на его команды. Починить это легко — нужно просто написать свой, асинхронный обработчик протокола. И это все, что нужно для того, чтобы зафиксировать ответ. На каждую команду модуль в итоге отвечает либо OK, либо ERROR. Смысл этих строк всегда можно определить по их началу. Все остальные строки, которые приходят от модуля, обрабатываются независимо от того, пришли они в ответ на команду или сами по себе. Если она начинается +CMT, то это информация о полученном SMS, и в ней содержится адрес отправителя. Если строка начинается с +CSQ, то она содержит информацию о качестве сигнала. Принятые SMS сообщения модуль направляет непосредственно в последовательный порт. Первая строчка посылается в составе ответа на команду AT+CSQ, авторую модуль присылает по собственной инициативе, но для нас это различие абсолютно несущественно. Чтобы мы могли распознать SMS сообщения в общем потоке сообщений от модуля, они должны начинаться с символа #, в противном случае сообщение игнорируется. Это позволяет избежать чтения их из памяти и последующего удаления.

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

Таких ловушек он может создать любое количество. Чтобы получать строки, начинающиеся с определенной последовательности символов, клиент создает специальный объект — ловушку. Поскольку такая архитектура не требует полного анализа ответов модуля на множество различных типов команд, код библиотеки в разы компактнее любой из известных мне библиотек. Полученные от модуля строки, отличные от OK, ERROR, которые не попали ни в одну из ловушек, просто игнорируются.

Что в итоге?

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

image

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

github.com/olegv142/GsmMon

Показать больше

Похожие публикации

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

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

Кнопка «Наверх»