Controle seu ESP32 usando Telegram Deixe um comentário

Se você é leitor assíduo aqui do blog, já deve ter percebido quão versátil o ESP32 é, podendo ser utilizado tanto para acionamentos simples quanto em projetos mais avançados de Internet das Coisas. Por contar com conectividade WiFi de forma já nativa, o ESP32 abre portas para interação com os mais diversos serviços via Internet. Neste post vamos tratar o uso do ESP32 com um popular comunicador instantâneo: o Telegram.

No projeto aqui desenvolvido, será possível controlar até 4 relés ligados no ESP32 e ler a temperatura ambiente e a umidade do ar, tudo via Telegram e a partir de qualquer smartphone ou computador conectado à Internet. Desta forma, você poderá “conversar” com seu projeto para que ele faça as ações propostas.

Essa aplicação abre portas para projetos de controle e monitoramento remotos dos mais diversos tipos. Podendo ser muito útil em situação onde o que se deseja monitorar e/ou controlar se encontra em local de difícil acesso ou de acesso restrito (como locais com risco biológico, por exemplo).

Material necessário

Para fazer este projeto, você precisará dos seguintes materiais:

Telegram – criação de conta

A primeira coisa a ser feita é você criar uma conta pessoal no Telegram. Para isso, basta baixar o aplicativo do Telegram no seu smartphone e se cadastrar. Segue abaixo o link para o aplicativo nas lojas de aplicativos do Android e iPhone:

Além disso, é importante você ter acesso à sua conta do Telegram via navegador. Para isso, acesse este site e siga as instruções do mesmo para obter tal acesso.

Criação de um bot Telegram para o ESP32

Já com a conta, devemos criar um bot no Telegram. Isso porque o ESP32 se comportará como um bot que você poderá “conversar” e solicitar o controle dos relés e a leitura da temperatura e umidade do ar.

Para criar o bot Telegram para o ESP32, siga o procedimento abaixo usando seu computador ou smartphone:

  1. Procure pelo BotFather, pesquisando por @botfather na busca de contatos, conforme mostra a figura 1:

    Telegram BotFather
    Figura 1 – BotFather (Telegram)
  2. No chat com o BotFather, digite a mensagem de texto /newbot e a envie para começar a criação de um bot Telegram.
  3. Será requisitado que você informe um nome para seu bot. Digite no chat o nome desejado para o bot e envie a mensagem. É importante ressaltar que este nome não permite espaços, acentos e cedilha (ç).
  4. Se o nome for válido, será requerido o username para seu bot. Este nome não permite espaços, acentos e cedilha (ç). Digite no chat o username desejado para o bot e envie a mensagem. Importante: este username deve, obrigatoriamente, finalizar com bot (por exemplo: teste_bot).
  5. Se o username desejado for válido (e se também estiver disponível), você receberá a confirmação de bot cadastrado, juntamente com um endereço web para ter um chat com o bot criado e um token de acesso (no local destacado em vermelho na figura 2). Guarde estas informações, elas serão necessárias mais a frente neste post.
    Segue na figura 2 um exemplo de cadastro de um bot para este projeto, cujo bot se chama FilipeFlop-ESP32 e o username é FilipeFlop-ESP32_bot.
Mensagem Telegram
Figura 2 – cadastro de um bot Telegram com o BotFather

Neste momento, o bot para o projeto no Telegram está criado e pronto para uso / associação com o ESP32.

Circuito esquemático

O circuito esquemático do projeto é visto na figura 3.

Circuito ESP32
Figura 3 – circuito esquemático do projeto

Sobre o circuito esquemático do projeto e sua operação, é importante ressaltar os seguintes itens:

  1. Pelo fato do shield de 4 relés permitir ser acionado somente com 5 V e o ESP32 disponibilizar no máximo 3,3 V em um GPIO configurado com saída, é preciso de um circuito de adequação de níveis de tensão. Esta é a função do circuito transistorizado do projeto.
  2. Como são usados transistores NPN no circuito de adequação de níveis de tensão entre ESP32 e shield de relés, a lógica de acionamento de um relé é invertida. Ou seja, para se acionar um relé, é preciso colocar o GPIO que o controla em nível baixo (0 V / GND) e vice-versa.
  3. Antes de se ligar cargas AC nas saídas dos relés, sempre observar se o mesmo suporta o acionamento da carga desejada. No caso dos relés utilizados no shield deste projeto, pode-se utilizar cargas AC que utilizem até 250 V de tensão de alimentação e consumam até 10A de corrente elétrica.

Bibliotecas necessárias

Este projeto faz uso de bibliotecas para leitura do sensor DHT22 (temperatura ambiente e umidade relativa do ar), comunicação com o Telegram e JSON. Todas as bibliotecas necessárias podem ser instaladas via Gerenciador de bibliotecas do Arduino IDE (Ferramentas > Placa > Gerenciar de Placas).

  • Biblioteca para comunicação com o Telegram: procure no Gerenciador de bibliotecas do Arduino IDE o nome da biblioteca: UniversalTelegramBot. Feito isso, instale a versão mais recente disponível.
  • Biblioteca para JSON: procure no Gerenciador de bibliotecas do Arduino IDE o nome da biblioteca: ArduinoJson. Feito isso, instale a versão 5.13.5.
  • Biblioteca para o sensor DHT22: procure no Gerenciador de bibliotecas do Arduino IDE o nome da biblioteca: DHT22 sensor library. Trata-se de uma biblioteca da Adafruit. Uma vez encontrado, instale as versões mais recente disponível.

Código-fonte do projeto

O código-fonte do projeto pode ser visto abaixo. Se você não sabe como programar o ESP32 com a Arduino IDE, leia este nosso artigo aqui do blog para ter maiores informações de como fazer isso.

Importante:

  1. Não se esqueça de substituir no código-fonte suas credenciais da rede wi-fi (nome da rede e senha) que o ESP32 deve se conectar. Substitua tais informações nos conteúdos de ssid_wifipassword_wifi.
  2. Não se esqueça de substuir no código-fonte seu token de acesso do Telegram, fornecido pelo BotFather. Substitua tal informação no conteúdo de token_acesso_telegram.
#include <Arduino.h>
#include <WiFi.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <DHT.h>

/* Definições do sensor de temperatura e umidade */
#define DHTPIN   5      /* GPIO que será ligado o pino 2 do DHT22 */

/* Definições da escolha do modelo de sensor */
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

/* Credenciais wi-fi */
#define ssid_wifi " "      /* Coloque aqui o nome da rede wiifi que o ESP32 deve se conectar */
#define password_wifi " "  /* Coloque aqui a senha da rede wiifi que o ESP32 deve se conectar */

/* Definições do Telegram */
#define TEMPO_ENTRE_CHECAGEM_DE_MENSAGENS   250 //ms

/* Token de acesso Telegram */
#define token_acesso_telegram " "  /* Coloque aqui o seu token de acesso Telegram (fornecido pelo BotFather) */

/* Definições das mensagens possíveis de serem recebidas */
#define CMD_CLIMA               "CLIMA"
#define CMD_LIGA_RELE_1         "L1"
#define CMD_LIGA_RELE_2         "L2"
#define CMD_LIGA_RELE_3         "L3"
#define CMD_LIGA_RELE_4         "L4"
#define CMD_DESLIGA_RELE_1      "D1"
#define CMD_DESLIGA_RELE_2      "D2"
#define CMD_DESLIGA_RELE_3      "D3"
#define CMD_DESLIGA_RELE_4      "D4"
#define CMD_LIGA_TODOS_RELES    "LL"
#define CMD_DESLIGA_TODOS_RELES "DD"

/* GPIOs usados */
#define GPIO_RELE1              23
#define GPIO_RELE2              22
#define GPIO_RELE3              21
#define GPIO_RELE4              19

/* Variáveis e objetos globais */
WiFiClientSecure client;
UniversalTelegramBot bot(token_acesso_telegram, client);
DHT dht(DHTPIN, DHTTYPE);
unsigned long timestamp_checagem_msg_telegram = 0;
int num_mensagens_recebidas_telegram = 0;
String resposta_msg_recebida;

/* Prototypes */
void init_wifi(void);
void conecta_wifi(void);
void verifica_conexao_wifi(void);
unsigned long diferenca_tempo(unsigned long timestamp_referencia);
String trata_mensagem_recebida(String msg_recebida);

/* 
 *  Implementações
 */
 
/* Função: inicializa wi-fi
 * Parametros: nenhum
 * Retorno: nenhum 
 */
void init_wifi(void) 
{
    Serial.println("------WI-FI -----");
    Serial.print("Conectando-se a rede: ");
    Serial.println(ssid_wifi);
    Serial.println("Aguarde...");    
    conecta_wifi();
}

/* Função: conecta-se a rede wi-fi
 * Parametros: nenhum
 * Retorno: nenhum 
 */
void conecta_wifi(void) 
{
    /* Se ja estiver conectado, nada é feito. */
    if (WiFi.status() == WL_CONNECTED)
        return;

    /* refaz a conexão */
    WiFi.begin(ssid_wifi, password_wifi);
    
    while (WiFi.status() != WL_CONNECTED) 
    {        
        vTaskDelay( 100 / portTICK_PERIOD_MS );
        Serial.print(".");
    }
  
    Serial.println();
    Serial.print("Conectado com sucesso a rede wi-fi ");
    Serial.println(ssid_wifi);
    Serial.print("IP: ");
    Serial.println(WiFi.localIP());
}

/* Função: verifica se a conexao wi-fi está ativa 
 *         (e, em caso negativo, refaz a conexao)
 * Parametros: nenhum
 * Retorno: nenhum 
 */
void verifica_conexao_wifi(void)
{
    conecta_wifi(); 
}

/* Função: calcula a diferença de tempo entre o timestamp
 *         de referência e o timestamp atual
 * Parametros: timestamp de referência
 * Retorno: diferença de tempo 
 */
unsigned long diferenca_tempo(unsigned long timestamp_referencia)
{
    return (millis() - timestamp_referencia);
}

/* Função: trata mensagens recebidas via Telegram
 * Parametros: mensagem recebida
 * Retorno: resposta da mensagem recebida 
 */
String trata_mensagem_recebida(String msg_recebida)
{
    String resposta = "";
    bool comando_valido = false;
    float temperatura_lida = 0.0;
    float umidade_lida = 0.0;

    /* Faz tratamento da mensagem recebida */
    if (msg_recebida.equals(CMD_CLIMA))
    {
        /* Responde com temperatura ambiente e umidade relativa do ar 
           obtidas do sensor DHT22 */
        temperatura_lida =  dht.readTemperature();
        umidade_lida = dht.readHumidity();
           
        resposta = "Informacoes do clima: temperatura = "+
                   String(temperatura_lida)+
                   "C e umidade = "+
                   String(umidade_lida)+"%";   
                   
        comando_valido = true;   
    }

    if (msg_recebida.equals(CMD_LIGA_RELE_1))
    {
        digitalWrite(GPIO_RELE1, LOW);
        
        /* Responde com confirmação que ligou relé 1 */
        resposta = "Rele 1 ligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_LIGA_RELE_2))
    {
        digitalWrite(GPIO_RELE2, LOW);
        
        /* Responde com confirmação que ligou relé 2 */
        resposta = "Rele 2 ligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_LIGA_RELE_3))
    {
        digitalWrite(GPIO_RELE3, LOW);
        
        /* Responde com confirmação que ligou relé 3 */
        resposta = "Rele 3 ligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_LIGA_RELE_4))
    {
        digitalWrite(GPIO_RELE4, LOW);
        
        /* Responde com confirmação que ligou relé 4 */
        resposta = "Rele 4 ligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_DESLIGA_RELE_1))
    {
        digitalWrite(GPIO_RELE1, HIGH);
        
        /* Responde com confirmação que desligou relé 1 */
        resposta = "Rele 1 desligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_DESLIGA_RELE_2))
    {
        digitalWrite(GPIO_RELE2, HIGH);
        
        /* Responde com confirmação que desligou relé 2 */
        resposta = "Rele 2 desligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_DESLIGA_RELE_3))
    {
        digitalWrite(GPIO_RELE3, HIGH);
        
        /* Responde com confirmação que desligou relé 3 */
        resposta = "Rele 3 desligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_DESLIGA_RELE_4))
    {
        digitalWrite(GPIO_RELE4, HIGH);
        
        /* Responde com confirmação que desligou relé 4 */
        resposta = "Rele 4 desligado";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_LIGA_TODOS_RELES))
    {
        digitalWrite(GPIO_RELE1, LOW);
        digitalWrite(GPIO_RELE2, LOW);
        digitalWrite(GPIO_RELE3, LOW);
        digitalWrite(GPIO_RELE4, LOW);
        
        /* Responde com confirmação que ligou todos relés */
        resposta = "Todos os reles foram ligados";
        comando_valido = true;
    }

    if (msg_recebida.equals(CMD_DESLIGA_TODOS_RELES))
    {
        digitalWrite(GPIO_RELE1, HIGH);
        digitalWrite(GPIO_RELE2, HIGH);
        digitalWrite(GPIO_RELE3, HIGH);
        digitalWrite(GPIO_RELE4, HIGH);
        
        /* Responde com confirmação que desligou todos relés */
        resposta = "Todos os reles foram desligados";
        comando_valido = true;
    }

    if (comando_valido == false)
        resposta = "Comando invalido: "+msg_recebida;      
 
    return resposta;
}

void setup() 
{
    Serial.begin(115200);
    
    /* Configura GPIOs de controle dos relés e deixa 
       todos os relés desacionados */
    pinMode(GPIO_RELE1, OUTPUT);
    pinMode(GPIO_RELE2, OUTPUT);
    pinMode(GPIO_RELE3, OUTPUT);
    pinMode(GPIO_RELE4, OUTPUT);
    digitalWrite(GPIO_RELE1, HIGH);
    digitalWrite(GPIO_RELE2, HIGH);
    digitalWrite(GPIO_RELE3, HIGH);
    digitalWrite(GPIO_RELE4, HIGH);

    /* Inicializa DHT22 */
    dht.begin();
    
    /* Inicializa a conexão wi-fi */
    init_wifi();

    /* Inicializa timestamp de checagem de mensagens recebidas via Telegram */
    timestamp_checagem_msg_telegram = millis();
}

void loop() 
{
    int i;
    
    /* Garante que o wi-fi está conectado */
    verifica_conexao_wifi();

    /* Verifica se é hora de checar por mensagens enviadas ao bot Telegram */
    if ( diferenca_tempo(timestamp_checagem_msg_telegram) >= TEMPO_ENTRE_CHECAGEM_DE_MENSAGENS)
    {
        /* Verifica se há mensagens a serem recebidas */
        num_mensagens_recebidas_telegram = bot.getUpdates(bot.last_message_received + 1);

        if (num_mensagens_recebidas_telegram > 0)
        {
            Serial.print("[BOT] Mensagens recebidas: ");
            Serial.println(num_mensagens_recebidas_telegram);
        }
        
        /* Recebe mensagem a mensagem, faz tratamento e envia resposta */
        while(num_mensagens_recebidas_telegram) 
        {
            for (i=0; i<num_mensagens_recebidas_telegram; i++) 
            {                
                resposta_msg_recebida = "";
                resposta_msg_recebida = trata_mensagem_recebida(bot.messages[i].text);
                bot.sendMessage(bot.messages[i].chat_id, resposta_msg_recebida, "");
            }
            
            num_mensagens_recebidas_telegram = bot.getUpdates(bot.last_message_received + 1);
        }
        
        /* Reinicializa timestamp de checagem de mensagens recebidas via Telegram */
        timestamp_checagem_msg_telegram = millis();
    }
}

Interação com o projeto

Uma vez gravado o código-fonte e com o mesmo rodando no ESP32, é hora de interagir com o projeto usando o Telegram. Para isso, utilize no chat com o bot (através do endereço web fornecido pelo BotFather) do projeto os comandos abaixo. Utilize-os da forma que estão (tudo em maiúsculo).

  • CLIMA: ao receber o texto “clima”, o bot responderá com a temperatura ambiente e umidade relativa do ar, ambas lidas do sensor DHT22.
  • L1: liga / aciona o relé 1.
  • D1: desliga / desaciona o relé 1.
  • L2: liga / aciona o relé 2.
  • D2: desliga / desaciona o relé 2.
  • L3: liga / aciona o relé 3.
  • D3: desliga / desaciona o relé 3.
  • L4: liga / aciona o relé 4.
  • D4: desliga / desaciona o relé 4.
  • LL: liga / aciona todos os quatro relés
  • DD: desliga / desaciona todos os quatro relés

A figura 4 mostra a conversa via usuário e ESP32 pelo Telegram. Desta forma, é possível “conversar” com o ESP32 e executar, à distância via Telegram, as ações do projeto.

Chat entre usuário e ESP32, via Telegram
Figura 4 – chat entre usuário e ESP32, via Telegram

Gostou deste post sobre como controlar 4 relés e medir temperatura e umidade com ESP32 via Telegram? Deixe seu comentário logo abaixo. Em caso de dúvidas, caso queira trocar uma ideia, ou até mesmo dividir seu projeto, acesse nosso Fórum!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *