Montamos a rede ZigBee mais simples, programa sob Mbed, comunicamos através do MQTT

Este artigo é um ótimo workshop de treinamento básico sobre o uso do módulo XBee em conjunto com um microcontrolador que possui o Mbed OS. O ZigBee é um padrão longo e firmemente enraizado nos sistemas Smart Home (por exemplo, é usado junto com o Z-Wave no hub Samsung SmartThings, consulte o nosso artigo ), é caracterizado por baixo consumo de energia, facilidade de uso e, mais interessante, a capacidade de criar redes mesh autoconfiguráveis. Você verá no workshop que realmente é assim - examinaremos a estrutura dessa rede por meio de um utilitário visualizador conveniente.

Supõe-se que você já saiba o que é o ZigBee e para que serve. Agora você deseja conectar seu primeiro módulo XBee e resolver seus problemas, sem precisar programar o módulo, mas apenas usá-lo como interface de comunicação. No final, enviaremos todos os dados através de um gateway MQTT improvisado em qualquer lugar, mesmo para um servidor local, até para a Internet. Decidimos mostrar tudo no exemplo do Mbed como o RTOS mais simples e acessível para iniciantes. Você ficará convencido de que tudo funciona "pronto para uso" e poderá começar imediatamente a fazer seu projeto, mesmo antes de estar lidando apenas com o Arduino.



O manual consistirá nas seguintes partes:

  1. Conexão e configuração do módulo XBee
  2. Conecte os módulos à rede
  3. Configuramos o módulo sem removê-lo da blindagem
  4. Recuperação de dados
  5. Enviando dados
  6. Criando um Gateway MQTT Simples

Mas primeiro, uma lista de componentes: o que é desejável ter para fazer todas as opções acima.

Componentes Necessários


  • Duas placas compatíveis com Mbed. Recomendamos a placa de treinamento STM32 Nucleo como relativamente barata e popular para fins educacionais. O processo de programação é simplificado ao máximo: colete o programa em um IDE gratuito on-line, faça o download do firmware montado e "solte" na placa, que aparecerá no sistema como uma unidade flash. Qual modelo específico a ser adotado não é importante, mas não o modelo mais antigo, preste atenção à quantidade de memória. Por exemplo, F401RE - damos apenas por definição, para que você não se confunda com sua diversidade e, a princípio, códigos alfabéticos incompreensíveis de processadores STM.


  • XBee-. Digi. «» , , , MBee, , , , . / : , . / Pro: , , Pro .

  • XBee Shield V2 ( SeeedStudio). - , RX TX XBee-.

  • Um conversor USB-UART com conector para XBee. É necessário para a configuração inicial. Os módulos XBee não estão equipados com uma interface USB (eles não têm nada a ver com isso). O USB é necessário única e exclusivamente para a comunicação entre o módulo e o computador e, no dispositivo, ele pode funcionar em um UART muito mais simples.

    O espaçamento dos slots dos módulos XBee é de 2,0 mm - para os eletrônicos não é padrão no sistema métrico (costumamos ver a etapa 2.54 de acordo com os padrões americanos). Portanto, infelizmente, esses módulos não são inseridos na placa de ensaio e eles sempre precisam de um adaptador.

    Qualquer adaptador é adequado aqui, pegamos este da Waveshare:


Conexão e configuração do módulo XBee


A coisa mais simples que você pode fazer com o módulo é conectá-lo ao computador diretamente via USB. Nós teremos acesso imediato aos seus parâmetros de configuração.

Instale o XCTU


Para trabalhar com o XBee, existe um programa oficial do XCTU. Faça o download e instale. A documentação diz que no Ubuntu você precisa adicionar um usuário a um grupo dialoutpara trabalhar com portas que não são de um superusuário - faça isso se você ainda não o fez:

sudo usermod -a -G dialout <username>

Faça o download do arquivo zip a partir do link, ele conterá um arquivo .run. Ele precisa ser executável (via chmod +x _no console ou: botão direito do mouse - Propriedades - Permissões) e executado ./40002881_V.run.

É importante iniciar a instalação não a partir da raiz (sem sudo), caso contrário, haverá problemas mais tarde.

A configuração é mais ou menos assim:



Programa XCTU


Após a instalação, você pode iniciar o programa executando o arquivo appno diretório em que instalou o programa (por padrão - ~/Digi/XCTU-NG).
 
A aparência será a seguinte:



Neste programa, você pode adicionar o módulo existente conectado à porta USB através de um adaptador. Clique no botão Discover com uma lupa. Uma janela é exibida solicitando que você selecione uma porta - como você pode ver, o programa detectou corretamente a porta no sistema /dev/ttyUSB0, este é o nosso adaptador USB-UART.



A janela sugere marcar a pesquisa. Obviamente, existe uma tentação de verificar tudo de uma vez para encontrar com certeza o seu módulo. Mas a pesquisa continuará por um longo tempo. Na prática, faz sentido deixar as caixas marcadas por padrão e escolher as opções mais comuns para a velocidade de transferência de dados, como na figura abaixo. Geralmente, os novos módulos são padronizados para 9600 e, para fins de treinamento, isso é mais do que suficiente, a velocidade aqui não é crítica para nós.



Como resultado, se tudo der certo, você será solicitado a selecionar o módulo encontrado:



Um pequeno erro foi notado: às vezes o módulo não estava em uma velocidade não padrão, a redefinição manual do módulo com o botão Redefinir durante a pesquisa e a redefinição da taxa de transmissão para o padrão (9600) ajudaram.

Alterar parâmetros do módulo


Além disso, estamos envolvidos na configuração do módulo. Muitos parâmetros serão eliminados, a maioria dos quais é inicialmente incompreensível. Felizmente, apenas alguns deles precisarão ser alterados para um início rápido.

ID de rede - PAN ID. Uma chave de rede comum, deve ser a mesma para todos os dispositivos para que eles estejam conectados à rede de forma independente. Coloque qualquer número, no nosso caso, fizemos 42.



CE - Coordenador ativado. Se houver 1, esse módulo atua como coordenador. Se for 0, o módulo atua como um roteador (roteador) - na verdade, ele simplesmente garante que os pacotes passem pela rede por si próprios. A maioria dos hosts geralmente são roteadores. Precisamos de um coordenador e dois roteadores em nossa rede, então coloque um aqui.

Há também a função "Dispositivo final" - este é um módulo que não realiza trabalhos de transferência de pacotes, mas apenas se comunica com outros roteadores e executa sua funcionalidade útil. Geralmente, ele está no modo de suspensão e acorda em intervalos definidos e descobre se há alguma mensagem. Esse módulo pode ser alimentado por uma bateria, enquanto o roteador e o coordenador devem estar sempre “online” e, como resultado, precisam de energia constante para manter toda a rede. Não consideraremos esse exemplo agora, pois é mais interessante para todos atribuir a função de roteadores e observar como a rede mudará automaticamente sua configuração.



AP - API ativado.Modo de operação. Os módulos XBee podem operar em dois modos: AT ou API. O modo AT é mais fácil para iniciantes, é uma substituição transparente da porta serial e trabalha com o módulo através dos comandos AT. No entanto, o modo API é muito mais rico em funcionalidades, permite configurar módulos remotamente, contém o endereço do remetente, retorna o status de entrega do pacote e muito mais. Além disso, as bibliotecas para interagir com o XBee pressupõem que o dispositivo seja usado no modo API. Portanto, substitua-o imediatamente pelo modo API, isso é feito configurando a unidade no campo correspondente.



O nome do módulo é Node Identifier. Uma opção útil para dar ao seu módulo um nome legível por humanos. Vamos dar esse nome - coordenador.



Depois disso, você pode atualizar as configurações no módulo pressionando o botão com um lápis:



2. Conecte os módulos à rede


Agora veremos que tipo de rede obteremos se configurarmos três módulos. O programa XCTU possui um visualizador de rede bastante conveniente, veremos claramente a topologia.

Vamos configurar todos os três módulos por vez, com os seguintes parâmetros:
  • PAN ID - número total, por exemplo 42
  • AP (API ativado) - definido como 1 (funciona no modo API)
  • NI (Node Identifier) ​​- forneça nomes compreensíveis aos módulos (coordenador, lâmpada e interruptor, se estivermos executando, por exemplo, um modelo do sistema Smart Home).
  • CE (ativação do coordenador) - defina um dos módulos como 1, ele será o coordenador.

Em seguida, aplique energia a todos os módulos. Posicione-os assim: o coordenador estará no conversor USB-UART e os outros dois (roteadores) estarão localizados nas placas XBee Shield na parte superior do Nucleo.

Se você fez tudo com cuidado, o belo vai acontecer. Os módulos se conectam automaticamente à rede. Você pode se comunicar com roteadores remotamente através do coordenador.

Se parece com isso. Clique no botão "Descobrir nós de rádio na mesma rede".



Você verá que dois módulos foram detectados e adicionados automaticamente:


E você pode alterar seus parâmetros em tempo real! 

O que ainda é ótimo: agora você pode ver o mapa de rede se alternar para o modo de trabalho em rede no canto superior direito.



Depois de espalhar os nós da rede com o mouse, você verá um triângulo. Observe que o tráfego para o módulo mais à direita pode ser de duas maneiras. E se você mover os módulos no espaço, verá que a imagem mudou e agora, talvez, outro módulo se tornará "extremo". Essa é a essência de uma rede autoconfigurável.

3. Configure o módulo XBee sem removê-lo da blindagem


Obviamente, será mais interessante trabalhar com o módulo XBee não através de um computador, mas controlando-o usando um programa no microcontrolador. Ou seja, conectá-lo à placa STM32Nucleo.
Vamos discutir como o módulo XBee pode se comunicar com o microcontrolador. E vamos começar com uma pequena tarefa: como configurar um módulo sem removê-lo do escudo de expansão? Você deve admitir que mover o módulo para a frente e para trás é inconveniente, ao mesmo tempo em que você deseja experimentar os parâmetros e é estranho por que você precisa de um módulo USB-UART separado, porque, em teoria, existe um na placa STM32Nucleo.

A solução é simples: precisamos transformar a placa Nucleo em uma ponte entre o módulo XBee e o conversor USB na placa.

Descrição geral da ideia


O microcontrolador STM32 que usamos possui várias interfaces UART a bordo. Cada uma dessas interfaces representa um canal de comunicação. Um deles está conectado ao conversor USB-UART para que possamos nos comunicar com o computador via USB no terminal. Dois outros ainda não são usados. Vamos conectar o módulo XBee a um deles, que também possui esse canal de comunicação. Você pode escolher qualquer UART, escolhemos por definição UART1.

A pinagem pode ser visualizada em MBed no canto superior direito, pressionando o botão de seleção da placa e depois na guia Pinagem. Por hábito, pode ser bastante difícil perceber essa imagem colorida. Existem muitas coisas aqui, uma vez que a placa possui muitas interfaces e existem dois números de pinos: relativos ao microcontrolador (PA_5, PA_6 - numeração de pinos) e relativos à placa (D13, D12 - inscrições na placa Nucleo, os mesmos números próximos aos terminais).


 
Acontece que no microcontrolador, a interface UART1 se comunicará com o módulo XBee e o UART2 - como antes, com o computador. O código interno redirecionará UART1 para UART2 e vice-versa.



Por conexões, ficará assim:



Fazendo uma "ponte" a partir de um microcontrolador


No nosso caso, podemos jumpers no escudo definir os números aos quais queremos conectar o módulo ZigBee. O módulo de comunicação TX será conectado ao pino 2 da placa (PA_9 no microcontrolador) e o RX ao pino 8 (também conhecido como PA_10).

Ele ficará assim:



O código que pegamos é chamado de Ponte Serial. Esta é a "ponte" entre os dois canais de comunicação. Carregamos o código no microcontrolador, que encaminha tudo o que chega à entrada do computador via UART2, para UART1 e vice-versa. Como se inseríssemos um canal entre duas fontes de informação (o Linuxsoids entenderá). Conectamos um módulo XBee ao UART1.
O código é muito simples, a única coisa que você precisa alterar são os números de pinos aos quais o dispositivo está conectado. Ou seja, crie PA_9 e PA_10, conforme indicado acima.
#include "mbed.h"
// Make a serial bridge from a serial I/O device on mbed to the PC
Serial pc(USBTX, USBRX); // tx, rx
Serial device(PA_9, PA_10); // tx, rx
// Defaults to 9600 baud on each device - use .baud(baudrate) to change
int main() {
 pc.printf("Hello!");
 while(1) {
   if(pc.readable()) {
     device.putc(pc.getc());
   }
   if(device.readable()) {
     pc.putc(device.getc());
   }
 }
}

É importante que, se você confundir a ordem das conclusões - por exemplo, cometa um erro e escreva PA_10, PA_9 em vez de PA_9, PA_10 - na ordem errada, o compilador não reportará um erro para você e o programa exibirá um erro no console após a reinicialização:
pinmap not found for peripheral

e não seguirá em frente, ou seja, em princípio, nada funcionará.

Depois de baixar esse código e definir corretamente os jumpers na blindagem, você pode conectar-se com segurança ao módulo XBee a partir do computador, como fez anteriormente com o adaptador USB-UART sem removê-lo da blindagem. Ele será detectado regularmente pelo programa XCTU.

Mesmo que você não precise dessa funcionalidade, verifique se o programa está funcionando, porque no próximo exemplo iremos nos comunicar com o módulo XBee do microcontrolador, e a conexão via UART1 já deve estar estabelecida (ou seja, os jumpers estão configurados corretamente e os números de pinos são indicados no programa) .

4. Aquisição de dados


Vejamos dois exemplos simples: como receber e enviar dados no nível do microcontrolador, usando o módulo XBee como uma interface de comunicação externa.

Existe uma biblioteca oficial dos fabricantes - empresas Digi. Encontra-se no repositório Mbed, existem comentários úteis sobre o uso e a lógica do código.

Primeiro, aprenderemos como obter dados - há um exemplo mais fácil. Teremos um módulo XBee conectado ao conversor USB-UART, enviaremos uma saudação à placa Nucleo e ela imprimirá essa saudação no console.



Abra o projeto nesta biblioteca. Como sempre, importe-o no compilador online como um programa.

Corrigir bibliotecas para módulos S2C


Lembre-se de que se você possui módulos da série S2C:



em vez da biblioteca padrão, é necessário usar a correção: XBeeLib_Fixed . Caso contrário, esses programas não funcionarão. Ele é adicionado ao projeto simplesmente removendo a biblioteca XBeeLib de lá e importando-a para o projeto XBeeLibFix. Nada mais precisa ser mudado.

Então: importe esta biblioteca para o compilador online: A



janela de importação do projeto será exibida. Lá, você precisa escolher o destino - para onde importamos:



Como projeto de destino, selecione nosso exemplo XBeeZB_Receive_Data.



Após o qual a biblioteca será importada para o projeto e, em seguida, com um movimento em negrito, excluímos a versão errada do XBeeLib.



Exemplo de compilação


Portanto, você importou o exemplo e substituiu a biblioteca, se necessário.
Veja o código de exemplo, é bastante simples. Ele define uma função de retorno de chamada que é chamada quando um pacote é recebido. Esta função imprime o conteúdo do pacote recebido no console. Então, se lhe enviarmos uma saudação, ela também a imprimirá.

Para que o exemplo seja compilado, você precisa escrever no exemplo as conclusões pelas quais somos responsáveis ​​pela comunicação com o módulo XBee, porque o programa não sabe a quais conclusões conectamos o hardware.

Portanto, vamos ao arquivo config.h e as linhas nele:

//#define RADIO_TX NC /* TODO: specify your setup's Serial TX pin connected to the XBee module DIN pin */
//#define RADIO_RX NC /* TODO: specify your setup's Serial RX pin connected to the XBee module DOUT pin */

Descomente, e em vez de NC, escrevemos, de acordo com quais conclusões conectamos os jumpers:

#define RADIO_TX PA_9
#define RADIO_RX PA_10

Da mesma forma, modificamos as linhas:

//#define DEBUG_TX NC /* TODO: specify your setup's Serial TX for debugging */
//#define DEBUG_RX NC /* TODO: specify your setup's Serial RX for debugging (optional) */

Nós escrevemos:

#define DEBUG_TX USBTX
#define DEBUG_RX USBRX

Se você encontrar um erro durante a compilação que não consegue encontrar device.h, basta atualizar a biblioteca Mbed na árvore do projeto (clique com o botão direito do mouse em -> Atualizar)

Depois disso, o programa será compilado com êxito e você poderá baixá-lo para o quadro.

Exemplo em execução


Depois de examinar o console, o que a placa Nucleo escreve, você verá o seguinte:



Como enviamos dados? A opção mais fácil: através do console no programa XCTU. Selecione no menu principal do programa: Ferramentas - Enviar pacotes.



Na parte inferior, há uma janela com as palavras Enviar pacotes. Crie um novo pacote clicando no "mais" à direita. Uma janela para criar um novo pacote será exibida. Selecione a guia HEX lá.



Digite o envio de dados:
7E 00 19 10 01 00 00 00 00 00 00 FF FF FF FE 00 00 48 65 6C 6C 6F 20 58 42 65 65 21 5A
(usando o botão "Enviar pacote selecionado" à direita da lista de pacotes)

Você verá o resultado no console do módulo de escuta:



Observe que ele apenas imprimiu a última parte do conjunto de bytes que você enviou. Essa é a carga útil real da mensagem. Observe também que se você enviar "apenas bytes" (qualquer combinação aleatória de bytes), o receptor não os emitirá.

Se você colocar um conjunto de bytes: 
48 65 6C 6C 6F 20 58 42 65 65 21
em qualquer conversor HEX-ASCIII (por exemplo, um ), verifique se isso significa "Olá XBee!"

Uma tarefa muito simples para execução independente: modifique o código de exemplo para exibir o texto da mensagem em ASCII, não em HEX, e você poderá ler este texto no terminal.

5. Enviando dados


Por analogia com o exemplo anterior, agora consideramos o envio de dados.



Tudo está aqui, como no exemplo anterior. Somente com a diferença que estamos abrindo no exemplo XBeeZB_Send_Data.

Exemplo de compilação


É importante que, se você tiver um módulo S2C (está claramente escrito nele),



conecte novamente a biblioteca com uma correção, caso contrário nada funcionará para você. Como fazer isso é descrito no exemplo anterior. 

Além disso, para obter uma compilação bem-sucedida, você precisa especificar os pinos do controlador usados, basta copiá-los do exemplo anterior.

Vemos o próprio código de exemplo. Ele mainusa vários métodos para enviar dados. Escolha o mais simples: envie dados ao coordenador. Nem precisamos registrar o endereço do coordenador, porque ele já está registrado na rede. Portanto, sem alterar a amostra, comentamos enquanto todas as linhas no final:
send_data_to_coordinator(xbee);
//send_broadcast_data(xbee);
//send_data_to_remote_node(xbee, remoteDevice);
//send_explicit_data_to_remote_node(xbee, remoteDevice);

E quando você começar, verá:



(se não o vir, basta reiniciar o quadro)

Como posso garantir que os dados cheguem ao coordenador? Por exemplo, o XCTU possui o modo de console de rede. Ativado pelo botão no canto superior direito. Nesse modo, você verá todos os pacotes na rede. Obviamente, ao mesmo tempo, você deve ter uma conexão serial com o coordenador. E não se esqueça de clicar no botão Abrir no canto superior esquerdo para torná-lo verde.



Você pode ver informações detalhadas sobre cada pacote na rede, selecionando-o na lista à esquerda:



Rolando até o final do conteúdo do pacote, você verá uma linha com o texto "send_data_to_coordinator":



Você pode tentar outros métodos de envio de dados, mas lá (por exemplo, para enviar para um nó selecionado separado), é necessário registrar o endereço do nó. Você pode ver os endereços de todos os módulos no programa XCTU. Como registrar endereços específicos é descrito exaustivamente no exemplo.

6. Fazemos o gateway MQTT


Tudo está ótimo, mas agora eu gostaria de trabalhar de alguma forma com esses dados fora da rede XBee, por exemplo, na Internet. Uma maneira de fazer isso é colocar o tradutor do XBee no popular protocolo MQTT. Então, da maneira usual, podemos assinar notificações de eventos e enviar comandos da interface do usuário, e esse programa pode ser localizado em qualquer lugar (se você usar um servidor MQTT externo e não local), e não apenas em nosso computador.

Abaixo está uma instrução. Em resumo, o programa iniciado no computador trocará dados do coordenador da rede por meio de uma conexão USB. Ela transmitirá esses dados para o protocolo MQTT.


Instale e configure o XBMQ


O programa que usaremos como gateway MQTT é chamado XBMQ, é aberto e gratuito. Existe em duas versões:

A versão Java será considerada, embora isso não seja muito fundamental: não a programaremos de qualquer maneira, apenas a instalaremos e a usaremos.
Para que o programa funcione, você precisará da biblioteca RXTX, que pode ser instalada simplesmente a partir do repositório:
sudo apt-get install librxtx-java

E, claro, você precisa do JDK (Java Development Kit). Ele existe em duas versões - do Oracle e OpenJDK, a segunda é recomendada. Provavelmente, o OpenJDK já está instalado no seu sistema; caso contrário, reinstale-o. O Java precisa no máximo 8, pois javax.xml.bind foi excluído do Java 11 e você precisa escolher uma alternativa com o JDK-8 como opção padrão ou criar uma configuração para este caso.

Faça o download do repositório do programa XBMQ:
git clone https://github.com/angryelectron/xbmq-java

Após o download dos códigos-fonte, coletaremos o arquivo binário do programa. Equipe
ant dist

montará um projeto para todos os principais sistemas operacionais. O programa compilado final será na pasta dist.
Agora configure este programa. Abrir arquivo
dist/xbmq.properties

e veja lá:
#
# Xbmq Properties.
#
#port = /dev/ttyUSB0
#baud = 9600
#rootTopic = ab123
#broker = tcp://test.mosquitto.org:1883
#username = user
#password = password

Remova o comentário e altere seus parâmetros. Os parâmetros são os seguintes: porta de conexão do coordenador ZigBee, velocidade, tópico raiz (todos os dados serão inseridos), endereço do servidor MQTT, nome de usuário e senha (se o servidor exigir).

Neste exemplo, apenas o endereço do servidor mudou - para o servidor mqtt local (mosquitto padrão do Linux). Tudo o resto foi deixado por padrão:

port = /dev/ttyUSB0
baud = 9600
rootTopic = ab123
broker = tcp://127.0.0.1:1883
username = user
password = password

Antes da próxima etapa, você deve instalar e executar o mosquito local no servidor MQTT: 
sudo apt-get install mosquitto


Lançamento do XBMQ


Finalmente, o programa pode ser lançado. Depois de conectar o conversor USB-UART com o módulo coordenador inserido, execute o programa:
./dist/xbmq.sh

Quando você executa o script, vemos a linha no console:
INFO - Starting XBMQ gateway ab123/0013A2004154EA46

Por último - este é exatamente o endereço do nosso coordenador. Se você se inscrever em todos os tópicos com um cliente MQTT externo, verá imediatamente 2 mensagens:
  • No tópico ab123/0013A2004154EA46/online- será 1, este é o último desejo (um bom exemplo de como esses parâmetros "especiais" são usados ​​na vida real)
  • O tópico ab123/0013A2004154EA46/logconterá a mesma frase de depuração “Iniciando o Gateway XBMQ ...” que você já viu no console

Agora tente enviar uma mensagem de outro módulo XBee externo - por exemplo, dê um exemplo ao enviar dados.

Como resultado, no programa MQTT.fx, se você assinar todos os tópicos (#), verá o seguinte:


A janela do programa MQTT.fx.

Ou seja, iniciando o exemplo estudado anteriormente com o envio de uma mensagem ao coordenador, veremos este texto ("send_data_to_coordinator") como parte Pacote MQTT. O tópico pai comum para nós é o especificado na configuração do programa ( ab123 , você pode alterá-lo para seu próprio país). Em seguida, vem o endereço do coordenador, depois o endereço do módulo do qual a mensagem veio. Finalmente, este tópico é chamado DataOut, porque são dados de saída. 

Obviamente, você verá essa imagem em qualquer outro cliente MQTT, seja MQTTLens ou mesmo apenasmosquitto_subno console.

Alguns comentários finais:
  • De uma maneira boa, este programa deve funcionar no modo daemon. Existe um arquivo xbmqd para isso, e o README diz como usá-lo.
  • Lembre-se de que, como ela xbmqcontém a porta, não podemos executar este programa ao mesmo tempo que o XCTU.

Agora você pode trabalhar com seu sistema usando o protocolo MQTT e gravar programas complexos e interessantes!


Tatyana Volkova - A autora do programa de treinamento na Internet das Coisas acompanha a “Samsung IT Academy”, especialista em programas de responsabilidade social corporativa no Samsung Research Center

All Articles