В предыдущей статье мы достаточно кратко рассмотрели организацию и процессинг 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 командами его записывает.


Логика следующая:


  1. Инициализируем устройства
  2. Подключаемся к WiFi
  3. Читаем показания датчиков
  4. Подключаемся к MQTT брокеру и отправляем показания в соответствующие топики
  5. Выключаем 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)


  1. Ivanii
    06.07.2018 09:19

    Наверно лучше вместо LM2576 использовать китайский модуль на MP2307, а если устройство большую часть времени спит то LD1117.


    1. iv_s
      06.07.2018 10:36
      +1

      Для питания подойдет любой китайский stepdown модуль, притом достаточно 1A выдавать, MP2307 так же жирно по максимальному току как и использованный LM2576, оба на 3А. Просто была кучка LM2576 их и взял.
      Про LD1117 в статье отметил:)

      Но все, что понижает линейный преобразователь — он просто рассеивает в тепло. Пиковый ток esp8622 около 0.4A, это значит с линейным преобразователем (9-3.3)*0.4 = 2.28Вт в никуда. Еще и расплавится.


      Для батарейного питания линейные преобразователи слишком дорого, если и использовать, то не с кроной, а с четырмя AA/AAA батарейками, например. Ну или преобразователь в корпусе TO220 с хорошим таким радиатором:)

      Отдельно замечу, что вообще-то wifi решение — не сильно про батарейку, слишком большое потребление. Обычно канал связи на низкопотребляемых протоколах, LoRa, SigFox, BLE и прочих с копеечным потреблением.

      Мотивация этого мини проекта — получить готовую «вещь» на очень популярном и просто программируемом(в том числе для желающих повторить) для использования в дальнейшем
      описании IIoT инфраструкуры.


      1. Ivanii
        06.07.2018 13:39

        Про 1117 я написал в случае большого процента сна, например 300 секунд сна 10 секунд работы, собственное потребление недорогих ШИМ достаточно велико.
        Также при небольшой разнице вход — выход может оказаться выгоднее линейный стабилизатор.


        1. iv_s
          06.07.2018 14:25

          Только не 1117, а какой-нибудь TPS78*, у 1117 5-10мА ток покоя. Как вечно горящий светодиод:)


      1. vasimv
        06.07.2018 17:37

        С китайскими модулями step-down надо быть осторожнее. Наткнулся тут недавно на то, что модули на MP2307 при отсутствии существенной нагрузки — сами по себе жрут почти 30-40 миллиампер. Для батарейного питания не подходят совершенно.


  1. sguslya
    06.07.2018 10:06
    +1

    Интересно спасибо за статью…
    Каким образом при помощи BPM можно помочь GPS, для навигации в здании (определить этаж).
    По относительной разнице давления при перемещении объекта пытаться предугадывать этаж?


    1. 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’.


  1. latonita
    06.07.2018 10:59
    +1

    Хочу вставить свои пять копеек по поводу mqtt topics и предложенного варианта /device_location/device_name/sensor, дабы не запутать впервые изучающих данную тему.

    Во-первых, первый слеш является лишним. Такое наименование может привести случайной путанице в дальнейшем. В данном случае первый уровень топика — ветка с пустым именем. Best practice — не использовать слеш впереди.

    Во-вторых, сама иерархия топиков не является чем-то зафиксированы протоколом. Каждый волен выбирать нотацию, которая удобнее всего подходит для конкретного применения. Желательно заранее продумать дальнейшее использование, деление на крупные кластеры ближе к корню. Для упрощения опроса датчиков, необходимо стандартизировать глубину вложенности данных и именование оконечных ветвей для задания wildcard подписок вроде +/sensors/+/+/temp

    Третье, чем короче названия, тем лучше. Передача данных с удалённых датчиков часто не бесплатна. Особенно, если их много.

    Четвёртое, идеальной структуры топиков продержаться возможно, только если делать каждый самому и с нуля. Либо заточить себя в жёсткую кабалу vendor lock-in. Большинство устройств не конфигурируются, ибо это ведёт к их удорожанию и удорожанию их внедрения. В итоге, вместо идеального соснового бора, всегда будет смешанный лес. Решается простейших способом, который сразу делает систему намного более гибкой — внедрение оркестратора-маршрутизатора, который получает данные как есть и пересылает далее как надо. Тот-же node-red прекрасно справляется с этой задачей.

    Ещё много чего можно добавить, как вспомню — напишу)


    1. iv_s
      06.07.2018 12:49

      Спасибо за дельный комментарий: ) Мы подумали, что было бы интересно собрать всех, кто занимается темой — сделали группу в телеграме. Если интересно, рады будем пообщаться: t.me/justiothings


  1. klivlend
    08.07.2018 22:13

    Спасибо большое за интересный материал! Совсем недавно начал заниматься данной тематикой и такой подарок!


  1. Spark9
    08.07.2018 22:13

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