segunda-feira, 5 de fevereiro de 2018

NodeMcu + MQTT + ANDROID = IOT.

            Olá pessoal que acompanha o blog! nos últimos anos temos ouvido falar muito de "internet das coisas" (IOT = internet of things) , uma arquitetura pensada na interação entre dispositivos via internet e estes com o usuário. Este será o primeiro post sobre o assunto e vamos começar com algo simples, vamos colocar 2 leds para representar o acionamento de 2 lâmpadas , e mais 2 leds para representar o acionamento de 2 relés que podem estar ligados a qualquer carga.Isto será feito através de um servidor nas nuvens dedicado a IOT(geralmente chamado de "BROKER"),dentro do conceito do  BROKER existe 2 tipos de informação o publish e o subscribe  que se refere ao envio e o recebimento de dados respectivamente,veja a figura a seguir.
          Apesar do NodeMcu ser o dispositivo a ser acionado e portanto deveria apenas receber dados (subscribe) mas ele também informa quais os tópicos(tipo de dispositivo acionado) que será usado naquela conexão, alem de poder enviar status de controle, sendo por este motivo representado como uma comunicação de envio e recepção.O  protocolo usado para fazer tudo funcionar é chamado de MQTT(Message Queue Telemetry Transport) que será o responsavel por fazer as máquinas conversarem entre si M2M(Machine to Machine).
         Para fazer toda a "mágica" acontecer é preciso ter instalado o software do Arduino com as libs do ESP8266,Abra a janela de preferências na interface Arduino e digite no campo “Additional Board Manager URLs” o seguinte endereço:  http://arduino.esp8266.com/stable/package_esp8266com_index.json , depois é só instalar as bibliotecas indo na aba do gerenciador de placas do Arduino, para usar o MQTT será necessario adicionar a biblioteca "PubSubClient" que pode ser baixada(aqui) e colocada dentro da pasta "libraries" nos arquivos de instalação do Arduino, deve ficar em algo assim "C:\Arduino\arduino-1.8.5\Sketchbook\libraries\PubSubClient" eu preferi deixar a pasta do executável fora da pasta padrão do windows para não ter problemas de acesso a arquivos por parte do programa arduino. Estando com tudo corretamente preparado é só rodar o código fonte que estará anexado a este post.
        Para usar o servidor MQTT vc deve criar seu cadastro(existem vários destes procure o que achar melhor),no meu caso usei o "cloudMQTT", apenas uma obrsevação no video errei ao dizer que os servidores estavam localizados nos EUA, na verdade um fica lá(na Virginia) e o outro na Europa(Irlanda), no  vídeo de demostração vou dar mais detalhes das configurações dele.
       Para usar o Android ou qualquer outro Sistema operacional para Smartphone pode se usar uma solução pronta(existem diversas opções) para gerenciar seu dispositivo, eu usei o "MQTT Dash", no vídeo de demostração abaixo vou dar mais detalhes.
       Para melhor acompanhamento do que está acontecendo com o modulo tudo que é feito é também enviado via porta serial (emulada), ou seja através de um terminal serial RS232 podemos acompanhar todos os passos do circuito.Observe que no codigo o comando para ligar e desligar tanto os reles quanto as lâmpadas(led) é o mesmo, ou seja posso padronizar os mesmos comandos para dispositivos diversos não necessitando ter vários comandos(um pra cada dispositivo).
       O circuito elétrico  de testes da protoboard ficou assim:
        Mas você deve estar se perguntando por que usar um BROKER(servidor nas nuvens) se poderia usar uma simples pagina HTTP?A resposta é devido a 2 fatores, o primeiro é que usando um webservidor você pode acessar seu dispositivo de qualquer ponto do planeta sem a necessidade de fazer muitas configurações(caso contrario precisaria de liberar a porta de seu modem e usar um serviço de DDNS ou VPN).O segundo motivo é que usando um protocolo como o MQTT que foi pensado,preparado e padronizado para o uso de IOT a comunicação é muito mais rápido do que usar uma pagina HTTP.
O código fonte:

//Autor: Aguivone    -  microcontroladores-C
//Descricao: Placa para acionar 4 leds usado um servidor MQTT.
//Data: 18/01/18
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <ESP8266WiFi.h>
#include <PubSubClient.h> // essa lib deve ser adicionada em seu programa do arduino
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//variaveis usadas na inicialização da wifi
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const char* ssid = "nome da wifi"; //Aqui o nome da sua rede local wifi
const char* password =  "senha"; // Aqui a senha da sua rede local wifi
const char* mqttServer = "algumacoisa.cloudmqtt.com"; // Aqui o endereço do seu servidor fornecido pelo site 
const int mqttPort =16000; // Aqui mude para sua porta fornecida pelo site
const char* mqttUser = "xxxxxx"; //  Aqui o nome de usuario fornecido pelo site
const char* mqttPassword = "hfjuytsgeh"; //  Aqui sua senha fornecida pelo site

WiFiClient espClient;
PubSubClient client(espClient);
/*
Equivalencia das saidas Digitais entre nodeMCU e ESP8266 (na IDE do Arduino)
-------------------------------------------------
NodeMCU / ESP8266  |  NodeMCU / ESP8266  |
D0 = 16            |  D6 = 12            |
D1 = 5             |  D7 = 13            |
D2 = 4             |  D8 = 15            |
D3 = 0             |  D9 = 3             |
D4 = 2             |  D10 = 1            |
D5 = 14            |                     |
-------------------------------------------------
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Definindo o nome dos pinos
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const int  LED_STATUS = 2; // led de status(estou usando o led que já vem no modulo esp. 
const int  ANALOGICA = A0; // porta analogica
//////////////configura os pinos dos reles/////////////////////////////
const int RELE1 = 0; 
const int RELE2 = 4;
const int LED1 = 5;
const int LED2 = 14;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//variaveis globais
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mqtt_callback(char* topic, byte* dados_tcp, unsigned int length);///dados_tcp = payload


void setup() { 
  pinMode(RELE1, OUTPUT);
  pinMode(RELE2, OUTPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  digitalWrite(RELE1,LOW);//desliga todos os reles
  digitalWrite(RELE2,LOW);
  digitalWrite(LED1,LOW);
  digitalWrite(LED2,LOW);
 
  Serial.begin(115200);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) 
  {    //inicialmente pisca o led da placa do nodemcu(é a mesma do ESP8266).
     delay(100);
    Serial.println("Conectando a WiFi..");
  }
  Serial.println("Conectado!"); 
  client.setServer(mqttServer, mqttPort);//configura servidor com as informações passadas
  client.setCallback(callback);
 
  while (!client.connected()) {
    Serial.println("Conectando ao servidor MQTT...");
    
    if (client.connect("Placa_leds", mqttUser, mqttPassword ))//colocar aqui o nome do dispositivo cliente("Placa_leds")
    {
 
      Serial.println("Conectado ao servidor MQTT!");  
      digitalWrite(LED_STATUS,HIGH); 
 
    } else {
 
      Serial.print("Falha ao conectar ");
      digitalWrite(LED_STATUS,LOW);
      Serial.print(client.state());
      delay(2000);
 
    }
  }
  
  client.publish("Status - placa_rele","Reiniciado!");
  client.publish("Placa_reles","Em funcionamento!");
  client.subscribe("RELE"); ///envia autorização para trabalhar com os topicos led e relé
  client.subscribe("LED"); 
}
 //////////////////
void callback(char* topic, byte* dados_tcp, unsigned int length) 
{
   String msg ; // cria variavel que será responsavel pelo tratamento das informações
   for(int i = 0; i < length; i++) //converte array de bytes em string
    {  char c = (char)dados_tcp[i];
       msg += c;
    } 
   digitalWrite(LED_STATUS,LOW);
   delay(100);   
   digitalWrite(LED_STATUS,HIGH); //só pra indicar que houve recepção 
   Serial.print("\n\r topico:");//sempre será o escolhido no subscribe
   Serial.print(topic);   
   Serial.print("\n\r Pacote recebido:");
   Serial.print(msg);
   if (strcmp(topic, "RELE") == 0)//recebeu comando para trabalhar com o dispositivo relé
   {
    for (int i = 0; i < length; i++) // Varre o vetor(array) inteiro do pacote recebido 
        {         
          //toma ação dependendo da string recebida:      
      
          if (msg.equals("L1"))
          {
              digitalWrite(RELE1, HIGH);
             
          }
          if (msg.equals("D1"))
          {
              digitalWrite(RELE1, LOW);
             
          }
          if (msg.equals("L2"))
          {
              digitalWrite(RELE2, HIGH);
              
          }
          if (msg.equals("D2"))
          {
              digitalWrite(RELE2, LOW);
              
          }
        }
   }
   if (strcmp(topic, "LED") == 0)//recebeu comando para trabalhar com o dispositivo led
   {
       for (int i = 0; i < length; i++) // Varre o vetor(array) inteiro do pacote recebido 
        {         
          //toma ação dependendo da string recebida:      
      
          if (msg.equals("L1"))
          {
              digitalWrite(LED1, HIGH);
              
          }
          if (msg.equals("D1"))
          {
              digitalWrite(LED1, LOW);
             
          }
          if (msg.equals("L2"))
          {
              digitalWrite(LED2, HIGH);
              
          }
          if (msg.equals("D2"))
          {
              digitalWrite(LED2, LOW);
             
          }
        }
   }
 
}
 
void loop() {        
     client.loop();
}

Vídeo de demonstração e algumas explicações:




            Espero ter ajudado a quem está iniciando neste fantástico mundo da tecnologia da internet das coisas(IOT).espero postar outros exemplos de uso em breve.

4 comentários :

  1. Poderia entrar em contacto comigo por favor professor ,cmsomautomotivo@hotmail.com

    ResponderExcluir
  2. Parabéns pelo video muito bem.explicado estou usando este código mas queria implementar uma condição de guarda seu status real de todos os equipamentos ligados ,e colocar um interruptor Wi-Fi poderia me ajudá por favor abraço Cristiano

    ResponderExcluir
  3. Ótima explicação, eu estava com dificuldades de configurar mais pinos no meu ESP.

    ResponderExcluir
  4. Fiz em casa 2 esp com tópicos diferentes apontando para mesma conta do cloud quando sobe o segundo tava os 2, é uma limitação do serviço?

    ResponderExcluir

olá,digite aqui seu comentário!