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.
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.
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.
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.
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.
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.
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.
/* * 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).
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.
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.
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.