banner

INDÚSTRIA DE 1 HOMEM SÓ


Você já pensou em uma INDÚSTRIA DE 1 HOMEM SÓ? E se você fosse o projetista e o próprio fabricante? Sei que falo para muitos engenheiros, empresários, funcionários de empresas, mas também quero falar aqui com os makers, os que querem transformar seu hobby em profissão, desenvolver um projeto, fabricar um produto e, por fim, vendê-lo. Então, neste vídeo, vamos falar um pouco sobre empreendedorismo, isso mencionando uma placa que montamos no vídeo COMO GANHAR DINHEIRO COM IOT. Vamos demonstrar a utilização do WiFi Manager junto com uma aplicação utilizando o App FernandoK. Para tal, utilizaremos um circuito pronto com sensores de gás, temperatura e umidade.






Captura de tela do aplicativo Fernando K






Gráficos com os dados do Firebase






Comandos dos botões






Recursos usados






Esquema – Sensores






Esquema – Botão

Botão em pull down






Botão que faz com que o ESP entre em AP (Access point)




Esquema – Relés







Esquema – Sinalização







Esquema – Fonte e proteções






CÓDIGO



Declarações e variáveis

#include <SparkFunHTU21D.h> // Biblioteca com as funções do sensor HTU21D
#include <IOXhop_FirebaseESP32.h> // Biblioteca com as funçoes do Firebase
#include <ArduinoJson.h>  // Biblioteca com as funções de manipulação de JSON
#include "esp_task_wdt.h" // Biblioteca com as funções de task 
// Bibliotecas para utilizarmos o WiFi Manager
#include <WebServer.h> 
#include <DNSServer.h> 
#include <WiFiManager.h> 

// URL da base de dados fornecido pelo Firebase para a conexão http
#define FIREBASE_HOST "URL.firebaseio.com/" 
#define FIREBASE_AUTH "" // Autenticação

const int pin_WiFi = 19; // Led indicador de conexão com WiFi
const int pin_digitalMQ2 = 26; // Leitura da saída digital do MQ-2
const int pin_analogicaMQ2 = 39; // Leitura analógica do MQ-2
const int pin_Rele1 = 16; // Acionamento do relé 1
const int pin_Rele2 = 17; // Acionamento do relé 2
const int pin_Buzzer = 18; // Acionamento do Buzzer
const int pin_AP = 5; // Pino do botão de configuração do Access Point

const String PATH_COMMANDS = "/Commands"; // Caminho padrão para os comandos no Firebase

String temp, humd; // Variáveis que receberão a temperatura e umidade do HTU21D

// Pinos do sensor (i2c - canal 1)
#define SDA 21 // Ligado ao SDA do HTU21D
#define SCL 22 // Ligado ao SCL do HTU21D

// Nome e senha da rede que o WiFi Manager criará quando estiver no modo AP (quando o botão ligado no pin_AP for pressionado)
const char* NOME_REDE_AP = "ESP_AP";
const char* SENHA_REDE_AP = "12345678";

// Objeto que representa o HTU21D
HTU21D htudSensor;

// Objeto que representa a conexão I2C (wire) do sensor
// Usando canal 1
TwoWire wireSensor = TwoWire(1); 

bool WiFiConfigMode = false;


Setup


void setup()
{
  // Inicia o WatchDog de tasks
  esp_task_wdt_init(30, true); 
  // Desabilita o WatchDogTimer de Hardware do Core 0
  disableCore0WDT(); 

  // Setup dos pinos GPIO's
  pinMode(pin_WiFi, OUTPUT);
  pinMode(pin_digitalMQ2, INPUT);
  pinMode(pin_analogicaMQ2, INPUT);
  pinMode(pin_Rele1, OUTPUT);
  pinMode(pin_Rele2, OUTPUT);
  pinMode(pin_Buzzer, OUTPUT);
  pinMode(pin_AP, INPUT);  
  
  // Inicia os pinos do Relé em nível alto, já que os relés operam em lógica invertida
  digitalWrite(pin_Rele1, HIGH);
  digitalWrite(pin_Rele2, HIGH);



// Inicia o HTU21D
  htu21Begin(); 
  // Inicia a saída serial
  Serial.begin(115200); 

  // Inicia o WiFi Manager
  wifiManagerBegin();

  // Aguarda 3s
  delay(3000); 

  // Inicia a conexão com o WiFi
  // WiFi.begin(ssid, password);
  // Enquanto não conectado, faz o Led indicador de rede piscar e envia uma mensagem pela serial
  while (WiFi.status() != WL_CONNECTED)
  {
    digitalWrite(pin_WiFi, LOW);
    delay(250);
    digitalWrite(pin_WiFi, HIGH);
    delay(500);
    Serial.println("Conectando ao WiFi ...");
  }



// Inicia a conexão com o Firebase
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

  // Inicia a função de callback usando o caminho de COMANDOS
  Firebase.stream(PATH_COMMANDS, [](FirebaseStream stream)
  {
    // Variáveis que recebem o caminho e valor retornado pelo callback
    String path, value; 

    //  Se o evento que vem do callback é de alteração "put"
    if (stream.getEvent() == "put")
    {
      // Obtemos os valores de path e value
      path = stream.getPath();
      value = stream.getDataString();

      // Se é o callback inicial quando a conexão é estabelecida
      if (path.equals("/")) 
      {
        // Sincronizamos as saídas para os relés de acordo com a mensagem recebida
        // Executa a função que interpreta o valor recebido e atualiza o estado dos relés
        syncFirebase(value);         
        // Envia a mensagem pela serial de sincronização
        Serial.println("Firebase sincronizado"); 
      }



      // Imprime na serial o caminho e o valor recebido (para debug)
      Serial.println(path + " - " + value); 

      // Se o caminho é para o RELE1, ligamos/desligamos conforme o comando ON/OFF
      if (path == "/RELE1") 
        value == "ON" ? digitalWrite(pin_Rele1, LOW) : digitalWrite(pin_Rele1, HIGH);
      else if (path == "/RELE2") // Se o caminho é para o RELE2, ligamos/desligamos conforme o comando ON/OFF
        value == "ON" ? digitalWrite(pin_Rele2, LOW) : digitalWrite(pin_Rele2, HIGH);
    }
  });

  // Cria a task que irá monitorar a saída digital do MQ-2 e acionará o buzzer se for necessário
  xTaskCreatePinnedToCore(gasAlerta, "gasAlerta", 10000, NULL, 0, NULL, 0);
  
  // Cria a task que lê o botão responsável por mudar o modo de WiFi do ESP para AP e iniciar o WebServer do WiFi Manager
  xTaskCreatePinnedToCore(wifiManagerEvent, "wifiManagerEvent", 10000, NULL, 0, NULL, 0);
}


Loop


void loop()
{
  // Se o modo AP não foi solicitado pelo botão
  if(!WiFiConfigMode)
  {    
    // Verificamos a reconexão de WiFi
    verifyWiFiReconnect();
    // Função que obtem os valores do sensor HTU21D
    readClimate(); 
    // Função que envia os dados para o Firebase
    sendClimateFirebase();     
  }
  // Aguarda 3 segundos
  delay(3000); 
}


gasAlerta


// Task que monitora a saída digital do MQ-2
void gasAlerta(void *p) 
{
  // Adiciona a task na lista do Watch
  esp_task_wdt_add(NULL); 
  while (1) // loop da task
  {    
    if(digitalRead(pin_digitalMQ2) == LOW) // se um disparo for detectado...(nível baixo)
    {
      digitalWrite(pin_Buzzer, HIGH); // ...liga o buzzer...
      Serial.println("Gas detectado!"); //  ...envia o alerta para a serial
      delay(3000);// ...aguarda por 3s....
      digitalWrite(pin_Buzzer, LOW);// ...desliga o buzzer.
    }
    esp_task_wdt_reset(); // reinicia o WatchDog de task
    delay(1); // um pequeno intervalo antes de reiniciar o loop da task
  }
}



wifiManagerEvent


// Task que lê o botão e inicia o WebServer do WiFi Manager quando ele estiver em HIGH
void wifiManagerEvent(void *p)
{
  // A função de configuração "startConfigPortal" pode levar muito tempo para terminar de ser executada (depende do tempo que usuário leva para configurar a nova conexão WiFi)
  // Por isso, optamos por não utilizar o watchdog nessa task
  // esp_task_wdt_add(NULL); 

  // Loop da task
  while (1) 
  {    
    // Verificamos se o botão foi pressionado
    if(digitalRead(pin_AP) == HIGH) 
    { 
      // Ativamos o buzzer para indicar que o botão foi pressionado
      digitalWrite(pin_Buzzer, HIGH); 
      delay(500);
      digitalWrite(pin_Buzzer, LOW);       

      // Iniciamos o WebServer do WiFi Manager
      WiFiManager wifiManager;



      // Setamos a flag que impede a execução do loop enquanto isso
      WiFiConfigMode = true;

      WiFi.disconnect(true);
      
      // Iniciamos o modo AP utilizando o nome e senha declarados anteriormente
      if(!wifiManager.startConfigPortal(NOME_REDE_AP, SENHA_REDE_AP))
      {
        // Se não der certo, exibimos erro
        Serial.println("Falha ao conectar");
        // Sinalizamos no buzzer com dois sons rápidos indicando falha
        digitalWrite(pin_Buzzer, HIGH); 
        delay(250);
        digitalWrite(pin_Buzzer, LOW); 
        delay(250);
        digitalWrite(pin_Buzzer, HIGH); 
        delay(250);
        digitalWrite(pin_Buzzer, LOW); 

        // Reiniciamos o ESP
        ESP.restart();
      }



      // Se não entrar no if, então o ESP não será reiniciado e o código abaixo será executado
      // Ativamos o buzzer por um tempo para sinalizar sucesso na operação
      digitalWrite(pin_Buzzer, HIGH); 
      delay(500);
      digitalWrite(pin_Buzzer, LOW); 
    }
    
    // A função de configuração "startConfigPortal" pode levar muito tempo para terminar de ser executada (depende do tempo que usuário leva para configurar a nova conexão WiFi)
    // Por isso, optamos por não utilizar o watchdog nessa task
    //esp_task_wdt_reset(); 
    // Aguardamos 1ms 
    delay(1); 
  }
}



htu21Begin e wifiManagerBegin


// Função que inicia o sensor de temperatura e umidade HTU21D
void htu21Begin()
{
  wireSensor.begin(SDA, SCL, 400000);
  htudSensor.begin(wireSensor);
}


// Função que inicia o WiFi Manager
void wifiManagerBegin()
{  
  WiFiManager wifiManager;
 
  // Utilizando esse comando, as configurações são apagadas da memória
  // Caso tiver salvo alguma rede para conectar automaticamente, ela é apagada
  // wifiManager.resetSettings();
 
  // Função callback para quando entra em modo de configuração AP
  wifiManager.setAPCallback(configModeCallback); 
  // Função callback para quando se conecta em uma rede, ou seja, quando passa a trabalhar em modo estação
  wifiManager.setSaveConfigCallback(saveConfigCallback); 
  // Cria uma rede de nome ESP_AP com senha 12345678
  wifiManager.autoConnect(NOME_REDE_AP, SENHA_REDE_AP); 
}

syncFirebase


// Função que ativa/desativa todos os relés de acordo com a mensagem recebida ao iniciar o Firebase
// (Sincronizando as saídas do ESP com os valores atuais do Firebase)
void syncFirebase(String value)
{
  /*
    EXEMPLO DE MENSAGEM RECEBIDA:
    "RELE1":"ON","RELE2":"ON"
  */

  //obtem uma substring a partir do texto "RELE1"
  String aux = value.substring(value.indexOf("RELE1"));
  //obtem a posição do  primeiro separador de valor ":"
  int posVar = aux.indexOf(":\"");

  String status = "";

  if (posVar != -1) //se foi encontrado o separador ....
  {
    posVar += 2; // ...acrescenta duas posição para saltar o separador
    for (int i = posVar; aux.charAt(i) != '\"'; i++) //varre a substring até as próximas aspas...
      status += aux.charAt(i);//...obtendo o valor

    Serial.println("Status RELE1:" + status); //envia para a serial o valor obtido

    if (status.equals("ON")) //...se o valor é ON, ativa o relé. (lógica invertida de ativação)
      digitalWrite(pin_Rele1, LOW);
    else if (status.equals("OFF")) //...se o vlor é OFF, desativa o relé.
      digitalWrite(pin_Rele1, HIGH);
  }



  //repete o processo para o relé 2
  status = "";

  aux = value.substring(value.indexOf("RELE2"));
  posVar = aux.indexOf(":\"");
  if (posVar != -1)
  {
    posVar += 2;
    for (int i = posVar; aux.charAt(i) != '\"'; i++)
      status += aux.charAt(i);

    Serial.println("Status RELE2:" + status);

    if (status.equals("ON"))
      digitalWrite(pin_Rele2, LOW);
    else if (status.equals("OFF"))
      digitalWrite(pin_Rele2, HIGH);
  }
}


sendClimateFirebase


// Função que envia os dados para o Firebase
void sendClimateFirebase()
{
  StaticJsonBuffer<150> jsonBufferSensor; //reserva de memóoria para oobjeto JSON que contem os dados dos sensores
  StaticJsonBuffer<50> jsonBufferTimestamp; //reserva de memória para o objeto JSON que contem o instante dos dados

  JsonObject& timestamp = jsonBufferTimestamp.createObject(); //cria o objeto JSON que conterá o instante
  timestamp[".sv"] = "timestamp"; //cria o campo do instante

  JsonObject& sensorData = jsonBufferSensor.createObject(); //cria o objeto JSON que conterá os dados dos sensores

  if (temp != "" && humd != "")//se os valores de temperatura e umidade são válidos...
  {
    sensorData["Temperatura"] = temp; //...atribui os valores ao JSON
    sensorData["Umidade"] = humd;
  }
  else //...se não são válidos, atribui uma mensagem de erro.
  {
    sensorData["Temperatura"] = "Erro na leitura";
    sensorData["Umidade"] = "Erro na leitura";
  }



  //atribui as leituras do sensor MQ-2 ao objeto JSON de dados
  sensorData["MQ-2 analogico"] = String(analogRead(pin_analogicaMQ2));
  sensorData["MQ-2 digital"] = String(digitalRead(pin_digitalMQ2));

  sensorData["timestamp"] = timestamp; //atribui o instante

  Firebase.push("/Dados", sensorData); //envia para o Firebase

  jsonBufferSensor.clear(); //limpa os objetos JSON criados
  jsonBufferTimestamp.clear();
}


configModeCallback e saveConfigCallback


// Quando o ESP iniciar e não conseguir conectar em uma rede wifi, essa função é chamada automaticamente pela lib wifi manager
// Função callback que indica que o ESP entrou no modo AP
void configModeCallback(WiFiManager *myWiFiManager) 
{    
  // Ativamos o buzzer para sinalizar que o modo AP foi iniciado
  digitalWrite(pin_Buzzer, HIGH);
  delay(500);
  digitalWrite(pin_Buzzer, LOW);

  Serial.println("Entrou no modo de configuração");
  Serial.println(WiFi.softAPIP()); //imprime o IP do AP
  Serial.println(myWiFiManager->getConfigPortalSSID()); //imprime o SSID criado da rede 
}


verifyWiFiReconnect


// Função que reconecta o WiFi, se necessário
void verifyWiFiReconnect()
{
  // Se a conexão caiu, tenta se conectar novamente 
  if(WiFi.status() != WL_CONNECTED) 
    WiFi.begin(); 
  
  // Sinaliza as tentativas piscando o LED indicador da conexão
  while (WiFi.status() != WL_CONNECTED)
  {
    digitalWrite(pin_WiFi, LOW);
    delay(250);
    digitalWrite(pin_WiFi, HIGH);
    delay(500);
    Serial.println("Conectando ao WiFi ...");
  }
}


readClimate


// Função que lê os valores do sensor HTU21D
void readClimate()
{
  // Retorna 999 caso dê erro de leitura
  float h = htudSensor.readHumidity(); //obtem a umidade
  float t = htudSensor.readTemperature(); //obtem a temperatura

  if (t < 900) //verifica se a leitura de temperatura é válida
    temp = String(t);
  else
    temp = "";

  if (h < 900) //verifica se a leitura de umidade é válida
    humd = String(h);
  else
    humd = "";
}



Informações disponíveis no Firebase






FAÇA O DOWNLOAD DOS ARQUIVOS




Nenhum comentário:

Tecnologia do Blogger.