В предыдущей статье мы достаточно кратко рассмотрели организацию и процессинг IoT данных с помощью проекта Apache NiFi. Этой статьей мы открываем серию, в которой детально расскажем о каждом этапе, начиная от самих устройств и заканчивая DataLake платформой аналитикой, машинным обучением, предсказанием аномалий и т.д.
Сейчас же начнем с самого первого уровня, непосредственно “вещей”, букве T из аббревиатуры IoT. С самого устройства, организации канала связи и использования протокола MQTT. Тренду IoT уже несколько лет, но по большей части представление о нем, как о лампочке и розетке, включающейся с телефона. Но на производстве, добыче, и в различных других индустриях десятками лет используются самые разнообразные сенсоры, значения с которых собираются в производственные SCADA. Всего-то подключить поток данных к интернету, и мы получаем тот самый IoT, точнее IIoT — индустриальный интернет вещей.
Зачем это все нужно если все эти десятки лет SCADA успешно управляет производственным циклом?
Причин несколько:
- Расширяются возможности по применению датчиков, например логистика, где на конкретной фуре или вагоне установлен датчик местоположения, а также различные дополнительные, такие как расход топлива или время простоя(ждать на вокзале пока вагон прицепят) — все это уже выходит за локальную сеть производства
- Количество сенсоров на устройствах растет, они требуют более сложной обработки, что не всегда можно сделать мощностями предприятия
- Развившиеся благодаря росту вычислительной мощности возможности машинного обучения и искусственного интеллекта, что можно использовать для оптимизации производства, поиска узких мест, выявления аномалий
В итоге, датчики на производстве уже не просто отправляют значения в SCADA. Нужна программная архитектура, которая позволит построить построить цепочку от конечного сенсора на каком-либо станке до вычислительного облака, в котором, исходя из истории работы станка, с помощью обученной модели обслуживающему персоналу прилетит сообщение «37% вероятность выхода из строя механизма, нужно отправить инженера».
Ну а теперь назад, к вещам! Обычно для демонстрации таких систем используются открытые наборы исторических показателей датчиков какой-либо индустрии. Но к сожалению в таком варианте «пощупать» систему не получиться. Нет, на завод мы не заберемся, а вот свою простую «вещь с интернетом» сделаем.
Наша сфера деятельности связана с серверными инфраструктурами, но некоторыми хобби-электронными навыками все же обладаем, так что «вещь» будет самодельная.
Выберем самый простой вариант мониторинга — климатический датчик, будем собирать данные о температуре, влажности и давлении.
Компонентная база
В качестве датчика возьмем BMP280.
Очень навороченная вещь, предназначен не только для метеоданных, но и, благодаря чувствительному барометру, для помощи GPS, для навигации в здании (определить этаж), для игр в помощь акселерометру. Мы же будем использовать его только для метеоданных.
Возьмем в качестве модуля такой:
В качестве одновременно контроллера и канала связи возьмем, уже наверное культовую, esp8266 (https://en.wikipedia.org/wiki/ESP8266)
В нашем случае, модуль ESP-07:
В качестве питания — 9В батарейка «Крона». Так как все устройства работают от 3.3В — нужен понижающий преобразователь. Рука тянется поставить любимый всеми линейный LD1117:
Но все, что понижает линейный преобразователь — он просто рассеивает в тепло. Пиковый ток esp8622 около 0.4A, это значит с линейным преобразователем (9-3.3)*0.4 = 2.28Вт в никуда. Еще и расплавится.
Поэтому собрали импульсный понижающий преобразователь на LM2576:
3 ампера точно хватит всем (по-настоящему, что из компонентной базы было, то и припаяли).
Схема
В качестве CAD использовался Eagle, схема получилась такая:
Для запуска esp8622 нужно притянуть RESET и CH_PD к плюсу(включает модуль), GPIO15 к минусу. Когда GPIO0 притянут к земле — модуль переходит в режим программирования, поэтому там стоит перемычка.
GPIO02 и GPIO15 используются как SDA/SDL линии шины I2C для подключения BMP280, а также любых других устройств на шину(штырьковый разъем JP5), например, дисплея, для отладки прямо на месте.
JP1 используется для подключения по UART (через UART-USB преобразователь) к компьютеру для программирования и отладки модуля.
На резисторах R6 и R5 собран делитель напряжения для АЦП, чтобы можно было следить за зарядом батареи.
Плата
Разводка получилась такая:
Скорее всего, в лучших традициях хоббийной схемотехники, нарушает все возможные правила, но главное — работает :)
Само устройство получилось такое:
Плата изготовлена по лазерно-утюжной технологии (один из тысяч примеров: http://cxem.net/master/45.php).
Программирование устройства
Для быстрого старта для esp8622 взяли прошивку NodeMCU.
NodeMCU представляет из себя интерпретатор Lua для esp8622 и кучу библиотек для различных устройств, датчиков, дисплеев и т.п.
Чтобы прошить устройство, сначала нужно эту прошивку получить. Документация предлагает несколько вариантов, но самый простой из них — сервис nodemcu-build.com, который позволяет, просто выбрав нужные модули, получить готовую прошивку на почту.
Для нашего устройства обязательно нужно выбрать MQTT, I2C (т.к. на этой шине расположен датчик), ну и сам датчик BME280 (у нас BMP280, но библиотека универсальная), а также ADC для контроля за батареей. После сборки прошивки — сервис отправит ее на указанную почту.
Дальше нужно замкнуть GPIO0 на землю и перевести модуль в режим программирования (перемычка JP2), подключить USB-UART переходник и передернуть питание.
Загрузка прошивки выполняется с помощью NodeMCU PyFlasher. Нужно выбрать соответствующий последовательный порт, саму прошивку и для модуля ESP-07 — Quad i/O, остальные режимы работать не будут.
Немного терпения, пока прошивка завершится, потом снять перемычку JP2, передернуть питание и в итоге наше устройство готово к пользовательскому коду.
Код
Настройки UART для подключения — 115200 8N1, подключившись каким-нибудь терминалом для последовательного порта(например, terminalbpp) можно прямо вводить lua команды, этакий REPL.
Но нас все же интересует менее эфемерная прошивка, чтобы после перезагрузки оставалась:)
При запуске NodeMCU начинает выполнять с флеш карты файл init.lua (если он есть). Вот его и напишем.
За образец берем пример из документации:
Для загрузки мы использовали простенькую утилитку Asmodat ESP LUA Loader. Она просто пропихивает в терминал file.open и построчно Lua командами его записывает.
Логика следующая:
- Инициализируем устройства
- Подключаемся к WiFi
- Читаем показания датчиков
- Подключаемся к MQTT брокеру и отправляем показания в соответствующие топики
- Выключаем WiFi, засыпаем до следующего измерения
Lua скрипт, схему и разводку платы мы выложили, в принципе там все достаточно прозрачно.
Места которые хотелось бы отметить:
Вход ADC esp8266 требует напряжение в диапазоне от 0 до 1В и на выходе дает соответствующее число от 0 до 1024. Для резисторов 39кОм и 470кОм — коэффициент для пересчета получается примерно 13. Т.е. для того чтобы оценить (не очень точно измерить) напряжение на батарее — нужно полученное значение умножить на 13 и поделить на 1024.
Так как сенсор BMP280 универсальный, у него несколько вариантов конфигурации для разных применений. Для NodeMCU инициализация датчика для климатических измерений выглядит так (одни магические числа):
bme280.setup(1, 1, 1, 1, 7, 0) -- weather mode
Подробнее про эти числа в документации. Ну, и в датащите на BMP280, приведенном выше.
Так и не удалось уйти в режим Deep Sleep, по какой-то причине модуль не будится.
Библиотека для работы с MQTT достаточно специфическая, невозможно точно определить, когда закрывать соединение. В сообществе куча вопросов по этому поводу без какого-либо решения. Есть различные обходные пути, например как этой статье.
Но в нашем случае мы просто таймаутом ждем несколько секунд, а потом выключаем WiFi.
Также, поддержка TLS хоть и заявлена, но завести ее так и не удалось, данные отправляются нешифрованные.
Отправка данных
Раз в минуту модуль подключается к WiFi и отправляет MQTT брокеру показания с датчиков.
Топики в MQTT следующего формата:
/device_location/device_name/sensor
Это позволяет подписываться на потоки данных с сенсоров как по местоположению так и на конкретные сенсоры, например, температура за окном:
/outdoor/#/temperature
MQTT брокер
В качестве MQTT брокера мы используем Eclipse Mosquitto. Чтобы установить, например в Debian нужны два пакета: mosquitto и mosquitto_clients.
В /etc/mosquitto/mosquitto.conf нужно прописать
require_certificate false # отключаем tls
allow_anonymous true # пускаем всех:)
Дальше запускаем наше устройство, с помощью утилиты mosquitto_sub подписываемся на топики устройств, следим за погодой)
root@baikal:~# mosquitto_sub -v -t "/outdoor/#"
/outdoor/iottest/temperature 30.07
/outdoor/iottest/pressure 713
/outdoor/iottest/humidity 38.765
/outdoor/iottest/voltage 439
/outdoor/iottest/temperature 30.09
/outdoor/iottest/pressure 713
/outdoor/iottest/humidity 38.445
/outdoor/iottest/voltage 451
/outdoor/iottest/temperature 29.93
/outdoor/iottest/pressure 713
/outdoor/iottest/humidity 38.400
/outdoor/iottest/voltage 452
Baikal тут упомянут не просто так. Мы всё же географически расположены рядом с Байкалом, так что для базовой станции под устройства не было других вариантов, кроме как использовать BFK 3.1 на ядре Baikal T-1 :)
В последующих статьях перейдем к передаче данных, полученных от IIoT в систему аналитики и визуализации и расскажем об очередях. И про Baikal, конечно :)
Комментарии (11)
sguslya
06.07.2018 10:06+1Интересно спасибо за статью…
Каким образом при помощи BPM можно помочь GPS, для навигации в здании (определить этаж).
По относительной разнице давления при перемещении объекта пытаться предугадывать этаж?iv_s
06.07.2018 10:55+1Вот их листовка
Аппноутов к сожалению нет, но судя по настройкам барометра из документации, да, по разнице давления определять этаж.
Они позиционируются как дополнительный, «улучшающий» сенсор к мобильному устройству.
Что-то типа такого алгоритма:
— акселерометр показывает постоянное вертикальное ускорение и одновременно уменьшается давление — значит поднимаемся на следующий этаж.
— акселерометер показывает вертикальное направление, давление одинаковое но изменилась влажность — перешли в другую комнату.
Цитата из датащита на эту тему:
3.5.3 Indoor navigation
Lowest possible altitude noise is needed. A very low bandwidth is preferred. Increased power
consumption is tolerated. Humidity is measured to help detect room changes. This setting is
suggested for the Android settings ‘SENSOR_DELAY_NORMAL’ and ‘SENSOR_DELAY_UI’.
latonita
06.07.2018 10:59+1Хочу вставить свои пять копеек по поводу mqtt topics и предложенного варианта /device_location/device_name/sensor, дабы не запутать впервые изучающих данную тему.
Во-первых, первый слеш является лишним. Такое наименование может привести случайной путанице в дальнейшем. В данном случае первый уровень топика — ветка с пустым именем. Best practice — не использовать слеш впереди.
Во-вторых, сама иерархия топиков не является чем-то зафиксированы протоколом. Каждый волен выбирать нотацию, которая удобнее всего подходит для конкретного применения. Желательно заранее продумать дальнейшее использование, деление на крупные кластеры ближе к корню. Для упрощения опроса датчиков, необходимо стандартизировать глубину вложенности данных и именование оконечных ветвей для задания wildcard подписок вроде +/sensors/+/+/temp
Третье, чем короче названия, тем лучше. Передача данных с удалённых датчиков часто не бесплатна. Особенно, если их много.
Четвёртое, идеальной структуры топиков продержаться возможно, только если делать каждый самому и с нуля. Либо заточить себя в жёсткую кабалу vendor lock-in. Большинство устройств не конфигурируются, ибо это ведёт к их удорожанию и удорожанию их внедрения. В итоге, вместо идеального соснового бора, всегда будет смешанный лес. Решается простейших способом, который сразу делает систему намного более гибкой — внедрение оркестратора-маршрутизатора, который получает данные как есть и пересылает далее как надо. Тот-же node-red прекрасно справляется с этой задачей.
Ещё много чего можно добавить, как вспомню — напишу)iv_s
06.07.2018 12:49Спасибо за дельный комментарий: ) Мы подумали, что было бы интересно собрать всех, кто занимается темой — сделали группу в телеграме. Если интересно, рады будем пообщаться: t.me/justiothings
klivlend
08.07.2018 22:13Спасибо большое за интересный материал! Совсем недавно начал заниматься данной тематикой и такой подарок!
Spark9
08.07.2018 22:13я очень люблю тематику «интернета вещей». Но вот тут в статье я увидел термин «IIoT — индустриальный интернет вещей.» и сразу вспомнил фильм «Крепкий орешек 4», в котором, в эру кнопочных телефонов умудрялись по сюжету перенаправлять электроэнергию в определенный узел системы. И так приятно становится, что рано или поздно фантазии авторов воплощаются в жизнь.
Ivanii
Наверно лучше вместо LM2576 использовать китайский модуль на MP2307, а если устройство большую часть времени спит то LD1117.
iv_s
Для питания подойдет любой китайский stepdown модуль, притом достаточно 1A выдавать, MP2307 так же жирно по максимальному току как и использованный LM2576, оба на 3А. Просто была кучка LM2576 их и взял.
Про LD1117 в статье отметил:)
Для батарейного питания линейные преобразователи слишком дорого, если и использовать, то не с кроной, а с четырмя AA/AAA батарейками, например. Ну или преобразователь в корпусе TO220 с хорошим таким радиатором:)
Отдельно замечу, что вообще-то wifi решение — не сильно про батарейку, слишком большое потребление. Обычно канал связи на низкопотребляемых протоколах, LoRa, SigFox, BLE и прочих с копеечным потреблением.
Мотивация этого мини проекта — получить готовую «вещь» на очень популярном и просто программируемом(в том числе для желающих повторить) для использования в дальнейшем
описании IIoT инфраструкуры.
Ivanii
Про 1117 я написал в случае большого процента сна, например 300 секунд сна 10 секунд работы, собственное потребление недорогих ШИМ достаточно велико.
Также при небольшой разнице вход — выход может оказаться выгоднее линейный стабилизатор.
iv_s
Только не 1117, а какой-нибудь TPS78*, у 1117 5-10мА ток покоя. Как вечно горящий светодиод:)
vasimv
С китайскими модулями step-down надо быть осторожнее. Наткнулся тут недавно на то, что модули на MP2307 при отсутствии существенной нагрузки — сами по себе жрут почти 30-40 миллиампер. Для батарейного питания не подходят совершенно.