Manual

do

Maker

.

com

Como fazer rede mesh com ESP8266 - Parte I

Como fazer rede mesh com ESP8266 - Parte I

Recentemente me perguntaram em um grupo do facebook sobre como fazer rede mesh com ESP8266, se era possível etc. Não tinha a resposta na hora e como não havia a necessidade atual ou iminente, não dei a devida atenção. Aí na última semana passei alguns dias escrevendo minhas anotações e estudos para transformar nesse post, mas infelizmente não consegui concluir a última etapa (presumo que seja a última etapa). De qualquer modo, decidi publicar pois desbravando esses passos iniciais, alguém pode conseguir finalizar e partilhar a solução. Nesse meio tempo tento escrever a parte II, resolvendo essa questão.

Introdução à rede mesh

Uma rede mesh é uma topologia de rede na qual cada nó da rede retransmite dados para a rede, isto é, todos os nós da rede distribuem dados na rede de forma cooperativa. Existem duas maneiras de retransmissão, sendo uma dela a técnica de flooding (com custo de banda) e a técnica de roteamento. Na técnica de roteamento o overhead é menor porque existe um caminho específico predefinido, como se fosse um jogo de tabuleiro; a origem tem que passar por A,B e C para chegar em D. Para inserir todos os caminhos possíveis, a ede deve permitir conexões continuas e deve reconfigurar-se em torno de paths quebrados; por exemplo, um ESP8266 sendo desligado. Esse já é o primeiro conceito dessa introdução que diferencia uma rede mesh de uma rede tradicional. Repare que até aqui não citei rede WiFi. Essas redes mesh são bastante difundidas em redes ZigBee e não me estenderei sobre essa rede porque nosso foco aqui é WiFi.

Rede mesh com ESP8266

Procurei no google images uma representação de rede mesh com ESP8266 para não ter que desenhar. Existem vários desenhos, mas esse tem alguns pontos interessantes.

A Espressif fez um ótimo documento sobre o suporte à rede mesh implementada no ESP8266 (bem, não é porque não conectei os nós que o documento não é bom). . No overview discorre-se sobre a situação em que a IoT necessita de um largo número de nós conectados a um mesmo gateway e nessa situação, a limitação está nesse roteador.

No desenho acima temos uma visão macro da rede mesh. Esses pontos representariam os principais pontos da interconexão de rede, de forma que muitos outros dispositivos poderiam estar conectados a partir desses pontos. A representação mais ampla e mais detalhada pode ser vista no próprio documento da Espressif, nesse desenho:

rede_mesh_com_esp8266-2.webp

Esse desenho mostra a área de cobertura em volta  dos nós. Mas enfim, com a topologia mesh você ampliará a área de cobertura em sua residência, permitindo atravessar desde a porta de entrada até o fundo do quintal de sua mansão  de forma fácil. Ou ainda, esparramar wifi pelos andares de seu prédio, de modo a permitir a implementação de uma estrutura de controle automatizada para IoT. Pelo menos é "o que eu acho", uma vez que não pude fazer a prova de conceito.

No modelo cooperativo simultâneo parece ser possível um certo tipo de alta disponibilidade (HA) com ESP8266, garantindo N origens do dado para 1 destino.

Diagrama de uma rede mesh

A rede é composta por diversos nós, tantos quanto desejado. Entre o roteador e os demais nós, há um ponto chave, chamado de "nó raiz", ou "root node". Abaixo dele, os dispositivos non-root nodes.

Após gravar a imagem, fiz a conexão serial ao ESP8266 e vi as mensagens de tentativa de conexão (com o demo_server rodando):

mesh_fail.webp

O "scan-ch:0" significa que o scan é feito em todos os canais. Se um canal for especificado, ele busca somente naquele canal. Eu não achei no código onde poderia mudar isso, mas provavelmente está na biblioteca que faz o link com o programa que compilamos.

Eu falo francamente que não faço ideia de quem é o nó raiz. Simplesmente conectei 2 ESP8266 esperando que eles se resolvessem entre sí. Não há também uma configuração que defina um nó.

Na rede mesh-online, o roteador conectado à internet permite o controle dos dispositivos na nuvem. A configuração padrão também não parece ser essa porque o ESP8266 não se conectou à minha rede.

As atribuições dos nós são bastante simples e bem definidas. O nó root recebe e envia pacotes, e também repassa pacotes vindos do servidor, aplicações mobile e nós abaixo do root. O demo_server deveria certamente juntar os nós. Fiz uma conexão a ele utilizando telnet na porta 7000.

Os non-root nodes tem duas características especificas.

Non-leaf node -  ele recebe e envia pacotes, bem como repassa os pacotes de ambos os lados da rede.

Leaf node: Somente recebe e envia pacotes, mas não os repassa.

O modo non-leaf é como um gateway, ou um firewall Linux fazendo forwarding. Já o leaf node é como uma estação se comunicando na rede, como se fosse por exemplo, um notebook.

Alcance da rede mesh com ESP8266 e características

A faixa de alcance está diretamente relacionada ao número de nós  da rede. Não importanto quantos dispositivos sejam enfim, todos os nós conseguem se conversar.

Uma rede mesh com ESP8266 pode ser programada para que os dispositivos se conectem automaticamente sem anúncio do SSID.

Uma rede mesh com ESP8266 pode  ser visível para que qualquer outro dispositivo se conecte à ela como um access-point comum.

Non-os SDK versus RTOS

Você tem duas opções de firmware para o ESP8266. Eu gosto de utilizar o Sming com o RTOS (Real Time Operating System), que disponibiliza um sistema de arquivos e a possibilidade de subir código parcial para o dispositivo. O sistema utilizado é o FreeRTOS, que é um sistema de tempo real multi-tarefa. Por fim, a interface AT é descartada nesse caso (afinal, quem quer um sistema operacional para trocar comandos AT?).

No caso de um non-os, o programa funciona de forma similar às microcontroladoras, usando timers e callbacks. Nesse caso, o usuário deve programar de acordo com as regras do espconn network interface e ter um pouco mais de cuidado para não gerar resets por WDT.

Eu particularmente prefiro utilizar Sming com RTOS, mas nesse caso em específico será necessário trocar o sistema por um Non-OS para poder implementar o Mesh_Demo.

Mãos à obra

Se você ainda não tem o cross-compiler, inicie desse ponto. Instale as dependedências prévias:

apt-get install git autoconf build-essential gperf bison flex texinfo libtool libncurses5-dev wget gawk libc6-dev-amd64 python-serial libexpat-dev

E siga também com a preparação do diretório de instalação:

mkdir /opt/Espressif
chown SeuUsuario /opt/Espressif/

E agora instale o Xtensa, já  como usuário comum, dentro do diretório /opt/Espressif

cd /opt/Espressif
git clone -b lx106 git://github.com/jcmvbkbc/crosstool-NG.git 
cd crosstool-NG
./bootstrap && ./configure --prefix=`pwd` && make && make install
./ct-ng xtensa-lx106-elf
./ct-ng build
PATH=$PWD/builds/xtensa-lx106-elf/bin:$PATH

O penúltimo passo foi o mais demorado, de fato.

Alguns dos links que estavam dispostos nesse artigo não estão mais disponíveis. Porém, há diversos projetos de rede mesh mais atuais. Vá ao GitHub e faça uma pesquisa.

Agora estamos munidos das ferramentas necessárias para nosso objetivo e podemos seguir. Primeiro, entre nesse link e pegue o ESP Mesh Demo, no menu "SDKs & Demos". Já aproveite para pegar o que mais lhe interessar, incluindo as referências da API.

Sugiro fortemente o download do guia do usuário nesse link. Nesse guia do usuário encontram-se códigos de exemplo, mas a mesh-demo no git deve ser o suficiente.

Antes de seguir, execute o script "format.sh". Apesar do nome assustador, ele simplesmente fará a conversão dos arquivos com o programa dos2unix.

Inicie o server local usando o demo_server.py. Eu criei um diretório chamado 'esp' e coloquei os downloads lá dentro. No meu caso, está em '/mnt/esp':

cd /mnt/esp/ESP8266_MESH_DEMO/mesh_demo
python demo_server.py

Rapidamente o terminal ficará preso e então será exibida a mensagem 'mesh server works':

server_works.webp

Agora em 'include', edite o arquivo 'user_config.h' mudando inicialmente o IP para seu respectivo server (essa máquina onde você rodou o mesh_server), IP MESH_ROUTER_SSID e MESH_ROUTER_PASSWD. Coloque as credenciais de sua rede wifi (router e senha). O arquivo ficou assim:

#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__
#include "c_types.h"

#define MESH_DEMO_PRINT  ets_printf
#define MESH_DEMO_STRLEN ets_strlen
#define MESH_DEMO_MEMCPY ets_memcpy
#define MESH_DEMO_MEMSET ets_memset
#define MESH_DEMO_FREE   os_free

static const uint16_t server_port = 7000;                  /*PORT USED BY USER IOT SERVER FOR MESH SERVICE*/
static const uint8_t server_ip[4] = {192, 168, 1, 3};   /*USER IOT SERVER IP ADDRESS*/
static const uint32_t UART_BAUD_RATIO = 115200;             /*UART BAUD RATIO*/
static const uint8_t MESH_GROUP_ID[6] = {0x18,0xfe,0x34,0x00,0x00,0x50};  /*MESH_GROUP_ID & MESH_SSID_PREFIX REPRESENTS ONE MESH NETWORK*/
static const uint8_t MESH_ROUTER_BSSID[6] = {0xB0, 0x48, 0x7A, 0xB4, 0xE3, 0x30};
/*
 * please change MESH_ROUTER_SSID and MESH_ROUTER_PASSWD according to your router
 */
#define MESH_ROUTER_SSID     "MeuRoteadorTPLINK"      /*THE ROUTER SSID*/
#define MESH_ROUTER_PASSWD   "minhaSenha"    /*THE ROUTER PASSWORD*/
#define MESH_SSID_PREFIX     "DobitAoByte"    /*SET THE DEFAULT MESH SSID PREFIX;THE FINAL SSID OF SOFTAP WOULD BE "MESH_SSID_PREFIX_X_YYYYYY"*/
#define MESH_AUTH            AUTH_WPA2_PSK  /*AUTH_MODE OF SOFTAP FOR EACH MESH NODE*/
#define MESH_PASSWD          "123123123"    /*SET PASSWORD OF SOFTAP FOR EACH MESH NODE*/
#define MESH_MAX_HOP         (4)            /*MAX_HOPS OF MESH NETWORK*/

#endif

Agora o próximo passo; construir uma imagem. Simplesmente você deveria executar o gen_misc.sh contido no diretório mesh_demo, mas o script possui erros. Então montei um genMisc.sh com as opções recomendadas que estão na página principal do git.

#!/bin/bash
export SDK_BASE=$(dirname $(pwd))

boot=new
echo "boot mode: $boot"

app=0
echo "$app"

spi_speed=40
echo "spi speed: $spi_speed MHz"


spi_mode=QIO
echo "spi mode: $spi_mode"

spi_size_map=2
echo "spi size: $spi_size KB"
echo ""
echo "start..."
 
echo ""

make clean

make COMPILE=gcc BOOT=$boot APP=$app SPI_SPEED=$spi_speed SPI_MODE=$spi_mode SPI_SIZE_MAP=$spi_size_map

Dê permissão de execução a ele e então execute-o:

chmod 750 genMisc.sh
sh genMisc.sh

Eu obtive alguns erros, mas para resumir; se obtiver erros com a string.h, siga esses passos:

cd /opt/Espressif/crosstool-NG
wget -O lib/libc.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libc.a
wget -O lib/libhal.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libhal.a
wget -c https://github.com/esp8266/esp8266-wiki/raw/master/include.tgz
tar zxvf include.tgz

Mas se o header estiver faltando, outros faltarão. Eu vi que faltaram alguns headers dentro desse diretório.  Para não ficar pegando um a um, baixei um SDK convencional, criei um diretório comum e copie todo o include do SDK comum para o SDK da rede mesh:

mkdir trash
cp -r /exemplo/sdkComum/include/* trash
cp -r /exemplo/sdkMesh/include/* trash
cp -r trash/* /exemplo/sdkMesh/include/
rm -rf trash

Fiz o mesmo para lib e ld. Ao término da compilação, foi uma imensa satisfação!

Gravar o novo firmware no ESP8266

Os arquivos gerados devem ser passados para o ESP8266, mas primeiro faça uma limpeza nele para evitar problemas. Os passos ficam assim:

#link simbolico, ou...
sudo ln -s esptool-master/esptool.py /usr/bin/

#...adicionando diretorio ao path
export PATH=$PATH:$(pwd)/esptool-master
echo "export PATH=$PATH:$(pwd)/esptool-master" >>/etc/profile

#limpando a flash (desconecte e reconecte o dispositivo apos esse comando)
esptool.py --port /dev/ttyUSB0 erase_flash

# eu usei a imagem compilada com meu genMisc.sh
./esptool/esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0x00000 bin/eagle.flash.bin 0x40000 bin/eagle.irom0text.bin

A execução

Após a imagem gravada e o dispositivo reiniciado (já com o demo_server rodando) eu fiz uma conexão telnet ao ESP8266 e obtive aquela tela mais acima, onde ele faz o scan para tentar se conectar, sem sucesso de conexão.

O firmware está funcionando, aquelas mensagens sequer aparecem se o demo_server não estiver rodando.

Testei trocar o MAC do router, conforme encontrado no arquivo mesh_demo/include/user_config.h. Coloquei o MAC do TP-LINK, o MAC do meu notebook onde executo o demo_server e por fim, voltei o MAC padrão, presumindo que ele próprio seria um router.

Enfim, espero que você possa tentar resolver a questão e em caso de sucesso, postar em um de nossos grupos. De qualquer modo continuarei nessa empreitada até a dissolução do problema e coloco a parte II do artigo.

Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.