Recents in Beach


Receba o meu conteúdo GRATUITAMENTE


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:




Postar um comentário

8 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
  4. muito bom!!!!! como expandir as portas analógicas? o ideal é que as lâmpadas sejam ligadas a um interruptor three way, então é necessário sensor de corrente para cada relé e estes usam portas analógicas. Outra solucação seria usar um esp32 e suas 18 portas adc. será que dá certo?

    ResponderExcluir
  5. Alguem pode me dizer uma foma de adcionar um interruptor fisico para esse projeto

    ResponderExcluir
  6. Infelizmente os links estão quebrados... Muita vontade de baixar e estudar os códigos... Tomara que fiquem disponíveis novamente!

    ResponderExcluir