Kit Iniciante ESP32 Basic Starter Kit AE312 – Curso Completo

Introdução
Este curso apresenta o Kit Iniciante ESP32 Basic Starter Kit AE312 (desenvolvido e fabricado pela Kuongshun), uma formação técnica e prática integral em computação física, sistemas embarcados e Internet das Coisas (IoT – Internet of Things). O conjunto é estruturado em torno da placa controladora DOIT ESP32 DEVKIT V1, equipada com o módulo de alta integração e alta confiabilidade ESP-WROOM-32 da Espressif Systems. Esse microcontrolador incorpora uma arquitetura de 32 bits de alto desempenho com dois núcleos de processamento Xtensa LX6, interface de conectividade de rádio frequência dupla Wi-Fi 802.11 b/g/n e Bluetooth v4.2 (BR/EDR e BLE – Bluetooth Low Energy), conversores analógico-digitais (ADC – Analog-to-Digital Converter) de aproximações sucessivas de 12 bits de resolução, canais de modulação por largura de pulso (PWM – Pulse Width Modulation) controlados por hardware dedicado através do periférico LEDC (LED Controller), sensores de toque capacitivo integrados (Touch Pins), interfaces seriais assíncronas (UART – Universal Asynchronous Receiver-Transmitter), barramentos síncronos de dois fios I2C (Inter-Integrated Circuit) e barramentos de alta velocidade SPI (Serial Peripheral Interface). O kit é acompanhado por uma seleção criteriosamente projetada de componentes discretos, módulos e transdutores industriais, incluindo transdutores piezelétricos ativos, sensores de presença e deslocamento volumétrico por infravermelho passivo (PIR – Passive Infrared) baseados no circuito integrado BISS0001, sensores de umidade relativa capacitiva e temperatura DHT11, módulos relé com isolamento galvânico por optoacoplador para controle de potência, displays gráficos matriciais de tecnologia OLED (Organic Light Emitting Diode) de 0,96 polegadas controlados pelo driver SSD1306 via barramento I2C, além de chaves tácteis, potenciômetros de precisão e uma protoboard de 830 pontos para prototipagem rápida e segura.
Este material didático foi elaborado sob as mais rigorosas diretrizes da engenharia eletrônica e do projeto de sistemas computacionais embarcados, sendo direcionado a engenheiros, estudantes, técnicos, projetistas de automação e desenvolvedores que buscam dominar os fundamentos do silício do ESP32 até o projeto de servidores de rede modernos e robustos. O itinerário formativo é conduzido em uma progressão contínua e autodidata: inicia-se pela exploração da arquitetura interna de registradores, barramentos de energia e mapeamento de pinos da placa DEVKIT V1; estabelece a cadeia de ferramentas de compilação (toolchain) da IDE Arduino 2.x com instalação de drivers de comunicação USB-Serial CP210x e protocolos de upload via esptool.py; avança pelo estudo analítico de eletrônica fundamental com dimensionamento de circuitos de polarização, filtros de ruído elétrico, condicionamento de sinais analógicos e técnicas de temporização não bloqueante com registradores de contagem; e consolida-se no desenvolvimento de sistemas conectados de automação residencial e telemetria climática em tempo real através de servidores Web HTTP embutidos, cobrindo tanto conexões de soquete síncrono quanto arquiteturas assíncronas de eventos orientados a objetos. Ao concluir este curso definitivo, você dominará integralmente as capacidades do microcontrolador ESP32, tornando-se plenamente capacitado para conceber, montar, codificar, depurar e implantar projetos inteligentes de automação residencial, monitoramento industrial e nós remotos de IoT.
O que você vai aprender:
- Compreender a topologia de hardware do microcontrolador ESP32, núcleos de processamento Xtensa LX6, distribuição de memória SRAM e memória Flash SPI externa
- Mapear os 30 pinos da placa DEVKIT V1, identificando restrições críticas de inicialização (Strapping Pins) e limitações do barramento ADC2 durante a operação do rádio Wi-Fi
- Configurar o ecossistema Arduino IDE 2.x, drivers USB-UART Silicon Labs CP210x e dominar o ritual de gravação manual e automática via circuito DTR/RTS
- Controlar entradas e saídas digitais em modo push-pull, dimensionando resistores de polarização para LEDs e técnicas de atenuação de ruído
- Amostrar grandezas analógicas através do conversor ADC de 12 bits, calculando a resolução de tensão teórica e analisando a não linearidade nas extremidades
- Modular canais de largura de pulso (PWM) através do periférico de hardware LEDC do ESP32, configurando frequência e resolução em bits independentes
- Construir sistemas de alarme e segurança utilizando o sensor de movimento por infravermelho passivo PIR HC-SR501 com temporização assíncrona não bloqueante via
millis()- Desenvolver um servidor Web HTTP standalone nativo com o ESP32 em modo Station (STA), servindo páginas HTML5 responsivas e controlando atuadores remotamente
- Criar interfaces web interativas com seletores de cores em tempo real (HTML5 Color Picker) para controle cromático de LEDs RGB via modulação PWM de três canais
- Comutar cargas elétricas em corrente contínua e alternada através de módulos relé, dominando o princípio de isolamento óptico galvânico e proteção contra surtos indutivos
- Implementar sincronização bidirecional de estado em tempo real entre chave física na bancada e interruptor virtual no navegador web via requisições assíncronas AJAX
- Construir uma estação meteorológica IoT conectada com sensor DHT11, servindo telemetria assíncrona de temperatura e umidade com a biblioteca ESPAsyncWebServer
- Renderizar textos e primitivas gráficas em display OLED de 0,96 polegadas SSD1306 através do protocolo de comunicação serial I2C com as bibliotecas Adafruit GFX e SSD1306
- Diagnosticar falhas comuns de compilação, conflitos de bibliotecas, travamentos por Brownout Detector e instabilidades de rede com um guia prático de troubleshooting
Material utilizado: Kit Iniciante ESP32 Basic Starter Kit AE312 disponível na loja RoboBuilders.
Visão Geral do Kit e Arquitetura de Hardware
O núcleo central do Kit Iniciante ESP32 Basic Starter Kit AE312 é a placa de desenvolvimento DOIT ESP32 DEVKIT V1, concebida em torno do poderoso módulo ESP-WROOM-32 da Espressif Systems. Ao contrário dos microcontroladores de 8 bits tradicionais que operam com frequências de clock de 16 MHz e capacidade computacional extremamente restrita, o ESP32 representa um salto de geração monumental, combinando poder computacional de 32 bits, conectividade sem fio de rádio frequência dupla e uma matriz abrangente de periféricos analógicos e digitais de alta precisão em um único encapsulamento monolítico (System-on-Chip – SoC).
A arquitetura computacional interna é baseada em dois núcleos de processamento Xtensa dual-core 32-bit LX6 (denominados Core 0 e Core 1), que podem operar em frequências de clock configuráveis dinamicamente entre 80 MHz e 240 MHz. Essa configuração em multiprocessamento simétrico (SMP – Symmetric Multiprocessing) permite que tarefas pesadas de rede sem fio — tais como a manutenção da pilha de protocolos TCP/IP LwIP, criptografia TLS/SSL e rotinas do rádio Wi-Fi 802.11 b/g/n e Bluetooth v4.2 — sejam executadas no Core 0 sob o escalonador do sistema operacional de tempo real FreeRTOS, enquanto o firmware da aplicação e os laços principais do usuário (setup() e loop()) rodam simultaneamente e sem bloqueios no Core 1. O silício integra 520 KB de memória SRAM interna para alocação dinâmica de dados e variáveis de execução, além de 4 MB (32 Mbits) de memória Flash SPI externa de alta velocidade (quad-SPI operando a até 80 MHz) conectada aos pinos internos do barramento Flash para armazenamento permanente do código binário e do sistema de arquivos embutido (LittleFS ou SPIFFS).
A placa incorpora um conversor USB para UART baseado no circuito integrado Silicon Labs CP2102 (ou CH340 nas revisões compatíveis), regulador linear de tensão de baixa queda (LDO – Low Dropout) de 3,3 V com capacidade nominal de suprir picos de corrente de até 800 mA necessários durante as transmissões de rádio Wi-Fi, conector Micro-USB para alimentação e depuração serial, cristal oscilador de 40 MHz para temporização do sistema e dois botões microtácteis dedicados: o botão de reinicialização de hardware (EN ou RST) e o botão de entrada em modo de gravação manual (BOOT ou GPIO 0).
Especificações Técnicas Oficiais da Placa DOIT ESP32 DEVKIT V1
A tabela a seguir consolida os parâmetros de engenharia elétrica e características funcionais de operação do hardware utilizado ao longo de todo o curso:
| Parâmetro de Engenharia | Especificação Técnica Oficial | Observação de Operação |
|---|---|---|
| SoC Principal | Espressif ESP32-D0WDQ6 (Módulo ESP-WROOM-32) | Processador dual-core de 32 bits Xtensa LX6 |
| Frequência de Clock da CPU | 80 MHz a 240 MHz ajustável (padrão de boot: 240 MHz) | Até 600 DMIPS de capacidade de processamento |
| Memória SRAM Interna | 520 KB (SRAM de dados e instruções) | Inclui 8 KB de SRAM rápida no subsistema RTC |
| Memória Flash SPI Externa | 4 MB (32 Megabits), barramento Quad-SPI | Armazena o firmware executável e sistema LittleFS |
| Conectividade Wi-Fi | 802.11 b/g/n (802.11n até 150 Mbps) | Faixa de 2,4 GHz com amplificador de potência embutido (+20 dBm) |
| Conectividade Bluetooth | Bluetooth v4.2 BR/EDR e BLE (Bluetooth Low Energy) | Potência de transmissão classe 1, 2 e 3 |
| Tensão Nominal do Silício (VDD) | 3,3 V DC (faixa operacional estrita: 3,0 V a 3,6 V) | Todas as portas GPIO operam rigorosamente em 3,3 V |
| Tensão de Entrada Recomendada (Vin) | 5,0 V a 9,0 V DC (máximo absoluto seguro: 12,0 V DC) | Regulada internamente para 3,3 V pelo circuito LDO |
| Alimentação Primária USB | 5,0 V DC via conector Micro-USB (barramento de 500 mA) | Fornecida diretamente pelo computador ou fonte externa |
| Capacidade de Corrente por GPIO | 12 mA a 40 mA por pino (recomendado contínuo: ≤ 12 mA) | Corrente total somada de todos os pinos: ≤ 1200 mA |
| Conversor Analógico-Digital (ADC) | 2 blocos de 12 bits SAR (ADC1: 8 canais, ADC2: 10 canais) | Faixa de leitura: 0 V a 3,3 V com atenuação de 11 dB |
| Conversor Digital-Analógico (DAC) | 2 canais de 8 bits (GPIO 25 e GPIO 26) | Converte valores de 8 bits em tensão analógica contínua |
| Canais de Modulação PWM (LEDC) | 16 canais independentes configuráveis via hardware | Resolução ajustável de 1 a 16 bits; até 40 MHz |
| Canais de Toque Capacitivo (Touch) | 10 sensores capacitivos integrados em GPIOs dedicadas | Detecção de aproximação e toque sem botões físicos |
| Interfaces Seriais UART | 3 controladores UART de alta velocidade (UART0, UART1, UART2) | UART0 multiplexada com o chip CP2102 de programação |
| Barramentos I2C | 2 controladores mestres/escravos (padrão: GPIO 21 SDA, GPIO 22 SCL) | Suporta taxas Standard (100 kHz) e Fast Mode (400 kHz) |
| Barramentos SPI | 3 controladores SPI (SPI, HSPI, VSPI) | VSPI padrão do usuário: MOSI 23, MISO 19, SCK 18, CS 5 |
| Coprocessador ULP | Coprocessador de Ultra-Baixo Consumo baseado em FSM | Monitora sensores em modo Deep Sleep consumindo ~10 µA |
| Temperatura de Operação | -40 °C a +85 °C | Adequado para ambientes industriais e embarcados |
Diagrama de Pinagem e Mapeamento Completo de GPIOs (30 Pinos)
A placa DOIT ESP32 DEVKIT V1 de 30 pinos organiza seus terminais em duas fileiras paralelas de 15 pinos em passo padrão de 2,54 mm, ideais para fixação em protoboard. Compreender a função de cada terminal e suas particularidades elétricas é o primeiro passo para o sucesso no desenvolvimento e para evitar a queima do componente.
A tabela a seguir apresenta o mapeamento sistemático de todos os 30 pinos físicos da placa DEVKIT V1:
| Pino Físico | Nome / Identificador | Tipo de Pino | Bloco Analógico / Periférico | Função de Boot / Cuidados Críticos | Aplicação Típica no Curso |
|---|---|---|---|---|---|
| Pino 1 | EN | Entrada Reset | Linha de Habilitação do Silício | Puxado para VCC via resistor pull-up; nível LOW reinicia | Botão de reset físico e circuito DTR |
| Pino 2 | GPIO 36 (VP) | Entrada Pura | ADC1_CH0 / Sensor Hall / RTC | Não possui circuito de saída digital nem resistores pull-up | Leitura analógica de alta sensibilidade |
| Pino 3 | GPIO 39 (VN) | Entrada Pura | ADC1_CH3 / Sensor Hall / RTC | Não possui circuito de saída digital nem resistores pull-up | Leitura de sinais externos puros |
| Pino 4 | GPIO 34 | Entrada Pura | ADC1_CH6 / RTC | Somente entrada; sem pull-up interno | Entrada analógica / chave de entrada |
| Pino 5 | GPIO 35 | Entrada Pura | ADC1_CH7 / RTC | Somente entrada; sem pull-up interno | Entrada analógica / leitura de bateria |
| Pino 6 | GPIO 32 | Entrada / Saída | ADC1_CH4 / Touch 9 / RTC 9 | Seguro para uso geral em qualquer modo | Leitura analógica ou acionamento geral |
| Pino 7 | GPIO 33 | Entrada / Saída | ADC1_CH5 / Touch 8 / RTC 8 | Seguro para uso geral em qualquer modo | Leitura analógica ou acionamento geral |
| Pino 8 | GPIO 25 | Entrada / Saída | ADC2_CH8 / DAC_1 / RTC 6 | Converte valores de 8 bits em tensão analógica real | Saída analógica DAC ou I/O |
| Pino 9 | GPIO 26 | Entrada / Saída | ADC2_CH9 / DAC_2 / RTC 7 | Inoperante como ADC quando o Wi-Fi está ligado | Canal de chaveamento e controle |
| Pino 10 | GPIO 27 | Entrada / Saída | ADC2_CH7 / Touch 7 / RTC 17 | Inoperante como ADC quando o Wi-Fi está ligado | Entrada do sensor de movimento PIR |
| Pino 11 | GPIO 14 | Entrada / Saída | ADC2_CH6 / Touch 6 / HSPI_CLK | Emite clock durante boot; cuidado com cargas sensíveis | Barramento SPI auxiliar ou I/O |
| Pino 12 | GPIO 12 | Entrada / Saída | ADC2_CH5 / Touch 5 / HSPI_Q | Strapping Pin (MTDI): Deve estar em LOW no boot para Flash 3.3V | I/O geral com cautela |
| Pino 13 | GPIO 13 | Entrada / Saída | ADC2_CH4 / Touch 4 / HSPI_ID | Seguro para uso geral | I/O de alta velocidade |
| Pino 14 | GND | Alimentação | Barramento de Terra de Referência | Potencial de 0 V comum de referência do sistema | Barramento comum da protoboard |
| Pino 15 | Vin | Alimentação | Entrada de Tensão Externa DC | Conectado à entrada do LDO (5 V a 9 V DC); bypass para USB | Alimentação de módulos e sensores de 5 V |
| Pino 16 | 3V3 | Alimentação | Saída Regulada de 3,3 V DC | Saída do regulador LDO interno (máx. 800 mA somado) | Alimentação do ESP32, OLED e sensores 3.3V |
| Pino 17 | GND | Alimentação | Barramento de Terra de Referência | Potencial de 0 V comum de referência do sistema | Barramento comum da protoboard |
| Pino 18 | GPIO 15 | Entrada / Saída | ADC2_CH3 / Touch 3 / HSPI_CS | Strapping Pin (MTDO): Puxado para HIGH emite log de boot serial | Linha de controle ou I/O |
| Pino 19 | GPIO 2 | Entrada / Saída | ADC2_CH2 / Touch 2 / LED Interno | Strapping Pin: Deve estar solto ou em LOW para entrar em flash | LED azul integrado na placa DEVKIT |
| Pino 20 | GPIO 0 | Entrada / Saída | ADC2_CH1 / Touch 1 / RTC 11 | Strapping Pin de Boot: Pressione botão BOOT para forçar LOW | Gravação de firmware via UART |
| Pino 21 | GPIO 4 | Entrada / Saída | ADC2_CH0 / Touch 0 / RTC 10 | Seguro para uso geral; multiplexado no barramento Touch | Entrada de botão, PWM e potenciômetro |
| Pino 22 | GPIO 16 (RX2) | Entrada / Saída | UART2_RX | Linha padrão de recepção de dados da Serial2 | Comunicação UART secundária |
| Pino 23 | GPIO 17 (TX2) | Entrada / Saída | UART2_TX | Linha padrão de transmissão de dados da Serial2 | Comunicação UART secundária |
| Pino 24 | GPIO 5 | Entrada / Saída | VSPI_CS / RTC 15 | Strapping Pin: Emite pulsos PWM transitórios no boot | Controle de LED digital e saídas |
| Pino 25 | GPIO 18 | Entrada / Saída | VSPI_CLK | Linha de clock padrão do barramento VSPI | Barramento de alta velocidade SPI |
| Pino 26 | GPIO 19 | Entrada / Saída | VSPI_MISO | Linha de entrada Master-In Slave-Out do barramento VSPI | Leitura de cartões SD ou sensores SPI |
| Pino 27 | GPIO 21 | Entrada / Saída | I2C_SDA | Linha de dados seriais do barramento I2C padrão | Conexão I2C do display OLED SSD1306 |
| Pino 28 | GPIO 3 (RX0) | Entrada / Saída | UART0_RX | Conectada ao conversor USB-Serial para programação | Monitor Serial e upload de sketch |
| Pino 29 | GPIO 1 (TX0) | Entrada / Saída | UART0_TX | Conectada ao conversor USB-Serial para programação | Monitor Serial e mensagens de debug |
| Pino 30 | GPIO 22 | Entrada / Saída | I2C_SCL | Linha de clock serial do barramento I2C padrão | Conexão I2C do display OLED SSD1306 |
⚠️ Atenção — Regra Inviolável de Hardware:
- Conflito de Concorrência entre ADC2 e Rádio Wi-Fi: O bloco interno ADC2 (canais GPIOs 0, 2, 4, 12, 13, 14, 15, 25, 26 e 27) compartilha circuitos internos e amplificadores operacionais com a seção de rádio frequência (Wi-Fi e Bluetooth). Por essa razão, no exato instante em que o firmware ativa a pilha de rádio com
WiFi.begin(), qualquer leitura executada viaanalogRead()nos pinos do ADC2 retornará invariavelmente valores espúrios ou falhará. Para leituras analógicas contínuas em projetos IoT conectados, utilize exclusivamente os pinos do bloco ADC1 (GPIOs 32, 33, 34, 35, 36 e 39).- Pinos Somente Entrada (Input Only): Os pinos GPIO 34, 35, 36 e 39 não possuem transistores complementares de saída na etapa interna de I/O nem resistores internos de pull-up ou pull-down configuráveis por software. Eles nunca devem ser configurados como
OUTPUT.- Tensão Máxima de Entrada: Todos os pinos GPIO do ESP32 são compatíveis estritamente com 3,3 V. Aplicar sinais de 5,0 V diretamente sobre qualquer pino do silício sem divisores resistivos ou transistores de conversão de nível lógico queimará instantaneamente os diodos de proteção de clamp e a porta interna do microcontrolador.
Inventário Físico do Kit (Packing List)
O Kit Iniciante ESP32 Basic Starter Kit AE312 traz em sua embalagem organizadora todos os elementos estruturais e eletroeletrônicos necessários para a execução completa das 10 lições práticas do curso. Abaixo encontra-se o inventário fotográfico oficial e a discriminação itemizada das peças:
A tabela a seguir discrimina quantitativamente todos os itens do conjunto:
| Item | Componente / Descrição Técnica | Quantidade | Função Principal nas Lições |
|---|---|---|---|
| 1 | Placa de Desenvolvimento DOIT ESP32 DEVKIT V1 (ESP-WROOM-32) | 1 unidade | Microcontrolador mestre de 32 bits dual-core com Wi-Fi/Bluetooth |
| 2 | Cabo de Comunicação e Alimentação Micro-USB para USB-A | 1 unidade | Conexão com o computador para upload de firmware e depuração serial |
| 3 | Display Gráfico OLED 0,96 Polegadas SSD1306 (128x64 pixels, I2C) | 1 unidade | Interface homem-máquina (IHM) gráfica para exibição de dados e telemetria |
| 4 | Sensor de Presença por Infravermelho Passivo PIR HC-SR501 | 1 unidade | Detecção volumétrica de presença e movimento térmico humano |
| 5 | Sensor Digital de Temperatura e Umidade Relativa DHT11 | 1 unidade | Monitoramento de variáveis termo-higrométricas do ambiente |
| 6 | Módulo Relé de 1 Canal 5 V com Isolamento Óptico por Optoacoplador | 1 unidade | Comutação de cargas de potência AC (lâmpadas) e DC com isolamento galvânico |
| 7 | Buzzer Piezelétrico Ativo de 5 V DC | 1 unidade | Transdutor acústico para emissão de alertas sonoros e alarmes |
| 8 | Potenciômetro Rotativo Linear de 10 kΩ com Eixo Estriado | 1 unidade | Divisor de tensão resistivo para amostragem analógica via ADC |
| 9 | Diodo Emissor de Luz (LED) RGB de Cátodo Comum de 5 mm | 1 unidade | Síntese aditiva de cores através de três canais PWM independentes |
| 10 | Diodo Emissor de Luz (LED) Difuso Vermelho de 5 mm | 3 unidades | Sinalização visual de estado lógico e indicação de alarmes |
| 11 | Diodo Emissor de Luz (LED) Difuso Verde de 5 mm | 3 unidades | Sinalização visual de estado lógico e confirmação de conexões |
| 12 | Diodo Emissor de Luz (LED) Difuso Azul de 5 mm | 3 unidades | Sinalização visual de estado lógico e canais de saída |
| 13 | Chaves Tácteis Tipo Pushbutton (4 terminais com capa) | 3 unidades | Entradas digitais por ação momentânea do usuário |
| 14 | Resistor de Filme de Carbono de 220 Ω (1/4 W, tolerância 5%) | 10 unidades | Limitação de corrente direta de polarização para LEDs |
| 15 | Resistor de Filme de Carbono de 10 kΩ (1/4 W, tolerância 5%) | 5 unidades | Polarização passiva de pull-down para botões e pull-up para barramentos |
| 16 | Resistor de Filme de Carbono de 1 kΩ (1/4 W, tolerância 5%) | 5 unidades | Atenuação e casamento de impedância de circuitos de entrada |
| 17 | Protoboard Profissional de 830 Pontos com Linhas de Alimentação Duplas | 1 unidade | Plataforma para prototipagem de circuitos eletrônicos sem solda |
| 18 | Kit de Cabos Jumper Flexíveis Macho-Macho de Diversos Comprimentos | 40 unidades | Roteamento de sinais e alimentação na protoboard |
| 19 | Cabos Jumper Flexíveis Macho-Fêmea de 20 cm | 10 unidades | Conexão entre a protoboard e os pinos do módulo relé e sensores |
| 20 | Estojo Organizador Plástico com Travas de Segurança | 1 unidade | Acomodação, proteção mecânica e transporte dos componentes |
| Total | Somatória Consolidada de Itens Físicos | 90 itens | Conjunto completo para 10 projetos didáticos completos |
Preparação de Ambiente e Instalação de Drivers
Antes de iniciar a codificação dos projetos práticos, é fundamental estabelecer um ambiente de desenvolvimento robusto, calibrado e com as versões de bibliotecas e compiladores devidamente pinadas. A heterogeneidade de versões nos pacotes de suporte a placas é uma das principais causas de erros de compilação em microcontroladores ESP32.
Download e Instalação da IDE Arduino 2.x
O desenvolvimento de firmware para o ESP32 pode ser conduzido na versão moderna da Arduino IDE 2.3.x (disponível para Windows, Linux e macOS no site oficial arduino.cc). A versão 2.x introduz autocompletar inteligente (IntelliSense), compilador incremental baseado em Language Server Protocol (LSP) e ferramenta de depuração avançada.
Instalação do Driver USB-Serial CP210x
A placa DOIT ESP32 DEVKIT V1 utiliza o circuito integrado Silicon Labs CP2102 (ou CP210x) para converter a interface USB do computador na interface UART síncrona/assíncrona do microcontrolador (pinos TX0 e RX0).
- Caso o sistema operacional não reconheça automaticamente a porta ao conectar o cabo Micro-USB, faça o download do driver oficial diretamente da Silicon Labs: Silicon Labs CP210x VCP Drivers.
- Execute o instalador
CP210xVCPInstaller_x64.exe(no Windows de 64 bits) e siga as instruções na tela. - No Windows, abra o Gerenciador de Dispositivos e expanda a seção Portas (COM e LPT). Ao conectar a placa, você verá o item
Silicon Labs CP210x USB to UART Bridge (COMx). Anote o número da porta COM associada.
Instalação do Pacote de Placas da Espressif na IDE Arduino
Para habilitar a compilação do código C/C++ da arquitetura Xtensa do ESP32 na IDE Arduino, devemos adicionar o repositório de placas da Espressif:
- Abra a IDE Arduino e navegue até o menu
Arquivo > Preferências(ou pressioneCtrl + Vírgula). - No campo URLs do Gerenciador de Placas Adicionais, insira rigorosamente a URL oficial do pacote estável da Espressif:
(Caso já existam outras URLs no campo, separe-as com uma vírgula ou clique no ícone lateral para adicionar em uma nova linha).https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
- Clique em OK para fechar a tela de preferências.
- No menu lateral esquerdo da IDE Arduino, clique no ícone de Gerenciador de Placas (Boards Manager) ou acesse
Ferramentas > Placa > Gerenciador de Placas.... - Na caixa de busca superior, digite
esp32. Localize o pacote oficial mantido pela Espressif Systems. - Selecione a versão estável 2.0.14 (ou a versão recomendada do kit) e clique em Instalar. Aguarde o download completo dos compiladores de cadeia cruzada (xtensa-esp32-elf-gcc), ferramentas de upload (esptool.py) e cabeçalhos de sistema.
Configuração de Parâmetros de Placa e Ritual de Gravação
Com o pacote devidamente instalado, configure as opções do compilador no menu Ferramentas:
- Placa:
DOIT ESP32 DEVKIT V1 - CPU Frequency:
240MHz (WiFi/BT) - Flash Frequency:
80MHz - Flash Mode:
QIO - Flash Size:
4MB (32Mb) - Partition Scheme:
Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) - Core Debug Level:
Nenhum(ouAvisodurante depuração) - Upload Speed:
921600(se houver erro de sincronismo, reduza temporariamente para115200) - Porta: Selecione a porta correspondente à placa (ex:
COM3ouCOM4).
O Ritual de Upload e o Botão BOOT
A placa DEVKIT V1 possui um circuito automático de auto-reset constituído por dois transistores bipolares NPN conectados aos sinais DTR (Data Terminal Ready) e RTS (Request to Send) da interface USB-Serial CP2102. Esse circuito manipula automaticamente os níveis lógicos das linhas EN (Reset) e GPIO 0 (BOOT).
No entanto, em diversos computadores e cabos com capacitância parasita elevada, o pulso transitório de descida na linha GPIO 0 pode falhar em sincronizar com a abertura do carregador de inicialização (ROM Bootloader). Quando isso ocorre, o console de compilação da IDE exibe a mensagem de espera cíclica:
Connecting........_____....._____.....
Quando essa sequência de pontos e traços surgir no rodapé da IDE, mantenha o botão BOOT pressionado firmemente na placa ESP32 até que a linha mude para Writing at 0x00010000... (100%). Nesse instante, solte imediatamente o botão BOOT. O processo de gravação prosseguirá até o status final Hard resetting via RTS pin..., confirmando a reinicialização bem-sucedida do firmware.
Tabela-Mestre de Bibliotecas do Curso
A tabela a seguir consolida todas as bibliotecas de software utilizadas ao longo das lições deste curso, com versões testadas e homologadas para a versão 2.0.14 do núcleo ESP32, garantindo imunidade total a quebras de API:
| Biblioteca (#include) | Buscar no Gerenciador | Versão Usada no Curso | Download ZIP (Espelho Oficial) | Lições que Utilizam |
|---|---|---|---|---|
<WiFi.h> | Embutida no pacote oficial ESP32 | 2.0.14 (Nativa do Core) | Já inclusa na instalação do pacote de placas | Lições 5, 6, 7, 8 e 9 |
<AsyncTCP.h> | AsyncTCP por me-no-dev / dvarrel | 1.1.4 | dvarrel/AsyncTCP | Lições 7, 8 e 9 |
<ESPAsyncWebServer.h> | ESPAsyncWebServer por me-no-dev | 1.2.4 | lacamera/ESPAsyncWebServer | Lições 7, 8 e 9 |
<DHT.h> | DHT sensor library por Adafruit | 1.4.6 | adafruit/DHT-sensor-library | Lição 9 |
<Adafruit_Sensor.h> | Adafruit Unified Sensor por Adafruit | 1.1.14 | adafruit/Adafruit_Sensor | Lição 9 (Dependência do DHT) |
<Adafruit_SSD1306.h> | Adafruit SSD1306 por Adafruit | 2.5.11 | adafruit/Adafruit_SSD1306 | Lição 10 |
<Adafruit_GFX.h> | Adafruit GFX Library por Adafruit | 1.11.10 | adafruit/Adafruit-GFX-Library | Lição 10 (Dependência do OLED) |
<Wire.h> | Embutida no pacote oficial ESP32 | 2.0.14 (Nativa do Core) | Já inclusa na instalação do pacote de placas | Lição 10 |
Lição 1: Entradas e Saídas Digitais (GPIOs, LEDs e Botões)
O controle de entradas e saídas de uso geral (GPIO – General Purpose Input/Output) constitui o alicerce fundamental de qualquer projeto de automação e sistemas embarcados. Nesta primeira lição prática, você dominará o chaveamento digital da placa DOIT ESP32 DEVKIT V1, manipulando simultaneamente uma saída digital em modo push-pull para acionamento de um diodo emissor de luz (LED) e uma entrada digital para amostragem do estado mecânico de uma chave táctil (pushbutton).
Teoria dos Circuitos de I/O e Polarização de Semicondutores
Cada pino GPIO do ESP32 é conectado a um circuito transceptor CMOS composto por dois transistores de efeito de campo complementares (um PMOS conectado ao barramento de alimentação de 3,3 V e um NMOS conectado ao barramento de terra GND). Quando um pino é configurado como OUTPUT através da função pinMode(pin, OUTPUT) e recebe o comando digitalWrite(pin, HIGH), o transistor PMOS superior é saturado, conectando diretamente o pino ao potencial de 3,3 V. Inversamente, quando recebe digitalWrite(pin, LOW), o transistor NMOS inferior entra em condução, drenando a corrente para o terra (0 V).
Ao acionar um diodo emissor de luz (LED), é estritamente obrigatório inserir em série um resistor limitador de corrente. Um LED é um semicondutor de junção P-N cuja relação entre corrente e tensão é exponencial: uma vez atingida a tensão de condução direta (), qualquer incremento minúsculo de tensão causará um aumento descontrolado de corrente que queimará instantaneamente o LED e a porta de saída do ESP32.
A dedução matemática do valor da resistência limitadora é realizada aplicando a Lei de Ohm e a Segunda Lei de Kirchhoff (Lei das Malhas):
Para um LED difuso vermelho comum presente no kit:
- Tensão de alimentação do microcontrolador:
- Tensão de condução direta típica do LED vermelho:
- Corrente direta de operação nominal recomendada:
Substituindo os parâmetros na equação de dimensionamento:
A potência dissipada sobre o corpo do resistor pelo efeito Joule é dada por:
Como a potência calculada de é ordens de grandeza inferior à capacidade máxima de dissipação do resistor de filme de carbono de () fornecido no kit, a operação térmica ocorre em regime perfeitamente frio e estável.
Na entrada digital (chave táctil), quando os contatos mecânicos estão abertos, o pino fica desconectado de qualquer potencial fixo, entrando em estado de alta impedância (Floating State). Nessa condição, o pino atua como uma antena suscetível a ruídos eletromagnéticos ambientes, alternando aleatoriamente entre 0 e 1. Para forçar um nível lógico baixo (0 V) garantido durante o repouso da chave, emprega-se uma configuração de resistor de pull-down externo de 10 kΩ. Ao pressionar o botão, o pino é conectado aos 3,3 V, estabelecendo o nível lógico alto estável.
Componentes Necessários para a Lição 1
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 3.3V |
| Diodo Emissor de Luz (LED) Vermelho | 1 unidade | Encapsulamento difuso de 5 mm, |
| Resistor de Filme de Carbono | 1 unidade | , , tolerância 5% (Vermelho-Vermelho-Marrom) |
| Chave Táctil Pushbutton | 1 unidade | Microswitch momentâneo de 4 terminais |
| Resistor de Filme de Carbono | 1 unidade | , , tolerância 5% (Marrom-Preto-Laranja) |
| Protoboard de 830 Pontos | 1 unidade | Barramento duplo de alimentação lateral |
| Cabos Jumper Flexíveis | 5 unidades | Conexões Macho-Macho |
Diagrama Esquemático e Montagem Prática na Protoboard
Conecte os componentes na protoboard seguindo o esquema elétrico e o diagrama de conexões ilustrados abaixo. Posicione a placa ESP32 no centro da protoboard, permitindo o acesso aos barramentos de pinos de ambos os lados.
A tabela a seguir discrimina as conexões ponto a ponto:
| Terminal de Origem | Terminal de Destino | Linha / Pino ESP32 | Função do Sinal |
|---|---|---|---|
| Ânodo do LED Vermelho (Terminal Longo) | Terminal 1 do Resistor | Linha intermediária protoboard | Nó de conexão da malha do LED |
| Terminal 2 do Resistor | Pino Digital do Microcontrolador | GPIO 5 | Saída digital de acionamento do LED |
| Cátodo do LED Vermelho (Terminal Curto) | Barramento Negativo da Protoboard | GND | Referência de terra (0 V) |
| Terminal A do Pushbutton | Barramento Positivo de Alimentação | 3V3 | Nível lógico alto de alimentação (3,3 V) |
| Terminal B do Pushbutton | Terminal 1 do Resistor | GPIO 4 | Entrada digital de leitura da chave |
| Terminal 2 do Resistor | Barramento Negativo da Protoboard | GND | Resistor de pull-down para o terra |
📦 Bibliotecas desta lição: nenhuma — o sketch faz uso exclusivo das rotinas nativas de manipulação de registradores digitais da IDE Arduino (
pinMode,digitalReadedigitalWrite), dispensando qualquer download externo.
Código-Fonte Completo Comentado Linha a Linha
Abra a IDE Arduino, crie um novo sketch (Arquivo > Novo Sketch) e insira o código abaixo, integralmente documentado em português:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 1: Entradas e Saidas Digitais (Pushbutton e LED)
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Definicao constante do pino GPIO conectado a chave tactil pushbutton
const int buttonPin = 4; // Pino GPIO 4 configurado como entrada digital
// Definicao constante do pino GPIO conectado ao anodo do diodo emissor de luz (LED)
const int ledPin = 5; // Pino GPIO 5 configurado como saida digital
// Declaracao de variavel inteira global para armazenar o estado logico lido da chave
int buttonState = 0; // Armazena 0 (LOW / GND) quando solto ou 1 (HIGH / 3.3V) quando pressionado
// Funcao de configuracao inicial do microcontrolador executada uma unica vez no boot
void setup() {
// Inicializa o canal de comunicacao serial assincrono na velocidade de 115200 bps
Serial.begin(115200);
// Configura o pino GPIO 4 como entrada digital de alta impedancia
pinMode(buttonPin, INPUT);
// Configura o pino GPIO 5 como saida digital push-pull de baixa impedancia
pinMode(ledPin, OUTPUT);
}
// Laco de execucao continua e concorrente do firmware
void loop() {
// Realiza a amostragem imediata do nivel logico presente no pino GPIO 4
buttonState = digitalRead(buttonPin);
// Imprime no Monitor Serial o estado numerico atual da chave para fins de telemetria
Serial.print("Estado do Botao: ");
Serial.println(buttonState);
// Estrutura de decisao condicional: verifica se o botao encontra-se acionado (HIGH)
if (buttonState == HIGH) {
// Caso verdadeiro: satura o transistor PMOS do GPIO 5, fornecendo 3,3V e acendendo o LED
digitalWrite(ledPin, HIGH);
} else {
// Caso falso: comuta o pino GPIO 5 para o potencial de terra (0V), apagando o LED
digitalWrite(ledPin, LOW);
}
// Insere uma pequena pausa temporal de 20 milissegundos para estabilizacao do laco
delay(20);
}
Gravação, Validação Prática e Análise de Funcionamento
- Conecte o cabo Micro-USB à porta USB do seu computador e selecione a porta COM correta em
Ferramentas > Porta. - Clique no botão Carregar (Upload). Se o console exibir a sequência
Connecting........_____, pressione e segure o botão BOOT na placa ESP32 até que a gravação inicie. - Abra o Monitor Serial (
Ctrl + Shift + M) e certifique-se de que a taxa de transmissão esteja ajustada rigorosamente para 115200 baud. - Em repouso, o LED permanece totalmente apagado e o terminal exibe sucessivamente a mensagem
Estado do Botao: 0. - Pressione o botão físico: no exato instante da compressão mecânica, o LED vermelho acende com brilho intenso e o Monitor Serial passa a exibir
Estado do Botao: 1. Ao soltar o botão, o LED apaga imediatamente.
💡 Dica de Engenharia — Pull-Up Interno: O microcontrolador ESP32 possui resistores de pull-up internos ativáveis por software (
pinMode(buttonPin, INPUT_PULLUP)). Quando configurado emINPUT_PULLUP, o resistor externo de 10 kΩ torna-se dispensável e a outra extremidade da chave deve ser conectada diretamente ao GND. Nessa topologia, a lógica torna-se invertida: solto lêHIGHe pressionado lêLOW.
Lição 2: Entradas Analógicas e Conversão ADC de 12 Bits
No mundo real, as grandezas físicas — temperatura, luminosidade, pressão, posição angular de eixos e nível de carga de baterias — variam de forma contínua no tempo, ao contrário dos sinais digitais que assumem apenas dois estados discretos. Para interpretar essas variáveis, o microcontrolador ESP32 conta com um periférico conversor analógico-digital (ADC – Analog-to-Digital Converter) de alto desempenho e resolução programável.
Arquitetura do SAR ADC de 12 Bits e Não Linearidade
O conversor analógico-digital do ESP32 opera sob o princípio de Registrador de Aproximações Sucessivas (SAR – Successive Approximation Register). Nesse processo, um comparador analógico interno de alta velocidade compara a tensão desconhecida de entrada contra uma tensão de referência gerada por uma rede capacitiva ponderada binariamente (DAC interno), determinando bit a bit o valor binário correspondente do bit mais significativo (MSB) até o bit menos significativo (LSB).
Diferentemente do Arduino Uno tradicional (cujo ADC possui resolução de 10 bits, dividindo a faixa em 1024 níveis), o ADC do ESP32 opera por padrão com 12 bits de resolução, mapeando a faixa de tensão analógica em níveis discretos de quantização (compreendidos entre e ).
A resolução teórica de tensão () para uma faixa nominal de com atenuação padrão de 11 dB é calculada por:
Para converter a leitura digital bruta de 12 bits () de volta ao seu valor físico de tensão correspondente em volts (), aplica-se a relação direta:
A Curva de Não Linearidade Real do ESP32
Em termos práticos de engenharia, o conversor ADC do ESP32 exibe uma curva de transferência com acentuada não linearidade nas extremidades superior e inferior:
- Zona Morta Inferior (0 V a ~100 mV): Tensões compreendidas entre 0 V e aproximadamente 0,1 V são lidas como 0 absoluto pelo conversor.
- Zona de Saturação Superior (~3,15 V a 3,3 V): Tensões analógicas acima de aproximadamente 3,15 V atingem o teto máximo de 4095 antes que a tensão de entrada atinja os 3,3 V nominais.
- Região Linear Central (0,15 V a 3,10 V): Entre 150 mV e 3,1 V, a resposta do ADC é altamente satisfatória para potenciômetros, termistores e sensores de automação.
Componentes Necessários para a Lição 2
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 |
| Potenciômetro Rotativo Linear | 1 unidade | , terminal central ajustável de 0 a 3,3 V |
| Protoboard de 830 Pontos | 1 unidade | Montagem do divisor resistivo |
| Cabos Jumper Flexíveis | 3 unidades | Conexões Macho-Macho |
Diagrama Esquemático e Montagem Prática
Um potenciômetro rotativo atua como um divisor de tensão resistivo ajustável. Os dois terminais externos são conectados respectivamente ao barramento de 3,3 V e ao terra GND, enquanto o terminal central (cursor móvel) coleta uma fração da tensão total proporcional ao ângulo de rotação mecânica do eixo.
A tabela a seguir orienta as conexões físicas na protoboard:
| Terminal do Potenciômetro | Ponto de Ligação na Protoboard | Linha / Pino ESP32 | Função do Sinal |
|---|---|---|---|
| Terminal Esquerdo (Pino 1) | Barramento Positivo de Tensão | 3V3 | Tensão de referência superior (3,3 V DC) |
| Terminal Central (Cursor / Pino 2) | Linha do Barramento de Sinal | GPIO 4 (ADC2_CH0) | Tensão analógica variável (0 V a 3,3 V) |
| Terminal Direito (Pino 3) | Barramento Negativo de Terra | GND | Referência de potencial de terra (0 V) |
📦 Bibliotecas desta lição: nenhuma — a leitura analógica utiliza a função interna
analogRead()do pacote de placas oficial da Espressif, operando sem dependências de código externo.
Código-Fonte Completo Comentado Linha a Linha
Digite o código abaixo na IDE Arduino e compile para a placa DEVKIT V1:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 2: Entradas Analogicas e Conversao ADC de 12 Bits
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Define a constante do pino GPIO conectado ao terminal central do potenciometro
const int potPin = 4; // GPIO 4 (Canal interno ADC2_CH0 do ESP32)
// Variavel inteira global para armazenar a leitura numerica bruta quantizada de 12 bits
int potValue = 0; // Armazenara valores inteiros na faixa de 0 a 4095
// Variavel de ponto flutuante para armazenar a tensao eletrica calculada correspondente
float voltage = 0.0; // Armazenara valores de tensao continua em volts (0.00V a 3.30V)
// Funcao de inicializacao dos parametros de hardware do microcontrolador
void setup() {
// Inicializa o barramento serial de comunicacao UART na velocidade de 115200 bps
Serial.begin(115200);
// Aguarda 1000 milissegundos para estabilizacao completa do circuito regulador LDO
delay(1000);
// Imprime o cabecalho de telemetria inicial na tela do computador
Serial.println("=================================================");
Serial.println("RoboBuilders AE312 - Telemetria Analogiica 12 Bits");
Serial.println("=================================================");
}
// Laco de execucao continua e amostragem de dados
void loop() {
// Realiza a conversao analogico-digital do sinal eletrico presente no GPIO 4
potValue = analogRead(potPin);
// Calcula a tensao proporcional real aplicando a resolucao de 12 bits (4095 niveis)
voltage = (potValue / 4095.0) * 3.3;
// Imprime a leitura bruta de quantizacao no Monitor Serial
Serial.print("Valor Bruto ADC (0-4095): ");
Serial.print(potValue);
// Imprime a tensao eletrica correspondente em volts com duas casas decimais
Serial.print(" | Tensao Calculada: ");
Serial.print(voltage, 2);
Serial.println(" V");
// Pausa a amostragem por 500 milissegundos para facilitar a leitura humana no monitor
delay(500);
}
Validação Prática no Monitor Serial e Plotter Gráfico
- Conecte a placa, faça o upload do sketch e abra o Monitor Serial ajustado para 115200 bps.
- Gire o eixo do potenciômetro totalmente no sentido anti-horário: o monitor exibirá leituras próximas de
0e tensão de0.00 V. - Gire o eixo gradualmente em direção ao meio: os valores subirão de maneira suave e contínua até aproximadamente
2048e1.65 V. - Ao atingir o batente máximo no sentido horário, a leitura alcançará
4095e a tensão registrará3.30 V. - Feche o Monitor Serial e abra o Plotter Serial (
Ferramentas > Plotter SerialouCtrl + Shift + L): ao girar o potenciômetro, você verá um gráfico temporal traçando em tempo real as ondas suaves de variação analógica.
Lição 3: Modulação por Largura de Pulso (PWM) com Periférico LEDC
O microcontrolador ESP32 é um dispositivo inteiramente digital: suas portas lógicas convencionais só conseguem emitir estados binários rígidos (0 V ou 3,3 V). Contudo, em inúmeras aplicações práticas de controle mecânico e automação — tais como variação da intensidade de lâmpadas (dimming), ajuste de velocidade de rotação de motores de corrente contínua e posicionamento angular de servomotores — é indispensável gerar uma tensão média variável. A técnica padrão de engenharia para alcançar essa proeza sem perdas resistivas de energia é a Modulação por Largura de Pulso (PWM – Pulse Width Modulation).
A Arquitetura do Periférico LEDC do ESP32
Ao contrário das placas Arduino AVR clássicas, que dependem da função síncrona analogWrite() atrelada a temporizadores rígidos de 8 bits associados a frequências fixas de 490 Hz ou 980 Hz, o ESP32 dispõe de um módulo de hardware dedicado extremamente sofisticado denominado LEDC (LED Controller).
O periférico LEDC incorpora:
- 16 Canais PWM Independentes: Divididos em dois grupos de 8 canais (canais de alta velocidade e canais de baixa velocidade).
- Frequência de Oscilação Ajustável por Software: Permite selecionar frequências desde 1 Hz até 40 MHz.
- Resolução de Duty Cycle Programável: De 1 bit até 16 bits de profundidade. Com resolução configurada em 8 bits, o duty cycle varia de 0 a 255; com 10 bits, varia de 0 a 1023; e com 12 bits, atinge de 0 a 4095 níveis de suavidade de atenuação.
Física e Matemática da Modulação PWM
O sinal PWM consiste em uma onda quadrada periódica de frequência fixa () cujo tempo em nível lógico alto () é modulado dentro do período total (). A razão percentual entre o tempo ativo e o período completo é definida como o Ciclo de Trabalho (Duty Cycle ):
O período total da forma de onda é o inverso da frequência configurada:
Para uma frequência de chaveamento padrão de :
A Tensão Média Eficaz () percebida pela carga (neste caso, a junção semicondutora do LED associada ao olho humano por persistência retiniana) é diretamente proporcional ao ciclo de trabalho:
Com uma resolução de 8 bits ():
Exemplos práticos de tensão média gerada:
- Duty Cycle de 0% (duty = 0): (LED totalmente apagado).
- Duty Cycle de 25% (duty = 64): (brilho tênue).
- Duty Cycle de 50% (duty = 127): (meio brilho).
- Duty Cycle de 100% (duty = 255): (brilho máximo saturado).
As Três Funções da API LEDC da Espressif
O controle PWM no núcleo ESP32 2.x é executado em três etapas rigorosas:
ledcSetup(canal, frequencia, resolucao): Configura o gerador de clock do canal (0 a 15), a frequência em Hertz e a resolução em bits (ex: 8 bits).ledcAttachPin(gpio, canal): Associa o canal gerador de PWM ao pino físico GPIO desejado.ledcWrite(canal, duty): Carrega o valor do ciclo de trabalho no registrador do comparador do canal.
Componentes Necessários para a Lição 3
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 |
| Diodo Emissor de Luz (LED) Vermelho | 1 unidade | Encapsulamento difuso de 5 mm |
| Resistor de Filme de Carbono | 1 unidade | , , tolerância 5% |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis | 2 unidades | Conexões Macho-Macho |
Tabela de Conexões de Pinos
| Terminal do Componente | Ponto de Ligação na Protoboard | Linha / Pino ESP32 | Função do Sinal |
|---|---|---|---|
| Ânodo do LED Vermelho | Terminal 1 do Resistor | Linha intermediária protoboard | Conexão em série limitadora |
| Terminal 2 do Resistor | Pino Digital do Microcontrolador | GPIO 4 | Saída modulada via canal LEDC 0 |
| Cátodo do LED Vermelho | Barramento Negativo da Protoboard | GND | Referência comum de 0 V |
📦 Bibliotecas desta lição: nenhuma — o periférico LEDC é implementado nativamente nos registradores de baixo nível do pacote oficial da Espressif Systems.
Código-Fonte Completo Comentado Linha a Linha
Carregue o seguinte sketch para implementar o efeito de respiração suave luminosa (Fading LED):
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 3: Modulacao por Largura de Pulso (PWM) com Periferico LEDC
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Define o pino GPIO que emitira a onda quadrada modulada
const int ledPin = 4; // GPIO 4 sera controlado pelo hardware PWM
// Definicao dos parametros operacionais de configuracao do periferico LEDC
const int freq = 5000; // Frequencia base do sinal PWM ajustada para 5 kHz (5000 Hz)
const int ledChannel = 0; // Utiliza o canal de hardware 0 (canais disponiveis: 0 a 15)
const int resolution = 8; // Resolucao de 8 bits (valores discretos de duty cycle: 0 a 255)
// Funcao de configuracao inicial do microcontrolador
void setup() {
// Inicializa o barramento serial para acompanhamento dos valores de duty cycle
Serial.begin(115200);
// 1. Configura as propriedades do temporizador do canal LEDC (canal, frequencia, resolucao)
ledcSetup(ledChannel, freq, resolution);
// 2. Conecta fisicamente o canal de geracao PWM ao pino GPIO 4 da placa
ledcAttachPin(ledPin, ledChannel);
// Emite aviso de inicializacao no console serial
Serial.println("Controle PWM LEDC Inicializado com Sucesso a 5 kHz / 8 Bits");
}
// Laco de execucao continua: executa os ciclos de fade-in e fade-out
void loop() {
// Laco progressivo (Fade In): incrementa o duty cycle de 0 ate 255 gradualmente
for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle++) {
// Escreve o novo ciclo de trabalho no registrador do canal LEDC
ledcWrite(ledChannel, dutyCycle);
// Imprime o valor instantaneo no Monitor Serial
Serial.print("Fade In -> Duty: ");
Serial.println(dutyCycle);
// Aguarda 15 milissegundos para permitir percepcao visual suave do brilho
delay(15);
}
// Laco regressivo (Fade Out): decrementa o duty cycle de 255 ate 0 gradualmente
for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) {
// Atualiza o ciclo de trabalho no registrador de hardware
ledcWrite(ledChannel, dutyCycle);
// Imprime o valor instantaneo no Monitor Serial
Serial.print("Fade Out -> Duty: ");
Serial.println(dutyCycle);
// Aguarda 15 milissegundos entre cada decremento de intensidade
delay(15);
}
}
Gravação, Validação Prática e Análise de Funcionamento
Após o upload, observe atentamente o comportamento do LED na protoboard:
- O LED inicia apagado, amplia suavemente seu brilho ao longo de aproximadamente 3,8 segundos até atingir a luminância máxima (255 níveis).
- Sem qualquer interrupção ou piscar perceptível (flicker), o brilho retrocede suavemente até apagar-se por completo, reiniciando o ciclo de respiração contínua.
- No Monitor Serial a 115200 bps, é possível observar a contagem matemática sequencial acompanhando a dinâmica do sinal.
Lição 4: Sensor de Movimento PIR e Temporização Não Bloqueante com Timers
A detecção de presença volumétrica e intrusão sem contato mecânico é um dos pilares da segurança patrimonial, automação predial e economia inteligente de energia em iluminação pública. Nesta lição, você integrará o consagrado sensor de presença por infravermelho passivo (PIR – Passive Infrared) HC-SR501 a um buzzer piezelétrico ativo de 5 V, implementando uma arquitetura de temporização assíncrona não bloqueante baseada em registradores de milissegundos (millis()).
Princípio Físico da Radiação Piroelétrica e Lente de Fresnel
Todo corpo material com temperatura superior ao zero absoluto (0 Kelvin / -273,15 °C) emite radiação eletromagnética proporcional à sua temperatura de acordo com a Lei de Planck e a Lei de Stefan-Boltzmann. O corpo humano (cuja temperatura interna média situa-se em aproximadamente 36,5 °C) emite radiação predominantemente no espectro infravermelho distante (Far-Infrared), com comprimento de onda de pico concentrado na faixa entre e .
O elemento transdutor montado sob a cúpula plástica branca é constituído por dois cristais piroelétricos balanceados (ex: titanato de bário ou tantalato de lítio) conectados em oposição de fase. Quando não há movimento no ambiente, a radiação ambiente incide uniformemente sobre os dois cristais, gerando tensões idênticas que se anulam mutualmente na entrada diferencial do amplificador interno.
A cúpula semiesférica translúcida é uma Lente de Fresnel multifacetada. Ela segmenta o campo de visão de 100 a 120 graus do sensor em múltiplos cones de detecção ópticos independentes intercalados por zonas cegas. Quando uma pessoa se desloca pelo ambiente, ela cruza sucessivamente esses cones de radiação: sua silhueta térmica atinge primeiro um cristal piroelétrico e, instantes depois, o segundo cristal. Essa defasagem temporal desbalanceia a entrada do circuito integrado processador BISS0001, gerando um pulso analógico amplificado que comuta a saída digital do módulo para HIGH (3,3 V).
Calibração dos Trimpots e Jumper de Disparo
A placa do módulo HC-SR501 possui dois potenciômetros de ajuste analógico e um seletor de jumper:
- Trimpot de Sensibilidade / Distância (Sx): Girar no sentido horário aumenta o alcance de detecção (ajustável de aproximadamente 3 metros até 7 metros).
- Trimpot de Atraso de Tempo (Tx): Define a largura do pulso de saída HIGH gerado a cada detecção (ajustável de 3 segundos até 300 segundos). Para controle direto por microcontrolador, recomenda-se girar o trimpot de tempo totalmente no sentido anti-horário (mínimo de ~3 segundos), transferindo toda a inteligência temporal para o firmware do ESP32.
- Jumper de Disparo (Trigger Mode):
- Posição L (Disparo Único / Não Repetitivo): O sensor emite um pulso HIGH e mantém a saída inibida até o término do tempo configurado no trimpot, mesmo que a pessoa continue se movendo no local.
- Posição H (Disparo Repetitivo Contínuo): A saída permanece em HIGH ininterruptamente enquanto houver movimento contínuo detectado nos cones de Fresnel. É a posição ideal para sistemas de alarme.
Temporização Não Bloqueante com millis()
O uso da função delay() em sistemas embarcados é uma prática altamente desencorajada na engenharia profissional. Durante um delay(3000), a CPU do microcontrolador é retida em um laço ocioso de consumo de ciclos de instrução: nenhuma leitura de botão é processada, nenhum pacote de rede Wi-Fi é atendido e nenhuma interrupção de emergência pode ser tratada.
A solução canônica é a temporização assíncrona por software baseada no contador millis(). A função millis() retorna um número inteiro sem sinal de 32 bits (unsigned long) representando a contagem acumulada de milissegundos decorridos desde a inicialização do microcontrolador.
A condição matemática de disparo é expressa por:
Dessa forma, o ESP32 consegue acionar o alarme sonoro, contar o tempo de segurança e continuar executando centenas de outras tarefas com máxima responsividade.
Componentes Necessários para a Lição 4
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 |
| Sensor de Presença PIR HC-SR501 | 1 unidade | Tensão de alimentação 5 V DC, saída lógica 3,3 V |
| Buzzer Piezelétrico Ativo | 1 unidade | Transdutor acústico de 5 V DC com oscilador interno |
| Protoboard de 830 Pontos | 1 unidade | Montagem do circuito |
| Cabos Jumper Flexíveis Macho-Fêmea e Macho-Macho | 6 unidades | Conexões de alimentação e sinal |
Diagrama Esquemático e Montagem Prática
Conecte o circuito conforme ilustrado a seguir. O sensor HC-SR501 requer alimentação primária de 5 V (fornecida pelo pino Vin da placa DEVKIT V1 quando conectada à porta USB), porém sua saída digital de dados opera em compatibilidade perfeita com a lógica de 3,3 V do ESP32. O buzzer ativo é acionado diretamente pelo pino GPIO 26.
Tabela de conexões elétricas ponto a ponto:
| Componente | Terminal Físico | Pino ESP32 | Função do Sinal |
|---|---|---|---|
| Sensor PIR HC-SR501 | VCC (+5V) | Vin | Alimentação principal de 5 V do sensor |
| Sensor PIR HC-SR501 | OUT (Sinal) | GPIO 27 | Sinal digital de detecção (0V repouso, 3.3V ativo) |
| Sensor PIR HC-SR501 | GND (Terra) | GND | Referência de 0 V comum |
| Buzzer Ativo | Terminal Positivo (+) | GPIO 26 | Saída digital de chaveamento do alarme sonoro |
| Buzzer Ativo | Terminal Negativo (-) | GND | Referência de 0 V comum |
📦 Bibliotecas desta lição: nenhuma — o sketch emprega apenas a função de registro de clock interno
millis()e comandos nativos de I/O (pinMode,digitalRead,digitalWrite).
Código-Fonte Completo Comentado Linha a Linha
Insira o código abaixo na IDE Arduino e realize o upload para a placa:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 4: Sensor de Movimento PIR e Temporizacao Nao Bloqueante com Timers
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Definicao constante do pino GPIO conectado ao terminal positivo do buzzer ativo
const int buzzerPin = 26; // Pino GPIO 26 atuara como saida digital de alarme
// Definicao constante do pino GPIO conectado ao terminal OUT do sensor de presenca PIR
const int motionSensor = 27; // Pino GPIO 27 recebera o pulso de nivel logico alto do sensor
// Variavel unsigned long de 32 bits para armazenar o carimbo de tempo da ultima atualizacao
unsigned long previousMillis = 0;
// Variavel para registrar a contagem instantanea de milissegundos do microcontrolador
unsigned long currentMillis = 0;
// Constante que estipula o intervalo de duracao sonora do alarme em milissegundos
const long interval = 3000; // O buzzer soara por 3000 milissegundos (3 segundos) apos a deteccao
// Rotina de configuracao executada uma unica vez durante a inicializacao
void setup() {
// Inicializa o barramento serial de comunicacao para emissao de mensagens de telemetria
Serial.begin(115200);
// Configura o pino do buzzer como saida digital de baixa impedancia
pinMode(buzzerPin, OUTPUT);
// Assegura que o buzzer inicie desligado (nivel logico LOW no terminal positivo)
digitalWrite(buzzerPin, LOW);
// Configura o pino conectado ao sensor PIR como entrada digital
pinMode(motionSensor, INPUT);
// Mensagem inicial de estabilizacao termica do sensor piroeletrico
Serial.println("=================================================");
Serial.println("Sistema de Alarme PIR Iniciado. Aguardando Estabilizacao...");
Serial.println("=================================================");
// Aguarda 20 segundos para que a substancia piroeletrica equilibre sua carga interna
delay(20000);
Serial.println("Sensor PIR Pronto e Operacional!");
}
// Laco de execucao continua e monitoramento em tempo real
void loop() {
// Amostra o estado logico instantaneo do sensor de presenca HC-SR501
int state = digitalRead(motionSensor);
// Atualiza a variavel de contagem temporal com os milissegundos decorridos do sistema
currentMillis = millis();
// Verifica se o sensor detectou perturbacao infravermelha no campo volumetrico
if (state == HIGH) {
// Registra o carimbo de tempo em que a presenca foi confirmada
previousMillis = currentMillis;
// Liga o buzzer ativo acionando o oscilador sonoro interno
digitalWrite(buzzerPin, HIGH);
// Imprime alerta no console serial
Serial.println("ALERTA: Movimento Detectado no Campo de Visao!");
} else {
// Caso a saida do sensor esteja em nivel baixo, verifica se o tempo de alarme expirou
if (currentMillis - previousMillis >= interval) {
// Desliga o buzzer assim que transcorridos 3 segundos da ultima presenca
digitalWrite(buzzerPin, LOW);
}
}
}
Validação Prática e Diagnóstico Operacional
- Conecte a placa e carregue o sketch. O Monitor Serial exibirá a mensagem de espera de estabilização térmica por 20 segundos.
- Durante esse período inicial, a substância cerâmica piroelétrica do HC-SR501 ajusta sua polarização galvânica interna em relação à temperatura ambiente. Não se mova em frente ao sensor nesse intervalo.
- Após a mensagem
Sensor PIR Pronto e Operacional!, passe a mão a cerca de 1 metro de distância da cúpula de Fresnel:- A linha OUT comutará para 3,3 V instantaneamente.
- O buzzer soará com tom contínuo estridente de alerta.
- O Monitor Serial registrará
ALERTA: Movimento Detectado no Campo de Visao!.
- Afaste-se do raio de cobertura: após 3 segundos sem movimento, o alarme silenciará automaticamente, retornando ao estado de vigília.
Lição 5: Servidor Web Wi-Fi Standalone para Controle de Chaves e Cargas
O verdadeiro diferencial que consolida o microcontrolador ESP32 como a plataforma preferencial para a Internet das Coisas (IoT) é a sua interface de rádio frequência Wi-Fi 802.11 b/g/n embutida no silício. Nesta lição, você transformará o ESP32 em um Servidor Web HTTP Standalone. O dispositivo conectará à sua rede sem fio local, atenderá requisições de navegadores web em computadores e celulares e fornecerá uma página HTML5 moderna e responsiva com interruptores deslizantes para controle independente de dois canais de iluminação (LEDs).
Arquitetura de Redes TCP/IP e o Protocolo HTTP
O firmware do ESP32 executa sobre a camada de rede uma implementação compacta da pilha de protocolos TCP/IP denominada LwIP (Lightweight IP). No modo Station (STA), o ESP32 atua como um nó cliente da rede local, associando-se ao seu roteador Wi-Fi através de um identificador de rede (SSID – Service Set Identifier) e senha criptografada (WPA2-PSK). Ao autenticar-se, o servidor DHCP do seu roteador atribui ao ESP32 um endereço IP local único (ex: 192.168.1.105).
O protocolo de comunicação da World Wide Web é o HTTP (Hypertext Transfer Protocol), que opera na camada de aplicação sobre o protocolo de transporte TCP (porta padrão 80). O fluxo de controle obedece ao modelo clássico de requisição e resposta (Request-Response):
- Conexão: O usuário digita o endereço IP do ESP32 na barra de endereços do navegador (Chrome, Safari, Firefox). O navegador estabelece um soquete TCP na porta 80 com o microcontrolador.
- Requisição HTTP GET: O navegador envia um cabeçalho de texto solicitando a página ou acionando um comando (ex:
GET /26/on HTTP/1.1). - Processamento: O microcontrolador analisa a string da requisição. Se encontrar a rota
/26/on, aciona a porta física GPIO 26 para HIGH. - Resposta HTTP: O ESP32 devolve o cabeçalho de resposta:
seguido do corpo do documento HTML5 estilizado com CSS3 contendo a interface gráfica e o estado atualizado dos interruptores.HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Connection: close - Fechamento: O ESP32 fecha o soquete TCP (
client.stop()), liberando memória RAM e buffers de rede para o próximo cliente.
Componentes Necessários para a Lição 5
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 com Wi-Fi |
| Diodo Emissor de Luz (LED) Vermelho | 1 unidade | Carga do Canal 1 (GPIO 26) |
| Diodo Emissor de Luz (LED) Verde | 1 unidade | Carga do Canal 2 (GPIO 27) |
| Resistores de Filme de Carbono | 2 unidades | , , tolerância 5% |
| Protoboard de 830 Pontos | 1 unidade | Montagem dos circuitos de sinalização |
| Cabos Jumper Flexíveis | 4 unidades | Conexões Macho-Macho |
Diagrama Esquemático e Montagem Prática
Monte os dois LEDs na protoboard protegidos por resistores limitadores de . O LED 1 será conectado ao pino GPIO 26 e o LED 2 será conectado ao pino GPIO 27.
Tabela de ligações:
| Componente | Terminal | Pino ESP32 | Função do Circuito |
|---|---|---|---|
| LED 1 (Vermelho) | Ânodo (via resistor ) | GPIO 26 | Canal de carga 1 controlado via Web |
| LED 1 (Vermelho) | Cátodo | GND | Referência de terra |
| LED 2 (Verde) | Ânodo (via resistor ) | GPIO 27 | Canal de carga 2 controlado via Web |
| LED 2 (Verde) | Cátodo | GND | Referência de terra |
📦 Bibliotecas desta lição:
<WiFi.h>(versão 2.0.14) — biblioteca nativa embutida diretamente no pacote oficial de placas ESP32 da Espressif Systems. Não requer nenhuma instalação adicional.
Código-Fonte Completo Comentado Linha a Linha
Abra o sketch abaixo na IDE Arduino. Substitua imperativamente as constantes REPLACE_WITH_YOUR_SSID e REPLACE_WITH_YOUR_PASSWORD pelo nome exato e senha da sua rede Wi-Fi doméstica de 2,4 GHz:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 5: Servidor Web Wi-Fi Standalone para Controle de Chaves e Cargas
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Inclusao da biblioteca oficial de conectividade Wi-Fi nativa do nucleo ESP32
#include <WiFi.h>
// Credenciais de autenticacao da rede Wi-Fi local (utilize apenas redes de frequencia 2,4 GHz)
const char* ssid = "REPLACE_WITH_YOUR_SSID"; // Nome da sua rede sem fio
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; // Senha da sua rede sem fio
// Cria uma instancia do servidor TCP escutando conexoes de entrada na porta padrao HTTP (80)
WiFiServer server(80);
// Variavel String para armazenar o cabecalho completo da requisicao HTTP recebida do cliente
String header;
// Variaveis auxiliares para rastreamento do estado operacional de cada uma das saidas
String output26State = "off"; // Estado inicial do canal 1 (GPIO 26): desligado
String output27State = "off"; // Estado inicial do canal 2 (GPIO 27): desligado
// Constantes de mapeamento dos pinos fisicos associados as cargas
const int output26 = 26; // Pino GPIO 26 conectado ao LED Vermelho
const int output27 = 27; // Pino GPIO 27 conectado ao LED Verde
// Variaveis de temporizacao para encerramento de conexoes TCP travadas
unsigned long currentTime = 0;
unsigned long previousTime = 0;
const long timeoutTime = 2000; // Limite de tempo de espera do cliente HTTP (2 segundos)
// Funcao de configuracao inicial do firmware e conexao a rede
void setup() {
// Inicializa a comunicacao serial a 115200 bps para exibicao do endereco IP local obtido
Serial.begin(115200);
// Configura os pinos das cargas como saidas digitais push-pull
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Define o estado inicial de ambos os pinos como LOW (cargas iniciam desligadas)
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
// Inicia o processo de conexao com o ponto de acesso Wi-Fi local
Serial.print("Conectando-se a rede Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Laco de espera ate que a associacao e a obtencao de IP via DHCP sejam concluidas
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Imprime no console a confirmacao de conexao e o endereco IP atribuido pelo roteador
Serial.println("");
Serial.println("Conexao Wi-Fi Estabelecida com Sucesso!");
Serial.print("Endereco IP Local do Servidor Web: ");
Serial.println(WiFi.localIP());
// Inicializa o servidor Web e passa a escutar requisicoes na porta 80
server.begin();
}
// Laco principal: atende requisicoes HTTP de navegadores e celulares
void loop() {
// Verifica se ha algum cliente HTTP tentando conectar-se ao servidor
WiFiClient client = server.available();
// Caso um cliente conecte-se ao soquete
if (client) {
currentTime = millis();
previousTime = currentTime;
Serial.println("Novo Cliente Conectado ao Servidor Web.");
String currentLine = ""; // Armazena a linha atual do cabecalho recebido
// Permanece atendendo o cliente enquanto conectado e dentro da janela de timeout
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
// Se houver bytes disponiveis para leitura no buffer TCP
if (client.available()) {
char c = client.read(); // Le um caractere do buffer de entrada
Serial.write(c); // Ecoa o caractere no console serial
header += c; // Concatena no cabecalho geral da requisicao
// Se o caractere for quebra de linha
if (c == '\n') {
// Se a linha atual estiver vazia, significa o fim dos cabecalhos da requisicao HTTP
if (currentLine.length() == 0) {
// Envia os cabecalhos de resposta HTTP padrao (200 OK)
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println(); // Linha em branco obrigatoria separando cabecalho de conteudo
// Analise de rotas: liga ou desliga o GPIO 26
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("Comando Recebido: GPIO 26 -> LIGAR");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("Comando Recebido: GPIO 26 -> DESLIGAR");
output26State = "off";
digitalWrite(output26, LOW);
}
// Analise de rotas: liga ou desliga o GPIO 27
else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("Comando Recebido: GPIO 27 -> LIGAR");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("Comando Recebido: GPIO 27 -> DESLIGAR");
output27State = "off";
digitalWrite(output27, LOW);
}
// Emissao do documento HTML5 responsivo
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// Estilos CSS3 embutidos para botoes deslizantes modernos
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");
// Corpo da pagina web
client.println("<body><h1>RoboBuilders ESP32 Web Server</h1>");
// Secao do canal GPIO 26
client.println("<p>GPIO 26 - Estado Atual: " + output26State + "</p>");
if (output26State == "off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">LIGAR</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">DESLIGAR</button></a></p>");
}
// Secao do canal GPIO 27
client.println("<p>GPIO 27 - Estado Atual: " + output27State + "</p>");
if (output27State == "off") {
client.println("<p><a href=\"/27/on\"><button class=\"button\">LIGAR</button></a></p>");
} else {
client.println("<p><a href=\"/27/off\"><button class=\"button button2\">DESLIGAR</button></a></p>");
}
client.println("</body></html>");
client.println(); // Linha final de terminacao
break; // Interrompe o laco de atendimento do cliente
} else {
currentLine = ""; // Limpa a linha para processar a proxima
}
} else if (c != '\r') {
currentLine += c; // Adiciona caractere a linha atual
}
}
}
// Limpa a variavel de cabecalho para a proxima requisicao
header = "";
// Encerra formalmente a conexao TCP com o cliente
client.stop();
Serial.println("Conexao Encerrada com o Cliente.\n");
}
}
Validação Prática e Controle pelo Navegador
- Faça o upload do firmware para a placa DEVKIT V1.
- Abra o Monitor Serial a 115200 bps. Você verá o processo de associação à rede Wi-Fi e a impressão do endereço IP concedido:
Conectando-se a rede Wi-Fi: MINHA_REDE_WIFI ...... Conexao Wi-Fi Estabelecida com Sucesso! Endereco IP Local do Servidor Web: 192.168.1.105 - Abra qualquer navegador web (no computador ou smartphone conectado à mesma rede Wi-Fi) e digite na barra de endereços:
http://192.168.1.105. - A página Web da RoboBuilders será renderizada instantaneamente:
- Clique em LIGAR no botão do GPIO 26: o LED vermelho acende imediatamente e o botão muda visualmente para cinza com o texto DESLIGAR.
- Clique em LIGAR no GPIO 27: o LED verde acende em paralelo.
- O Monitor Serial exibirá o log em tempo real de cada requisição HTTP recebida e processada.
Lição 6: Servidor Web com Controle de Cores para LED RGB
Após dominar o chaveamento binário liga/desliga pela rede, você avançará para o controle cromático e analógico em tempo real através do protocolo Wi-Fi. Nesta lição, você desenvolverá um servidor Web com seletor de paleta de cores gráfico (HTML5 Color Picker) para sintonizar dinamicamente qualquer cor do espectro visível em um LED RGB de cátodo comum utilizando três canais de modulação PWM independentes do periférico LEDC.
Teoria da Síntese Aditiva de Cores e LED RGB
O olho humano percebe as cores através de células fotorreceptoras da retina denominadas cones, sensíveis primariamente a três faixas do espectro visível: vermelho (~650 nm), verde (~530 nm) e azul (~460 nm). Pelo princípio da síntese aditiva de cores (RGB – Red, Green, Blue), a sobreposição em proporções variáveis dessas três emissões luminosas permite gerar milhões de cores perceptíveis pelo cérebro humano.
O LED RGB integra em um único encapsulamento epóxi difuso de 5 mm três pastilhas semicondutoras de emissão óptica independentes. Em um modelo de cátodo comum, o terminal mais longo do componente é o terra comum (GND), enquanto os outros três terminais correspondem aos ânodos individuais dos canais Vermelho (Red), Verde (Green) e Azul (Blue).
Conversão Cromática Hexadecimal e PWM
No padrão Web HTML5, uma cor é selecionada na interface gráfica em formato hexadecimal (#RRGGBB), onde cada par representa uma intensidade de 8 bits em base 16:
A conversão para valores decimais inteiros de 8 bits (0 a 255) determina o duty cycle que será injetado em cada canal de modulação PWM via periférico LEDC do ESP32:
A tensão média eficaz de cada canal óptico do LED é proporcional ao valor decodificado:
Componentes Necessários para a Lição 6
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 com Wi-Fi |
| Diodo Emissor de Luz (LED) RGB | 1 unidade | Encapsulamento difuso de 5 mm, Cátodo Comum |
| Resistores de Filme de Carbono | 3 unidades | , , tolerância 5% |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis | 5 unidades | Conexões Macho-Macho |
Diagrama Esquemático e Montagem Prática
Identifique os 4 terminais do LED RGB: o terminal mais longo é o Cátodo Comum (conecte ao GND). O terminal ao lado do cátodo no sentido isolado é o Vermelho (conecte via resistor de ao GPIO 13). Os outros dois terminais do lado oposto são o Verde (via resistor de ao GPIO 12) e o Azul (via resistor de ao GPIO 14).
Tabela de conexões de pinos:
| Terminal do LED RGB | Ligação Intermediária | Pino ESP32 | Canal LEDC Associado |
|---|---|---|---|
| Terminal Vermelho (Red) | Resistor em série | GPIO 13 | Canal PWM LEDC 1 |
| Cátodo Comum (Pino Longo) | Conexão direta ao terra | GND | Referência de 0 V |
| Terminal Verde (Green) | Resistor em série | GPIO 12 | Canal PWM LEDC 2 |
| Terminal Azul (Blue) | Resistor em série | GPIO 14 | Canal PWM LEDC 3 |
📦 Bibliotecas desta lição:
<WiFi.h>(versão 2.0.14) — embutida no pacote de suporte de placas oficial ESP32 da Espressif Systems.
Código-Fonte Completo Comentado Linha a Linha
Carregue o firmware abaixo ajustando o nome e senha da sua rede Wi-Fi local:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 6: Servidor Web com Controle de Cores para LED RGB
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Inclusao da biblioteca Wi-Fi do ESP32
#include <WiFi.h>
// Credenciais da rede Wi-Fi local de 2,4 GHz
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Inicializacao do servidor Web HTTP na porta 80
WiFiServer server(80);
// Variaveis de texto para decodificar os parametros hexadecimais recebidos da requisicao GET
String redString = "0";
String greenString = "0";
String blueString = "0";
int pos1 = 0;
int pos2 = 0;
// Mapeamento dos pinos fisicos GPIO conectados aos anodos do LED RGB
const int redPin = 13; // Pino do canal Vermelho
const int greenPin = 12; // Pino do canal Verde
const int bluePin = 14; // Pino do canal Azul
// Parametros de configuracao do periferico PWM LEDC
const int freq = 5000; // Frequencia de 5000 Hz
const int redChannel = 1; // Canal PWM 1 para o Vermelho
const int greenChannel = 2; // Canal PWM 2 para o Verde
const int blueChannel = 3; // Canal PWM 3 para o Azul
const int resolution = 8; // Profundidade de 8 bits (valores de 0 a 255)
// Cabecalho da requisicao recebida
String header;
// Controle de tempo de timeout de conexao TCP
unsigned long currentTime = 0;
unsigned long previousTime = 0;
const long timeoutTime = 2000;
// Configuracao inicial do sistema e associacao dos canais PWM
void setup() {
Serial.begin(115200);
// 1. Configuracao dos canais LEDC com frequencia de 5 kHz e 8 bits de resolucao
ledcSetup(redChannel, freq, resolution);
ledcSetup(greenChannel, freq, resolution);
ledcSetup(blueChannel, freq, resolution);
// 2. Vinculacao dos canais de hardware aos respectivos pinos GPIO
ledcAttachPin(redPin, redChannel);
ledcAttachPin(greenPin, greenChannel);
ledcAttachPin(bluePin, blueChannel);
// Inicia com todos os canais em 0 (LED RGB apagado)
ledcWrite(redChannel, 0);
ledcWrite(greenChannel, 0);
ledcWrite(blueChannel, 0);
// Conexao com o roteador Wi-Fi
Serial.print("Conectando-se ao Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi Conectado!");
Serial.print("Servidor Web RGB Disponivel no IP: ");
Serial.println(WiFi.localIP());
// Inicia o servidor Web
server.begin();
}
// Laco de atendimento e parsing de cor
void loop() {
WiFiClient client = server.available();
if (client) {
currentTime = millis();
previousTime = currentTime;
Serial.println("Novo Cliente Conectado ao Servidor RGB.");
String currentLine = "";
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
if (c == '\n') {
if (currentLine.length() == 0) {
// Cabecalhos HTTP padrao
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Decodifica a URL no formato: GET /?r255g0b128& HTTP/1.1
if (header.indexOf("GET /?r") >= 0) {
pos1 = header.indexOf('r');
pos2 = header.indexOf('g');
redString = header.substring(pos1 + 1, pos2);
pos1 = header.indexOf('g');
pos2 = header.indexOf('b');
greenString = header.substring(pos1 + 1, pos2);
pos1 = header.indexOf('b');
pos2 = header.indexOf('&');
blueString = header.substring(pos1 + 1, pos2);
// Atualiza os ciclos de trabalho de hardware com os novos valores inteiros
ledcWrite(redChannel, redString.toInt());
ledcWrite(greenChannel, greenString.toInt());
ledcWrite(blueChannel, blueString.toInt());
Serial.print("Atualizacao de Cor -> R: ");
Serial.print(redString);
Serial.print(" | G: ");
Serial.print(greenString);
Serial.print(" | B: ");
Serial.println(blueString);
}
// Envia a pagina HTML5 contendo o seletor visual de cores
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<style>body { text-align: center; font-family: Arial, sans-serif;}");
client.println(".color-btn { padding: 15px 30px; font-size: 20px; border: none; border-radius: 8px; cursor: pointer; color: white; margin: 10px; }");
client.println("</style></head>");
client.println("<body><h1>RoboBuilders - Servidor LED RGB</h1>");
client.println("<p>Selecione uma cor para ajustar o LED instantaneamente via Wi-Fi:</p>");
// Botoes rapidos com cores primarias e secundarias pre-configuradas
client.println("<p><a href=\"/?r255g0b0&\"><button class=\"color-btn\" style=\"background: #ff0000;\">Vermelho</button></a></p>");
client.println("<p><a href=\"/?r0g255b0&\"><button class=\"color-btn\" style=\"background: #00ff00;\">Verde</button></a></p>");
client.println("<p><a href=\"/?r0g0b255&\"><button class=\"color-btn\" style=\"background: #0000ff;\">Azul</button></a></p>");
client.println("<p><a href=\"/?r255g255b0&\"><button class=\"color-btn\" style=\"background: #e6b800;\">Amarelo</button></a></p>");
client.println("<p><a href=\"/?r180g0b255&\"><button class=\"color-btn\" style=\"background: #9900cc;\">Roxo</button></a></p>");
client.println("<p><a href=\"/?r0g0b0&\"><button class=\"color-btn\" style=\"background: #333333;\">Desligar LED</button></a></p>");
client.println("</body></html>");
client.println();
break;
} else {
currentLine = "";
}
} else if (c != '\r') {
currentLine += c;
}
}
}
header = "";
client.stop();
Serial.println("Cliente Desconectado.\n");
}
}
Validação Prática e Demonstração
- Acesse o IP do ESP32 pelo celular ou computador.
- Clique no botão Vermelho: o pino GPIO 13 recebe duty cycle de 255 e o LED emite vermelho puro.
- Clique em Amarelo: o firmware mistura simultaneamente o canal Vermelho (255) e o canal Verde (255), gerando a cor amarela brilhante por síntese aditiva.
- Clique em Roxo: os canais Vermelho e Azul atuam em conjunto, criando o tom púrpura.
- Pressione Desligar LED: os três canais voltam a 0 V, cessando a emissão óptica.
Lição 7: Servidor Web com Módulo Relé e Isolamento Galvânico
Nas lições anteriores, manipulamos exclusivamente componentes de baixa potência que operam no nível lógico do microcontrolador (3,3 V DC). Entretanto, na automação residencial e industrial de missão crítica, a função primordial do sistema é controlar cargas elétricas reais de alta potência: lâmpadas fluorescentes e LED de 110 V/220 V AC, solenoides hidráulicos, bombas d’água, aquecedores resistivos e motores monofásicos. Para interfacear o sinal frágil do silício com a alta tensão da rede sem risco de choques elétricos ou queima do microcontrolador, o elemento padrão de engenharia é o Módulo Relé com Isolamento Galvânico por Optoacoplador.
Princípio Eletromecânico e Força Contraeletromotriz
Um relé eletromecânico é um interruptor operado magneticamente. Ele é composto por uma bobina de fio de cobre esmaltado enrolada sobre um núcleo ferromagnético, uma mola de retorno e um conjunto de contatos mecânicos metálicos:
- COM (Comum): O terminal central que se conecta eletricamente à fonte de energia da carga.
- NO / NA (Normalmente Aberto): O contato que permanece fisicamente aberto em repouso. A corrente só flui para a carga quando a bobina do relé é energizada.
- NC / NF (Normalmente Fechado): O contato que permanece fisicamente fechado em repouso, conduzindo corrente enquanto a bobina estiver desenergizada.
Quando a bobina é submetida a uma corrente contínua, o campo magnético atrai a armadura de ferro, fechando o contato NA. No momento em que a corrente da bobina é bruscamente interrompida pelo microcontrolador, o campo magnético colapsa violentamente, induzindo uma tensão reversa de polaridade oposta de valor altíssimo conhecida como Força Contraeletromotriz (FCEM – Back EMF), governada pela Lei da Indução de Faraday-Lenz:
Em uma bobina de relé, essa tensão induzida de pico pode ultrapassar a em uma fração de microssegundo! Se essa energia atingisse o pino GPIO do ESP32, o transistor interno seria destruído instantaneamente. Por esse motivo, o módulo relé integra na placa um diodo de roda-livre (flyback diode) 1N4148 em antiparalelo com a bobina, oferecendo um caminho fechado de recirculação para dissipar a corrente indutiva com segurança.
Potência e Cargas em Corrente Alternada (AC)
Para cargas alimentadas pela rede elétrica alternada comercial ( ou a ), a potência aparente () e a potência ativa real () consumida pela carga com fator de potência são dadas por:
O relé do módulo suporta correntes de comutação de até em (carga resistiva de até ), garantindo ampla margem para automação residencial.
O Papel do Optoacoplador e do Jumper JD-VCC
O módulo do kit possui isolamento óptico integral proporcionado por um optoacoplador (circuito integrado de 4 pinos). Dentro dele, um emissor infravermelho aciona um fototransistor através de uma barreira isolante de silicone sem qualquer contato físico entre o circuito do ESP32 e a bobina do relé.
- Com o jumper JD-VCC / VCC instalado: A bobina é alimentada pela mesma fonte de 5 V que alimenta a placa ESP32 (Vin). É a montagem padrão de bancada.
- Sem o jumper JD-VCC: Você conecta uma fonte externa de 5 V exclusiva nos pinos JD-VCC e GND do relé, isolando galvanicamente 100% da corrente de pico do microcontrolador.
Introdução aos Servidores Web Assíncronos (ESPAsyncWebServer)
Nas lições 5 e 6, utilizamos a biblioteca síncrona WiFiServer. Embora funcional para projetos simples, ela atende um único cliente por vez de forma sequencial e bloqueante.
Nesta Lição 7, avançamos para o padrão profissional da indústria com a biblioteca ESPAsyncWebServer suportada pela AsyncTCP. Esse ecossistema opera de forma totalmente não bloqueante e assíncrona orientada a eventos: o microcontrolador pode processar requisições simultâneas de dezenas de navegadores web conectados ao mesmo tempo, sem perder estabilidade, sem reter o processador em laços ociosos e com tempo de resposta quase instantâneo.
Componentes Necessários para a Lição 7
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 |
| Módulo Relé de 1 ou 2 Canais 5 V | 1 unidade | Com optoacoplador e contatos 10A 250VAC |
| Diodo Emissor de Luz (LED) Vermelho | 1 unidade | Representação segura da carga AC |
| Resistor de Filme de Carbono | 1 unidade | , |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis Macho-Fêmea e Macho-Macho | 6 unidades | Conexões de alimentação e dados |
⚠️ Atenção — Regra de Segurança em Bancada: Para garantir a segurança integral de estudantes e evitar o manuseio de tensões perigosas de 110 V / 220 V da rede elétrica de tomadas durante as práticas de bancada, conectaremos o relé para chavear um LED alimentado pelos 3,3 V do próprio circuito. O princípio de chaveamento de contatos secos (COM e NA) é rigorosamente idêntico ao de uma lâmpada residencial de alta tensão.
Diagrama Esquemático e Montagem Prática
Tabela de conexões de controle:
| Terminal do Módulo Relé | Pino ESP32 | Função Elétrica |
|---|---|---|
| VCC | Vin (5V) | Alimentação lógica do optoacoplador |
| GND | GND | Referência comum de terra |
| IN1 | GPIO 26 | Sinal lógico de comando (LOW ativa relé) |
| COM (Comum) | 3V3 | Alimentação da carga de teste |
| NO (Normalmente Aberto) | Ânodo LED (via resistor ) | Saída ligada à carga |
📦 Bibliotecas desta lição:
ESPAsyncWebServerpor me-no-dev (versão 1.2.4)AsyncTCPpor me-no-dev / dvarrel (versão 1.1.4)- Instalação via ZIP: Faça o download dos repositórios oficiais AsyncTCP e ESPAsyncWebServer. Na IDE Arduino, acesse
Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP..., selecione os arquivos baixados e reinicie a IDE.
Código-Fonte Completo Comentado Linha a Linha
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 7: Servidor Web com Modulo Rele e Isolamento Galvanico
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Importacao das bibliotecas necessarias para o servidor assincrono
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Credenciais de conexao com a rede Wi-Fi local de 2,4 GHz
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Parametros de configuracao do rele
#define RELAY_NO true // Define que a carga esta conectada no contato Normalmente Aberto (NA)
#define NUM_RELAYS 1 // Quantidade de canais de rele controlados
// Mapeamento dos pinos GPIO conectados as entradas de sinal dos reles
int relayGPIOs[NUM_RELAYS] = {26}; // Canal 1 conectado no GPIO 26
// Parametros de consulta URL para as rotas HTTP GET
const char* PARAM_INPUT_1 = "relay";
const char* PARAM_INPUT_2 = "state";
// Criacao da instancia do servidor assincrono na porta padrao HTTP (80)
AsyncWebServer server(80);
// Template da pagina Web responsiva embutida na memoria Flash via literal raw
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RoboBuilders - Controle de Rele</title>
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.2rem; color: #1c1c1c;}
p {font-size: 1.5rem;}
.switch {position: relative; display: inline-block; width: 90px; height: 44px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 44px}
.slider:before {position: absolute; content: ""; height: 36px; width: 36px; left: 4px; bottom: 4px; background-color: #fff; border-radius: 50%; transition: .4s}
input:checked + .slider {background-color: #fa634f}
input:checked + .slider:before {transform: translateX(46px)}
</style>
</head>
<body>
<h2>RoboBuilders ESP32 Rele Web Server</h2>
<h4>Canal 1 - Carga de Potencia (GPIO 26)</h4>
<label class="switch">
<input type="checkbox" onchange="toggleCheckbox(this)" id="1">
<span class="slider"></span>
</label>
<script>
function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?relay=26&state=1", true); }
else { xhr.open("GET", "/update?relay=26&state=0", true); }
xhr.send();
}
</script>
</body>
</html>
)rawliteral";
// Funcao de configuracao inicial do microcontrolador
void setup() {
Serial.begin(115200);
// Inicializacao dos pinos dos reles como saida digital
for (int i = 0; i < NUM_RELAYS; i++) {
pinMode(relayGPIOs[i], OUTPUT);
// Modulos rele comuns ativam com nivel logico LOW (logica invertida)
if (RELAY_NO) {
digitalWrite(relayGPIOs[i], HIGH); // HIGH = Rele Desligado
} else {
digitalWrite(relayGPIOs[i], LOW); // LOW = Rele Ligado
}
}
// Conexao com a rede Wi-Fi local
Serial.print("Conectando-se ao Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConexao Wi-Fi Estabelecida!");
Serial.print("Servidor Assincrono de Rele Disponivel no IP: ");
Serial.println(WiFi.localIP());
// Rota raiz: entrega a pagina HTML responsiva
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
// Rota de comando assincrono: /update?relay=26&state=1
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
String inputMessage1;
String inputMessage2;
// Verifica se os dois parametros obrigatorios foram passados na URL
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
inputMessage1 = request->getParam(PARAM_INPUT_1)->value(); // Numero do GPIO
inputMessage2 = request->getParam(PARAM_INPUT_2)->value(); // Estado: 1 ou 0
int relayPin = inputMessage1.toInt();
int relayState = inputMessage2.toInt();
// Comuta o estado do rele considerando a logica do modulo
if (RELAY_NO) {
digitalWrite(relayPin, relayState == 1 ? LOW : HIGH);
} else {
digitalWrite(relayPin, relayState == 1 ? HIGH : LOW);
}
Serial.print("Comando Rele -> GPIO: ");
Serial.print(relayPin);
Serial.print(" | Novo Estado: ");
Serial.println(relayState == 1 ? "LIGADO (Ativo)" : "DESLIGADO (Repouso)");
}
// Responde instantaneamente ao cliente sem bloquear o fluxo
request->send(200, "text/plain", "OK");
});
// Inicia formalmente a escuta assincrona de conexoes
server.begin();
}
void loop() {
// Com o ESPAsyncWebServer, o laco loop() permanece totalmente livre para outras rotinas!
}
Validação Prática e Diagnóstico de Operação
- Grave o código na placa e observe o Monitor Serial confirmando o IP atribuído.
- Acesse o IP pelo navegador: você verá um interruptor moderno estilizado na cor oficial Coral da RoboBuilders.
- Clique no interruptor:
- O navegador dispara uma requisição assíncrona AJAX de milissegundos para
/update?relay=26&state=1. - Você ouvirá o clique sonoro mecânico característico da atracação da armadura ferromagnética do relé.
- O LED vermelho indicador do módulo acende e a carga de teste (LED na protoboard) é alimentada.
- O navegador dispara uma requisição assíncrona AJAX de milissegundos para
- Desative o interruptor: a armadura desarma com clique mecânico e a carga apaga imediatamente.
Lição 8: Sincronização Bidirecional de Estado em Tempo Real (Web e Botão Físico)
Um dos maiores desafios no projeto de sistemas IoT para casas inteligentes (Smart Homes) e automação predial é a sincronização bidirecional de estados. Imagine uma lâmpada controlada tanto pelo aplicativo no celular quanto pelo interruptor mecânico tradicional na parede: se um usuário liga a lâmpada fisicamente no interruptor da parede, o aplicativo no smartphone precisa refletir instantaneamente o estado “Ligado” sem que a página precise ser recarregada.
Nesta Lição 8, você implementará essa arquitetura avançada com o ESP32. O circuito integrará uma saída digital (LED), uma entrada digital (botão físico com algoritmo de eliminação de ruídos mecânicos – debouncing) e um servidor Web assíncrono que troca mensagens em tempo real via chamadas assíncronas AJAX/JavaScript.
O Algoritmo de Debounce por Software
Todo interruptor mecânico físico é composto por lâminas metálicas elásticas. No instante do fechamento dos contatos, as lâminas sofrem minúsculas oscilações mecânicas (bouncing) durante uma janela de 5 a 50 milissegundos, gerando uma sequência rápida de pulsos transitórios de subida e descida que o processador veloz de 240 MHz do ESP32 interpretaria erroneamente como dezenas de cliques sucessivos.
Para eliminar esse ruído sem adicionar capacitores externos caros, emprega-se o filtro de debounce por software:
- Ao detectar uma alteração na leitura do pino, o sistema registra o tempo atual:
lastDebounceTime = millis(). - Se o sinal permanecer no novo estado de forma ininterrupta por um período superior a um limiar seguro (), o novo estado é validado como real e a carga comuta de estado.
Sincronização na Camada Web via AJAX (setInterval)
Na página Web carregada no navegador do usuário, um script em linguagem JavaScript executa uma função periódica em segundo plano a cada 1 segundo (1000 ms) através de setInterval():
- O script dispara uma requisição assíncrona
XMLHttpRequestsilenciosa para o endpoint/statedo ESP32. - O ESP32 responde instantaneamente com uma string de texto simples contendo o estado real da porta (
1ou0). - O JavaScript atualiza a propriedade visual
checkeddo componente<input type="checkbox">e o texto do rótulo na tela sem piscar ou recarregar a página.
Componentes Necessários para a Lição 8
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 com Wi-Fi |
| Diodo Emissor de Luz (LED) Vermelho | 1 unidade | Carga de saída sinalizadora (GPIO 2) |
| Resistor de Filme de Carbono | 1 unidade | , |
| Chave Táctil Pushbutton | 1 unidade | Entrada manual física |
| Resistor de Filme de Carbono | 1 unidade | , (Resistor de pull-down) |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis | 5 unidades | Conexões Macho-Macho |
Tabela de Conexões de Pinos
| Componente | Terminal | Pino ESP32 | Função do Circuito |
|---|---|---|---|
| LED Vermelho | Ânodo (via resistor ) | GPIO 2 | Saída digital sincronizada (também LED onboard) |
| LED Vermelho | Cátodo | GND | Referência de terra |
| Chave Pushbutton | Terminal A | 3V3 | Alimentação lógica de 3,3 V |
| Chave Pushbutton | Terminal B | GPIO 4 | Entrada digital amostrada com debounce |
| Resistor | Terminal B da chave para o terra | GND | Polarização estável de pull-down |
📦 Bibliotecas desta lição:
ESPAsyncWebServerpor me-no-dev (versão 1.2.4)AsyncTCPpor me-no-dev / dvarrel (versão 1.1.4)- Nenhuma outra biblioteca externa é requerida.
Código-Fonte Completo Comentado Linha a Linha
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 8: Sincronizacao Bidirecional de Estado em Tempo Real (Web e Botao)
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Importacao das bibliotecas necessarias para o servidor assincrono e rede
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Credenciais da rede Wi-Fi local de 2,4 GHz
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Parametro de consulta URL para atualizacao de estado
const char* PARAM_INPUT_1 = "state";
// Mapeamento dos pinos fisicos do circuito
const int output = 2; // GPIO 2 controla o LED (saida)
const int buttonPin = 4; // GPIO 4 conectado a chave tactil (entrada)
// Variaveis de rastreamento de estado da carga
int ledState = LOW;
// Variaveis de filtragem de repique mecânico (debounce)
int buttonState;
int lastButtonState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // Tempo de acomodacao mecânica de 50 milissegundos
// Instancia do servidor Web assincrono na porta 80
AsyncWebServer server(80);
// Template da pagina Web responsiva com JavaScript para sincronizacao assincrona
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>RoboBuilders - Sincronizacao IoT</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.2rem; color: #1c1c1c;}
h4 {font-size: 1.4rem; color: #555;}
.switch {position: relative; display: inline-block; width: 90px; height: 44px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 44px}
.slider:before {position: absolute; content: ""; height: 36px; width: 36px; left: 4px; bottom: 4px; background-color: #fff; border-radius: 50%; transition: .4s}
input:checked + .slider {background-color: #fa634f}
input:checked + .slider:before {transform: translateX(46px)}
</style>
</head>
<body>
<h2>RoboBuilders - Sincronizacao Bidirecional</h2>
%BUTTONPLACEHOLDER%
<script>
function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?state=1", true); }
else { xhr.open("GET", "/update?state=0", true); }
xhr.send();
}
// Funcao AJAX executada periodicamente a cada 1000 milissegundos para polling de estado
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var inputChecked;
var outputStateM;
if( this.responseText == 1){
inputChecked = true;
outputStateM = "Ligado (ON)";
} else {
inputChecked = false;
outputStateM = "Desligado (OFF)";
}
document.getElementById("output").checked = inputChecked;
document.getElementById("outputState").innerHTML = outputStateM;
}
};
xhttp.open("GET", "/state", true);
xhttp.send();
}, 1000);
</script>
</body>
</html>
)rawliteral";
// Funcao de substituicao dinamica de marcadores no template HTML durante a carga inicial
String processor(const String& var){
if(var == "BUTTONPLACEHOLDER"){
String buttons = "";
String outputStateValue = (digitalRead(output) ? "checked" : "");
buttons += "<h4>Saida GPIO 2 - Estado: <span id=\"outputState\">" + String(digitalRead(output) ? "Ligado (ON)" : "Desligado (OFF)") + "</span></h4>";
buttons += "<label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}
void setup(){
Serial.begin(115200);
// Inicializacao dos pinos
pinMode(output, OUTPUT);
digitalWrite(output, LOW);
pinMode(buttonPin, INPUT);
// Conexao Wi-Fi
Serial.print("Conectando ao Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi Conectado!");
Serial.print("Servidor de Sincronizacao Ativo no IP: ");
Serial.println(WiFi.localIP());
// Rota raiz: entrega o HTML com os marcadores substituidos pela funcao processor
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Rota de alteracao de estado disparada pela interface Web
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
if (request->hasParam(PARAM_INPUT_1)) {
String message = request->getParam(PARAM_INPUT_1)->value();
ledState = message.toInt();
digitalWrite(output, ledState);
Serial.print("Comando Web Recebido -> Novo Estado: ");
Serial.println(ledState ? "LIGADO" : "DESLIGADO");
}
request->send(200, "text/plain", "OK");
});
// Rota de consulta de estado disparada pelo AJAX em segundo plano
server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) {
request->send(200, "text/plain", String(digitalRead(output)).c_str());
});
server.begin();
}
void loop() {
// Leitura com debounce do botao fisico na bancada
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
// Ao transicionar de LOW para HIGH (borda de subida ao pressionar)
if (buttonState == HIGH) {
ledState = !ledState; // Inverte o estado da carga
digitalWrite(output, ledState);
Serial.print("Botao Fisico Pressionado -> Saida Alterada para: ");
Serial.println(ledState ? "LIGADO" : "DESLIGADO");
}
}
}
lastButtonState = reading;
}
Validação Prática e Demonstração
- Acesse o endereço IP da placa no navegador do smartphone ou computador.
- Pressione o interruptor virtual na tela: o LED físico acende na protoboard e o interruptor se posiciona na cor Coral ativado.
- Agora, pressione o botão mecânico físico na protoboard:
- O LED apaga fisicamente na hora.
- Em menos de 1 segundo (próximo ciclo AJAX), o interruptor deslizante na tela do seu celular se move automaticamente para a posição desligada sem que você precise tocar na tela ou dar refresh na página!
- Pressione o botão físico novamente: o LED acende e a tela do smartphone atualiza para ligado instantaneamente.
Lição 9: Servidor Web Assíncrono com Telemetria de Temperatura e Umidade (DHT11)
A telemetria ambiental e o monitoramento em tempo real de variáveis climáticas são aplicações onipresentes em estufas agrícolas, centros de processamento de dados (CPDs), controle de processos industriais e conforto térmico residencial. Nesta lição, você desenvolverá uma estação meteorológica IoT completa baseada no sensor DHT11, servindo dados em tempo real através de um painel gráfico com ícones estilizados FontAwesome e requisições assíncronas periódicas sem sobrecarregar a CPU.
Princípio Físico do Sensor DHT11 e Psicrometria
O sensor DHT11 integra em sua cápsula plástica azul ventilada dois transdutores complementares e um microcontrolador interno de 8 bits dedicado:
- Transdutor de Umidade Relativa: Composto por um substrato de polímero higroscópico posicionado entre dois eletrodos condutores. Conforme a quantidade de vapor d’água na atmosfera varia, a constante dielétrica e a condutividade superficial do polímero alteram-se proporcionalmente.
- Transdutor de Temperatura: Um termistor do tipo NTC (Negative Temperature Coefficient), semicondutor cerâmico cuja resistência elétrica decresce exponencialmente com o aumento da temperatura ambiente.
Psicrometria e Umidade Relativa
A Umidade Relativa () expressa a relação percentual entre a pressão parcial de vapor d’água presente na mistura gasosa () e a pressão de saturação de vapor () para aquela mesma temperatura:
A pressão de vapor de saturação cresce exponencialmente com a temperatura de acordo com a formulação termodinâmica de Tetens:
O Protocolo Serial Customizado 1-Wire de 40 Bits
Diferente do barramento padrão 1-Wire da Maxim/Dallas, o DHT11 utiliza uma linha de dados bidirecional serial proprietária com pull-up:
- O ESP32 envia um pulso de início mantendo a linha em nível baixo por pelo menos e liberando para nível alto por .
- O sensor responde puxando a linha para nível baixo por e nível alto por .
- Em seguida, transmite 40 bits sequenciais de dados:
- Byte 1: Parte inteira da umidade relativa
- Byte 2: Parte decimal da umidade relativa
- Byte 3: Parte inteira da temperatura (°C)
- Byte 4: Parte decimal da temperatura (°C)
- Byte 5: Checksum de validação (soma dos bytes 1 + 2 + 3 + 4)
- A biblioteca oficial da Adafruit decodifica esses pulsos e valida o checksum antes de disponibilizar as grandezas. O tempo mínimo entre leituras consecutivas do DHT11 deve ser de pelo menos 1 a 2 segundos.
Componentes Necessários para a Lição 9
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 com Wi-Fi |
| Sensor Digital de Temperatura e Umidade DHT11 | 1 unidade | Módulo com resistor de pull-up integrado de 3 pinos |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis Macho-Fêmea e Macho-Macho | 3 unidades | Conexões de alimentação e barramento |
Tabela de Conexões de Pinos
| Terminal do DHT11 | Pino ESP32 | Função do Sinal |
|---|---|---|
| VCC (+) | 3V3 | Alimentação lógica de 3,3 V |
| DATA (Sinal / Out) | GPIO 4 | Linha serial bidirecional de dados |
| GND (-) | GND | Referência de 0 V comum |
📦 Bibliotecas desta lição:
DHT sensor librarypor Adafruit (versão 1.4.6)Adafruit Unified Sensorpor Adafruit (versão 1.1.14)ESPAsyncWebServerpor me-no-dev (versão 1.2.4)AsyncTCPpor me-no-dev / dvarrel (versão 1.1.4)- Instalação via Gerenciador:
Sketch > Incluir Biblioteca > Gerenciar Bibliotecas...-> busque porDHT sensor librarye clique em Instalar (selecione “Install All” para incluir o Adafruit Unified Sensor).
Código-Fonte Completo Comentado Linha a Linha
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 9: Servidor Web Assincrono com Telemetria Climática (DHT11)
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Inclusao das bibliotecas de rede assincrona e do sensor DHT11
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
// Credenciais da rede Wi-Fi local de 2,4 GHz
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Definicao do pino fisico de comunicacao com o sensor
#define DHTPIN 4 // Pino digital GPIO 4 conectado a linha de dados do DHT11
// Selecao do modelo de transdutor utilizado
#define DHTTYPE DHT11 // Tipo: DHT 11
// Inicializacao do objeto transdutor DHT
DHT dht(DHTPIN, DHTTYPE);
// Instancia do servidor Web assincrono na porta padrao HTTP (80)
AsyncWebServer server(80);
// Funcao dedicada a leitura e conversao da temperatura ambiente em graus Celsius
String readDHTTemperature() {
// Realiza a leitura da temperatura atraves da biblioteca
float t = dht.readTemperature();
// Verifica se a leitura falhou (retorno NaN - Not a Number)
if (isnan(t)) {
Serial.println("Falha na leitura do sensor DHT11!");
return "--";
} else {
Serial.print("Temperatura Lida: ");
Serial.print(t);
Serial.println(" *C");
return String(t, 1); // Retorna a temperatura com 1 casa decimal formatada
}
}
// Funcao dedicada a leitura e conversao da umidade relativa do ar em porcentagem
String readDHTHumidity() {
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Falha na leitura do sensor DHT11!");
return "--";
} else {
Serial.print("Umidade Relativa Lida: ");
Serial.print(h);
Serial.println(" %");
return String(h, 1); // Retorna a umidade com 1 casa decimal formatada
}
}
// Template HTML5 responsivo com icones FontAwesome e atualizacao assincrona
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RoboBuilders - Estacao Climatica IoT</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css">
<style>
html {font-family: Arial; display: inline-block; margin: 0px auto; text-align: center; background-color: #f4f4f4;}
h2 {font-size: 2.2rem; color: #1c1c1c;}
p {font-size: 2.5rem; color: #333;}
.units {font-size: 1.2rem;}
.dht-labels {font-size: 1.5rem; vertical-align: middle; padding-bottom: 15px;}
.card {background-color: #ffffff; padding: 20px; border-radius: 12px; max-width: 450px; margin: 20px auto; box-shadow: 0 4px 8px rgba(0,0,0,0.1);}
</style>
</head>
<body>
<h2>RoboBuilders - Telemetria DHT11</h2>
<div class="card">
<p>
<i class="fas fa-thermometer-half" style="color: #fa634f;"></i>
<span class="dht-labels">Temperatura:</span>
<span id="temperature">%TEMPERATURE%</span>
<sup class="units">°C</sup>
</p>
<p>
<i class="fas fa-tint" style="color: #00add6;"></i>
<span class="dht-labels">Umidade:</span>
<span id="humidity">%HUMIDITY%</span>
<sup class="units">%</sup>
</p>
</div>
<script>
// Funcao AJAX assincrona para atualizacao da temperatura a cada 10 segundos (10000 ms)
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000);
// Funcao AJAX assincrona para atualizacao da umidade a cada 10 segundos (10000 ms)
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 10000);
</script>
</body>
</html>)rawliteral";
// Processador para injetar valores iniciais nos placeholders
String processor(const String& var){
if(var == "TEMPERATURE"){
return readDHTTemperature();
} else if(var == "HUMIDITY"){
return readDHTHumidity();
}
return String();
}
void setup(){
Serial.begin(115200);
// Inicializa o sensor DHT11
dht.begin();
// Conexao com a rede Wi-Fi
Serial.print("Conectando-se ao Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi Conectado com Sucesso!");
Serial.print("Painel de Telemetria Climática Disponivel no IP: ");
Serial.println(WiFi.localIP());
// Rota principal: entrega a pagina inicial com as primeiras leituras
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Endpoint de telemetria assincrona de temperatura: /temperature
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
// Endpoint de telemetria assincrona de umidade: /humidity
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTHumidity().c_str());
});
server.begin();
}
void loop(){
// O servidor opera de forma puramente assincrona!
}
Validação Prática e Demonstração
- Realize o upload do firmware e monitore a porta COM para capturar o IP local.
- Abra o navegador web no endereço IP exibido:
- A página carregará um cartão estilizado com sombras suaves e ícones modernos em alta resolução.
- Os valores de temperatura (ex:
24.5 °C) e umidade relativa (ex:58.0 %) serão exibidos instantaneamente.
- Aproxime a mão ou assopre suavemente próximo ao sensor para alterar a umidade do ar expirado:
- Em menos de 10 segundos, os números na tela serão atualizados automaticamente via chamada assíncrona silenciosa, sem qualquer cintilação visual na página!
Lição 10: Interface Gráfica com Display OLED 0.96 Polegadas SSD1306 via Barramento I2C
Na conclusão das lições práticas do curso, você implementará uma interface física homem-máquina (IHM) gráfica de alta fidelidade visual integrando um display gráfico matricial monocromático OLED de 0,96 polegadas baseado no controlador SSD1306 através do barramento serial síncrono I2C.
Tecnologia Emissiva OLED e Controlador SSD1306
Diferentemente dos módulos de cristal líquido tradicionais (LCD – Liquid Crystal Display), que exigem uma fonte de luz de fundo (backlight) acesa ininterruptamente, a tecnologia OLED (Organic Light Emitting Diode) é puramente emissiva: cada ponto individual da matriz de pixels é um diodo orgânico microscópico que emite luz própria quando estimulado por corrente elétrica.
Essa característica confere ao display OLED vantagens operacionais extraordinárias para sistemas embarcados:
- Contraste Infinito: Para representar a cor preta, o pixel correspondente é simplesmente desligado por completo (corrente nula), eliminando o vazamento de luz característico dos LCDs e proporcionando leitura perfeita no escuro.
- Eficiência Energética: O consumo de corrente é diretamente proporcional à quantidade de pixels acesos na tela, tornando-o perfeito para nós remotos de IoT alimentados por baterias:
- Ângulo de Visão Amplo: Nitidez visual mantida em ângulos superiores a 160 graus sem distorção cromática.
O Barramento I2C e o Buffer de Vídeo (FrameBuffer)
A comunicação com o microcontrolador é realizada através do barramento I2C (Inter-Integrated Circuit), utilizando apenas dois fios de dados:
- SDA (Serial Data Line): Linha bidirecional de dados (padrão no ESP32: GPIO 21).
- SCL (Serial Clock Line): Linha de clock sincronizador gerada pelo microcontrolador mestre (padrão no ESP32: GPIO 22).
O endereço I2C padrão de 7 bits do driver SSD1306 na fábrica é 0x3C (ou 0x3D caso o resistor SMD de seleção na parte traseira da placa seja comutado).
Para renderizar elementos gráficos complexos (círculos, retângulos, linhas diagonais e caracteres tipográficos) sem cintilação, a biblioteca aloca na memória SRAM do ESP32 um Buffer de Vídeo (FrameBuffer) correspondente a toda a área da tela:
Todas as operações de desenho (print, drawLine, drawCircle) alteram apenas os bits desse buffer local na memória RAM. A transferência física para a controladora SSD1306 ocorre unicamente no momento em que a função display.display() é executada, enviando os 1024 bytes através do barramento I2C em alta velocidade (Fast Mode a 400 kHz).
O tempo aproximado de envio de cada quadro completo é expresso por:
Componentes Necessários para a Lição 10
| Componente | Quantidade | Especificação Técnica |
|---|---|---|
| Placa DOIT ESP32 DEVKIT V1 | 1 unidade | Microcontrolador Dual-Core Xtensa LX6 |
| Display Gráfico OLED 0,96 Polegadas | 1 unidade | Resolução , I2C, endereço 0x3C |
| Protoboard de 830 Pontos | 1 unidade | Montagem experimental |
| Cabos Jumper Flexíveis | 4 unidades | Conexões Macho-Macho |
Tabela de Conexões de Pinos
| Terminal do Display OLED | Linha / Pino ESP32 | Função do Barramento |
|---|---|---|
| VCC | 3V3 | Alimentação lógica de 3,3 V DC |
| GND | GND | Referência comum de 0 V |
| SCL (Clock) | GPIO 22 | Linha de clock do barramento I2C mestre |
| SDA (Dados) | GPIO 21 | Linha serial de dados do barramento I2C mestre |
📦 Bibliotecas desta lição:
Adafruit SSD1306por Adafruit (versão 2.5.11)Adafruit GFX Librarypor Adafruit (versão 1.11.10)<Wire.h>(versão nativa do pacote ESP32)- Instalação: No Gerenciador de Bibliotecas, busque por
Adafruit SSD1306e clique em Instalar (aceitando a instalação da dependência Adafruit GFX).
Código-Fonte Completo Comentado Linha a Linha
Carregue o sketch de demonstração gráfica alfanumérica no ESP32:
// =========================================================================
// Curso RoboBuilders - ESP32 Basic Starter Kit AE312
// Projeto 10: Interface Grafica com Display OLED 0.96 SSD1306 via I2C
// Placa: DOIT ESP32 DEVKIT V1
// Codigo 100% comentado linha a linha em portugues
// =========================================================================
// Inclusao das bibliotecas de barramento I2C e aceleracao grafica da Adafruit
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Definicao dimensional da resolucao do display em pixels
#define SCREEN_WIDTH 128 // Largura horizontal da matriz OLED (128 colunas)
#define SCREEN_HEIGHT 64 // Altura vertical da matriz OLED (64 linhas)
// Criacao da instancia do objeto controlador SSD1306
// Parametros: largura, altura, ponteiro para o barramento I2C (&Wire) e pino de reset (-1 se compartilhado)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Funcao de configuracao inicial do firmware
void setup() {
// Inicializacao da comunicacao serial assincrona a 115200 bps
Serial.begin(115200);
// Inicializa o display OLED no endereco I2C padrao 0x3C com geracao de tensao interna de chaveamento (SWITCHCAPVCC)
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// Caso ocorra falha de deteccao de hardware no barramento I2C
Serial.println(F("ERRO CRITICO: Nao foi possivel inicializar o display OLED SSD1306!"));
// Retem a execucao em laco infinito para protecao
for(;;);
}
Serial.println("Display OLED SSD1306 Inicializado com Sucesso!");
// Aguarda 2 segundos para estabilizacao completa dos circuitos internos
delay(2000);
// Limpa completamente todos os 1024 bytes do buffer de video na memoria RAM
display.clearDisplay();
// Define o tamanho da fonte tipografica (escala 1 = 6x8 pixels por caractere)
display.setTextSize(1);
// Define a cor de escrita dos pixels como WHITE (em display monocromatico, acende o pixel)
display.setTextColor(WHITE);
// Posiciona o cursor de desenho nas coordenadas cartesianas X=0 (coluna 0) e Y=10 (linha 10)
display.setCursor(0, 10);
// Renderiza a primeira linha de texto institucional no buffer de memoria
display.println("RoboBuilders Brasil");
// Ajusta a escala da fonte para tamanho 2 (12x16 pixels por caractere) para destaque visual
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 26);
// Renderiza a identificacao do modelo do microcontrolador
display.println("ESP32 IoT");
// Desenha uma linha horizontal decorativa de divisao grafica (X1=0, Y1=48, X2=127, Y2=48)
display.drawFastHLine(0, 48, 128, WHITE);
// Retorna a escala 1 para os detalhes do curso no rodape da tela
display.setTextSize(1);
display.setCursor(0, 54);
display.println("Kit AE312 - Completo");
// Transfere o conteudo consolidado do buffer da RAM para os pixels fisicos da tela via I2C
display.display();
}
// Laco de execucao continua
void loop() {
// O display OLED permanece estatico exibindo as informacoes de alta nitidez
}
Validação Prática e Demonstração
- Realize o upload do firmware para a placa.
- Observe a tela frontal do display OLED acender imediatamente com fundo preto puro de altíssimo contraste.
- As três linhas de informação serão exibidas com geometria perfeitamente nítida:
- Topo:
RoboBuilders Brasil(Fonte tamanho 1) - Centro:
ESP32 IoT(Fonte tamanho 2 destacada) - Divisória: Linha horizontal geométrica contínua
- Rodapé:
Kit AE312 - Completo(Fonte tamanho 1)
- Topo:
Guia Diagnóstico (Troubleshooting)
A engenharia de sistemas embarcados exige rigor metodológico na identificação e solução de falhas elétricas, lógicas e de compilação. A matriz diagnóstica a seguir consolida as principais ocorrências técnicas observadas no desenvolvimento prático com o Kit Iniciante ESP32 Basic Starter Kit AE312, apontando a causa raiz e a ação corretiva imediata:
| Sintoma Observado | Causa Raiz Provável | Ação Corretiva Recomendada |
|---|---|---|
Console exibe Connecting........_____ e falha com Timed out waiting for packet header | O circuito automático DTR/RTS da placa falhou em sincronizar o pulso de descida na linha GPIO 0 com o ROM Bootloader devido à capacitância parasita do cabo USB. | No exato instante em que a sequência Connecting... surgir no rodapé da IDE Arduino, mantenha o botão BOOT pressionado na placa ESP32 até a barra de progresso iniciar; em seguida, solte-o. Substitua cabos USB longos ou de baixa qualidade por cabos de dados curtos com blindagem de malha. |
Erro de compilação: fatal error: ESPAsyncWebServer.h: No such file or directory | A biblioteca assíncrona não está instalada no diretório de bibliotecas da IDE ou foi descompactada com nome de pasta incorreto. | Baixe o repositório oficial em formato ZIP, acesse Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP... e selecione o arquivo. Se instalado manualmente, renomeie a pasta extraída para rigorosamente ESPAsyncWebServer (removendo sufixos como -master). Reinicie a IDE Arduino. |
Erro de compilação: fatal error: AsyncTCP.h: No such file or directory | Ausência da biblioteca de transporte assíncrono AsyncTCP, dependência estrutural obrigatória do ESPAsyncWebServer. | Instale a biblioteca AsyncTCP através do menu Adicionar Biblioteca .ZIP... na IDE Arduino conforme a Tabela-Mestre de Bibliotecas da seção de preparação. |
Erro de compilação: fatal error: DHT.h: No such file or directory | A biblioteca do sensor de temperatura DHT não foi instalada ou sua dependência fundamental (Adafruit Unified Sensor) está ausente. | Abra o Gerenciador de Bibliotecas da IDE Arduino (Ctrl + Shift + I), busque por DHT sensor library por Adafruit e clique em Instalar. Ao surgir o pop-up de dependências, clique obrigatoriamente em Install All para garantir a presença do driver unificado. |
Monitor Serial exibindo caracteres estranhos e ilegíveis (ex: ?) | Descasamento entre a taxa de transmissão em bauds configurada no firmware e a velocidade selecionada no console. | Altere a caixa seletora de velocidade no canto superior direito do Monitor Serial para rigorosamente 115200 baud, que é o padrão utilizado em todas as rotinas Serial.begin(115200) do curso. |
ESP32 reiniciando em loop infinito exibindo Brownout detector was triggered | Queda abrupta da tensão de alimentação abaixo de 2,7 V DC durante os picos de corrente da transmissão de rádio Wi-Fi (+20 dBm). | Conecte a placa diretamente a uma porta USB 3.0 ou use um hub USB energizado externamente. Evite portas USB frontais de gabinetes conectadas por cabos internos longos. Se necessário, insira um capacitor eletrolítico de a entre os pinos 3V3 e GND da protoboard para amortecer transientes. |
Monitor Serial preso em Connecting to WiFi.. com pontos infinitos | Credenciais de rede (SSID ou senha) digitadas incorretamente, ou tentativa de conexão a uma rede Wi-Fi exclusiva de 5,0 GHz. | O rádio do chip ESP32 opera estritamente na faixa de frequência de 2,4 GHz. Certifique-se de que o roteador possui rede de 2,4 GHz ativada. Revise se o nome da rede e a senha no código não contêm espaços extras ou erros de digitação. |
Sensor DHT11 retornando -- ou Falha na leitura do sensor DHT11! | Conexão incorreta dos pinos, mau contato na protoboard ou ausência de resistor de pull-up na linha de dados. | Verifique se o pino de dados está conectado no GPIO correto (GPIO 4 no Projeto 9). Caso utilize o sensor DHT11 discreto de 4 pinos (sem placa de suporte), adicione um resistor externo de ou entre a linha DATA e os 3,3 V. |
| Display OLED SSD1306 com tela totalmente preta sem acender pixels | Inversão das linhas I2C (SDA e SCL), endereço hexadecimal incorreto ou falta da chamada display.display(). | Certifique-se de que o pino SDA do display está no GPIO 21 e o pino SCL no GPIO 22. Verifique se a inicialização no código utiliza o endereço 0x3C. Lembre-se de que comandos gráficos apenas alteram a RAM; a tela só atualiza fisicamente após executar display.display(). |
| Módulo Relé com LED aceso, mas a armadura não atraca e a carga não comuta | Alimentação insuficiente de corrente para a bobina eletromecânica de 5 V ou lógica de acionamento invertida. | A bobina do relé consome entre 70 mA e 90 mA em 5 V e deve ser alimentada pelo pino Vin (5 V USB) do ESP32, e nunca pelo pino 3V3 (que não possui tensão nem corrente suficientes para chavear a mola). Verifique também se o jumper JD-VCC está devidamente inserido nos terminais da placa. |
| Leitura analógica no ADC retornando sempre 0 ou 4095 após ligar o Wi-Fi | Conflito de hardware entre o conversor ADC2 e o amplificador de potência do rádio Wi-Fi. | O bloco ADC2 (GPIOs 0, 2, 4, 12, 13, 14, 15, 25, 26 e 27) é desabilitado internamente pelo driver de rádio da Espressif quando a função WiFi.begin() é chamada. Para leituras analógicas com Wi-Fi ativo, utilize exclusivamente pinos do bloco ADC1 (GPIOs 32, 33, 34, 35, 36 ou 39). |
| Chave táctil registrando múltiplos acionamentos com um único toque | Repique mecânico das lâminas metálicas elásticas do botão (bouncing). | Implemente o filtro de debounce por software com janela temporal de 50 milissegundos utilizando millis() (conforme ensinado na Lição 8), ou conecte um capacitor cerâmico de em paralelo com os terminais do botão. |
Solução de problemas
Olá! Sou o assistente técnico da RoboBuilders. Descreva seu problema com o Kit Iniciante ESP32 Basic Starter Kit AE312 – Curso Completo e eu ajudarei a encontrar a solução.
O assistente usa IA e pode errar. Confirme informações críticas no datasheet oficial do fabricante.