Use o Raspberry Pi para controlar o NodeMCU – Parte 2 4

Esta é a segunda e última parte do projeto mostrando como usar o Raspberry Pi para controlar o NodeMCU,  e neste projeto você pode controlar as saídas de até cinco NodeMCUs diferentes com uma GUI feita em Python com TKinter.

Detalhe ESP8266 NodeMCU

O controle é feito pela Internet utilizando MQTT, ou seja, o controle pode ser feito de qualquer lugar do mundo com conectividade à Internet. Aqui será mostrado como programar os NodeMCUs de forma a fazerem o proposto.

Material necessário

Além do material listado na parte 1, você precisará de:

  • Cinco NodeMCUs (cada um com um cabo micro-USB e fonte 5V para alimentação, com no mínimo 1A de corrente de saída)
  • Cinco elementos que deseja acionar / desacionar através do output (LEDs, relés, válvulas solenóides, etc.).
    No caso deste projeto, como forma de exemplo, serão controlados cinco LEDs. Dessa forma, serão necessários 5 resistores 220ohm 1/4W e 5 LEDs (cor a sua escolha).
  • É recomendável o uso de protoboards também (400 ou 830 pontos), conforme necessidade do seu projeto.

Lembre-se que para este projeto você não precisa necessariamente ter 5 placas NodeMCU, você pode usar, por exemplo, o programa com apenas um NodeMCU conectado e fazer os testes necessários.

Recomendações e requisitos

Antes de prosseguir com o projeto para controlar o NodeMCU usando Raspberry Pi, recomendo fortemente que leia nossos artigos listados abaixo. Eles servem de pré-requisito para a programação e uso do NodeMCU conforme é preciso aqui neste projeto.

Portanto, deste ponto em diante, assume-se que seu NodeMCU esteja totalmente operacional, a biblioteca PubSubClient esteja instalada e que seja possível programá-lo pela Arduino IDE.

Circuito esquemático

O circuito esquemático em que cada NodeMCU é envolvido depende muito do que você deseja controlar (LEDs, relés, válvulas solenóides, etc.). Como exemplo, assumirei que LEDs serão controlados.

Sendo assim, deve-se montar cinco circuitos conforme circuito esquemático da figura 1:

Usando Raspberry Pi para controlar o NodeMCU

O resistor utilizado nos testes tem o valor de 10K, mas você pode usar outros valores.

Código-fonte do programa para controlar o NodeMCU

Conforme foi visto na parte 1 deste projeto para controlar o NodeMCU usando Raspberry Pi, todos os botões da GUI quando clicados fazem com que seja enviado um texto exclusivo (“BT1“, “BT2“, “BT3“, “BT4” e “BT5“) num determinado tópico. Portanto, cada NodeMCU deverá ser capaz de se subescrever ao mesmo tópico o qual o texto é enviado e tratar a mensagem, de modo a “decidir” se a mensagem foi para ele ou não. Dessa forma:

  • O NodeMCU 1 deverá alterar o output D0 se receber o texto “BT1” no referido tópico MQTT
  • O NodeMCU 2 deverá alterar o output D0 se receber o texto “BT2” no referido tópico MQTT
  • O NodeMCU 3 deverá alterar o output D0 se receber o texto “BT3” no referido tópico MQTT
  • O NodeMCU 4 deverá alterar o output D0 se receber o texto “BT4” no referido tópico MQTT
  • O NodeMCU 5 deverá alterar o output D0 se receber o texto “BT5” no referido tópico MQTT

Desta forma, para cada NodeMCU, deve-se alterar o valor da variável “CmdNodeMCU” para “BT1”, “BT2”, “BT3”, “BT4” ou “BT5”, dependendo do NodeMCU a ser programado (fazendo com que cada NodeMCU obedeça a um texto somente).

Segue abaixo o código-fonte. Preste atenção nos comentários, eles explicam passos importantes de todo o projeto.

//Programa: NodeMCU e MQTT - controle do NodeMCU pela GUI Python
//Autor: MakerHero e Pedro Bertoleti

#include <ESP8266WiFi.h> // Importa a Biblioteca ESP8266WiFi
#include <PubSubClient.h> // Importa a Biblioteca PubSubClient

//defines:
//defines de id mqtt e tópicos para publicação e subscribe
#define TOPICO_SUBSCRIBE "MQTTDisplayRaspPi"     //tópico MQTT de escuta. 
                                                 //ATENÇÃO: deve ser o mesmo tópico de publish utilizado na Raspberry PI!!!
                                                 
#define ID_MQTT  "NodeMCUGUIPython"     //id mqtt (para identificação de sessão)
                                        //IMPORTANTE: este deve ser único no broker (ou seja, 
                                        //            se um client MQTT tentar entrar com o mesmo 
                                        //            id de outro já conectado ao broker, o broker 
                                        //            irá fechar a conexão de um deles).
                               

//defines - mapeamento de pinos do NodeMCU
#define D0    16
#define D1    5
#define D2    4
#define D3    0
#define D4    2
#define D5    14
#define D6    12
#define D7    13
#define D8    15
#define D9    3
#define D10   1


// WIFI
const char* SSID = "SSID"; // SSID / nome da rede WI-FI que deseja se conectar
const char* PASSWORD = "SENHA"; // Senha da rede WI-FI que deseja se conectar
 
// MQTT
const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar
int BROKER_PORT = 1883; // Porta do Broker MQTT

//Variáveis e objetos globais
WiFiClient espClient; // Cria o objeto espClient
PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient
char EstadoSaida = '0';  //variável que armazena o estado atual da saída
char CmdNodeMCU[3] = {'B','B', 'B'};   //ATENÇÃO: troque o "BBB" por um dos códigos enviados pela Raspberry PI ("BT1", "BT2", "BT3", "BT4" ou "BT5"),
                                       //         de modo que cada NodeMCU "espere" apenas por um deles
 
//Prototypes
void initSerial();
void initWiFi();
void initMQTT();
void reconectWiFi(); 
void mqtt_callback(char* topic, byte* payload, unsigned int length);
void VerificaConexoesWiFIEMQTT(void);
void InitOutput(void);

/* 
 *  Implementações das funções
 */
void setup() 
{
    //inicializações:
    InitOutput();
    initSerial();
    initWiFi();
    initMQTT();
}
 
//Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial 
//        o que está acontecendo.
//Parâmetros: nenhum
//Retorno: nenhum
void initSerial() 
{
    Serial.begin(115200);
}

//Função: inicializa e conecta-se na rede WI-FI desejada
//Parâmetros: nenhum
//Retorno: nenhum
void initWiFi() 
{
    delay(10);
    Serial.println("------Conexao WI-FI------");
    Serial.print("Conectando-se na rede: ");
    Serial.println(SSID);
    Serial.println("Aguarde");
    
    reconectWiFi();
}
 
//Função: inicializa parâmetros de conexão MQTT(endereço do 
//        broker, porta e seta função de callback)
//Parâmetros: nenhum
//Retorno: nenhum
void initMQTT() 
{
    MQTT.setServer(BROKER_MQTT, BROKER_PORT);   //informa qual broker e porta deve ser conectado
    MQTT.setCallback(mqtt_callback);            //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega)
}
 
//Função: função de callback 
//        esta função é chamada toda vez que uma informação de 
//        um dos tópicos subescritos chega)
//Parâmetros: nenhum
//Retorno: nenhum
void mqtt_callback(char* topic, byte* payload, unsigned int length) 
{
    char MsgRecebida[3];
    
    //se a mensagem não tem três caracteres (ou seja, não é "BT1", "BT2", "BT3", "BT4" ou "BT5"), 
    //automaticamente ela é inválida. Nesse caso, nada mais é feito com a mensagem recebida.
    if (length != 3)
      return;

    //obtem a string do payload recebido
    for(int i = 0; i < length; i++) 
       MsgRecebida[i] = (char)payload[i];
   
    //avalia se a mensagem é para este NodeMCU
    if (memcmp(MsgRecebida,CmdNodeMCU,3) == 0)
    {
        if (EstadoSaida == '0') 
        {
           digitalWrite(D0,HIGH);
           EstadoSaida = '1';    
        }
        else
        {
           digitalWrite(D0,LOW);
           EstadoSaida = '0';    
        }
    }    
}
 
//Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair)
//        em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito.
//Parâmetros: nenhum
//Retorno: nenhum
void reconnectMQTT() 
{
    while (!MQTT.connected()) 
    {
        Serial.print("* Tentando se conectar ao Broker MQTT: ");
        Serial.println(BROKER_MQTT);
        if (MQTT.connect(ID_MQTT)) 
        {
            Serial.println("Conectado com sucesso ao broker MQTT!");
            MQTT.subscribe(TOPICO_SUBSCRIBE); 
        } 
        else 
        {
            Serial.println("Falha ao reconectar no broker.");
            Serial.println("Havera nova tentatica de conexao em 2s");
            delay(2000);
        }
    }
}
 
//Função: reconecta-se ao WiFi
//Parâmetros: nenhum
//Retorno: nenhum
void reconectWiFi() 
{
    //se já está conectado a rede WI-FI, nada é feito. 
    //Caso contrário, são efetuadas tentativas de conexão
    if (WiFi.status() == WL_CONNECTED)
        return;
        
    WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI
    
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(100);
        Serial.print(".");
    }
  
    Serial.println();
    Serial.print("Conectado com sucesso na rede ");
    Serial.print(SSID);
    Serial.println("IP obtido: ");
    Serial.println(WiFi.localIP());
}

//Função: verifica o estado das conexões WiFI e ao broker MQTT. 
//        Em caso de desconexão (qualquer uma das duas), a conexão
//        é refeita.
//Parâmetros: nenhum
//Retorno: nenhum
void VerificaConexoesWiFIEMQTT(void)
{
    if (!MQTT.connected()) 
        reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita
    
     reconectWiFi(); //se não há conexão com o WiFI, a conexão é refeita
}

//Função: inicializa o output em nível lógico baixo
//Parâmetros: nenhum
//Retorno: nenhum
void InitOutput(void)
{
    pinMode(D0, OUTPUT);
    digitalWrite(D0, LOW);          
    EstadoSaida = '0';
}


//programa principal
void loop() 
{   
    //garante funcionamento das conexões WiFi e ao broker MQTT
    VerificaConexoesWiFIEMQTT();

    //keep-alive da comunicação com broker MQTT
    MQTT.loop();
}

Projeto em ação!

Agora, basta juntar tudo e comandar os outputs pela GUI na Raspberry PI! Veja abaixo um gif animado mostrando o projeto em ação, utilizando um NodeMCU:

Projeto em funcionamento

Gostou do projeto para controlar o NodeMCU usando Raspberry Pi? Deixe seu comentário logo abaixo.

Faça seu comentário

Acesse sua conta e participe

4 Comentários

  1. Olá, parabéns pelo tutorial, muito útil e didático. Para o meu projeto de TCC estou tentado a usar essa comunicação entre o ESP32 e o Raspberry Pi Zero W, estes que contém módulo wifi embutidos e são muito semelhantes aos que foram utilizados nesse tutorial. Então gostaria de saber quais as mudanças de código necessárias para utilizar o ESP32 no lugar do ESP8266?

    1. Cassio, bom dia e obrigado pelos elogios.

      Para adaptar o código do ESP8266 para o ESP32, eu ACHO (digo acho pois estou sem ESP8266 e ESP32 perto de mim nesse momento) que basta fazer o seguinte:

      1- Trocar a linha:

      #include // Importa a Biblioteca ESP8266WiFi

      Pela linha:

      #include

      2- Modificar as chamadas de:

      digitalWrite(D0,HIGH);
      digitalWrite(D0,LOW);

      Trocando D0 pelo GPIO do ESP32 que deseja que o LED fique (isso variará de acordo com seu projeto).

      Atenciosamente,
      Pedro Bertoleti

  2. Meus parabéns para mais um excelente artigo da série sobre NodeMCU. Venho acompanhando todos desde o início.
    Sobre o acesso a rede externa, eu tenho uma dúvida.
    Se além do normal, que é o WiFi.begin(SSID, PASSWORD), para se acessar ela for necessária autenticação via proxy, é possível usar o NodeMCU nestas condições? Pois num ambiente doméstico esta autenticação normalmente não é necessária, mas num ambiente comercial e/ou industrial este é um requisito de segurança de rede.

    PS. Eu me formei em engenharia no outro lado da Serra da Mantiqueira, na Unifei, em Itajubá.

    Angelo José Roncali da Silva
    1. Angelo, muito obrigado por acompanhar os artigos e pelos elogios!

      Entendi seu problema. Infelizmente, eu nunca cheguei ao ponto de precisar utilizar o NodeMCU com autenticação via proxy. Desculpa não conseguir responder sua pergunta.

      Atenciosamente,
      Pedro Bertoleti