Рубрики
Проекты на ESP8266

Создание Mesh сети между модулями ESP32 и NodeMCU ESP8266

Стремительно развивающиеся технологии интернета вещей (Internet of Things, IoT) приводят к значительному ежегодному увеличению количества устройств, подключающихся к сети Интернет. В этих условиях обычный домашний роутер (router) уже может не справляться с подключением такого большого количества устройств. У большинства обычных роутеров количество подключаемых устройств не превышает 32. Решить данную проблему увеличения количества подключаемых устройств можно с помощью так называемого Mesh роутера или использовать технологию Mesh сетей (Mesh Network).

В данной статье мы рассмотрим создание и настройку Mesh сети на основе модулей ESP32 и NodeMCU ESP8266. Узлы нашей Mesh сети будут взаимодействовать с помощью технологии Wi-Fi. Один из наших модулей ESP будет подключен к ноутбуку, при помощи которого мы будем собирать данные со всех 4-х датчиков нашей сети. В нашей сети мы будем использовать как модули ESP32, так и модули ESP8266. Используя аналогичный подход, вы можете создать Mesh сеть на основе только модулей ESP32, или только модулей ESP8266.

Принципы работы Mesh сетей

Информационные сети, организованные по топологии Mesh, получили за последнее десятилетие широкое признание. Масштабы проектов выросли до тысяч точек доступа и десятков тысяч пользователей. Mesh-сети представляют наиболее интересные решения, интегрирующие различные сетевые и радиотехнологии, и потому в полной мере отвечают все более растущим требованиям абонентов (мобильность, QoS, безопасность).

Большинство существующих в настоящее время Mesh-сетей построены с использованием наиболее распространенного сейчас беспроводного стандарта Wi-Fi. Преимущества такого решения очевидны – широкий спектр дешевых стандартных абонентских устройств определяет коммерческую успешность проектов.

Mesh – это сетевая топология, в которой беспроводные устройства объединяются многочисленными (часто избыточными) соединениями, вводимыми по стратегическим соображениям. Это определение достаточно хорошо соответствует функциям развертываемых сетей такого класса.

Mesh-сети могут иметь как полносвязную топологию, в которой каждый узел соединен со всеми остальными узлами сети, так и частично связанную топологию, в которой каждый узел соединен с частью узлов сети.

Mesh-сети могут быть самоорганизующимися и настраиваемыми. В настоящее время, в основном, распространены самоорганизующиеся Mesh-сети.

Топология Мesh-сетей основана на децентрализованной схеме организации связи между активными узлами сети. Узлы доступа, используемые в Мesh-сетях, не только предоставляют услуги абонентского доступа, но и выполняют функции маршрутизаторов (ретрансляторов) для других узлов той же сети. За счет этого появляется возможность создания больших зон покрытия сети с взаимозаменяемыми активными узлами, высокую отказоустойчивость сети, а также возможность масштабирования (в этом случае новые узлы добавляются в сеть автоматически).

Достоинства Mesh-сетей:

  1. Быстрое автоматическое развертывание и наращивание сети. В современных Mesh-сетях узлы могут автоматически присоединяться и покидать сеть в любое время. Подобные сети могут быть развернуты в любом месте даже при отсутствии инфраструктуры фиксированной сети.
  2. Самоорганизация, самовосстановление и само балансирование (нагрузки) сети. Mesh-сети обладают значительно большей устойчивостью чем традиционные беспроводные сети. Автоматическая конфигурация и маршрутизация позволяет сети быть самоорганизующейся и самовосстанавливающейся. Сеть продолжает функционировать даже если один или несколько узлов выйдут из строя.
  3. Увеличенная зона покрытия. Высокие скорости передачи данных требуют больших соотношений сигнал/шум. Однако, поскольку уровень сигнала уменьшается экспоненциально с увеличением расстояния, то в традиционных сетях не всегда удается обеспечить высокие скорости передачи данных для удаленных узлов. При этом в Mesh-сетях уровень сигнала восстанавливается с каждым скачком, поэтому теоретически зона покрытия такой сети может увеличиваться неограниченно при сохранении показателей качества функционирования для всех узлов.
  4. Определения местоположения узлов без использования технологии GPS.
  5. Низкие инфраструктурные и операционные расходы. В большинстве случаев Mesh-сети требуют для своего функционирования значительного меньшего числа транспортных (частотных) каналов, чем традиционные беспроводные сети, что значительно уменьшает расходы на развертывание сети. Поскольку Mesh-сети являются самоорганизующимися и самовосстанавливающимися, то это означает уменьшение расходов на администрирование, обслуживание и техническую поддержку подобных сетей – значительно меньших, чем в сотовых или других сетях с централизованной архитектурой.
  6. Устойчивое функционирование в условиях многолучевого распространения радиоволн, радиопомехах и отсутствии прямой видимости. За счет технологии множества скачков Mesh-сети позволяют обеспечить связь за препятствиями (нет прямой видимости) и устойчивы к радиопомехам и многолучевому распространению радиоволн.

Недостаток Mesh-сетей заключается в том, что они используют промежуточные пункты для передачи данных. Это может вызвать задержку при пересылке информации и как следствие снизить качество трафика реального времени (например, речи или видео). Вследствие этого часто вводят ограничения на количество точек доступа в одном кластере.

Как работает ESP-Mesh сеть

ESP-Mesh представляет собой самоорганизующуюся и само восстанавливаемую сеть. Ее официальную документацию можно прочитать на этой странице.

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

Теоретически, Mesh сеть может содержать неограниченное число узлов, но в данном проекте мы в целях упрощения ограничимся построением Mesh сети из 4-х улов. Узлами нашей сети будут модули ESP8266 и ESP32. Для их программирования для работы в режиме Mesh сети мы будем использовать библиотеку painlessMesh, доступную для Arduino IDE.

Необходимые компоненты

  1. NodeMCU ESP8266 – 2 шт. (купить на AliExpress).
  2. ESP32 Dev Board – 2 шт. (купить на AliExpress).
  3. Датчик BMP280 – 2 шт. (купить на AliExpress).
  4. Датчик DHT22 (купить на AliExpress).
  5. Датчик DS18B20 (купить на AliExpress).
  6. Макетная плата.
  7. Соединительные провода.
  8. USB кабель (для программирования и подачи питания).

Схема проекта

Схема Mesh сети на основе модулей ESP32 и ESP8266 представлена на следующем рисунке.

В данной схеме мы подключили датчики давления BMP280 к модулям ESP32, к одной плате NodeMCU ESP8266 мы подключили датчик температуры и влажности DHT22, а к другой – датчик температуры DS18B20 (более подробно про работу с ним вы можете прочитать в этой статье).

Внешний вид собранной конструкции проекта показан на следующем рисунке.

Объяснение программы для создания Mesh сети на основе модулей ESP32 и ESP8266

Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.

Для программирования модулей ESP32 и ESP8266 мы будем использовать среду Arduino IDE. Для написания программы мы будем использовать библиотеку Painless Mesh – с помощью нее мы и будем программировать логику работы нашей Mesh сети. Для установки данной библиотеки в Arduino IDE выберите пункт Sketch->Include Library->Manage Libraries и выполните поиск painlessMesh. После этого нажмите на install и данная библиотека будет установлена в вашу Arduino IDE. И, как показано на следующем рисунке, при установке данной библиотеки рекомендуется установить дополнительные компоненты для работы с ней. Установите их все.

В схеме нашего проекта мы использовали датчики DS18B20, DHT22 и BMP280. Библиотеки для работы с ними вы можете установить аналогичным образом (через пункт Sketch->Include Library->Manage Libraries).

Также вы их можете скачать по следующим ссылкам:

Примечание: код программы, который мы далее будем объяснять, используется для наших всех 4-х плат. Вы можете загружать его как в модули ESP32, так и в модули ESP8266.

Код программы для модуля, к которому подключен датчик BME280

Для загрузки кода программы в модули (у нас в проекте это модули ESP32 — Node_1 и Node_2), к которым подключены датчики BME280, раскомментируйте соответствующую строку #define BME_280 в начале программы.

Код программы для модуля ESP8266, к которому подключен датчик DHT

К одному из модулей ESP8266 (NODE_3) в нашем проекте подключен датчик DHT22. Аналогичным образом раскомментируйте в коде программы соответствующую строку для него.

Код программы для модуля ESP8266, к которому подключен датчик DS18B20

Аналогичным образом раскоментируйте в программе для этого модуля соответствующую строку.

Также, если вы хотите включить/выключить логи в программе, то снимите/поставьте комментарий к строке #define ENABLE_LOG.

Теперь приступим к рассмотрению всего кода программы. Вначале в коде программы мы подключим библиотеки painlessMesh и Arduino_JSON.

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

Далее инициализируем строковую переменную nodeName – с помощью нее мы будем идентифицировать узлы в нашей сети. Также инициализируем переменные вещественного типа для хранения данных температуры, влажности и давления.

Далее в программе мы будем использовать макросы #ifdef и #endif чтобы включить или исключить определенные части кода. Первая часть нашего кода для датчика BME280, ее мы начнем со строки #ifdef BME_280. Далее подключим библиотеки, необходимые для работы с данным датчиком. Затем создадим объект BME280I2C. После этого зададим переменные, с которыми будет работать объект нашего класса.

То же самое повторим и для датчика DHT22. Начнем код для него со строки #ifdef DHT22, подключим библиотеку DHT.h, зададим контакт, к которому подключен датчик и создадим объект класса DHT.

Аналогичным образом поступим и с датчиком DS18B20. Этот датчик требует для своей работы подключения библиотек OneWire и DallasTemperature. Также для работы с ним создадим объект OneWire и передадим адрес данного объекта в объект DallasTemperature (его мы также создаем).

Далее зададим параметры доступа к сети Wi-Fi – идентификатор сети, пароль и номер порта. Эти параметры должны быть одинаковыми для всех узлов внутри нашей сети.

Также создадим еще три объекта – Scheduler, painlessMesh и JSONVar.

Далее мы создадим задачу в виде потока, который будет всегда выполняться и вызывать функцию спустя некоторое время. Эта задача будет использоваться для передачи широковещательных сообщений (broadcast message) всем узлам в сети. В задаче у нас будет три параметра. Первый будет определять как часто задача будет вызывать функцию, второй будет задавать время жизни задачи (у нас это бесконечность), а третий содержит указатель на вызываемую функцию.

Затем мы запрограммируем функцию sendMessage() – она будет передавать сообщение всем узлам в сети. Эта функция будет вызывать другую функцию, которая будет возвращать строку JSON.

Далее мы запрограммируем функцию receivedCallback() – она будет выполнять действия при приеме сообщения. Если вы хотите что то делать с принимаемым сообщением, вам необходимо изменить код этой функции под свои задачи. У функции два параметра – идентификатор узла (node id) и сообщение в качестве указателя.

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

Далее запрограммируем функцию nodeTimeAdjustedCallback() – она будет вызываться для задания временных сдвигов (задержек), необходимых для «комфортной» работы нашей mesh сети.

Затем в функции setup() нашей программы мы инициализируем последовательную связь со скоростью 115200 бод и напечатаем имя узла. Таким образом мы в окне монитора последовательной связи будем контролировать работу нашей сети. Также мы зададим класс setDebugMsgTypes() для mesh объекта, который будет вести логи сообщений ERROR | STARTUP. Далее мы инициализируем нашу Mesh сеть при помощи передачи соответствующих параметров (SSID, пароля и номера порта) в функцию init(). Учтите, что данная функция также требует указателя на Scheduler (планировщик задач) чтобы работать правильно.

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

Далее мы добавим задачу в планировщик задач (task scheduler) и включим ее с помощью метода taskSendMessage.enable(). Когда эта команда выполнится, то разные задачи будут выполняться одновременно в фоновом режиме.

Также функция setup содержит все необходимые нам макросы ifdef and endif, которые используются для инициализации различных датчиков в нашем проекте. Вначале настроим датчик BME280. Мы в коде программы будем инициализировать его и проверять его версию поскольку датчики BME280 выпускаются в разных версиях.

И, наконец, мы сконфигурируем датчики DHT22 и DS18B20 с помощью соответствующих макросов ifdef и #endif.

В основной функции нашей программы void loop() мы не будем делать ничего кроме обновления нашей Mesh сети с помощью метода mesh.update(), который будет работать со всеми запрограммированными нами задачами. Эти задачи не будут работать если не использовать этот метод update.

Одна из основных функций в нашей программе – это функция construnct_json(), которая формирует (конструирует) JSON строку и возвращает ее вызываемой функции. Эту функцию мы начнем с вызова метода bme.read(), которая считает с датчика BME280 необходимые нам параметры. Далее мы разделим считанное значение давления на 100 чтобы получить значение давления в миллибарах. Затем мы инициализируем наш массив JSON и введем в него имя датчика, имя узла, данные температуры и давления и затем извлечем эти данные из массива с помощью функции JSON.stringify() для вывода их на экран и для возврата значения нашей функции construnct_json(). Также укажем макросы ifdef и endif для того чтобы включить или выключить лог наших параметров.

Аналогичные операции проделаем и для датчиков DHT22 и DS18B20.

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

Тестирование работы Mesh сети на основе модулей ESP8266 и ESP32

Для тестирования работы проекта мы подали питание на все наши модули ESP. Результаты работы проекта вы сможете увидеть в окне монитора последовательной связи. Пример выводимых данных в окно монитора последовательной связи вы можете посмотреть на следующем рисунке.

На представленном рисунке видно, что мы получаем данные от всех 4-х датчиков, что свидетельствует об успешном функционировании нашей Mesh сети. Более подробно работу проекта вы можете посмотреть на видео, представленном в конце статьи.

Исходный код программы (скетча)

Видео, демонстрирующее работу проекта

Источник статьи

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

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