banner

IOT com Múltiplos ESP32




Pessoal, neste vídeo vamos fazer com que ESPs com sensores DHT enviem dados de temperatura e umidade através do protocolo ESPNOW para outro ESP que está conectado à internet. Então, este ESP conectado à internet vai enviar os dados recolhidos dos outros ESPs para um servidor MQTT
Tudo isso usando o dashboard do IBM Watson ligado em um Gateway do ESP32, que se comunica simultaneamente com WiFi 2.4
Esse vídeo, portanto, engloba bastante assunto e é bastante útil para a Internet das Coisas.







RECURSOS USADOS

  • ESP32
  • Resistor 4.7k ohm
  • Protoboard
  • Jumpers
  • DHT22







MONTAGEM ESP32 DHT22






CÓDIGO

Bibliotecas necessárias

SimpleDHT



PubSubClient







FLUXOGRAMA ESP32 GATEWAY





CÓDIGO ESP32 GATEWAY

#include <esp_now.h>
#include <WiFi.h>
#include <PubSubClient.h>

//SSID e senha para se conectar à internet
#define SSID "TestESP"
#define PASSWORD "12345678"

//Server MQTT que iremos utilizar
#define MQTT_SERVER "quickstart.messaging.internetofthings.ibmcloud.com"

//Nome do tópico que devemos enviar os dados
//para que eles apareçam nos gráficos
#define TOPIC_NAME "iot-2/evt/status/fmt/json"

//ID que usaremos para conectar 
//QUICK_START deve permanecer como está
const String QUICK_START = "d:quickstart:arduino:";

//No DEVICE_ID você deve mudar para um id único
//Aqui nesse exemplo utilizamos o MAC Address
//do dispositivo que estamos utilizando
//Servirá como identificação no site
//https://quickstart.internetofthings.ibmcloud.com
const String DEVICE_ID = "3C71BF448181";

//Concatenamos o id do quickstart com o id do nosso
//dispositivo
const String CLIENT_ID =  QUICK_START + DEVICE_ID;

//Cliente WiFi que o MQTT irá utilizar para se conectar
WiFiClient wifiClient;

//Cliente MQTT, passamos a url do server, a porta
//e o cliente WiFi
PubSubClient client(MQTT_SERVER, 1883, wifiClient);

//Estrutura de comunicação entre os ESPs com DHT e o gateway
//Os ESPs com DHT irão enviar esta estrutura
//Para que o gateway receba é necessário que no código dos ESP com DHT tenha outra struct igual a esta
typedef struct {
  char id[30];
  float humidity;
  float temperature;
}SensorData;


Setup


void setup() {
  //Inicia serial
  Serial.begin(115200);

  //Inicia WiFi
  setupWiFi();

  //Inicia ESPNOW
  setupEspNow();

  //Conecta ao server MQTT
  connectToMQTTServer();
}


SetupWiFi

void setupWiFi(){
  //Desconecta e reseta as configurações da WiFi
  WiFi.disconnect(true, true);

  //O modo deve ser tanto AP quanto Station
  WiFi.mode(WIFI_AP_STA);

  //Mandamos conectar na rede
  WiFi.begin(SSID, PASSWORD);
  Serial.println("");

  //Enquanto não estiver conectado à rede WiFi
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }

  //Se chegou aqui está conectado
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(SSID);

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  //IMPORTANTE: O valor do softAP mac address deve ir no código dos ESPs com DHT
  Serial.print("softAPmacAddress: "); 
  Serial.println(WiFi.softAPmacAddress());
}


SetupEspNow

void setupEspNow() {
  //Se a inicialização foi bem sucedida
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
    //Registra a função que será executada quando chegarem dados dos ESPs com DHT
    esp_now_register_recv_cb(OnDataRecv);
  }
  //Se houve erro na inicialização
  else {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
}

ConnectToMQTTServer

//Função responsável por conectar ao server MQTT
void connectToMQTTServer() {
  Serial.println("Connecting to MQTT Server...");
  //Se conecta ao id que definimos
  if (client.connect(CLIENT_ID.c_str())) {
    //Se a conexão foi bem sucedida
    Serial.println("connected");
  } else {
    //Se ocorreu algum erro
    Serial.print("error = ");
    Serial.println(client.state());
  }
}

OnDataRecv


//Função que serve de callback para nos avisar
//quando chegou algo dos ESPs com DHT
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
  Serial.println("Received");
  SensorData* sensorData = (SensorData*) data;

  //Envia para o Server MQTT
  sendToMQTT(sensorData);
}

SendToMQTT


void sendToMQTT(SensorData* sensorData) {
  //Criamos o json que enviaremos para o server MQTT
  String msg = createJsonString(sensorData);
  Serial.print("Publish message: ");
  Serial.println(msg);

  //Publicamos no tópico onde o servidor espera para receber 
  //e gerar o gráfico
  client.publish(TOPIC_NAME, msg.c_str());
}

createJsonString

//Função responsável por criar
//um Json com os dados lidos
String createJsonString(SensorData* sensorData) {
  String data = "{";
    data+= "\"d\": {";
      data+="\""+String(sensorData->id)+"\":{";
        data+="\"temperature\":"+String(sensorData->temperature);
        data+=",";
        data+="\"humidity\":"+String(sensorData->humidity);
      data+="}";
    data+="}";
  data+="}";
  return data;
}

Loop


//Não precisamos fazer nada no loop
//Sempre que chegar algo de um dos ESPs com DHT
//a função OnDataRecv é executada automaticamente
//já que adicionamos como callback utilizando a função
//esp_now_register_recv_cb
void loop() {
}




FLUXOGRAMA ESP32 DHT




Código ESP32 DHT

#include <esp_now.h>
#include <WiFi.h>
#include <SimpleDHT.h>

//Identificação para o gateway saber quem está enviando os dados
//Modifique para cada ESP com DHT que for usar
#define ID "sensor1"

//Canal usado para conexão
//Caso a comunicação do ESPNOW não funcione tente mudar para outro canal WiFi
#define CHANNEL 6

#define DHTPIN 4 //Pino onde está o DHT
#define INTERVAL 5000 //Intervalo entre os envios dos dados do sensor

//Marca quando foi feito o último envio os dados
uint32_t lastTimeSent = 0;

//Objeto que realiza a leitura da umidade e temperatura
SimpleDHT22 dht;

//IMPORTANTE: 
//Mac Address do gateway
//Primeiro execute o código do gateway, abra o monitor serial dele e altere aqui pelo softAPmacAddress
//que aparecer para o gateway
uint8_t gatewayMacAdress[6] = {0x3C,0x71,0xBF,0x44,0x81,0x81};
esp_now_peer_info_t gateway;

//Estrutura de comunicação entre os ESPs com DHT e o gateway
//Os ESPs com DHT irão enviar esta estrutura
//Para que o gateway receba é necessário que no código do gateway tenha outra struct igual a esta
typedef struct {
  char id[30];
  float humidity;
  float temperature;
}SensorData;

//Guarda o valor da umidade e temperatura lida para ser enviada para o gateway
SensorData sensorData;

Setup


void setup() {
  Serial.begin(115200);

  //Inicializa a WiFi
  setupWiFi();
  //Inicializa o ESPNow e adiciona o callback de envio
  setupEspNow();

  //Adiciona o gateway como um peer do ESPNOW
  addGatewayAsPeer();
}

SetupWiFi

void setupWiFi() {
  //Reseta as configurações da WiFi
  WiFi.disconnect(true, true);

  //Colocamos o ESP em modo AP
  WiFi.mode(WIFI_AP);

  //Faz o AP utilizar o canal passado em "CHANNEL"
  bool hidden = true;
  WiFi.softAP(ID, "12345678", CHANNEL, hidden);
}

SetupEspNow

void setupEspNow() {
  //Se a inicialização foi bem sucedida
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
    //Registra a função que nos informará sobre o status do envio
    //A função que será executada é onDataSent e está declarada mais abaixo
    esp_now_register_send_cb(onDataSent);
  }
  //Se houve erro na inicialização
  else {
    Serial.println("ESPNow Init Failed");
    //Reinicializa o ESP
    ESP.restart();
  }
}

AddGatewayAsPeer

void addGatewayAsPeer() {
  //Canal de comunicação
  gateway.channel = CHANNEL;

  //0 para não usar criptografia
  gateway.encrypt = 0;

  //Interface utilizada na comunicação do ESPNOW
  gateway.ifidx = WIFI_IF_AP;

  //Copia o endereço do array para a estrutura
  memcpy(gateway.peer_addr, gatewayMacAdress, sizeof(gatewayMacAdress));

  //Adiciona gateway como peer
  esp_now_add_peer(&gateway);
}

OnDataSent

//Função que serve de callback para nos avisar
//sobre a situação do envio que fizemos
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  //Mostramos se o status do envio foi bem sucedido ou não
  Serial.print("Status: "); 
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}


Loop


void loop()
{
  uint32_t now = millis();

  //Se o tempo desde o último envio for maior que o intervalo definido
  if(now - lastTimeSent > INTERVAL)
  {
    //Faz a leitura da temperatura e umidade
    readSensor();

    //Envia dados do sensor
    sendSensorData();

    //Marca o tempo do último envio como agora
    lastTimeSent = now;
  }
}

ReadSensor

void readSensor() {
  Serial.println("READ");

  //Faz a leitura da temperatura e umidade
  float h, t;
  int status = dht.read2(DHTPIN, &t, &h, NULL);

  //Se a leitura foi bem sucedida
  if (status == SimpleDHTErrSuccess) {
    //Guarda na struct a id e os valores da umidade e da temperatura
    strcpy(sensorData.id, ID);
    sensorData.humidity = h;
    sensorData.temperature = t;
  }
}

SendSensorData

void sendSensorData() {
  //Envia a struct para o gateway
  esp_err_t result = esp_now_send(gatewayMacAdress, (uint8_t*) &sensorData, sizeof(sensorData));
  Serial.print("Send Status: ");
  //Se o envio foi bem sucedido
  if (result == ESP_OK) {
    Serial.println("Success");
  }
  //Se aconteceu algum erro no envio
  else {
    Serial.println("Error");
  }
}






FAÇA O DOWNLOAD DOS ARQUIVOS:

PDF

INO









6 comentários:

  1. Bom dia. não consigo encontrar a lib esp-now.. quem pode me ajudar?

    ResponderExcluir
    Respostas
    1. https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/include/esp32/esp_now.h

      Excluir
  2. tem como fazer um esp nao sleve e server que possa tanto enviar como receber mensagens

    ResponderExcluir
  3. Boa tarde, isso é possível usar como um ESP32 lê o banco de dados e depois envia as informações para os atuadores? É possível ter as duas formas de comunicação?

    ResponderExcluir

Tecnologia do Blogger.