Seguindo nosso projeto de um interruptor WiFi para lâmpada, hoje daremos mais um passo. Iremos nesse artigo preparar a inteligência do nosso projeto, o firmware que será gravado no ESP8266-01.
Caso tenha perdido a primeira etapa do nosso projeto, poderá conferir os detalhes no nosso primeiro artigo da série, onde fizemos a apresentação do projeto e apresentamos o hardware proposto.
Correções no circuito
Antes de começarmos a falar do firmware temos que fazer algumas atualizações no nosso projeto. O circuito proposto na versão inicial apresentou algumas instabilidades na inicialização do ESP-01. Isso ocorre pois o módulo pode entrar em modo programação e não iniciar o firmware corretamente. Fiz um artigo explicando como configurar os GPIOs do ESP-01 para evitar esse problema.
A versão atualizada do circuito também está disponível no github assim como o layout modificado da placa. O esquema elétrico pode ser conferido na imagem a seguir:
Firmware do ESP8266-01
O firmware foi desenvolvido e gravado no ESP utilizando a IDE do arduino. Para fazer a configuração da IDE para utilizar os módulos ESP e para saber como gravar o módulo no mesmo ambiente podemos seguir este artigo disponibilizado aqui mesmo no Embarcados.
O firmware foi codificado para conectar na sua rede WiFi. Para isso, é necessário, no código, inserir o nome da sua rede (SSID) e a senha. Para evitar que o módulo pegue um IP diferente cada vez que se conectar, precisamos fixa-lo, ajustando o IP, DNS e máscara da rede no código.
A estrutura do código é simples, ele recebe uma requisição do aplicativo através do método GET e responde enviando uma mensagem via HTTP, essa mensagem segue a seguinte estrutura: [{Lampada:XX,Led:XX}]. XX é o estado da lâmpada que pode ser ON ou OFF, ZZ é o estado da função Led (falaremos sobre essa função mais a frente). A requisição do app pode solicitar o status da lâmpada e função led (/?status), controlar a lampada (/?lamp=on/off) ou a função led (/?led=on/off).
Esse projeto foi pensado para ser algo fácil e didático, a segurança das informações não foram consideradas. As mensagens trocadas não contêm nenhum tipo de criptografia e podem ser vistas facilmente através de qualquer browser. Caso precise de algum tipo de segurança sinta-se livre para modificar o código como quiser.
A função led foi pensada para ajudar a encontrar o interruptor quando o ambiente está escuro. Dessa forma, um led irá operar de forma inversa à lâmpada. Sempre que a lâmpada estiver desligada o led estará ligado. Seja por questão de economia de energia ou simplesmente por estar atrapalhando o sono quando em um quarto, você pode não querer este led aceso. Para isto poderá desligar a função.
Alem de ser controlada pelo aplicativo, a lâmpada também pode ser ligada ou desligada ao receber um pulso de um botão ou interruptor. A função que faz o tratamento da chave no ESP-01 já faz um debounce por software para evitar ruídos. Caso tenha algum problema com o código ou tenha que retirar o ESP da placa, aproveitamos a modificação do circuito para inserir na placa um jumper que permite fazer o acionamento da lâmpada direto pelo interruptor. A placa pode ser adquirida com a equipe MAZZA G-TEC que está apoiando este projeto em conjunto com o Embarcados.
Segue o código que deve gravado no ESP8266-01:
#include <ESP8266WiFi.h>
// Definição dos pinos
#define LED_PIN 2
#define LAMP_PIN 0
#define BT_PIN 3
// Configuração de IP da rede
IPAddress myIP(192,168,0,118);
IPAddress myDNS(192,168,0,1);
IPAddress myMASC(255,255,255,0);
void hardwareInit(void);
void trataRequest(void);
void enviaResposta(WiFiClient client, bool lampada, bool led);
void atualizaSaidas(bool lampada, bool led);
bool trataChave(void);
// Dados da rede WiFi
const char* ssid = "######";
const char* password = "******";
const char* headerHTLM = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<!DOCTYPE HTML>\n<html>\n";
// Corpo da resposta segue a estrutura -> [{Lampada:XX,Led:ZZ}]
const char* tailHTML = "</html>\n";
bool statusLamp = 0;
bool funcaoLed = 1;
WiFiServer server(80);
void setup(){
Serial.begin(115200);
hardwareInit();
Serial.print("\nConectando a rede: ");
Serial.println(ssid);
WiFi.begin(ssid, password); // Conecta na rede
WiFi.config(myIP, myDNS, myMASC); // Configura IP estático
int i = 0;
while (WiFi.status() != WL_CONNECTED){
delay(1000);
Serial.print(".");
if(++i > 30) ESP.restart(); // Reinicia ESP após 30 segundos
}
Serial.println("\nWiFi Conectado!");
server.begin(); // Inicia Server
Serial.print("Use essa URL para conectar: https://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop(){
trataRequest(); // Trata requisição do app
atualizaSaidas(statusLamp, funcaoLed);
if(trataChave()) statusLamp = !statusLamp;
}
void hardwareInit(void){ // Inicializa hardware
pinMode(LED_PIN, OUTPUT);
pinMode(LAMP_PIN, OUTPUT);
pinMode(BT_PIN, INPUT);
digitalWrite(LED_PIN, HIGH);
digitalWrite(LAMP_PIN, HIGH);
}
void trataRequest(void){ // Trata requisição do app
WiFiClient client = server.available(); // Testa se foi feita requisição
if(!client) return;
while(!client.available()) delay(1); // Aguarda recepção dos dados
String request = client.readStringUntil('\r');// Le dados
client.flush();
if(request.indexOf("status") != -1){
enviaResposta(client, statusLamp, funcaoLed);// Responde requisição
return;
}
if(request.indexOf("lamp") != -1){
if(request.indexOf("on") != -1) statusLamp = true; // Liga lampada
if(request.indexOf("off") != -1) statusLamp = false; // Desliga lampada
enviaResposta(client, statusLamp, funcaoLed);
return;
}
if(request.indexOf("led") != -1){
if(request.indexOf("on") != -1) funcaoLed = true; // Liga função led
if(request.indexOf("off") != -1) funcaoLed = false; // Desliga função led
enviaResposta(client, statusLamp, funcaoLed);
return;
}
}
void enviaResposta(WiFiClient client, bool lampada, bool led){
// Monta corpo da resposta seguindo a estrutura -> [{Lampada:XX,Led:ZZ}]
String resposta = "[{Lampada:";
if(lampada) resposta = resposta + "ON";
else resposta = resposta + "OFF";
resposta += ",Led:";
if(led) resposta = resposta + "ON";
else resposta = resposta + "OFF";
resposta += "]}";
client.print(headerHTLM);
client.print(resposta);
client.print(tailHTML);
}
void atualizaSaidas(bool lampada, bool led){
if(lampada){
digitalWrite(LAMP_PIN, LOW);
digitalWrite(LED_PIN, HIGH);
} else{
digitalWrite(LAMP_PIN, HIGH);
if(led) digitalWrite(LED_PIN, LOW);
else digitalWrite(LED_PIN, HIGH);
}
}
bool trataChave(void){
const unsigned long Delay = 50; // Variaveis para debouce da chave
static unsigned long tempoDebounce = 0;
static int estadoChave = HIGH, ultimaLeitura = HIGH;
bool flag = false;
int leitura = digitalRead(BT_PIN);
if(leitura != ultimaLeitura) tempoDebounce = millis();
if((millis() - tempoDebounce) > Delay){
if(leitura != estadoChave){
estadoChave = leitura;
if(estadoChave == HIGH) flag = true;
}
}
ultimaLeitura = leitura;
return(flag);
}
Mesmo sem o aplicativo, podemos começar a fazer simulações com nosso código utilizando um browser, só precisamos digitar na URL o IP do nosso módulo seguido da requisição que desejamos:
- https://192.168.0.118/?lamp=off
- https://192.168.0.118/?led=on
- https://192.168.0.118/?status
Para isso precisamos estar conectados na mesma rede que o ESP.
Conclusão
Estamos finalizando mais uma etapa do nosso projeto, no próximo artigo faremos nosso aplicativo para Android utilizando a ferramenta APP Inventor do MIT. Se tiver alguma dúvida ou problema com o código deixe seu comentário para que possamos ajudar. Até a próxima.





Alguém conseguiu descobrir o que e o VR “U” ?
Caso queira adicionar botões na página web . Tipo liga. desliga o que teria que fazer no codigo
Queria usar a mesma estrutura do código porém em rede externa
Vou testar … mais gostaria de saber se vc tem algo desse jeito mais usando junto o interruptor three way … caso ele pode ligar pela web e desligar pelo interruptor e vice versa
Ola Paulo Henrique.
Este projeto foi pensado para usar um interruptor simples (ou um botão qualquer). Por conta da distancia dos interruptores não acho que atualmente seja viável utilizar interruptores paralelos. Talvez uma modificação no código ajude, vou pensar nisso e fazer alguns testes.
É possível ligar e desligar tanto pelo interruptor quanto pelo celular utilizando a rede wifi. O módulo e o celular tem que estar na mesma rede.
Abraço.
Show de bola…
mais ainda não testei o seu cod … mais da para adaptar porque eu to usando um sensor de tensão tbm .. então sei qual é o status que ta a lampada .. se ela ta ligada ou desligada
Isso mesmo, através do comando STATUS o módulo te retorna o estado da lâmpada.
Josemar, também sou formado pela USJT. Tenho uma dúvida em relação a esta questão. Se por algum motivo cai o sinal do Wifi.. Eu consigo controlar a lâmpada?
Gostei muito deste Artigo, muito fácil e claro!
E já faz quase tudo o que eu precisava e com EQ ainda pra ajudar!
Bom que gostou Rogério, logo estará disponível o artigo sobre o aplicativo.
Parabéns pelo artigo, bem didático.
Obrigado Carlos, que bom que curtiu.