A tecnologia é uma das coisas às quais temos certeza que evolui constantemente. Desde simples equipamentos do dia-a-dia até sistemas monumentais como a infraestrutura de grandes players do mercado (como Google, Microsoft e Amazon), a tecnologia evolui a passos largos e torna reais possibilidades que antes eram improváveis. Hoje, com preços cada vez mais acessíveis, é possível adquirir módulos que tornam possíveis até aos hobistas e makers fazer projetos totalmente ligados à Internet, ampliando (e muito) o que os sistemas embarcados podem fazer.

Nessa linha de pensamento, a fabricante Espressif Systems vem se mostrado um grande expoente, sobretudo com seu mais recente ESP32. O ESP32 criou ainda mais possibilidades para prototipação rápida (e, da mesma forma, projetos completos) que precisem de bom poder computacional (processamento e quantidades de memórias) e conectividade.

E, hoje em dia, a grande maioria das plataformas IoT permite comunicação com dispositivos através de MQTT, um protocolo ultraleve e altamente aplicável a sistemas embarcados devido a pouca influência no consumo energético e pouca exigência de recursos computacionais (armazenamento, processamento e memória RAM) e banda de Internet.

Este artigo juntará as duas coisas: vai te ensinar a enviar e receber dados via MQTT usando o ESP32, de forma que você possa ter seu primeiro contato com o mundo da Internet das Coisas com este fabuloso chip.

 

 

Material necessário

Para enviar seus primeiros dados via MQTT com um ESP32, você precisará apenas de um módulo que tenha o ESP32. Um exemplo é o módulo WiFi LoRa 32(V2), fabricado pela empresa HELTEC. Uma foto do mesmo pode ser vista na figura 1.

 

Figura 1 - Módulo WiFi LoRa 32(V2), juntamente com sua antena para o Rádio LoRa e pin-headers
Figura 1 - Módulo WiFi LoRa 32(V2), juntamente com sua antena para o Rádio LoRa e pin-headers

 

Uma vantagem de usar este módulo é sua versatilidade, já que este dispõe de conectividade LoRa e um display OLED 0.96” em conjunto com o ESP32. totalizando portanto três tipos de conectividade: Wi-Fi, LoRa e Bluetooth. Isso será muito útil conforme você avançará seus estudos em Internet das Coisas, uma vez que isso exigirá mais recursos (incluindo conectividade) e você já os terá em mãos com este módulo.

Além do módulo referido, você precisará de um roteador com acesso à Internet (e, por consequência, o nome da rede e a senha da rede dele), que será o roteador que o módulo irá se conectar. Você pode utilizar o mesmo roteador que usa para acessar a Internet na sua casa, por exemplo.

 

 

Visão geral do módulo WiFi LoRa 32(V2)

Este módulo possui como unidade central de processamento e conectividade o SoC (System on Chip) ESP32, do fabricante Espressif. Para mais informações deste, consulte o sua página oficial: https://www.espressif.com/en/products/hardware/esp32/overview  .

 

Em resumo, as especificações técnicas do módulo WiFi LoRa 32(V2) são:

  • Contém um ESP32, trazendo consigo conectividade Wi-Fi e Bluetooth
  • Frequência de operação: 240MHz
  • Memória Flash: 64M-bits
  • Wi-Fi: 802.11 b/g/n/e/i
  • Bluetooth: suporta o Bluetooth “tradicional” e BLE
  • Display OLED 0.96” da cor azul
  • Rádio LoRa, utilizando como chip o SX1276 ou SX1278, e com sensibilidade de recepção de -139dBm
  • Alcance máximo do LoRa (utilizando antena oferecida no módulo): 3 Km em área aberta.
  • Frequências de LoRa disponíveis para se trabalhar: 868-915?923 MHz (para versões com o chip SX1276) 433-510 MHz (para versões com o chip SX1278).
  • Faixa de temperatura para operação: de -40°C até + 80°C
  • Tensão de alimentação do módulo: 5V

 

Em suma, podemos observar que se trata de uma solução completa para a grande maioria dos protótipos e projetos de pequeno e médio porte que envolvam Internet das Coisas.

Para mais informações, consulte as informações do módulo presente no site oficial do fabricante: http://www.heltec.cn/project/wifi-lora-32/?lang=en

 

Pinagem do módulo

A pinagem do módulo WiFi LoRa 32(V2) pode ser vista na figura 2.

  

Figura 2 - pinagem do módulo WiFi LoRa 32(V2). Fonte da imagem: https://www.fernandok.com/2018/10/introducao-ao-esp32-wifi-lora.html
Figura 2 - pinagem do módulo WiFi LoRa 32(V2). Fonte da imagem: https://www.fernandok.com/2018/10/introducao-ao-esp32-wifi-lora.html

 

 

Porém, devemos prestar atenção nos seguintes pontos importantes relacionados a pinagem deste módulo:

  • O display OLED utiliza GPIOs para comunicação I²C diferentes daqueles assumidos por grande parte das bibliotecas OLED disponíveis. Portanto, na Arduino IDE, utilize a chamada “Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN);” antes da inicialização de qualquer biblioteca de display OLED. Isso fará com que seja usada a I²C correta para o display.
  • Se você não for utilizar LoRa em seu projeto, não utilize em seu projeto os GPIOs que constam funções do LoRa (GPIOs 26, 27, 14, 18, 5 e 19).
  • Se você não for utilizar o display OLED em seu projeto, não utilize em seu projeto os GPIOs que constam funções do display (GPIOs 4 e 15).
  • As entradas analógicas do módulo suportam tensão MÁXIMA de 1,8V. Qualquer valor acima disso nas entradas analógicas pode danificar permanentemente o módulo.
  • A corrente máxima que um GPIO configurado como output pode fornecer é 12mA. Não respeitar este limite significa, muitas vezes, danificar permanentemente o ESP32.
  • Os GPIOs configurados como input suportam a tensão de, no máximo, 3,3V. Não respeitar este limite significa, muitas vezes, danificar permanentemente o ESP32.
  • Segundo recomendações do fabricante, não ligue o módulo com a antena do rádio LoRa desconectada.

 

 

Antes de tudo: preparação para utilização do módulo com a Arduino IDE

Agora chegou a hora de configurar a Arduino IDE para programar os módulos WiFi LoRa 32(V2). Antes de mais nada, assegure-se de estar com a versão mais recente da Arduino IDE instalada. para isso, baixe a versão mais recente da Arduino IDE aqui: https://www.arduino.cc/en/main/software 

Assim que estiver com a Arduino IDE mais atual instalada, siga os procedimentos abaixo. Infelizmente, as bibliotecas originais do fabricante do módulo possuem algumas falhas para comunicação com o display OLED e com o chip LoRa, desta forma eu preparei o procedimento de forma a contornar esses problemas e permitir que você a aproveitar 100% dos recursos do módulo.

 

Instalação das bibliotecas básicas para o ESP32

1. Na Arduino IDE, vá até a tela de preferências clicando em em File → Preferences

2. Clique no botão ao lado do campo “Additional Boards Manager URLs”

3. Na nova janela que abrir, no campo “Enter additional URLs, one for each row”, insira o seguinte endereço: https://dl.espressif.com/dl/package_esp32_index.json e clique em “Ok”

4. Na janela de preferências, clique em “Ok”

5. Vá até o gerenciador de placas, clicando em Tools → Board → Boards Manager…

6. Na janela do gerenciador de placas, insira no campo de busca o texto “esp32” (sem as áspas)

7. Clique sobre a opção “esp32 by Espressif Systems” e depois no botão “Install”

8. Aguarde o download e instalação da biblioteca acabarem. Após alguns segundos, a biblioteca estará instalada.

 

 

Instalação das bibliotecas de LoRa e display OLED

1. Após o procedimento acima, é hora de instalar a biblioteca para utilizar o rádio LoRa. Para isso, baixe o arquivo zip da biblioteca acessando o endereço https://github.com/sandeepmistry/arduino-LoRa/archive/master.zip 

Na Arduino IDE, vá em Sketch → Include Library → Add .zip Library. Na janela que surgir, vá até a pasta que você salvou a biblioteca baixada, clique sobre o arquivo .zip e clique em Ok

2. Feito isso, a biblioteca está adicionada e pronta para uso.

 

IMPORTANTE: a biblioteca considera que o chip LoRa está ligado em pinos diferentes dos que estão ligados no módulo WiFi LoRa 32(V2). Desta forma, para utilizar a biblioteca sem problemas, inclua em seu programa os seguintes defines:

 

#define SCK_LORA 5#define MISO_LORA 19#define MOSI_LORA 27#define RESET_PIN_LORA 14#define SS_PIN_LORA 18

 

E, ao inicializar o chip LoRa, utilize o seguinte código:

 

SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA);
LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN);
    
 if (!LoRa.begin(BAND))
        Serial.println("Falha ao iniciar radio LoRa");
 else
        Serial.println("Radio LoRa inicializado corretamente");

 

3. Agora, é o momento de instalar a biblioteca do display OLED. Para isso, vá em Sketch → Include Library → Manage Libraries. No campo de busca, digite “ADAFRUIT SSD1306” procure pela biblioteca da Adafruit, conforme mostra a figura 3.

  

Figura 3 - biblioteca da Adafruit para o display OLED
Figura 3 - biblioteca da Adafruit para o display OLED

 

 

4. Em “Select Version” selecione a versão mais recente e clique em “Install”. Após alguns segundos, a biblioteca estará instalada e pronto para uso.

 

IMPORTANTE: o display OLED utiliza GPIOs para comunicação I²C diferentes daqueles assumidos por grande parte das bibliotecas disponíveis. Portanto, na Arduino IDE, utilize a chamada “Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN);” antes da inicialização de qualquer biblioteca de display OLED. Em termos de código-fonte, ficaria assim:

Utilizar os seguintes includes:
#include
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
Ao declarar o objeto:
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 16);

Ao inicializar:
Wire.begin(4, 15);
display.begin(SSD1306_SWITCHCAPVCC, 0x3c)

 

 

5. Repita os passos 3 e 4 (nas partes referentes à instalação da biblioteca) para a biblioteca “Adafruit GFX Library”. Ela também é necessária para se utilizar os displays OLED.

6. Repita os passos 3 e 4 (nas partes referentes à instalação da biblioteca) para a biblioteca “Heltec ESP32 Dev-Boards”. Ela é necessária para se conseguir comunicação e acesso a alguns recursos do módulo.

7. Pronto, agora você possui bibliotecas para aproveitar 100% dos recursos do módulo WiFi LoRa 32(V2).

 

Instalação da biblioteca MQTT - PubSubClient

Agora chegou a hora de instalarmos a biblioteca PubSubClient, biblioteca na qual permitirá com que o módulo WiFi LoRa 32(V2) se comunique com a Internet utilizando o protocolo MQTT. Tal biblioteca é open-source, podendo ser obtida gratuitamente em: https://github.com/knolleary/pubsubclient 

 

Para instalar esta biblioteca, vamos seguir o procedimento abaixo:

1. Acesse o repositório da biblioteca ( https://github.com/knolleary/pubsubclient ) e baixe-a clicando em “Clone or Download” e depois em “Download ZIP” , conforme mostra a figura 4.

  

Figura 4 - Obtenção da biblioteca PubSubClient diretamente do repositório oficial
Figura 4 - Obtenção da biblioteca PubSubClient diretamente do repositório oficial

 

 

Guarde o arquivo ZIP baixado em uma pasta conhecida / de fácil acesso para você

 

2. Agora, na Arduino IDE, vamos instalar a biblioteca que acabamos de baixar. Para isso, vamos clicar no menu “Sketch”, depois em “Incluir Biblioteca” e, por fim, clicar em “Adicionar biblioteca .ZIP”, conforme a figura 5.

 

Figura 5 - caminho para inclusão de biblioteca Arduino em formato de arquivo compactado
Figura 5 - caminho para inclusão de biblioteca Arduino em formato de arquivo compactado

 

 3. Na janela que abrir, procure pela arquivo da biblioteca que você baixou (conforme passo 1 deste procedimento) e clique em “Abrir”. Desta forma, concluímos a instalação da biblioteca PubSubClient!

 

Código-fonte

É chegada a hora do código-fonte do seu primeiro projeto de Internet das Coisas: envio e recepção de dados via MQTT com o ESP32. O código-fonte está abaixo. Neste projeto, faremos uso apenas da parte Wi-Fi, logo o código-fonte deste não fará referência ao LoRa e display OLED contidos no módulo.

 

IMPORTANTE: preste muita atenção nos comentários contidos no código-fonte. Eles são de grande importância para o entendimento completo do projeto.

 

 

/*
 * Programa: envio de dados via MQTT com ESP32
 * Autor: Pedro Bertoleti
 * Data: Outubro/2019
 */
#include <stdio.h>         
/* Header para funções de Wi-Fi do ESP32 */
#include <WiFi.h>          
/* Header da biblioteca de MQTT */
#include <PubSubClient.h>  
/*  
*  Defines da serial de debug
*/
#define DEBUG_UART_BAUDRATE        115200
/* 
* Defines do MQTT 
*/
/* Tópico MQTT para o qual o ESP32 enviará os dados */
#define MQTT_PUB_TOPIC "INCB_ESP32_MQTT_pub"
/* Tópico MQTT do qual o ESP32 receberá dados */
#define MQTT_SUB_TOPIC "INCB_ESP32_MQTT_sub"
/* Substitua aqui por um identificador único para você. 
   Caso seu identificador coincidir com o de alguem no 
   mesmo broker MQTT, um dos dois terá a conexão derrubada. */         
#define MQTT_ID        "INCB_ESP32_MQTT_ID0001"  
/* 
* Variáveis globais do Wi-Fi e MQTT
*/
/*  Nome da rede wi-fi que o módulo vai se conectar */
const char* ssid_wifi = " ";  
/*  WI-FI network password */
const char* password_wifi = " ";     
/* Objeto para conexão a Internet (Wi-Fi) */
WiFiClient espClient;     
/* Endereço do broker MQTT que o módulo deve se conectar */
const char* broker_mqtt = "broker.hivemq.com"; 
/* Porta do broker MQTT que deve ser utilizada (padrão: 1883) */
int broker_port = 1883;                     
/* Objeto para conexão com broker MQTT */
PubSubClient MQTT(espClient); 
/* 
* Prototypes 
*/
void init_wifi(void);
void init_MQTT(void);
void connect_MQTT(void);
void connect_wifi(void);
void verify_wifi_connection(void);
void mqtt_callback(char* topic, byte* payload, unsigned int length); 
/* Função: inicaliza conexão wi-fi
 * Parâmetros: nenhum
 * Retorno: nenhum 
 */
void init_wifi(void) 
{
    delay(10);
    Serial.println("------ WI-FI -----");
    Serial.print("Tentando se conectar a seguinte rede wi-fi: ");
    Serial.println(ssid_wifi);
    Serial.println("Aguarde");    
    connect_wifi();
}
/* Função: Configura endereço do broker e porta para conexão com broker MQTT
 * Parâmetros: nenhum
 * Retorno: nenhum 
 */
void init_MQTT(void)
{
    MQTT.setServer(broker_mqtt, broker_port);
    /* Informa que todo dado que chegar do broker pelo tópico definido em MQTT_SUB_TOPIC
       Irá fazer a função mqtt_callback ser chamada (e essa, por sua vez, irá escrever
       os dados recebidos no Serial Monitor */
    MQTT.setCallback(mqtt_callback);
}
/* Função: conecta-se ao broker MQTT (se não há conexão já ativa)
 * Parâmetros: nenhum
 * Retorno: nenhum 
 */
void connect_MQTT(void) 
{
    while (!MQTT.connected()) 
    {
        Serial.print("* Tentando se conectar ao seguinte broker MQTT: ");
        Serial.println(broker_mqtt);
        
        if (MQTT.connect(MQTT_ID)) 
        {
            Serial.println("Conexao ao broker MQTT feita com sucesso!");
            /* Após conexão, se subescreve no tópico definido por MQTT_SUB_TOPIC.
               Dessa forma, torna possível receber informações do broker por 
               este tópico. */
            MQTT.subscribe(MQTT_SUB_TOPIC);
        } 
        else 
        {
            Serial.println("Falha ao se conectar ao broker MQTT.");
            Serial.println("Nova tentativa em 2s...");
            delay(2000);
        }
    }
}
/* Função: connect to wifi network
 * Parâmetros: nenhum
 * Retorno: nenhum 
 */
void connect_wifi(void) 
{
    /* If module is already connected to a WI-FI, there is nothing to do here. 
       If there isn't WI-FI connection established, a WI-FI connection is done */
    if (WiFi.status() == WL_CONNECTED)
        return;
        
    WiFi.begin(ssid_wifi, password_wifi);
    
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(100);
        Serial.print(".");
    }
  
    Serial.println();
    Serial.print("Successfully connected to WI-FI network: ");
    Serial.println(ssid_wifi);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
}
/* Função: verifica se há conexão wi-fi ativa (e conecta-se caso não haja)
 * Parâmetros: nenhum
 * Retorno: nenhum 
 */
void verify_wifi_connection(void)
{
    connect_wifi(); 
}
/*Função: função de callback 
*         esta função é chamada toda vez que chegam dados
*         pelo tópico definido em MQTT_SUB_TOPIC
* Parâmetros: nenhum
* Retorno: nenhum
*/
void mqtt_callback(char* topic, byte* payload, unsigned int length) 
{
    String msg_broker;
    char c;
    /* Obtem a string do payload (dados) recebido */
    for(int i = 0; i < length; i++) 
    {
       c = (char)payload[i];
       msg_broker += c;
    }
    Serial.print("[MQTT] Dados recebidos do broker: ");        
    Serial.println(msg_broker);        
}
/* 
 *  Setup
 */
void setup() 
{
    /* Configuração da serial (usada para debug no Serial Monitor */  
    Serial.begin(DEBUG_UART_BAUDRATE);
    /* Inicializa conexão wi-fi */
    init_wifi();
    /* inicializa conexão MQTT */
    init_MQTT();
    connect_MQTT();
}
/* 
 *  Programa principal
 */
void loop() 
{
    char dados_mqtt[100] = {0};
    /* Verifica se a conexão wi-fi está ativa e, em caso negativo, reconecta-se ao roteador */
    verify_wifi_connection();
    /* Verifica se a conexão ao broker MQTT está ativa e, em caso negativo, reconecta-se ao broker */
    connect_MQTT();
    /* Envia a frase "Comunicacao MQTT via ESP32" via MQTT */
    sprintf(dados_mqtt, "Comunicacao MQTT via ESP32");
    MQTT.publish(MQTT_PUB_TOPIC, dados_mqtt); 
    /* Keep-alive do MQTT */
    MQTT.loop();
    /* Espera 5 segundos até próximo envio */
    delay(5000);    
}

 

 

Antes de compilar e rodar, certifique-se que a placa “Heltec_WiFi_LoRa_32” esteja selecionada em Tools > Board.

 Para compilar, enviar o software compilado ao módulo, basta fazer da mesma forma como você faria no Arduino convencional. Ou seja, clique sobre o ícone em forma de “V” (em laranja na figura 4) para compilar e, para gravar o software no módulo, basta clicar no ícone em forma de seta para a direita (em amarelo na figura 6).

 

Figura 6 - botões da Arduino IDE para compilação e gravação de software
Figura 6 - botões da Arduino IDE para compilação e gravação de software

 

 

Teste do projeto

Para testar o projeto, você pode utilizar qualquer cliente MQTT disponível para computador ou smartphones. Neste artigo, vamos utilizar o MQTTLens (link para download: https://chrome.google.com/webstore/detail/mqttlens/hemojaaeigabkbcookmlgmdigohjobjm?hl=pt-BR )

 

Para visualizar as informações enviadas por MQTT, siga o procedimento abaixo:

1. Abra o MQTTLens e clique em “Connections +”.

2. Agora, vamos preencher os campos “Connection name” e “Hostname” da janela “Add a new Connection” conforme a figura 7. Deixe os demais campos como estão.

  

Figura 7 - Dados de conexão MQTT (configuração do cliente MQTTLens)
Figura 7 - Dados de conexão MQTT (configuração do cliente MQTTLens)

 

 

3. No final da tela “Add a new Connection”, devemos agora clicar em “CREATE CONNECTION”. Automaticamente, o cliente MQTTLens irá se conectar ao broker.

4. No campo Subscribe, vamos preencher com o MQTT_PUB_TOPIC utilizado no código-fonte do projeto (para o exemplo dado: INCB_ESP32_MQTT_pub). Já no campo Publish, vamos preencher com o MQTT_SUB_TOPIC utilizado no código-fonte do projeto (para o exemplo dado: INCB_ESP32_MQTT_sub).

5. Em seguida, clique no botão SUBSCRIBE (em verde, à direita do campo).

6. Se o módulo WiFi LoRa 32(V2) estiver funcionando / ligado e conectado à Internet, iremos ver as mensagens com as medições, conforme mostra a figura 8.

 

Figura 8 - mensagens MQTT enviadas
Figura 8 - mensagens MQTT enviadas

 

 

7. Pronto! Usando um cliente MQTT é possível, de qualquer lugar do mundo, receber dados do seu ESP32.

8. Para enviar dados ao ESP32 a partir deste cliente MQTT, digite a mensagem desejada no campo Message e clique em Publish (exemplo de mensagem: Teste de envio de dados para ESP32). Após pouco tempo (poucos segundos, no máximo) mensagem aparecerá no Serial Monitor, conforme mostra a figura 9.

Dessa forma, você também pode, de qualquer lugar do mundo, enviar mensagens para seu ESP32.

 


 

 

 

Conclusão

Neste artigo vimos como preparar o ESP32 para enviar e receber mensagens via MQTT e, além disso, fizemos um pequeno projeto para tal utilidade.

Dada a importância do MQTT nos projetos de Internet das Coisas, este projeto / exemplo aqui apresentado é de suma importância para os mais iniciantes entrarem no mundo da Internet das Coisas. Com base no que aqui foi apresentado, o leitor é capaz de continuar seus experimentos e estudos com MQTT e evoluir para o MQTT com autenticação, algo requerido por algumas plataformas IoT.