Manual

do

Maker

.

com

Rede mesh com Arduino e Raspberry usando NRF24L01

Rede mesh com Arduino e Raspberry usando NRF24L01

E finalizando a série, vamos ver a rede mesh funcionando. Mas primeiramente quero deixar claro alguns detalhes relacionados à estrutura.

Mesh com Arduino e Raspberry

Nem todos os sketches estão disponíveis para outra arquitetura como por exemplo, ESP8266. Utilizando o ESP8266 como gateway mesh eu percebi congelamentos e em alguns momentos, a perda da comunicação com o nó de testes. prefira o setup sempre com Arduino e se precisar fazer uma bridge, adicione um bluetooth ou um ESP8266 como slave (eca).

Conceito

Para quem não sabe, uma rede mesh funciona da seguinte maneira; um master e N slaves, sendo suportados até 254 nós ao master. O master é chamado de gateway (pelo menos em todos os casos que vi). O gateway é a saída (ou entrada) dos dados coletados dos N dispositivos. O master (ou gateway) deve ter o ID 0.

A rede mesh permite que dispositivos sejam endereçados pelo gateway, de modo que você não precisa se preocupar com o endereçamento de cada um dos nós ou a topologia da rede (sempre tem um "mas", descrito lá embaixo). Quando um nó está fora do alcance direto, ele faz uma rota através dos outros nós para então entregar os dados.

Os nós (slaves, não confundir com a quarta pessoa do verbo) podem tanto transmitir quanto receber dados e para isso o rádio permite a comunicação através de dois canais, tal como qualquer rede bidirecional. São chamados "pipes", controlados através de lógica implementada no sketch.

Quando um nó se perde, ele deve se reconectar automaticamente à rede (se possível) e essa lógica também é implementada pelo programador, no caso das bibliotecas que vamos utilizar.

Configuração do Raspberry Pi

Se você está acompanhando essa série de comunicação com o NRF24L01, deve ter lido o artigo anterior. Nele está disposta toda a configuração e uma comunicação simples (sem mesh) entre Arduino e Raspberry. No artigo anterior, o mais importante é que você consiga fazer o wiring e a configuração do dispositivo no Raspberry. Minha sugestão é que esteja com o sistema devidamente atuallizado, porque do jeito que está escrito no artigo anterior foi como procedi, sem problemas. Com versões mais antigas do sistema houve uma série de complicações que precisaram ser sanadas. Se por alguma razão você não pode atualizar seu Raspberry Pi, pode ser bom dar uma olhada nesse artigo também.

No artigo anterior também expliquei que o wiring está relacionado ao número dos pinos, mas o driver BMC referencia o GPIO, portanto atente-se à tabela para saber a que pinos deve conectar o NRF24L01 (na tabela no post anterior está especificado como RPi - P1 Connector). Na programação, referencie o número do GPIO, descrito na coluna RPI da mesma tabela:

pinout_many_boards.webp

Bibliotecas necessárias no Arduino

As bibliotecas necessárias podem ser encontradas diretamente no Library Manger da IDE do Arduino. Infelizmente não pude dedicar tempo suficiente para cobrir o funcionamento de forma satisfatória a garantir que você não terá nenhum problema, mas nessa prova de conceito está completamente funcional. Serão necessárias as seguintes bibliotecas:

rf24-libraries.webp

A RF24G é uma intrusa nessa lista, mas não havia como eliminá-la. Também, instalá-la não causará nenhum problema.

RF24Mesh

Não sei se todas as bibliotecas para rede mesh funcionam da mesma maneira, por isso vou citar diretamente a RF24Mesh e suas características.

Começando pelo endereçamento e roteamento para módulos de rádio frequência, ela permite uma larga rede de sensores, mas acredito que essa parte seja característica de qualquer rede mesh.

Os nós recebem uma assinatura numérica entre 1 e 255, sendo que 0 é reservado para o gateway. Tudo o que for relacionado a seu funcionamento também é definido pelo master, que além do endereço atribui rotas.

Quando um nó é movido fisicamente ou simplesmente perde a conexão com a rede (seja por problema de sinal, alimentação etc), ele pode ser configurado para automaticamente se juntar à rede mesh novamente e reconfigurar a sí próprio dentro da rede.

Característico de redes mesh, os nós podem ser movidos para longe do master, usando outros nós para rotear o tráfego sobre distâncias extendidas.

Recursos disponíveis na biblioteca em sua versão atual

Atualmente você encontrará os seguintes recursos:

  • Funcionalidade básica usando um Arduino ou RPi como nó master, com capacidade de enviar ou receber dados de outros nós.
  • Endereçamento dinâmico baseado em um identificador único pré assinado. Não tão bom, mas veremos mais a respeito.
  • Configuração de endereços dinâmico on-the-fly e da topologia de rede.
  • Roteamento automático e manipulação de dados. Os nós se juntarão para extender o alcance dos links de  rádio pelo roteamento de dados, conforme necessário.

 

Para o Arduino, basta instalar como supracitado. Para o Raspberry, um pouco mais de "braço" será necessário. Seguindo o tutorial anterior, você já terá em algum lugar do seu Raspberry o diretório RF24. Dentro do mesmo diretório que está o RF24, copie a RF24Network:

wget -c https://github.com/TMRh20/RF24Network/archive/master.zip

Descomprima o arquivo master.zip e se pretende guardá-lo, renomeie para o que desejar, mas não mantenha o mesmo nome ou ele será sobescrito.

Entre no diretório RF24Network e execute os seguintes comandos:

sudo su
make && make install
cd examples_RPi
make
./helloworld_rx
#ou...
./helloworld_tx

Resumidamente, você estará testando o funcionamento, nada de mais. O bom de executar esse programa é pelo fato da constatação de seu funcionamento (pelo menos em relação à comunicação com o dispositivo NRF24L01 no sistema):

gettingstarted-raspberry-nrf24l01.webp

Ctrl+C para finalizar o programa, não precisa ler ou escrever nada por enquanto.

Feito isso, agora desça um nível de diretório (cd ..) e copie a RF24Mesh; descomprima-a da mesma forma que foi feito com a RF24Network, então faça o que quiser com o arquivo baixado e em seguida suba para o nível de diretório criado.

wget -c https://github.com/TMRh20/RF24Mesh/archive/master.zip

E após entrar no diretório:

(se já não estiver como root)
sudo su
make && make install

Tem exemplo para RPi também. Adivinha?

cd examplesRPi && make && make install

Executar o primeiro teste com a rede mesh

Nesse ponto podemos considerar a configuração concluída. Tudo o que acontecer de anômalo daqui pra frente podemos considerar problemas. Execute o exemplo recém compilado RF24Mesh_Example_Master:

./RF24Mesh_Example_Master

Agora na IDE do Arduino, abra o exemplo **File > Examples > RF24Mesh >**RF24Mesh_example.

O sketch tem sua explicação no header, então para não me repetir:

/** RF24Mesh_Example.ino by TMRh20
 *
 * This example sketch shows how to manually configure a node via RF24Mesh, and send data to the
 * master node.
 * The nodes will refresh their network address as soon as a single write fails. This allows the
 * nodes to change position in relation to each other and the master node.
 */


#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>
#include <EEPROM.h>
//#include <printf.h>


/**** Configure the nrf24l01 CE and CS pins ****/
RF24 radio(7, 8);
RF24Network network(radio);
RF24Mesh mesh(radio, network);

/**
 * User Configuration: nodeID - A unique identifier for each radio. Allows addressing
 * to change dynamically with physical changes to the mesh.
 *
 * In this example, configuration takes place below, prior to uploading the sketch to the device
 * A unique value from 1-255 must be configured for each node.
 * This will be stored in EEPROM on AVR devices, so remains persistent between further uploads, loss of power, etc.
 *
 **/
#define nodeID 1


uint32_t displayTimer = 0;

struct payload_t {
  unsigned long ms;
  unsigned long counter;
};

void setup() {

  Serial.begin(115200);
  //printf_begin();
  // Set the nodeID manually
  mesh.setNodeID(nodeID);
  // Connect to the mesh
  Serial.println(F("Connecting to the mesh..."));
  mesh.begin();
}



void loop() {

  mesh.update();

  // Send to the master node every second
  if (millis() - displayTimer >= 1000) {
    displayTimer = millis();

    // Send an 'M' type message containing the current millis()
    if (!mesh.write(&displayTimer, 'M', sizeof(displayTimer))) {

      // If a write fails, check connectivity to the mesh network
      if ( ! mesh.checkConnection() ) {
        //refresh the network address
        Serial.println("Renewing Address");
        mesh.renewAddress();
      } else {
        Serial.println("Send fail, Test OK");
      }
    } else {
      Serial.print("Send OK: "); Serial.println(displayTimer);
    }
  }

  while (network.available()) {
    RF24NetworkHeader header;
    payload_t payload;
    network.read(header, &payload, sizeof(payload));
    Serial.print("Received packet #");
    Serial.print(payload.counter);
    Serial.print(" at ");
    Serial.println(payload.ms);
  }
}

Vamos às partes tristes primeiro. Não dá pra ser tão dinâmico quanto se deseja; cada nó deve ter um NodeID para se juntar à rede mesh. Se isso precisar ser configurado automaticamente, ficará por sua conta a implementação de um algorítimo que possa atribuir um número mágico para cada nó a entrar na rede. Considerando que não tem como adivinhar se esse número mágico já foi atribuido a outro nó, a opção viável é manter uma tabela dos dispositivos de cada rede. Não tem escapatória.

O nodeID é gravado na EEPROM dos dispositivos AVR, de modo a manter a persistência em caso de falhas, uploads, queda de energia and so on, and so forth.

O resto é liso, não tem quase nada de código. Você sempre poderá usar o sketch de exemplo como base, uma vez que ele tem implementado o tratamento de reconexão.

O exemplo do Raspberry já está em execução e aguardando por nós (não confundir "nós" com "a gente"). Suba o sketch no Arduino agora e veja a mágica acontecer:

https://youtu.be/E90VLBLgPsc

Inscreva-se no nosso canal Manual do Maker 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.