Controle seu ESP32 usando Telegram 8

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 MakerHero-ESP32 e o username é MakerHero-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.

Faça seu comentário

Acesse sua conta e participe

8 Comentários

    1. Bom dia Francisco.

      O que difere o ESP32 NODEMCU para o ESP32 padrão é a plataforma open-source para IOT. Ou seja, o NODEMCU tem um firmware aberto. Em resumo, o uso do ESP32 NODEMCU é mais indicado para aplicações que terão interações envolvendo IOT.

      Att.

  1. boa noite eu usava esse controle, mais do nada ele parou de funcionar
    meu ESP32 compila normalmente porem o TELEGRAM não responde nada
    o q devo fazer?
    poderia me dar uma força nessa??

    GRATO.

  2. Estou tentando fazer funcionar, mas nao vem as mensagens para o esp8266.. Eu li algo que estao pedindo SSL…sera que eh isso?

    1. Olá Rafael,

      Provavelmente sim. Vamos dar uma olhadinha mais a fundo nisso e qualquer coisa atualizamos o post.

      Abraço!
      Rosana – Equipe MakerHero

  3. Ola,
    Funciona no ESP8266?

    1. O meu funcionava perfeitamente e depois de uma atualização do telegram deixou de funcionar. Sabe se foi geral?