Automação de baixo custo com ESP01



Automação utilizando ESP01 com 16 relés. Este é um modelo de projeto, super barato, por sinal, que vou te mostrar hoje, a partir do qual você pode multiplicar os módulos e chegar até 128 relés, isso porque é possível colocar até oito expansores de portas neste microcontrolador. No nosso circuito, você terá uma aplicação em um smartphone que comunica com o ESP01. Este estará com um expansor que contará com 16 portas, cada uma ligada a um relé. Temos ainda uma fonte regulável de 3v3. Vamos, portanto, controlar um módulo de relé de 16 canais utilizando o ESP01 através do aplicativo Android, que vou disponibilizar para você.



Onde encontrar placa de relês: https://bit.ly/2JKYcGO

Relembrando

Importante destacar, pessoal, que usei neste circuito um chip que chama MCP23016. Não menos importante é você assistir ao vídeo EXPANSOR DE IOS PARA ESP32, ESP8266 E ARDUINO, no qual testo o dispositivo e mostro que ele funciona para estes três tipos de placas.



MCP23016

Temos aqui uma imagem do MCP23016, esse chip com 28 pinos. Devo te contar que existe também o modelo MCP23017, que é mais comum e não precisa de resistor e capacitor, pois tem um clock interno. Isso facilita, mas a sua pinagem é diferente da que mostramos neste vídeo.



Endereço

Para definir o endereço do MCP23016, utilizamos os pinos A0, A1 e A2. Bastando deixar eles em estado HIGH ou LOW para a troca de endereço.
O endereço será formado da seguinte forma:

MCP_Address = 20 + (A2 A1 A0)



Onde A2 A1 A0 podem tomar valores HIGH/LOW, formando assim um número binário de 0 a 7.

Por exemplo:
                 A2 > GND , A1 > GND, A0 > GND (significa 000, logo 20+0 = 20)
Ou então,
                 A2 > HIGH , A1 > GND, A0 > HIGH (significa 101, logo 20+5 = 25)



Comandos

Aqui temos uma tabela com os comandos para comunicação:



Acessos

GP0 / GP1 – Data Port Registers
São dois registradores que fornecem acesso às duas portas do GPIO.
A leitura do registrador fornece o estado dos pinos naquela porta.
Bit = 1 > HIGH                   Bit = 0 > LOW


IODIR0 / IODIR1
São dois registradores que controlam o modo de pino. (Entrada ou Saída)
Bit = 1 > INPUT                                 Bit = 0 > OUTPUT



Estrutura para a comunicação

Aqui tratamos do endereço do chip, comando de acesso e dados, que é uma espécie de protocolo que precisa ser feito para o envio de informações.





Programa

Faremos um programa que consiste em comunicar o ESP01 com o MCP23016, a fim de termos mais GPIOs para utilizar. Esses novos 16 GPIOs que teremos, então, controlarão um módulo relé de 16 canais.
Os comandos serão enviados para o ESP01 através de um aplicativo Android.




MCP23016




ESP-01



Essa é uma placa de 16 relés.



Montagem ESP01




Bibliotecas e variáveis

Vamos incluir as bibliotecas responsáveis pela comunicação i2c e por criar o Access Point e o webserver. Definimos o endereço do chip e das portas. Por fim, as variáveis para guardarmos os valores dos pinos do MCP.

#include <Wire.h> // responsável pela comunicação i2c.
#include <ESP8266WiFi.h>//responsável por criar o accesspoint e o webserver

WiFiServer server(80);//webserver para acessarmos através do aplicativo 

//endereço I2C do MCP23016
#define MCPAddress 0x20
//ENDEREÇOS DE REGISTRADORES
#define GP0  0x00   // DATA PORT REGISTER 0 
#define GP1  0x01   // DATA PORT REGISTER 1 
#define IODIR0  0x06   // I/O DIRECTION REGISTER 0 
#define IODIR1  0x07   // I/O DIRECTION REGISTER 1

// guarda os valores dos pinos do MCP
uint8_t currentValueGP0 = 0; 
uint8_t currentValueGP1 = 0; 


Setup

Inicializamos o ESP01 e configuramos as portas. Também efetuamos a configuração do Access Point e inicializamos o server.

void setup()   {
  Serial.begin(9600);
  delay(1000);
  Wire.begin(0,2); //ESP01
  Wire.setClock(200000);

  configurePort(IODIR0, OUTPUT);
  configurePort(IODIR1, OUTPUT);

  writeBlockData(GP0, 0x00);
  writeBlockData(GP1, 0x00);

  setupWiFi(); //configuração do Access Point
  server.begin();//inicializa o server

}


Loop

Aqui verifico se algum cliente foi conectado ao server. Efetuamos ainda a leitura da primeira linha de requisição. Extraímos os dados para manipulação, definimos o cabeçalho padrão de resposta e enviamos esta resposta ao cliente.

void loop() {
    WiFiClient client = server.available();  
    // Verifica se um cliente foi conectado
    if (!client)
    {
      return;
    }

   String req = client.readStringUntil('\r');// Faz a leitura da primeira linha da requisição

   /* 
        /MR é o header prefixo para saber se a requisição 
        é a esperada para os relés
   */
   if(req.indexOf("/MR") != -1)
   {
      parserData(req);  //a partir da requisição extrai os dados para manipulação                                         
   }
   else{
    Serial.println("invalid request");
    return;
  }
  client.flush();
 
  String s = "HTTP/1.1 200 OK\r\n";        // cabeçalho padrão de resposta
  client.print(s);                         // envia a resposta para o cliente
  delay(1);   
} // end loop


parserData

A partir da requisição, buscamos os dados referentes aos relés. Enviamos, então, os dados para o MCP23016.




//a partir da requisição busca os dados referente aos relés
void parserData(String data)
{
   uint8_t relay = -1;
   uint8_t gp = -1;
   uint8_t value = -1;
   int index =  data.indexOf("/MR"); //busca o index do prefixo MR

   if(data[index+5] == '/') // /MR01/1, onde 0 = GP; 1 = RELE; 1 = ESTADO(on/off)
   {
     gp    = data[index+3]-'0';
     relay = data[index+4]-'0';
     value = data[index+6]-'0';
     //envia os dados para o MCP23016
     //[relay-1] porque o MCP vai de 0-7 os pinos
     writePinData(relay-1, value, gp);
   }

}


configurePort

Configuramos o modo dos pinos GPIO (GP0 ou GP1).

//configura o modo dos pinos GPIO (GP0 ou GP1)
//como parametro passamos:
//  port: GP0 ou GP1 
//  INPUT para todos as portas do GP trabalharem como entrada
//  OUTPUT para todos as portas do GP trabalharem como saida
//  custom um valor de 0-255 indicando o modo das portas (1=INPUT, 0=OUTPUT) 
//  ex: 0x01 ou B00000001 ou 1 : indica que apenas o GPX.0 trabalhará como entrada, o restante como saida
void configurePort(uint8_t port, uint8_t custom)
{
  if(custom == INPUT)
  {
    writeBlockData(port, 0xFF);
  }
  else if(custom == OUTPUT)
  {
    writeBlockData(port, 0x00);
  }
  else
  {
    writeBlockData(port, custom);
  }
}


writePinData

Nesta parte do código, mudamos o estado de um pino desejado e enviamos os dados para o MCP.

//muda o estado de um pino desejado, passando como parametro:
//pin = pino desejado; value = 0/1 (on/off); gp = 0/1 (PORT do MCP)
void writePinData(int pin, int value, uint8_t gp)
{
    uint8_t statusGP = 0;
    
    if(gp == GP0) statusGP = currentValueGP0;
    else statusGP = currentValueGP1;
    
    if (value == 0)
    {
      statusGP &= ~(B00000001 << (pin)); // muda o pino para LOW
    }
    else if (value == 1)
    {
      statusGP |= (B00000001 << (pin)); // muda o pino para HIGH
    }

    if(gp == GP0) currentValueGP0 = statusGP;
    else currentValueGP1 = statusGP;
    //envia os dados para o MCP
    writeBlockData(gp, statusGP);    
    delay(10);
}


writeBlockData & setupWiFi

Aqui, enviamos dados para o MCP23016 através do barramento i2c. Na sequência, configuramos as propriedades para habilitar o Access Point. Por fim, configuramos o WiFi para o modo Access Point e criamos um AP com SSID e PASSWORD.

//envia dados para o MCP23016 através do barramento i2c
//reg: REGISTRADOR
//data: dados (0-255)
void writeBlockData(uint8_t port, uint8_t data)
{
  Wire.beginTransmission(MCPAddress);
  Wire.write(port);
  Wire.write(data);
  Wire.endTransmission();
  delay(10);
}

//configura as propriedades para habilitar o ACCESS POINT
void setupWiFi()
{
  WiFi.mode(WIFI_AP);
  WiFi.softAP("ESP01_RELAY", "12345678");
}


Aplicativo

Para criar o aplicativo utilizamos o MIT App Inventor 2, que pode ser acessado através do link: http://ai2.appinventor.mit.edu/.

O aplicativo consiste em duas telas contento oito pares de botões em cada, indicando o estado de cada relé.




A seguir veremos alguns dos blocos de programação utilizados:


IMPORTANTE: o endereço IP padrão do ESP como Access Point é 192.168.4.1

1.       Quando a tela inicializa guardamos na memória o IP e chamamos o procedimento para recuperar o estado dos botões (ON/OFF).
2.       Chama a outra tela




1.       Ao clicar no botão ON de algum dos relés, faremos alterações visuais no botão (blocos verdes). WebViewer1.GoToUrl faz uma requisição para o nosso ESP01 concatenando na url os dados MR01/1.
2.       Ao clicar no botão OFF de algum dos relés, faremos alterações visuais no botão (blocos verdes). WebViewer1.GoToUrl faz uma requisição para o nosso ESP01 concatenando na url os dados MR01/0.




Esse procedimento serve para recuperar o estado dos botões (relés), pois, ao mudar de tela, ela volta ao padrão de criação.
O bloco amarelo se repete para cada um dos pares de botões.



Seguem os arquivos do projeto para download:
Arquivo de projeto MIT App Inventor 2 – download
APK do aplicativo para instalar no android – download


Faça o download dos outros arquivos:




3 comentários:

  1. Fernando, muito obrigado por semear o conhecimento!!!!!

    ResponderExcluir
  2. Fernando, muito obrigado
    pode dar uma dica como faço para utilizar só o esp8266 sem o mcc23016
    por exe: wemos d1 mini

    ResponderExcluir
  3. Fernando, muito obrigado
    pode dar uma dica como faço para utilizar só o esp8266 sem o mcc23016
    por exe: wemos d1 mini

    ResponderExcluir

Tecnologia do Blogger.