quarta-feira, 4 de agosto de 2021

REDE MESH COM NINA W106 - ESP-MESH - ARDUINO PlatformIO

REDE MESH COM NINA W106 - ESP-MESH - ARDUINO PlatformIO


PARTE I

O objetivo deste BLOG é demonstrar como é possível utilizar o módulo NINA W106 para implementar um rede MESH. Foram utilizados 3 NINA W106 para os testes.

O ESP-MESH permite que vários dispositivos (nódulos) se comuniquem entre si sob uma única rede local sem fio. Neste guia, mostraremos como começar com a ESP-MESH usando o núcleo Arduino.

"O ESP-MESH é um protocolo de rede construído no topo do protocolo Wi-Fi. O ESP-MESH permite que inúmeros dispositivos (chamados de nós) espalhados por uma grande área física (tanto dentro como ao ar livre) sejam interligados sob uma única WLAN (Wireless Local-Area Network)."

ARQUITETURA DE REDE WI-FI ATUAL

Em uma arquitetura de rede Wi-Fi tradicional, um único nó (ponto de acesso – geralmente o roteador) está conectado a todos os outros nós (estações). Cada nó pode se comunicar entre si usando o ponto de acesso. No entanto, isso se limita à cobertura wi-fi do ponto de acesso. Todas as estações devem estar no intervalo para se conectar diretamente ao ponto de acesso. Isso não acontece com a ESP-MESH.

ARQUITETURA DE REDE ESP-MESH

Com o ESP-MESH, os nós não precisam se conectar a um nó central. Nós são responsáveis por transmitir transmissões uns aos outros. Isso permite que vários dispositivos se espalhem por uma grande área física. Os Nós podem se auto-organizar e conversar dinamicamente uns com os outros para garantir que o pacote atinja seu destino final de nó. Se qualquer nó for removido da rede, ele será capaz de se auto-organizar para garantir que os pacotes cheguem ao seu destino.

Biblioteca PainlessMesh

"PainlessMesh é uma verdadeira rede ad-hoc, o que significa que não é necessário planejamento, controlador central ou roteador. Qualquer sistema de 1 ou mais nódulos se auto-organizará em malha totalmente funcional. O tamanho máximo da malha é limitado (pensamos) pela quantidade de memória no heap que pode ser alocada ao buffer de subconsoções e, portanto, deve ser realmente muito alta." 

Arduino  PlatformIO (Instalação)

1) Baixe e instale o Visual Studio Code


2) Execute o Visual Studio Code


3) Na opção EXTENSIONS (canto esquerdo), procure por PlatformIO e Instale. Aguarde!

4) Uma vez instalado o PlatformIO, vá em PIO Home e crie um Novo Projeto e digite os parâmetros abaixo e então Finish


Aguarde alguns minutos para instalação do SDK. A instalação do SDK ficará em 

C:\Users\USER\.platformio>
e os fontes em
C:\Users\USER\Documents\PlatformIO\Projects\blink\src\main.cpp

5) Na opção EXPLORER você verá o projeto e o código fonte (Arduino Sintax). 


6) Observe o arquivo Platformio.ini que foi criado, você pode futuramente mudar para aceitar outro tipo de framework, como exemplo, ESP-IDF.

[env:nina_w10]
platform = espressif32
board = nina_w10
framework = arduino

Exemplo básico ESP-MESH (mensagens de transmissão)

Para começar com esp-MESH, vamos primeiro experimentar com o exemplo básico da biblioteca. Este exemplo cria uma rede de malha na qual todas as placas transmitem mensagens para todas as outras placas.

Experimentamos este exemplo com quatro placas NINA W106. Você pode adicionar ou remover placas. 

Copie o código abaixo para o Arduino  - PlatformIO

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-mesh-esp32-esp8266-painlessmesh/
  
  This is a simple example that uses the painlessMesh library: https://github.com/gmag11/painlessMesh/blob/master/examples/basic/basic.ino
*/

#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

  Scheduler userScheduler; // to control your personal task
  painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessageTASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  String msg = "Ola do no 1";
  msg += mesh.getNodeId();
  mesh.sendBroadcastmsg );
  taskSendMessage.setIntervalrandom( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

// Needed for painless library
void receivedCallbackuint32_t fromString &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n"frommsg.c_str());
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n"nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n"mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

  mesh.initMESH_PREFIXMESH_PASSWORD, &userSchedulerMESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  userScheduler.addTasktaskSendMessage );
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

Adicione em PlatformIO.ini

lib_deps = painlessmesh/painlessMesh @ ^1.4.5
    ArduinoJson
    arduinoUnity
    TaskScheduler
    AsyncTCP


Antes de carregar o código, você pode configurar o MESH_PREFIX (é como o nome da rede MESH) e as variáveis MESH_PASSWORD (você pode defini-lo para o que quiser).

Em seguida, recomendamos que você altere a seguinte linha para cada placa para identificar facilmente o nó que enviou a mensagem. Por exemplo, para o nó 1, altere a mensagem da seguinte forma:

Como funciona o código

Comece incluindo a biblioteca PainlessMesh.

#include "painlessMesh.h"

Detalhes MESH
Em seguida, adicione os detalhes da malha. O MESH_PREFIX se refere ao nome da malha. Você pode alterá-lo para o que quiser.

#define MESH_PREFIX "o que quiser"
A MESH_PASSWORD, como o nome sugere, é a senha do mesh. Você pode alterá-lo para o que quiser.

#define MESH_PASSWORD "suasenha"
Todos os nós na malha devem usar o mesmo MESH_PREFIX e MESH_PASSWORD.

O MESH_PORT refere-se à porta TCP na qual você deseja que o servidor mesh seja executado. O padrão é 5555.

# define MESH_PORT 5555

#define   MESH_PREFIX     "o que quiser"
#define   MESH_PASSWORD   "suasenha"
#define   MESH_PORT       5555

Agendador (Scheduler)

É recomendado evitar o uso de delay() no código de rede mesh. Para manter a malha, algumas tarefas precisam ser realizadas em segundo plano. Usar delay() interromperá essas tarefas e pode fazer com que a malha perca estabilidade/desmorone.

Em vez disso, é recomendado usar TaskScheduler para executar suas tarefas que são usadas no próprio painlessMesh.

A linha a seguir cria um novo Scheduler chamado userScheduler.

Scheduler userScheduler; // para controlar sua tarefa pessoal

Scheduler userScheduler; // 

painlessMesh

Crie um objeto painlessMesh chamado mesh para lidar com a rede em malha.

painlessMesh  mesh;

Crie tarefas

Crie uma tarefa chamada taskSendMessage responsável por chamar a função sendMessage() a cada segundo enquanto o programa estiver em execução.

Task taskSendMessageTASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

Envie uma mensagem para o Mesh

A função sendMessage() envia uma mensagem para todos os nós na rede de mensagens (broadcast).

void sendMessage() {
  String msg = "Ola do no 1";
  msg += mesh.getNodeId();
  mesh.sendBroadcastmsg );
  taskSendMessage.setIntervalrandom( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

A mensagem contém o texto “Ola do no 1” seguido pelo ID do chip da placa.

String msg = "Olá do nó 1";
msg + = mesh.getNodeId();

Para transmitir uma mensagem, basta usar o método sendBroadcast() no objeto mesh e passar como argumento a mensagem (msg) que deseja enviar.

mesh.sendBroadcastmsg );

Cada vez que uma nova mensagem é enviada, o código muda o intervalo entre as mensagens (um a cinco segundos).

taskSendMessage.setIntervalrandom( TASK_SECOND * 1, TASK_SECOND * 5 ));

Funções de retorno de chamada de malha

A seguir, várias funções de retorno de chamada são criadas e serão chamadas quando eventos específicos acontecerem na malha.

A função receivedCallback() imprime o remetente da mensagem (de) e o conteúdo da mensagem (msg.c_str ()).

// Needed for painless library
void receivedCallbackuint32_t fromString &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n"frommsg.c_str());
}

A função newConnectionCallback() é executada sempre que um novo nó se conecta à rede. Esta função simplesmente imprime o ID do chip do novo nó. Você pode modificar a função para fazer qualquer outra tarefa.

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n"nodeId);
}

A função changedConnectionCallback() é executada sempre que uma conexão muda na rede (quando um nó entra ou sai da rede).

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

A função nodeTimeAdjustedCallback() é executada quando a rede ajusta a hora, para que todos os nós sejam sincronizados. Ele imprime o deslocamento.

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n"mesh.getNodeTime(),offset);
}

Setup

Em setup(), inicialize o monitor serial.

void setup() {
  Serial.begin(115200);

Escolha as mensagens de Debug

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages


Inicialize a malha com os detalhes definidos anteriormente.

 mesh.initMESH_PREFIXMESH_PASSWORD, &userSchedulerMESH_PORT );

Atribua todas as funções de retorno de chamada aos eventos correspondentes.

  mesh.initMESH_PREFIXMESH_PASSWORD, &userSchedulerMESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

Finalmente, adicione a função taskSendMessage ao userScheduler. O Scheduler é responsável por lidar e executar as tarefas no momento certo.

userScheduler.addTasktaskSendMessage );

Por fim, habilite o taskSendMessage, para que o programa comece a enviar as mensagens para a malha.

taskSendMessage.enable();

Para manter a malha em execução, adicione mesh.update() ao loop().

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

Testes

Faça upload do código fornecido para todas as suas placas. Não se esqueça de modificar a mensagem para identificar facilmente o nó emissor

Com as placas conectadas ao seu computador, abra uma conexão serial com cada placa. Você pode usar o Serial Monitor ou um software como o PuTTY e abrir várias janelas para todas as placas.

Você deve ver que todos os fóruns recebem mensagens uns dos outros. Por exemplo, essas são as mensagens recebidas pelo Nó 1. Ele recebe as mensagens dos Nó 2, 3 e 4.

ESP-MESH Básico Exemplo 4 Placas Arduino Serial Monitor

Testes com 4 NINA W106


2 NINA W106

3 NINA W106

Duvidas:
suporte@smartcore.com.br

REFERÊNCIAS
https://github.com/espressif/esp-mdf
https://github.com/espressif/esp-mdf/tree/master/examples/get-started
ESP-MESH with ESP32 and ESP8266: Getting Started | Random Nerd Tutorials

Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br

 

Nenhum comentário:

Postar um comentário