1. Situação
Em uma sala pequena, a iluminação pode permanecer acesa mesmo quando há claridade suficiente. Também pode ser útil acompanhar o nível de luz e, quando necessário, assumir o controle manual pelo celular ou notebook conectado à mesma rede.
Chegou a hora de juntar o percurso. O sistema vai perceber a luminosidade do ambiente, decidir quando a iluminação deve ser acionada, permitir controle pela rede e apresentar o estado em uma aplicação Web. O objetivo não é adicionar tecnologias por quantidade, mas integrar corretamente o que já foi aprendido.
O núcleo é o mesmo, mas a forma de testar a página Web muda conforme o ambiente.
| Ambiente | Sensor e LED | Wi-Fi | Página Web |
|---|---|---|---|
| ESP32 física | ✓ Completo | ✓ Rede 2,4 GHz compatível | ✓ Completo na mesma rede local |
| Wokwi com gateway público | ✓ Completo, usando o módulo de fotoresistor | ✓ Wokwi-GUEST | △ O servidor executa, mas o navegador não consegue iniciar uma conexão de entrada |
| Wokwi com Private IoT Gateway | ✓ Completo | ✓ Wokwi-GUEST | ✓ Completo em http://localhost:9080/ |
Um projeto começa pela necessidade, não pelo componente.
Em uma sala pequena, a iluminação pode permanecer acesa mesmo quando há claridade suficiente. Também pode ser útil acompanhar o nível de luz e, quando necessário, assumir o controle manual pelo celular ou notebook conectado à mesma rede.
Um LDR percebe a luminosidade e gera um valor analógico para o ESP32.
Um LED representa a lâmpada do projeto. Não usaremos rede elétrica nesta atividade.
No modo automático, o ESP32 decide o estado da iluminação a partir da leitura do LDR e de um limiar calibrado.
Uma página Web mostra a leitura, o modo e o estado da iluminação e permite escolher Ligar, Desligar ou Automático.
Primeiro faremos cada parte funcionar sozinha. Só depois integraremos tudo. Se sensor, LED e rede forem testados ao mesmo tempo, fica mais difícil descobrir onde está um erro.
A arquitetura mostra o papel de cada parte do sistema.
Placa deste projeto: continue usando a ESP32 DevKit baseada no ESP32 original / ESP32-WROOM-32 adotada desde o módulo 6. No Wokwi, escolha ESP32 DevKit v1. GPIO 34 e as observações de ADC desta etapa se referem a essa família.
| Componente | Função | Ligação-base |
|---|---|---|
| ESP32 | Processamento, Wi-Fi e servidor HTTP. | Placa central do projeto. |
| LDR | Perceber a luminosidade. | Divisor de tensão ligado ao GPIO 34. |
| Resistor 10 kΩ | Completar o divisor de tensão do LDR. | Entre o ponto de leitura e GND. |
| LED + resistor 220 Ω | Representar a iluminação. | GPIO 23 → resistor → LED → GND. |
Com essa orientação, a leitura tende a aumentar com mais luz e diminuir no escuro. O valor exato depende do LDR, do resistor e do ambiente; por isso o limiar será calibrado, não tratado como número universal.
No ESP32 clássico, o GPIO 34 é uma entrada do ADC1 e é somente entrada. Isso combina com o LDR e traz outra vantagem importante: os canais ADC2 possuem restrições quando o Wi-Fi está em uso, enquanto o ADC1 evita esse conflito neste projeto.
É o mesmo pino do LED usado no percurso com ESP32. Reutilizar a montagem reduz mudanças desnecessárias e facilita a comparação com os blocos anteriores.
Abra um projeto ESP32 DevKit v1 no Wokwi. O simulador não precisa reproduzir o divisor com componentes passivos discretos: use o componente Photoresistor (LDR) Sensor, que já possui LDR e resistor interno.
| Pino do sensor Wokwi | ESP32 |
|---|---|
| VCC | 3V3 |
| GND | GND |
| AO | GPIO 34 |
O circuito do LED permanece o mesmo. No simulador, altere o controle de luminosidade do fotoresistor para produzir leituras claras e escuras.
Uma diferença importante: no divisor físico desenhado acima, a leitura tende a aumentar com mais luz. No módulo de fotoresistor do Wokwi, a leitura tende a aumentar no escuro. O código abaixo possui uma configuração explícita para lidar com essa diferença sem esconder o que está acontecendo.
Antes de Wi-Fi, navegador ou página Web, precisamos responder algo mais simples: o ESP32 consegue medir a luz e controlar o LED corretamente?
Uma etapa pequena produz evidência antes da integração.
Carregue o código abaixo e altere a iluminação sobre o sensor. Na ESP32 física, abra o Monitor Serial em 115200; no Wokwi, o Monitor Serial acompanha automaticamente a velocidade configurada pelo programa. Observe primeiro uma leitura claramente iluminada e outra claramente escura. Depois escolha LIMIAR entre esses dois valores.
Montagem física do diagrama: mantenha LEITURA_MAIOR_NO_ESCURO = false. Wokwi com Photoresistor Sensor: use LEITURA_MAIOR_NO_ESCURO = true. Assim, o restante da lógica permanece igual nos dois ambientes.
const int LDR = 34;
const int LED = 23;
const int LIMIAR = 2000; // ajuste depois de observar claro e escuro
// Física do diagrama: false
// Wokwi Photoresistor Sensor: true
const bool LEITURA_MAIOR_NO_ESCURO = false;
bool ambienteEscuro(int leitura) {
if (LEITURA_MAIOR_NO_ESCURO) {
return leitura > LIMIAR;
}
return leitura < LIMIAR;
}
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
}
void loop() {
int luminosidade = analogRead(LDR);
bool escuro = ambienteEscuro(luminosidade);
digitalWrite(LED, escuro ? HIGH : LOW);
Serial.print("Luminosidade: ");
Serial.print(luminosidade);
Serial.print(" | Ambiente: ");
Serial.println(escuro ? "escuro" : "claro");
delay(500);
}Ao mudar a luminosidade, a leitura deve variar de forma perceptível. Quando o código classificar o ambiente como escuro, o LED deve acender; quando classificar como claro, deve apagar.
Primeiro confira LEITURA_MAIOR_NO_ESCURO. Na montagem física do diagrama ela deve ser false; no sensor do Wokwi, true. Se a montagem física estiver diferente do diagrama, observe as leituras e ajuste conscientemente essa configuração.
Localmente o sistema já percebe e age. Agora queremos ver o estado e controlar o modo a partir de outro dispositivo da rede.
O navegador deixa de ser apenas teste de HTTP e passa a ser a interface do projeto.
No Bloco 6, o ESP32 entrou no Wi-Fi e funcionou como servidor HTTP. Aqui reutilizamos esse conhecimento com uma finalidade maior: a página mostra luminosidade, estado da iluminação e modo de operação.
Celular ou notebook abre a página e envia comandos.
O ESP32 recebe as requisições, monta a página e altera o estado do projeto.
| Rota | Ação |
|---|---|
/ | Mostra o painel atual. |
/ligar | Seleciona modo manual e liga o LED. |
/desligar | Seleciona modo manual e desliga o LED. |
/auto | Ativa a decisão automática pelo LDR. |
Na ESP32 física, celular/notebook e placa devem estar em uma rede que permita comunicação entre os dispositivos. Não precisamos expor o protótipo à Internet para provar a integração.
| Ambiente | Como testar |
|---|---|
| Gateway público | Use Wokwi-GUEST e senha vazia. Sensor, LED, automação e conexão Wi-Fi funcionam, mas o navegador não consegue entrar no servidor HTTP simulado. |
| Private IoT Gateway | Em conta compatível com esse recurso, use Wokwi-GUEST, ative o gateway privado e abra http://localhost:9080/ no Chrome, Firefox ou Edge. |
Não confunda limitação do simulador com erro no código. Se o gateway público estiver sendo usado, não conseguir abrir a página é o comportamento esperado.
Sensor, decisão, atuador e HTTP já foram estudados. A próxima etapa junta essas partes em um único programa cumulativo.
O código final não introduz outra tecnologia: ele integra peças já compreendidas.
ESP32 física: troque NOME_DA_REDE e SENHA_DA_REDE pela rede de laboratório e mantenha LEITURA_MAIOR_NO_ESCURO = false para a montagem do diagrama. Wokwi: use Wokwi-GUEST, senha vazia e LEITURA_MAIOR_NO_ESCURO = true. Nos dois casos, ajuste LIMIAR com base nas leituras obtidas no teste local.
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "NOME_DA_REDE";
const char* senha = "SENHA_DA_REDE";
const int LDR = 34;
const int LED = 23;
const int LIMIAR = 2000; // calibre no teste local
// Física do diagrama: false
// Wokwi Photoresistor Sensor: true
const bool LEITURA_MAIOR_NO_ESCURO = false;
const unsigned long TEMPO_MAX_WIFI = 10000;
WebServer servidor(80);
enum Modo { MANUAL, AUTOMATICO };
Modo modo = AUTOMATICO;
bool ledLigado = false;
bool servidorDisponivel = false;
bool ambienteEscuro(int leitura) {
if (LEITURA_MAIOR_NO_ESCURO) {
return leitura > LIMIAR;
}
return leitura < LIMIAR;
}
void definirLed(bool estado) {
ledLigado = estado;
digitalWrite(LED, estado ? HIGH : LOW);
}
void atualizarAutomacao() {
if (modo != AUTOMATICO) return;
int luminosidade = analogRead(LDR);
definirLed(ambienteEscuro(luminosidade));
}
String montarPagina() {
int luminosidade = analogRead(LDR);
String pagina = "<!DOCTYPE html><html><head>";
pagina += "<meta charset='utf-8'>";
pagina += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
pagina += "<meta http-equiv='refresh' content='2'>";
pagina += "<title>Ambiente MbB</title>";
pagina += "<style>body{font-family:Arial;max-width:520px;margin:30px auto;padding:16px}";
pagina += "a{display:inline-block;margin:6px;padding:12px 16px;background:#07515f;color:white;text-decoration:none;border-radius:8px}";
pagina += ".painel{padding:16px;border:1px solid #ccc;border-radius:12px}</style>";
pagina += "</head><body><div class='painel'>";
pagina += "<h1>Ambiente MbB</h1>";
pagina += "<p>Luminosidade: " + String(luminosidade) + "</p>";
pagina += "<p>Iluminacao: " + String(ledLigado ? "LIGADA" : "DESLIGADA") + "</p>";
pagina += "<p>Modo: " + String(modo == AUTOMATICO ? "AUTOMATICO" : "MANUAL") + "</p>";
pagina += "<a href='/ligar'>Ligar</a>";
pagina += "<a href='/desligar'>Desligar</a>";
pagina += "<a href='/auto'>Automatico</a>";
pagina += "</div></body></html>";
return pagina;
}
void voltarParaInicio() {
servidor.sendHeader("Location", "/");
servidor.send(303, "text/plain", "");
}
void configurarServidor() {
servidor.on("/", []() {
servidor.send(200, "text/html", montarPagina());
});
servidor.on("/ligar", []() {
modo = MANUAL;
definirLed(true);
voltarParaInicio();
});
servidor.on("/desligar", []() {
modo = MANUAL;
definirLed(false);
voltarParaInicio();
});
servidor.on("/auto", []() {
modo = AUTOMATICO;
atualizarAutomacao();
voltarParaInicio();
});
}
void conectarWiFiSemBloquearParaSempre() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, senha);
Serial.print("Conectando ao Wi-Fi");
unsigned long inicio = millis();
while (WiFi.status() != WL_CONNECTED &&
millis() - inicio < TEMPO_MAX_WIFI) {
delay(500);
Serial.print(".");
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
servidor.begin();
servidorDisponivel = true;
Serial.print("Abra no navegador: http://");
Serial.println(WiFi.localIP());
} else {
servidorDisponivel = false;
Serial.println("Wi-Fi indisponivel.");
Serial.println("A automacao local continuara funcionando.");
}
}
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
definirLed(false);
configurarServidor();
conectarWiFiSemBloquearParaSempre();
}
void loop() {
if (servidorDisponivel && WiFi.status() == WL_CONNECTED) {
servidor.handleClient();
}
atualizarAutomacao();
delay(20);
}ESP32 física: abra o IP mostrado no Monitor Serial a partir de um dispositivo da mesma rede. Wokwi com Private IoT Gateway: abra http://localhost:9080/. Use Ligar e Desligar; o modo deve mudar para MANUAL e o LED deve obedecer ao comando. No gateway público do Wokwi, esta prova pelo navegador não está disponível.
Escolha Automático e altere a luminosidade. A página deve atualizar a leitura e o LED deve apagar em condição clara e acender em condição escura, de acordo com o limiar calibrado e com a direção de leitura configurada para o seu ambiente.
O programa espera a conexão Wi-Fi por no máximo 10 segundos. Se a rede estiver indisponível, a página Web não inicia, mas o ESP32 continua lendo o sensor e controlando o LED no modo automático.
Se a placa iniciar sem rede e a rede aparecer depois, reinicie o protótipo nesta versão do projeto para abrir o servidor. O ponto principal é separar uma função local de uma função de conectividade.
RTOS, CAN, RS-232, BLE e LCD I2C foram estudados porque são importantes no percurso, mas não precisam aparecer obrigatoriamente no projeto final. Uma integração boa usa apenas o que resolve o problema. O LCD I2C pode ser acrescentado depois como extensão local, após validar eletricamente o módulo disponível.
O Bloco 9 agora deixa de ser teoria e vira critério de projeto.
O núcleo do Ambiente MbB trabalha com valor de luminosidade, modo de operação e estado do LED. Ele não precisa de nome, localização de pessoa, biometria ou histórico de usuários para cumprir sua finalidade.
Não crie cadastro de pessoas ou logs pessoais se eles não forem necessários para o objetivo do projeto.
A senha do Wi-Fi é usada no código apenas como simplificação de laboratório. Não publique o arquivo com uma senha real nem mostre a credencial em capturas de tela.
Para o projeto-base, mantenha o servidor na rede local. Um túnel público só deve ser usado quando houver uma necessidade definida e controles compatíveis com a exposição.
O servidor deste protótipo não implementa login nem permissões. Portanto, qualquer dispositivo que consiga alcançar o ESP32 pode tentar acessar as rotas. HTTPS/TLS protegeria o transporte, mas ainda seria necessário decidir quem pode comandar o sistema.
Antes da entrega, complete esta frase no relatório: “O projeto coleta apenas __________ porque sua finalidade é __________. Ele fica acessível somente __________. A principal limitação de segurança é __________.”
Um projeto não termina quando “funciona uma vez”. Precisamos de testes reproduzíveis e evidências de que cada requisito foi atendido.
A entrega final é pequena, objetiva e baseada em evidências.
| Teste | Ação | Resultado esperado |
|---|---|---|
| T1 — Sensor | Alterar a luz sobre o LDR. | Leitura muda de forma perceptível. |
| T2 — Manual ligar | Abrir /ligar pelo painel. | Modo MANUAL e LED ligado. |
| T3 — Manual desligar | Abrir /desligar. | Modo MANUAL e LED desligado. |
| T4 — Automático claro | Ativar Automático e aumentar a luminosidade. | O sistema classifica a condição como clara e o LED fica apagado. |
| T5 — Automático escuro | Reduzir a luz sobre o LDR. | Ao cruzar o limiar, o LED acende. |
| T6 — Rede | Na placa física, acessar o IP por outro dispositivo da mesma rede. No Wokwi com Private Gateway, abrir http://localhost:9080/. | Painel abre e os comandos chegam ao ESP32. |
| T7 — Falha de rede | Com o modo automático ativo, interromper a rede e variar a luminosidade. | A página fica indisponível, mas a decisão local sobre o LED continua funcionando. |
Diagrama: mostrar sensor, ESP32, rede, aplicação e atuador.
Código: entregar a versão final sem expor senha real de Wi-Fi.
Evidência: registrar o painel funcionando e pelo menos quatro testes da tabela, incluindo o T7 de falha de rede.
Explicação: descrever em poucas linhas o que é automático, o que é comandado pelo usuário e como os dados percorrem o sistema.
Segurança: registrar a decisão de dados e a principal limitação do protótipo.
Ambiente de execução: registrar se a camada Web foi validada na ESP32 física ou no Wokwi com Private IoT Gateway. O gateway público do Wokwi não permite comprovar conexões de entrada no servidor.
Quem concluir o projeto-base pode escolher uma evolução que tenha propósito: exibir estado em LCD I2C, acrescentar outro sensor, representar uma abertura com servo ou reorganizar tarefas com RTOS. A extensão deve responder a uma necessidade clara e ser testada separadamente antes de entrar no sistema.
Ao concluir este projeto, você não apenas “montou um circuito”. Você passou por entrada e saída, sensores, atuadores, programação, conectividade, IoT, protocolos, proteção e segurança e usou esse conhecimento para construir e justificar um sistema integrado.