Hoje vamos fazer uma introdução
ao protocolo MQTT (Message Queue Telemetry Transport), método bastante útil
para IOT (Internet das Coisas), cujo principal uso é proporcionar comunicação
entre máquinas, ou seja, Machine-to-Machine (M2M). Vamos, portanto, dar os
primeiros passos com Ubidots IOT platform, expondo sua utilização em um exemplo
com ESP32 LoRa. Isso também com um sensor DHT22, sendo o envio de informações feito
com o protocolo MQTT.
O protocolo MQTT foi criado
pela IBM há muito tempo atrás e passou a ser bastante utilizado para IOT com o
barateamento dos chips e a facilidade de acesso a internet. No exemplo
específico que vamos fazer aqui vamos usar o Ubidots, que é um broker, ou
melhor, um site com um broker.
Demonstração
Recursos usados
·
ESP32 Display LoRa
·
DHT22
·
Resistor 4k7 ohm
·
Conta (trial 30 dias ou paga) no Ubidots
·
Protoboard
Protocolo MQTT
Publish e Subscribe
Ubidots IoT Platform
Assuntos que serão abordados
·
Criando uma nova conta
·
Criando um novo Dashboard
·
Criando o ESP32-DHT Device
·
Obtendo dados MQTT – Device ID e Topic
·
Obtendo dados MQTT – Token
·
Criação de variáveis no Ubidots
·
Criando Widgets de umidade e temperatura
Criando nova conta
Para criar uma conta acesse
www.ubidots.com e clique em SIGN UP
1. Nome da empresa
2. Estágio do projeto:
Escolhemos o estágio
Discovery, indicando que é um projeto de testes.
3. Criar aplicação
1. Seu nome
2. Seu email
3. Criar perfil
1. Login
2. Senha
3. Iniciar teste grátis
Criando novo Dashboard
1. Clique em create a new
dashboard
2. Digite um nome para o
Dashboard e clique no botão
Criando ESP32-DHT Device
1. Clique em Device Management
e em Devices
2. Clique em Create Device ou
em +
3. Uma aba será aberta
listando os tutoriais existentes no site help.ubidots para a configuração e
programação de microcontroladores de
acordo com os seus respectivos fabricantes. Criaremos um dispositivo em branco.
4. Preencha os campos
A. Nome do dispositivo
B. Rótulo (Será parte do
tópico usado pelo MQTT Client)
C. Criar
5. Após o dispositivo ser
criado ele será listado na página de dispositivos conforme a figura
A. Nome do dispositivo
B. Última atualização
C. Data/hora de criação do
dispositivo
D. Organização referente ao
dispositivo
E. Adicionar organização e
Deletar dispositivo
Obtendo dados MQTT – Device ID e Topic
1. Selecione o dispositivo
2. Os valores de Device ID e o
tópico são escritos conforme as imagens
A porta utilizada é 1883.
3. O token é obtido conforme
as imagens 3.1 e 3.2
Criando Variáveis
Para criarmos um widget que
referencia uma variável de um device, a mesma já deve estar criada no device.
OBS: As variáveis são criadas
automaticamente pelo Ubidots após um envio de Json, mas para isso é necessário
ligar o ESP32 ao menos uma vez. Para referenciarmos os widgets sem que seja
necessário ligar o ESP, devemos seguir estes passos.
1. Em Devices selecione o
dispositivo
2. Clique em Add Variable e
depois em Raw
Obs: Defina as mesmas Labels
do código fonte (no arquivo MQTT_Client.h)
3. Digite o label
(VARIABLE_LABEL_TEMPERATURE )
4. Repita os passos para a
variável de umidade
(VARIABLE_LABEL_HUMIDITY)
Criando Widgets
1. Vá para a página de
dashboards.
2. Clique em um dos botões
Criando Widgets – Temperatura
3. Selecionamos a opção
Thermometer
4. Clique em Add Variables
5. Siga os passos para
selecionar a variável de temperatura
6. Clique em confirmar
Criando Widgets – Umidade
1. Adicione outro widget
2. Selecione a opção Tank
3. Clique em Add Variables
4. Selecione ESP32-DHT ,clique
em humidity e depois em confirmar
5. Por fim, clique em
confirmar
6. O Widget de umidade
aparecerá abaixo do de temperatura
7. Você pode organizar
arrastando as janelas
Montagem
Código
Declarações e variáveis
#include <Arduino.h> #include <SimpleDHT.h> //Biblioteca referente ao DHT22 #include "displayESP32LoRa.h" //Arquivo com as funções referentes ao display lora #include "MQTT_Client.h" //Arquivo com as funções de mqtt float temperature; //Temperatura que será obtida pelo sensor DHT float humidity; //Umidade que será obtida pelo sensor DHT const int pinDHT = 22; //Pino que é ligado no sensor DHT SimpleDHT22 dht22(pinDHT); //Objeto que possui os métodos de leitura dos valores do sensor DHT
Setup
void setup() { //Para debug, iniciamos a comunicação serial com 115200 bps Serial.begin(115200); //Inicializa display lora if(!loraDisplayConfig()) ESP.restart(); //Exibe mensagem no display showDisplay(0, "Setting up mqtt...", true); Serial.println("Setting up mqtt..."); //Inicializa mqtt (conecta o esp com o wifi, configura e conecta com o servidor da ubidots) if(!mqttInit()) { delay(3000); showDisplay(0, "Failed!", false); Serial.println("Failed!"); ESP.restart(); } showDisplay(0, "OK", false); Serial.println("OK"); }
Loop
void loop() { //Se o esp foi desconectado do ubidots, tentamos reconectar if(!client.connected()) reconnect(); //Lê a temperatura e umidade e exibimos no display passando uma flag (que sinaliza sucesso na leitura) if(getClimate()) showClimate(true); else showClimate(false); //Esperamos 2.5s antes de exibir o status do envio para dar efeito de pisca no display delay(2500); if(sendValues(temperature, humidity)) { Serial.println("Successfully sent data"); showDisplay(4,"Successfully sent data", false); } else { Serial.println("Failed to send sensor data"); showDisplay(4,"Failed to send sensor data", false); } //Esperamos 2.5s para dar tempo de ler as mensagens acima delay(2500); }
Loop – Leitura de valores do
DHT22
//Obtém temperatura e umidade do sensor bool getClimate() { int err = SimpleDHTErrSuccess; //Passamos as variáveis 'temperature' e 'humidity' por parâmetro na função chamada 'read2', elas serão retornadas por referência //Se não for retornado o código de SimpleDHTErrSuccess (sucesso), exibimos o valor de erro obtido if ((err = dht22.read2(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { Serial.print("Read DHT22 failed, err="); Serial.println(err); //Zera valores temperature = humidity = 0; return false; } return true; }
Loop – Exibição de valores no display
//Essa função exibe os valores com suas respectivas unidades de medida para caso a flag 'success' seja true //Caso a flag 'success' seja false, exibimos apenas um traço '-' void showClimate(bool success) { if(success) { showDisplay(0, "Temperature: "+String(temperature)+" °C", true); showDisplay(1, "Humidity: "+String(humidity)+" %", false); Serial.println("Temperature: "+String(temperature)+" °C"); Serial.println("Humidity: "+String(humidity)+" %"); } else { showDisplay(0, "Temperature: -", true); showDisplay(1, "Humidity: -", false); Serial.println("Temperature: -"); Serial.println("Humidity: -"); } }
MQTT_Client – Declarações e variáveis
#include <WiFi.h> #include <PubSubClient.h> //Biblioteca para as publicações via mqtt #include "displayESP32LoRa.h" //Arquivo com as funções referentes ao display lora #define WIFISSID "MEU_SSID" //Coloque seu SSID de WiFi aqui #define PASSWORD "MEU_PASSWORD" //Coloque seu password de WiFi aqui #define TOKEN "xxxxxx" //Coloque seu TOKEN do Ubidots aqui #define VARIABLE_LABEL_TEMPERATURE "temperature" //Label referente a variável de temperatura criada no ubidots #define VARIABLE_LABEL_HUMIDITY "humidity" //Label referente a variável de umidade criada no ubidots #define DEVICE_ID "xxxxxx" //ID do dispositivo (Device id, também chamado de client name) #define SERVER "things.ubidots.com" //Servidor do Ubidots (broker) //Porta padrão #define PORT 1883 //Tópico aonde serão feitos os publish, "esp32-dht" é o DEVICE_LABEL #define TOPIC "/v1.6/devices/esp32-dht" //Objeto WiFiClient usado para a conexão wifi WiFiClient ubidots; //Objeto PubSubClient usado para publish–subscribe PubSubClient client(ubidots);
MQTT_Client – Inicialização
bool mqttInit() { //Inicia WiFi com o SSID e a senha WiFi.begin(WIFISSID, PASSWORD); //Loop até que o WiFi esteja conectado while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Establishing connection to WiFi.."); } //Exibe no monitor serial Serial.println("Connected to network"); //Seta servidor com o broker e a porta client.setServer(SERVER, PORT); //Conecta no ubidots com o Device id e o token, o password é informado como vazio while(!client.connect(DEVICE_ID, TOKEN, "")) { Serial.println("MQTT - Connect error"); return false; } Serial.println("MQTT - Connect ok"); return true; }
MQTT_Client – Reconexão
void reconnect() { //Loop até que o MQTT esteja conectado while (!client.connected()) { //sinaliza desconexão do mqtt no display showDisplay(0,"Disconnected", true); showDisplay(1, "Trying to reconnect mqtt...", false); Serial.println("Attempting MQTT connection..."); //Tenta conectar if (client.connect(DEVICE_ID, TOKEN,"")) Serial.println("connected"); else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 2 seconds"); //Aguarda 2 segundos antes de retomar delay(2000); } } //Sinaliza reconexão do mqtt no display showDisplay(4,"Reconnected", false); }
MQTT_Client – Envio (publish)
//Envia valores por mqtt //Exemplo: {"temperature":{"value":24.50, "context":{"temperature":24.50, "humidity":57.20}}} bool sendValues(float temperature, float humidity) { char json[250]; //Atribui para a cadeia de caracteres "json" os valores referentes a temperatura e os envia para a variável do ubidots correspondente sprintf(json, "{\"%s\":{\"value\":%02.02f, \"context\":{\"temperature\":%02.02f, \"humidity\":%02.02f}}}", VARIABLE_LABEL_TEMPERATURE, temperature, temperature, humidity); if(!client.publish(TOPIC, json)) return false; //Atribui para a cadeia de caracteres "json" os valores referentes a umidade e os envia para a variável do ubidots correspondente sprintf(json, "{\"%s\":{\"value\":%02.02f, \"context\":{\"temperature\":%02.02f, \"humidity\":%02.02f}}}", VARIABLE_LABEL_HUMIDITY, humidity, temperature, humidity); if(!client.publish(TOPIC, json)) return false; //Se tudo der certo retorna true return true; }
Código ESP32
Json
Display LoRa
#ifndef _DISPLAY_LORA_ #define _DISPLAY_LORA_ #include "SSD1306.h" //Define os pinos que serão utilizados pelo display LoRa #define SCK 5 // GPIO5 -- SX127x's SCK #define MISO 19 // GPIO19 -- SX127x's MISO #define MOSI 27 // GPIO27 -- SX127x's MOSI #define SS 18 // GPIO18 -- SX127x's CS #define RST 14 // GPIO14 -- SX127x's RESET #define DI00 26 // GPIO26 -- SX127x's IRQ(Interrupt Request) SSD1306 display(0x3c, 4, 15); //Construtor do objeto do display LoRa
Display LoRa – loraDisplayConfig
//Configura Display LoRa bool loraDisplayConfig() { //Configura RST do oled como saida pinMode(16,OUTPUT); //Reseta o OLED digitalWrite(16, LOW); //Aguarda 50ms delay(50); //Enquanto o OLED estiver ligado, GPIO16 deve estar HIGH digitalWrite(16, HIGH); //Inicializa display if(!display.init()) return false; //Inverte a tela verticalmente (de ponta cabeça) display.flipScreenVertically(); //Configura a fonte do display display.setFont(ArialMT_Plain_10); //Aguarda 200ms delay(200); //Limpa display display.clear(); return true; } #endif
Display LoRa – showDisplay
//Exibe mensagem recebida como parâmetro void showDisplay(int line, String msg, bool clear) { //Limpa o display if(clear) { display.clear(); //Configura alinhamento de texto à esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //Configura fonte do texto display.setFont(ArialMT_Plain_10); } //Escreve na pos 0,25 a mensagem display.drawString(0 , line*10 , msg); //Exibe no display display.display(); }
Instalação de bibliotecas
Pubsubclient
*Display LoRa anexado junto ao
projeto
Faça o download dos arquivos:
3 Comentários
O link para o pdf não esta funcionando.
ResponderExcluirOlá Fernando, primeiramente muito fã do seu trabalho. Simplesmente sensacional. Gostei muito desse projeto. Como seria se implementar dois ESP? Um lendo o sensor, transmitindo em lota para outro escrever no mqqt. Novamente parabéns!
ResponderExcluirGostaria muito de estudar contigo, Fernando. Confesso, também que estou ansioso pelo seu livro!!! Parabéns pelos conteúdos publicados. Tenho aprendido muito com seus videos!
ResponderExcluir