Введение
![](https://habrastorage.org/files/760/21a/8ef/76021a8ef5fc430594284d70fca188b5.png)
В прошлой статье были рассмотрены основные особенности беспроводной технологии ZigBee. В этой части мы поговорим о том, как быстро начать работу с данной технологией на практике. Для этого были выбраны модули ETRX357, имеющие встроенную прошивку, которая позволяет работать с сетевыми функциями и управлять аналоговой и цифровой периферией с помощью набора AT-команд. Также в статье будут более подробно разобраны вопросы касающиеся типов устройств в сети ZigBee и безопасности сети. В конце мы соберем сеть сбора данных, которая будет получать информацию о температуре от нескольких беспроводных устройств.
1. Модули ETRX357
Познакомимся с выбранной аппаратной платформой. Модули ETRX357 построены на базе микросхемы EM357 от компании Silicon Labs. Данная микросхема является системой на кристалле — процессорное ядро Cortex-M3 + ВЧ-приемопередатчик, работающий на частоте 2,4 ГГц.
Модули ETRX357 доступны в 4 модификациях:
- ETRX357 – модуль со встроенной чип антенной. Максимальная выходная мощность радиосигнала +8 дБм.
- ETRX357HR – модуль с u.FL-разъемом для подключения внешней антенны. Максимальная выходная мощность радиосигнала +8 дБм.
- ETRX357-LRS – модуль со встроенной чип антенной и встроенным усилителем мощности. Максимальная выходная мощность радиосигнала +20 дБм.
- ETRX357HR-LRS – модуль с u.FL-разъемом для подключения внешней антенны и встроенным усилителем мощности. Максимальная выходная мощность радиосигнала +20 дБм.
Экспериментальные измерения дальности связи для модулей ETRX357 и ETRX357-LRS в условиях прямой видимости:
- ETRX357 – уверенный прием на расстоянии ~300 метров
- ETRX357-LRS – уверенный прием на расстоянии ~900 метров
Ниже представлена сводная таблица по основным характеристикам модуля:
Характеристики | Описание |
---|---|
Процессорное ядро | ARM Cortex-M3 |
ВЧ-приемопередатчик | 2.4 ГГц |
Объем Flash/RAM, Кб | 192 / 12 |
Энергопотребление | TX: 42 мА @ +8 дБм |
RX: 26.5 мА | |
«сон»: 400 нА | |
Рабочий диапазон напряжений | 2.1 — 3.6 В |
Рабочий диапазон температур | -40...+85 °C |
Более подробную информацию по техническим характеристикам можно получить в документации на модули[1].
2. Встроенная прошивка
Все модули идут со встроенной прошивкой от производителя, и для начала работы достаточно подать питание на модуль, подключить линии TxD и RxD последовательного интерфейса UART, через который осуществляется взаимодействие с модулем с помощью AT-команд. Все команды можно условно разделить на 2 типа:
- Работа с сетевыми функциями. Например:
- Организация сети/подключение к существующей сети
- Отправка адресных/групповых/широковещательных сообщений
- Чтение/запись регистров удаленных узлов
- Работа с периферией модуля. Например:
- Настройка портов ввода/вывода
- Управление мощностью ВЧ-приемопередатчика
- Включение/выключения вывода информационных сообщений по последовательному интерфейсу
Также стандартная прошивка включает в себя набор функций, который позволяют в некоторых случаях обойтись без внешнего микроконтроллера или управляющего устройства. Полный перечень команд можно посмотреть в руководстве[2], ниже перечислены лишь наиболее часто используемые. Некоторые команды из этого списка потребуются нам для создания нашей системы сбора данных.
Команда | Описание |
---|---|
AT+PANSCAN | Просканировать эфир на наличие доступных для подключения сетей |
AT+EN | Организация сети |
AT+JN | Подключение к любой доступной сети |
AT+DASSL | Покинуть текущую сеть |
AT+DASSR:<адрес устройства> | Отправить удаленному устройству команду на выход сети |
Команда | Описание |
---|---|
AT+UCAST:<адрес устройства>=<сообщение> | Отправка адресного сообщения |
AT+MCAST:<макс. число ретрансляций>,<ID группы>,<сообщение> | Организация сети |
AT+BCAST:<макс. число ретрансляций>,<сообщение> | Подключение к любой доступной сети |
AT+SCAST:<сообщение> | Отправить данные на Sink-узел |
Максимальная длина сообщения: 72 байта.
Важно: групповые сообщения являются частным случаем широковещательных, поэтому не стоит отправлять их с высокой частотой следования (в документации указано не более 8 групповых/широковещательных сообщение в течение 8 секунд). Кроме этого стоит обратить внимание на то, что групповые сообщения не принимаются спящими конечными устройствами.
Команда | Описание |
---|---|
ATSXX? | Чтение содержимого регистра SXX |
ATSXX=YYYY | Запись в регистр SXX значение YYYY |
ATREMS:<адрес устройства>,XX? | Чтение содержимого регистра SXX удаленного узла |
ATREMS:<адрес устройства>,XX=YYYY | Запись в регистр SXX удаленного узла значения YYYY |
Возможен побитовый доступ к встроенным S-регистрам. Для этого в команде на чтение/запись, после XX требуется указать номер бита, к которому необходимо обратиться. Например:
ATS001? # чтение состояния 1 бита из регистра S00
ATS001=1 # запись 1 в 1 бит регистра S00
ATS1812? # чтение состояния 18 бита из регистра S18
ATREMS:0000,0AE? # чтение состояния 14 бита из регистра S0A удаленного узла с коротким адресом 0000
![](https://habrastorage.org/files/1ab/df8/21c/1abdf821c9f94886acc672d3d6372ffc.png)
Теперь перейдем к более детальному рассмотрению процесса построения сети ZigBee. Работать будем с отладочными платами на которых установлен мезонинный радиомодуль и ZigBee-USB-шлюзом. На отладочных платах есть несколько аналоговых датчиков, о которых будет рассказано позже. С них мы будем снимать показания и отправлять на центральный узел сбора данных, где это все будет обрабатываться. Шаг за шагом мы будем создавать нашу систему сбора данных и разберём основные трудности, которые могут возникнуть в процессе.
Опишем будущую систему сбора данных:
- ZigBee-USB-шлюз является координатором сети и подключен к ПК
- ZigBee-USB-шлюз является центральным узлом сбора данных
- Два радиомодуля собирают данный с датчика температуры и освещенности и передают их центральный узел сбора данных с интервалом 1 раз в 10 секунд
- На ПК работает программа, которая полученные оцифрованные значения температуры переводит в градусы Цельсия и выводит в консоль
![](https://habrastorage.org/files/4ba/f1a/d0a/4baf1ad0a1db4a8c87658652f8e3c54a.jpg)
3. Создание сети ZigBee
Выше была упомянута команда AT+EN, которая позволяет организовать сеть. Устройство, которому данная команда была отправлена по последовательному интерфейсу, становится координатором сети. По умолчанию, координатор самостоятельно выбирает наиболее подходящий частотный канал, генерирует короткий и длинный адрес сети.
AT+EN
JPAN:24,949D,56370DE37E0DC0FF
# 24 - частотный канал
# 949D - короткий идентификатор сети
# 56370DE37E0DC0FF - длинный идентификатор сети
Ниже представлен список регистров, значение которых влияет на процесс создания ZigBee-сети:
Маска каналов – регистр S00. Данная маска определяет, какие каналы могут быть использованы. Напомним, спецификация технологии ZigBee определяет 16 частотных каналов (нумерация с 11 по 26). Регистр 2 байтный, поэтому установкой 0/1 можно разрешить/запретить использовать соответствующий канал. Эта установка действует как для координатора при создании сети, так и для всех остальных устройств, которые хотят присоединиться к доступной сети.
ПримерATS00=0001 # разрешаем использовать только 11 частотный канал ATS00=FFFF # разрешаем использовать любой доступный частотный канал
Выходная мощность приемопередатчика – регистр S01. Данный параметр применяется к радиомодулю при создании сети или при подключении к доступной сети, и действует в течение всего времени нахождения устройства в сети. В процессе работы в ZigBee-сети данный параметр поменять нельзя. Единственная возможность это сделать – покинуть сеть, поменять значение в регистре на новое, покинуть сеть и подключиться заново. Все возможные значения, которые можно записать в регистр S01, указаны в документации[2].
ПримерATS01=8 # устанавливает выходную мощность +8 дБм # (актуально для модулей ETRX357. Для LRS-версий модулей # подходящие значения необходимо смотреть в документации)
- Предпочтительные значения для короткого и длинного идентификаторов — регистры S02 и S03. По умолчанию в данных регистрах записаны 0. Для координатора это значит, что при организации сети он автоматически сгенерирует подходящие значения. Для всех остальных устройств – подключаться к любой доступной сети. В противном случае, если значение регистров отлично от 0, то действуют следующие правила:
- координатор постарается присвоить новой сети соответствующие идентификаторы
- все остальные устройства будут пытаться подключиться к сети с заданными идентификаторами
Для координатора есть один важный момент: если при попытке создать сеть с предустановленными идентификаторами уже существует сеть с такими же параметрами, то совпадающие идентификаторы будут сгенерированы автоматически.
- Тип устройства — старшие 4 бита в регистре S0A. Типы устройств будут рассмотрены чуть позже. Сейчас скажем, что тип устройства определяется при подключении к сети и может быть изменен аналогичным способом с изменением выходной мощностью приемопередатчика.
4. Безопасность сети
В сетях ZigBee за безопасность отвечает специальный узел – Trust-центр. Координатор по умолчанию является Trust-центром. Также Trust-центром может быть любой роутер (FFD-устройство), в случае, если сеть создавалась в режиме распределенного Trust-центра (об этом будет рассказано в конце данной главы).
Список обязанностей Trust-центра:
- разрешение на подключение других устройств
- работа с ключами шифрования (периодическое обновление ключей, уведомление других узлов об обновлении ключа)
В сетях ZigBee используется два ключа:
- Link Key — данный ключ используется для установки защищенного соединения между двумя устройствам в сети для обмена данными. Ключ, который устройство получает в момент подключения к сети называется Trust Center Link Key, а все другие ключи, которые могут быть полученные в процессе работы устройства — Application Layer Link Keys. По умолчанию, Trust Center Link Key передается в открытом виде, что представляет дыру в безопасности, так как в момент подключения нового устройства к сети этот ключ можно перехватить
- Network Key — данный ключ используется для шифрования данных на сетевом уровне ZigBee стека. Он генерируется Trust-центром и периодически обновляется. Все устройства в отдельно взятой сети ZigBee имеют единый Network Key. С его помощью осуществляется шифрование всех сетевых пакетов. По умолчанию, Trust-центр передает Network Key зашифрованный с помощью Link Key
Чтобы предотвратить потенциальную компрометацию данных, передаваемых в сети, можно использовать несколько вариантов:
- передавать Link Key по нестандартному каналу связи/другому протоколу связи
- использовать предустановленный во все устройства ключ
- использовать механизм разрешения подключения на стороне Trust-центра (данный метод не защитит от компрометации, но зато чужие устройства не смогут участвовать в работе сети случайно или намерено)
В данной статье мы рассмотрим вариант с предустановленным Link Key. Минус данного подхода, это необходимость записи соответствующей конфигурации во все модули. Но для нашей маленькой сети это не критично. В стандартной прошивке модулей ETRX357 Link Key можно установить с помощью записи соответствующего значения в регистр S09. Кроме этого необходимо в регистре S0A установить в 1 следующие биты:
- бит 2 — установка в 1 принуждает узел передавать Network Key зашифрованным с помощью Link Key при попытке переподключения любых устройств
- бит 4 — -//- при попытке подключения новых узлов
- бит 8 — установка в 1 заставляет узел использовать предустановленный Link Key
ATS09=ABCDEFFEDCBACBAFEDDEFABCBAFEDCFF:password # задаем Link Key
# :password - пароль для обращения к защищенному регистру
ATS0A8=1
ATS0A4=1
ATS0A2=1
Установка битов 2 и 4 на всех узлах кроме координатора является необязательной процедурой. Плюсы данного подхода:
- нет необходимости в записи предпочтительного идентификатора (короткого и/или длинного) сети, которые узлы будут пытаться использовать для подключения. Устройства смогут подключиться только к сети с установленным Link Key
- злоумышленник не сможет получить Link Key, так как он не будет передаваться в открытом виде
- к сети не сможет подключиться «чужое» устройство
Укажем ещё на одну интересную возможность: в регистре S0A 9 бит отвечает за включение особой функции — создать сеть в режиме распределенного Trust-центра. В данном режиме работы любой роутер (FFD-устройство) может разрешить новым устройствам подключиться к текущей сети. Режим распределенного Trust-центра используется при развертывании больших сетей, чтобы избежать задержек на подключение всех беспроводных узлов. После того как сеть развернута, с помощью команды AT+BECOMETC выбирается Trust-центр, который будет заниматься регулированием политики безопасности. Чтобы обеспечить безопасность сети в данном режиме работы также необходимо позаботиться о предустановке/получении Link Key. В противном случае, пока не будет выбран Trust-центр, любое ZigBee-устройство потенциально сможет беспрепятственно подключиться к сети.
5. Типы ZigBee-устройств
В предыдущей статье были рассмотрены основные типы ZigBee-устройств. Напомним главные особенности и остановимся подробнее на типах конечных устройств:
координатор (COO) – устройство, которое организовало сеть. Участвует в процессе маршрутизации сетевого трафика, выполняет обязанности Trust-центра (кроме случая с режимом распределенного Trust-центра). Не уходит в спящий режим, поэтому такое устройство должно иметь стационарный источник питания
- роутер (FFD) — устройство, которое при подключении имело тип FFD (полнофункциональное устройство). Как и координатор такое устройство участвует в маршрутизации сетевого трафика и все замечания для координатора по поводу спящего режима справедливы и для роутера.
Перечисленные устройства выступают в качестве родительских узлов для конечных устройств. Максимальное число дочерних узлов у роутера или координатора может достигать 32. Родительские устройства отвечают за прием и хранение(*) сообщений для конечных устройств, которые подключены к ним. Конечные устройства, в свою очередь, общаются с сетью через родителей. Каждый раз, когда новое конечное устройство подключается к сети или же когда старое переподключается, для него определяется родитель, который делает запись в специальной таблице дочерних устройств. В этой таблице хранится короткий и длинный адрес дочернего узла и его тип. Рассмотрим доступные типы конечных устройств:
конечное устройство (ZED) — устройство, которое не участвует в работе сети по маршрутизации трафика, подключении новых устройств и т.д. Для данного типа спецификация технологии ZigBee не предусматривает наличие спящего режима. Поэтому при описании родителя (*) означала, что они не хранят сообщения для ZED-устройств. Предполагается, что у ZED-устройства приемник всегда включен и родительский узел сразу же по получении адресного сообщения переправляет его адресату. Так что данные устройства тоже должны иметь стационарный источник питания.
спящее конечное устройство (SED) — сетевые обязанности для данного типа устройств аналогичны предыдущему типу. Отличие лишь в поддержке спящего режима, который объявлен в спецификации технологии ZigBee. Такие устройства большую часть времени проводят в режиме сна и могут работать от батареечного источника питания длительное время. Определение «длительного времени» здесь зависит от приложения, но если рассмотреть пример с беспроводным ZigBee-выключателем, то срок работы такого устройства от одного комплекта дисковых батареек может составить 2-3 года[3]. Такие устройства выходят из спящего режима только по какому-либо внешнему событию (по прерыванию от таймера, чтобы оцифровать показания датчика; по нажатию на кнопку и т.д.) или же когда пришло время отправлять пакет данных. Для того, чтобы получать сообщения от родительского узла, спящие узлы используют Polling-механизм. О нем мы поговорим чуть позже.
- мобильное конечное устройство (MED) — аналог спящего конечного устройства (SED), с тем лишь исключением, что запись о нем в дочерней таблице родительского узла хранится непродолжительное время — от нескольких секунд до нескольких минут (для спящего конечного устройства время хранения записи может составлять до 48 дней). Это сделано, исходя из названия типа, для того, чтобы такое устройство могло перемещаться по помещению/объекту не вызывая коллизий при передаче сообщении. Коллизия может возникнуть, если у нескольких родителей будет запись об одном и том же узле. Данный тип устройства не описан в спецификации ZigBee и является типом расширения функций SED-устройства в реализации стека ZigBee от Silicon Labs.
Пример сети ZigBee
![](https://habrastorage.org/files/dfa/28d/42e/dfa28d42e5a941c09f98126fd49c4c82.png)
Конечные устройства всегда подключаются через FFD-устройство, которое на момент подключения имело наилучший показатель качества связи. В процессе работы может возникнуть ситуация, когда роутер вышел из строя или его забрали на сервисное обслуживание. В таком случае, после нескольких попыток восстановить связь с родителем, конечное устройство начнет поиск нового родительского узла. На рисунке связь между мобильным узлом и родителем обозначена пунктирной линией. Через определенный промежуток времени MED-устройство может присоединиться к сети через другого родителя.
Polling-механизм
Данный механизм используется в нескольких целях:
мобильные и конечные устройства таким образом могут получать сообщения, которые хранятся для них в родительском узле.
- предотвращение удаления записи о себе из таблицы дочерних устройств.
По спецификации ZigBee для спящих конечных устройств, адресные сообщения хранятся родителем ~7.68 секунды. Причем, если частота следования адресных сообщения для SED/MED-устройства выше указанного значения, то сообщения будут перезаписываться. Следовательно, для обеспечения надежной доставки данных спящее конечное устройство должно опрашивать родительский узел достаточно часто. В связи с этим для спящих конечных устройств существует два интервала опроса: Short Poll и Long Poll интервалы.
Short Poll интервал используется при ожидании подтверждения успешности транзакции, например, при отправке пакета с данными о показаниях датчика. Обычно данный интервал задается равным 1 секунде. После того, как подтверждение получено, устройство переходит в спящий режим и далее используется Long Poll интервал.
Long Poll интервал обычно задается в достаточно большим — от нескольких минут до нескольких дней. Это позволяет спящему конечному устройству сохранять место в дочерней таблице родителя. Родитель может вычеркнуть конечное устройство из своей таблицы, если оно не вышло вовремя на связь. В таком случае проспавшее свой момент конечное устройство обязано будет переподключиться к сети.
Более подробную информацию о Polling-механизме можно посмотреть в руководстве по ZigBee-стеку от Silicon Labs. В стандартной прошивке для модулей ETRX357 опрос родительского узла осуществляется по прерыванию от таймера/счетчика 0.
6. Создание сети сбора данных
Базовая теория рассказана, перейдем к практике. Для работы с радиомодулями ETRX357 будет использоваться модуль на Python. Все рекомендации по его использованию даны в сопутствующем README-файле.
6.1 Настройка ZigBee-устройств
Запишем в каждый узел соответствующую конфигурацию. Все три устройства — USB-шлюз и две отладочные платы — были подключены к компьютеру и каждое было соответствующим образом сконфигурировано:
- для USB-шлюза использовалась ветка координатора ("COO") из конфигурационного файла
- для модулей на отладочных платах — ветка спящих конечных устройств ("SED") из конфигурационного файла
#!/usr/bin/env python3
# coding=utf-8
import rfconf
import serial.tools.list_ports
def main():
# читаем конфигурацию из файла sensor_nwk.xml
configurator = rfconf.ModuleConfigReader("sensor_nwk.xml")
supp_nodes = configurator.get_avail_nodes()
supp_nodes = dict(enumerate(supp_nodes))
if len(supp_nodes) > 0:
print("Configuration XML file support {} nodes:".format(len(supp_nodes)))
print(supp_nodes)
# для всех устройств в описании которых есть "Telegesis"
for com in serial.tools.list_ports.comports():
if com.description.split()[0] == "Telegesis":
tgmodule = rfconf.ModuleInterface(com.device)
usr_choice = int(input("How would you like to configure that node: "))
tgmodule.set_node_type(supp_nodes[usr_choice])
tgmodule.write_config(configurator)
else:
print("There is nothing to do")
if __name__ == "__main__":
main()
<rfconfig>
<node type="COO">
<!-- Link Key -->
<reg name="S09" password="password" overwrite="y" type="string">
12341234123412341234123412341234
</reg>
<!-- Настройки безопасности -->
<reg name="S0A" password="password" overwrite="n" type="hex">
0114
</reg>
<!-- Выходная мощность передатчика -->
<reg name="S01" overwrite="y" type="int">
3
</reg>
<!-- Стать Sink-узлом -->
<reg name="S10" overwrite="n" type="hex">
10
</reg>
</node>
<node type="SED">
<!-- Link Key -->
<reg name="S09" password="password" overwrite="y" type="string">
12341234123412341234123412341234
</reg>
<!-- Настройки безопасности -->
<reg name="S0A" password="password" overwrite="n" type="hex">
0114
</reg>
<!-- Выходная мощность передатчика -->
<reg name="S01" overwrite="y" type="int">
3
</reg>
<!-- Включить автоматический поиск Sink-узла -->
<reg name="S10" overwrite="n" type="hex">
100
</reg>
<!-- Включение альтернативной функциональности PB5 -->
<reg name="S15" overwrite="n" type="hex">
2000
</reg>
<!-- Настройка портов ввода/вывода -->
<reg name="S13" overwrite="y" type="hex">
00FF7EFB
</reg>
<reg name="S16" overwrite="y" type="hex">
00008204
</reg>
<!-- Запись начального значения регистра S16,
которое будет действовать после сброса -->
<reg name="S17" overwrite="y" type="hex">
00008204
</reg>
<!-- Настройка портов ввода/вывода -->
<reg name="S18" overwrite="y" type="hex">
00FD58E7
</reg>
<!-- Запись начального значения регистра S18,
которое будет действовать после сброса -->
<reg name="S19" overwrite="y" type="hex">
00FD58E7
</reg>
<!-- Настройка таймера/счетчика 7 -->
<reg name="S37" overwrite="y" type="int">
40
</reg>
<reg name="S38" overwrite="y" type="hex">
8110
</reg>
<!-- Настройка переходов в различные режимы энергопотребления -->
<!-- Переход в режим 2 при подключении к сети -->
<reg name="S28" overwrite="y" type="int">
0003
</reg>
<!-- Переход в режим 0 при нажатии на кнопку 1 (PA0) -->
<reg name="S23" overwrite="y" type="hex">
0001
</reg>
<!-- Переход в режим 2 при нажатии на кнопку 2 (PA1) -->
<reg name="S24" overwrite="y" type="hex">
0003
</reg>
</node>
</rfconfig>
Несколько комментариев по поводу настройки спящих конечных устройств. Для того, чтобы минимизировать энергопотребление радиомодуля, необходимо отключить всю неиспользуемую периферию: светодиодную индикацию и питание датчика освещения. Кроме этого необходимо все неиспользуемые выводы сконфигурировать на вход с подтяжкой или выход. За настройку портов ввода/вывода отвечает несколько 32-разрядных регистров:
- регистр S13 вспомогательный регистр, позволяющий определить направление вывода (Hi-Z, вход с подтяжкой, push-pull выход, выход с открытым коллектором)
- регистр S16 настраивает определенный вывод в качестве входа (запись 0) или в качестве выхода (запись 1). Радимодуль имеет 3 порта A, B, C по 8 выводов. Запись настроек можно производить как записью отдельного бита, меняя каждый вывод по-отдельности, так и делать изменения сразу для всей группы. Регистр не является энергонезависимым, поэтому если необходимо постоянное применение определенной конфигурации, то её необходимо записать в регистр S17. Значение данного регистра автоматически переносится в регистр при подаче питания или при сбросе.
- регистр S18 задает логический уровень на выходе вывода. Если вывод настроен как выход, то запись 0/1 в определенный бит установит соответствующий логический уровень. Если вывод настроен как вход с подтяжкой, то запись 0/1 будет активировать подтяжку к питанию или к земле. Регистр S18 как и регистр S16 тоже не является энергонезависимым. Его начальное значение можно записать в регистр S19, значение из которого будет скопировано при сбросе.
Более подробную информацию по возможным настройкам портов ввода/вывода можно посмотреть в документации по AT-командам[2]. В конфигурационном файле для спящих узлов записано значение, которое отключает всю ненужную для нашей задачи периферию за исключением вывода, использующегося для питания датчика температуры, и входа АЦП. Для того, чтобы задействовать вход АЦП необходимо в регистре S15 установить бит 13 в 1 (задействование альтернативной функциональности вывода PB5). На отладочной плате установлен датчик температуры LM61.
![](https://habrastorage.org/files/0dd/d26/3ed/0ddd263ed9e9433592942f88e464b3bb.png)
6.2 Организация передачи данных на центральный узел сбора
Для того, чтобы спящие конечные устройства автоматически присылали данные на центральное устройство, воспользуемся встроенной функцией, которая может быть вызвана по прерыванию или событию. В нашей задаче мы хотим получать информацию о температуре через определенные интервалы времени. Поэтому необходимо воспользоваться одним из встроенных таймеров, который и будет вызывать встроенную функцию. Пусть прерывание от таймера/счетчика 7 будет возникать каждые 10 секунд. Для задания порога срабатывания таймера/счетчика 7 используется регистр S37. Пороговое значение в секундах определяется по следующей формуле:
![](https://habrastorage.org/files/f7a/b2f/612/f7ab2f612e044f3a8c911d09a9b9ba00.png)
Номер вызываемой по прерыванию от таймера/счетчика 7 функции записывается в регистр S38. Необходимая нам функция имеет номер 0110, которая отправляет данные о состоянии всех портов ввода/выывода, напряжении питания и оцифрованные значения АЦП на Sink-узел. Для того, чтобы она автоматически перезапускала таймер, необходимо старший бит (S38F) в регистре S38 установить в 1. Итоговое значение, которое необходимо записать – 8110. Об этой возможности встроенной прошивки можно почитать в документации[3]. Ниже дана краткая информация о том, что такое Sink-узел.
Sink-узлы
Каждое устройство в сети ZigBee имеет собственный уникальный короткий идентификатор (PANID). Координатор всегда имеет короткий адрес 0000 и очень часто именно его делают центральным узлом сбора данных. Однако, бывают случаи, когда координатором является устройство, не имеющее внешних интерфейсов (UART, SPI и т.д.) и требуется отправлять данный с датчиков на какой-то другой узел. Одно из решений – в собственном приложении, взаимодействующем с модулями ETRX357, вручную задать адрес устройства, которое будет собирать и обрабатывать поступающую информацию. Недостатки данного подхода:
- если используется короткий идентификатор при отправке адресных сообщений с данными:
- устройство сбора данных может при определенных обстоятельствах покинуть сеть и при переподключении ему будет выдан новый идентификатор
- короткий идентификатор выдается при подключении узла к сети. В связи с этим могут возникнуть сложности с настройкой узлов, которые должны передавать пакеты данных на узел сбора данных
- если используется длинный идентификатор при отправке адресных сообщений с данными:
- в случае замены узла сбора данных возникает проблема с обновлением длинного идентификатора во всех узла, в которых он использовался. Этот пункт справедлив и для случая использования короткого идентификатора
Для того, чтобы упростить механизм отправки данных на определенные узлы в сети, в стандартной прошивке модулей ETRX357 имеется специальная надстройка — стать Sink-узлом — которую может задействовать любой роутер в сети. Чтобы сделать роутер Sink-узлом, 4 бит в регистре S10 необходимо установить в единицу. Во всех узлах, которые используют встроенные функции, отправляющие данные на Sink, или же желающие использовать специальную команду для отправки сообщений на Sink, необходимо установить 8 бит в регистре S10 или использовать команду AT+SSINK для осуществления поиска ближайшего Sink-узла. Sink-устройство периодически отправляет широковещательные сообщения в сеть и все узлы, получившие его, делают запись в своей адресной таблице. В случае большой сети, вводят несколько Sink-узлов, которые принимают данные от ближайших соседей. Устройства, отправляющие данные на Sink-узел, автоматически выбирают наиболее подходящий узел сбора данных, используя информацию о качестве связи. Это позволяет разгрузить устройства сбора данных, а также предотвратить сбои в получении данных, так как в случае выхода из строя одного из Sink-узлов сеть автоматически перестроит маршруты.
После этого можно отправлять данные на Sink с помощью команды AT+SCAST:
# отправка сообщения на Sink
AT+SCAST:Hello
# (для примера) отправка обычного адресного сообщения
AT+UCAST:CAFE=Hello
AT+UCAST:000D6F00024CBCCC=Hello
6.3 Снижение энергопотребления спящих устройств
По умолчанию все модули находятся в режиме энергосбережения 0, независимо от задаваемого типа. Переход в спящий режим и обратно можно реализовать с помощью вызова соответствующей встроенной функции по какому-нибудь событию.
Энергопотребление модулей в различных режимах
![](https://habrastorage.org/files/362/3d4/9ec/3623d49ec6464bf6bef5f358b7c6f1dd.png)
Пусть спящие устройства переходят в режим энергосбережения 2 при подключении к сети (регистр S28). Обратите внимание, что модули, находящиеся в режимах 2-4, не отвечают на команды, отправленные по последовательному интерфейсу UART. В связи с этим необходимо предусмотреть возможность перехода модуля в режим 0 и обратно, для того, чтобы была возможность внести изменения в конфигурацию устройства или в логику его работы. Однако, есть возможность настроить выход из сна с помощью отправки символа по интерфейсу UART (более подробно см. описание регистра S11). На отладочных платах есть 4 кнопки, каждая из которых может активировать определенную встроенную функцию по прерыванию. Мы будем использовать кнопки 1 и 2 (выводы PA0 и PA1). Команды для задания соответствующей конфигурации:
# Функция, переводящая модуль в режим 0 - 0001
# Функция, переводящая модуль в режим 2 - 0003
# Переход в режим 2 при подключении к сети
ATS28=0003
# Переход в режим 0 при нажатии кнопки 1
ATS23=0001
# Переход в режим 2 при нажатии кнопки 2
ATS24=0003
Ниже приведены графики энергопотребления для спящих конечных устройств в различных режимах работы:
![](https://habrastorage.org/files/5e6/795/518/5e67955187984b0091f6b4d4f5651564.png)
![](https://habrastorage.org/files/f5f/d71/9b8/f5fd719b801e460b94ae834427d8e4d4.png)
![](https://habrastorage.org/files/c2c/22f/833/c2c22f833ebd4367af0d02126c62c461.png)
![](https://habrastorage.org/files/d6d/1d5/a1c/d6d1d5a1c9994abbbe3094042aaac6c3.png)
Пики, идущие с интервалом 1 секунда, это работа Polling-механизма. Этот интервал может быть увеличен или уменьшен, в зависимости от того, требуется двусторонний канал связи или нет. Интервал в 1 секунду позволяет гарантировать надежную доставку адресных сообщений на спящие устройства. Увеличение Polling-интервала уменьшает среднее энергопотребление устройства, но и доставить сообщение для него будет сложнее.
![](https://habrastorage.org/files/e52/ebf/e4b/e52ebfe4b926480cbbf3755073364ff8.png)
6.4 Обработка данных
После того, как устройства сконфигурированы, необходимо отправить команду для организации сети координатору. В проекте на GitHub, в папке examples, есть файл sensor_nwk.py. В нем содержится простая реализация функций создания сети и обработки данных, поступающих на координатор. Для нашей задачи достаточно лишь перевести оцифрованные значения температуры в градусы Цельсия. После этого в консоль выводится информация об адресе устройства и полученной температуре. Также ничто не мешает добавить отправку полученных данных куда-то на сервер, где они будут отображаться в личном кабинете пользователя.
#!/usr/bin/env python3
# coding=utf-8
import rfconf
import serial.threaded
class TemperatureReader(rfconf.ETRXModuleReader):
TEMP_POS = 2
NODEID_POS = 0
def handle_line(self, data):
if not data:
# пропускаем пустые строки
return
# формат получаемых данных от конечных устройств:
# SDATA: <Long ID>,<GPIO state>,<ADC0>,<ADC1>,<SeqNO>,<VCC>
info, *payload = rfconf.response_split(data)
if info == "SDATA":
nodeid = payload[self.NODEID_POS]
temp = int(payload[self.TEMP_POS], 16)
# преобразовываем значение АЦП в соответствие с
# документацией на LM61
temp = (temp / 10 - 600) / 10
print("Node: {} - Temperature: {:.2f}".format(nodeid, temp))
def leave_network(node):
LEAVE_NWK_CMD = "AT+DASSL"
node.write_command(LEAVE_NWK_CMD)
resp = node.read_resp()
# По умолчанию команда AT+DASSL после статусного сообщения "OK"
# выдает сообщение о том, что устройство успешно покинуло сеть "LeftPAN"
if resp[-1] == "OK":
msg = ""
while not msg:
msg = node.readline()
print(msg)
else:
print(resp[-1])
def get_network_info(coordinator):
NWK_INFO_POS = 1
GET_NWK_INFO_CMD = "AT+N"
coordinator.write_command(GET_NWK_INFO_CMD)
resp = coordinator.read_resp()
if resp[-1] == "OK":
nwk_info = resp[NWK_INFO_POS]
*nused, ch, txpower, panid, longid = rfconf.response_split(nwk_info)
print("network already created - ", end="")
print("ch: {}, PANID: {}, EUI64: {}".format(ch, panid, longid))
def create_network(coordinator):
NWK_INFO_POS = 1
NWK_PARAMS_POS = 1
CREATE_NWK_CMD = "AT+EN"
coordinator.write_command(CREATE_NWK_CMD)
resp = coordinator.read_resp()
if resp[-1] == "OK":
# Сеть успешно создана
nwk_info = resp[NWK_INFO_POS]
info, ch, sid, lid = rfconf.response_split(nwk_info)
print("network is created - ", end="")
print("ch: {}, PANID: {}, EUI64: {}".format(ch, sid, lid))
else:
# Проблемы с созданием сети - либо она уже была создана,
# либо координатор не может создать сеть с заданными параметрами
get_network_info(coordinator)
def main():
coo_node = rfconf.ETRXModule("<COMXX координатора (Windows) или /dev/<ttyUSBXX> (Linux)>", node_type="COO")
reader = TemperatureReader(coo_node)
# отправляем команду на создание сети
create_network(coo_node)
ser = coo_node.get_serial_interface()
reader_thread = serial.threaded.ReaderThread(ser, reader)
# читаем и обрабатываем поступающие данные
with reader_thread as protocol:
reader_thread.join()
if __name__ == "__main__":
main()
![](https://habrastorage.org/files/b95/77b/9ab/b9577b9ab6e349528c97d49db7811ea6.png)
7. Заключение
В данной статье мы разобрали процесс создания простой сети сбора данных, которая передает информацию от датчиков температуры на центральный узел сбора данных. Были разобраны основные особенности настройки ZigBee-радиомодулей для энергоэффективной и безопасной передачи информации. Как вы могли видеть, со стандартными настройками Polling-механизма и включенным датчиком температуры энергопотребление устройства составило ~250 мкА. При емкости источника питания 1 Ач, автономное время работы беспроводного устройства может составить до 4000 часов (~160 дней). А если провести дополнительные оптимизации, то это также позволит продлить срок службы. Также были рассмотрены возможности встроенных функций, которые для нашей задачи позволили обойтись без внешнего микроконтроллера.
Буду признателен, если в комментариях вы укажете на моменты, которые остались непонятными после прочтения данной статьи. В этом случае я смогу её дополнить. Если у вас возникнут вопросы, присылайте их мне на почту или пишите в комментариях.
P.S. Измерение энергопотребления спящих конечных устройств были выполнены с помощью утилиты Energy Profiler, входящей в состав пакета Simplicity Studio, и отладочной платы EFM32GG-STK3700 с Advanced Energy Monitor. Подробности можно почитать в Application Note от Silicon Labs. Данная утилита помимо энергопотребления устройства, получаемое через отладочную плату STK3700, позволяет отслеживать какие именно функции в вашем коде являются наиболее энергозатратными при выполнении. Только для активации функции профилирования кода требуется наличие SWO интерфейса у целевого устройства.
Список литературы
- Описание модулей ETRX357 без усилителя и с усилителем
- Руководство по AT-командам стандартной прошивки модулей ETRX357
- Описание ZigBee-выключателя, работающего от батареек от Silicon Labs
- Описание отладочного комплекта ETRX3DVKA357
Список статей
- Беспроводные сети ZigBee. Часть 1 [Вводная]
- Беспроводные сети ZigBee. Часть 2 [Работа с радиомодулями ETRX35X]
Полезные ссылки
- Видео о технологии ZigBee
- Python-модуль для работы со встроенной прошивкой ETRX357