Kit Robô Avançado 4wd Camera Tutoriais Esp32 Wifi App RB2056 AD174 – Curso Completo

Kit Robô Avançado 4wd Camera Tutoriais Esp32 Wifi App RB2056 AD174 — Curso Completo com Projetos Práticos

Introdução

O Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 (RB2056) da RoboBuilders é uma plataforma robótica educacional de alto nível tecnológico, desenvolvida para explorar sistemas embarcados de tempo real, controle dinâmico de tração e transmissão de vídeo sem fio. O núcleo de processamento do robô é centralizado no poderoso módulo ESP32-CAM, composto por um microcontrolador de arquitetura de 32 bits com núcleo duplo Xtensa LX6 operando a frequências de até 240 extMHz240\, ext{MHz}, conectividade de rede sem fio Wi-Fi 802.11 b/g/n, Bluetooth v4.2 BR/EDR e BLE (Bluetooth Low Energy), além de uma memória PSRAM (Pseudo Static Random Access Memory) externa de 4 MB dedicada ao buffer de captura e codificação de imagens. A plataforma embarca um sensor óptico CMOS de 2 megapixels OV2640 acoplado a uma antena externa omnidirecional de 2,4 GHz com pigtail coaxial IPEX para alcance estendido de rádiofrequência, um robusto estágio de acionamento de potência em ponte H dupla L298N, tração integral distribuída em quatro motores DC com caixa de redução metálica/plástica (motores TT de relação 1:48), e um chassi estrutural duplo em acrílico usinado com rodas de borracha de alta aderência. O sistema implementa conectividade local em modo de ponto de acesso autônomo (SoftAP — Software-enabled Access Point), permitindo tanto a transmissão contínua de fluxo de vídeo em formato MJPEG (Motion JPEG) sobre requisições HTTP (Hypertext Transfer Protocol) em navegadores web quanto o controle remoto bidirecional de baixa latência através de soquetes de rede TCP (Transmission Control Protocol) e do aplicativo móvel proprietário KUONGSHUN.

Este material didático foi elaborado para atuar como uma referência definitiva de engenharia para estudantes de robótica, desenvolvedores de firmware, engenheiros eletrônicos e entusiastas da automação. O curso conduz o projetista por uma jornada técnica estruturada em módulos rigorosamente espelhados na documentação e engenharia oficial do fabricante Kuongshun: iniciando pelo reconhecimento volumétrico e montagem mecânica do chassi passo a passo; avançando para a configuração criteriosa do ambiente na Arduino IDE (Integrated Development Environment), instalação dos drivers do conversor USB-Serial CH340 e fixação da versão de suporte da placa de silício no pacote ESP32 2.0.12; aprofundando-se na cinemática de tração diferencial e nos sketches de locomoção básica autônoma; e culminando na implementação dos servidores de streaming e teleoperação via interface Web responsiva e aplicativo Android embarcado.

O que você vai aprender:

  • Compreender a arquitetura interna do SoC ESP32-CAM, seu barramento DVP com a câmera OV2640 e a alocação de quadros de vídeo na memória PSRAM externa;
  • Montar passo a passo a estrutura mecânica do chassi 4WD, suportes dos motores TT, módulo driver L298N, suporte da câmera e antena de alto ganho com suas respectivas ferragens;
  • Dimensionar o circuito de alimentação e barramento elétrico composto por duas células de íons de lítio 18650, chave geral e proteção contra afundamento de tensão (brownout reset);
  • Configurar o ecossistema de desenvolvimento na Arduino IDE, instalando o driver USB-Serial CH340 e fixando de forma estável o pacote de placas ESP32 na versão pinada 2.0.12;
  • Dominar a cinemática de tração 4WD com acionamento diferencial (skid-steer), modulando largura de pulsos (PWM) e sentido de giro dos quatro motores através do driver L298N;
  • Analisar e compilar códigos-fonte linha a linha para marcha à frente, marcha à ré, conversões e aceleração suave via loops de controle analógico;
  • Configurar a rede local sem fio em modo SoftAP (Access Point) com SSID broadcast KUONGSHUN-AD174 e autenticação WPA2-PSK;
  • Desenvolver um servidor HTTP embarcado multitarefa na biblioteca esp_http_server para streaming contínuo de vídeo MJPEG via chunked transfer encoding;
  • Estabelecer um servidor TCP na porta 100 para decodificação de tramas binárias de telemetria e pilotagem remota em tempo real;
  • Instalar o aplicativo oficial KUONGSHUN.apk no smartphone Android através de link direto, configurando permissões de rádio e operando o robô com joystick virtual;
  • Diagnosticar falhas sistêmicas de hardware e firmware através de um guia completo de troubleshooting, solucionando perda de pacotes, aquecimento e inversão de eixos.

Material utilizado: Kit Robô Avançado 4wd Camera Tutoriais Esp32 Wifi App RB2056 AD174.

Visão Geral do Kit e Arquitetura de Hardware

A engenharia do Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 (RB2056) combina de maneira otimizada o poder computacional de um microcontrolador dual-core moderno com a robustez eletromecânica clássica dos acionamentos por ponte H. Diferente de projetos tradicionais de robótica educacional que demandam duas placas físicas separadas (como um microcontrolador Arduino Uno acoplado a um módulo ESP32 externo por cabos seriais adicionais), o kit AD174 simplifica drasticamente a topologia física ao concentrar toda a inteligência do sistema — inteligência de máquina, roteamento de rede Wi-Fi, servidor web, servidor TCP de telemetria, streaming de vídeo e geração de sinais de temporização PWM de alta frequência — diretamente dentro de uma única placa controladora ESP32-CAM, montada sobre uma placa de expansão e gravação USB Tipo-C com conversor CH340.

O Módulo Microcontrolador ESP32-CAM e a Câmera OV2640

O coração do robô é o consagrado módulo ESP32-CAM, fabricado pela AI-Thinker e baseado no silício ESP32-D0WDQ6 da Espressif Systems. Esse microchip integra dois núcleos de processamento Xtensa 32-bit LX6 com clock configurável entre 80 extMHz80\, ext{MHz} e 240 extMHz240\, ext{MHz}, entregando até 600 DMIPS de capacidade de cálculo. Em seu encapsulamento interno, o microcontrolador conta com 520 extKB520\, ext{KB} de memória SRAM (Static Random Access Memory) e 448 extKB448\, ext{KB} de memória ROM para inicialização do bootloader.

Entretanto, aplicações de visão computacional e streaming de vídeo de alta resolução impõem uma demanda de armazenamento que supera com folga a memória interna nativa dos microcontroladores padrão. Um único quadro (frame) de imagem capturado na resolução SVGA (800imes600800 imes 600 pixels) em formato bruto RGB565 consumiria:

Tamanho do Frame=800imes600imes2 extbytes=960.000 extbytes≈937,5 extKB \text{Tamanho do Frame} = 800 imes 600 imes 2\, ext{bytes} = 960.000\, ext{bytes} \approx 937,5\, ext{KB}

Este valor excede a totalidade da SRAM do microcontrolador. Por essa razão, a placa ESP32-CAM integra em seu circuito impresso um chip de memória externa PSRAM de 4 extMB4\, ext{MB} (32 extMbit32\, ext{Mbit}), comunicando-se com o processador através de um barramento QSPI (Quad Serial Peripheral Interface) de alta velocidade a 40 extMHz40\, ext{MHz}. O subsistema de software da Espressif ativa e mapeia automaticamente essa memória no espaço de endereçamento do heap do sistema através do compilador e das diretivas do firmware, permitindo que a biblioteca esp_camera.h aloque múltiplos buffers de recepção de imagem (frame buffers) diretamente na PSRAM com a chamada CAMERA_FB_IN_PSRAM.

O sensor óptico conectado ao módulo é o OmniVision OV2640, um sensor CMOS de alta sensibilidade e baixo consumo de energia que conta com um motor de compressão JPEG embutido no próprio silício. Isso significa que a conversão dos dados brutos dos fotodiodos para o fluxo binário comprimido .jpg é realizada diretamente pelo hardware do sensor óptico antes da transferência para o ESP32. A interface física entre a câmera OV2640 e a placa ESP32-CAM é constituída por um barramento paralelo DVP (Digital Video Port) de 8 linhas de dados (Y2Y_2 a Y9Y_9), três linhas de sincronismo e temporização de varredura (VSYNCVSYNC, HREFHREF e PCLKPCLK), uma linha de sinal de clock mestre gerada pelo ESP32 (XCLKXCLK, configurada a 20 extMHz20\, ext{MHz}), linhas de energia e reset (PWDNPWDN, RESETRESET), e o barramento serial de configuração de dois fios SCCB (Serial Camera Control Bus, protocolo compatível com I2CI^2C) composto pelos pinos SIODSIOD (dados) e SIOCSIOC (clock).

A tabela abaixo descreve detalhadamente o pinout elétrico de interligação entre o sensor OV2640 e os terminais GPIO do ESP32-CAM:

Sinal da Câmera OV2640Função do BarramentoPino GPIO no ESP32-CAMCaracterísticas Elétricas e Temporização
PWDNPower Down (Ativação em nível alto)GPIO 32Controla o estado de repouso de baixo consumo da câmera
RESETReset por hardware-1 (Não conectado)O reset é gerenciado por software através do barramento SCCB
XCLKMaster Clock de entrada do sensorGPIO 0Sinal de clock gerado pelo canal LEDC0 a 20 extMHz20\, ext{MHz}
SIODLinha de Dados de Configuração SCCBGPIO 26Comunicação serial tipo I2CI^2C para ajuste de registradores
SIOCLinha de Clock de Configuração SCCBGPIO 27Clock de sincronismo serial SCCB (frequência típica de 100 extkHz100\, ext{kHz})
Y9Bit de Dados de Vídeo 7 (MSB)GPIO 35Pino de entrada digital DVP (canal de leitura rápida de pixels)
Y8Bit de Dados de Vídeo 6GPIO 34Pino de entrada digital DVP
Y7Bit de Dados de Vídeo 5GPIO 39Pino de entrada digital DVP
Y6Bit de Dados de Vídeo 4GPIO 36Pino de entrada digital DVP
Y5Bit de Dados de Vídeo 3GPIO 21Pino de entrada digital DVP
Y4Bit de Dados de Vídeo 2GPIO 19Pino de entrada digital DVP
Y3Bit de Dados de Vídeo 1GPIO 18Pino de entrada digital DVP
Y2Bit de Dados de Vídeo 0 (LSB)GPIO 5Pino de entrada digital DVP
VSYNCSincronismo Vertical de QuadroGPIO 25Pulso que demarca o início e o término de um quadro completo de imagem
HREFReferência Horizontal de LinhaGPIO 23Sinal que valida a transmissão dos bytes de pixels de uma linha ativa
PCLKPixel Clock de Saída do SensorGPIO 22Clock síncrono com cada byte de pixel disponibilizado em Y2…Y9Y_2 \dots Y_9
LED FlashIluminação auxiliar de alta intensidadeGPIO 4Transistor de chaveamento de corrente conectado a LED branco ultra-brilhante

⚠️ Atenção aos pinos compartilhados: Na placa ESP32-CAM, o pino GPIO 4 aciona diretamente o LED flash de alta potência. Devido à sua intensidade e consumo de corrente (podendo atingir mais de 150 extmA150\, ext{mA} em plena luminosidade), o controle de brilho deve ser executado obrigatoriamente através de modulação por largura de pulso (PWM) configurada no periférico de hardware LEDC (LED Control) do ESP32, evitando sobrecarga térmica na placa. Além disso, os pinos GPIO 13, 14, 15, 2 e 12 são estrategicamente utilizados para o controle do driver L298N, exigindo atenção à ordem de inicialização do periférico de rádio Wi-Fi para que não ocorram acionamentos involuntários dos motores durante o boot.

O Driver de Potência de Ponte H Dupla L298N

Para controlar o sentido de rotação e a velocidade angular dos quatro motores de corrente contínua, o robô utiliza o consagrado circuito integrado L298N, montado em um módulo de potência com dissipador de calor de alumínio anodizado aletado. O L298N é um circuito monolítico de 15 pinos encapsulado no padrão Multiwatt15, composto internamente por duas pontes H completas construídas com transistores bipolares de junção (TBJ) em configuração Darlington de alta corrente.

Cada meia-ponte H do L298N suporta uma tensão de alimentação de carga (VsV_s) de até 46 extV46\, ext{V} e corrente contínua de até 2 extA2\, ext{A} por canal, com picos tolerados de até 3 extA3\, ext{A} para transientes de partida de motores. O módulo integra internamente oito diodos de supressão de surtos de comutação indutiva (flyback diodes), essenciais para dissipar com segurança a força contraeletromotriz gerada pela indutância das bobinas dos motores quando a corrente é repentinamente interrompida pelo chaveamento dos transistores:

Vind=−LdidtV_{ind} = -L \frac{di}{dt}

Sem esses diodos de recirculação rápida, picos de alta tensão reversa poderiam perfurar a junção semicondutora dos transistores do L298N e induzir ruído de alta frequência nas trilhas de alimentação lógica do ESP32-CAM.

O módulo L298N conta ainda com um regulador de tensão linear integrado LM7805 de 5 extV5\, ext{V}. Um jumper removível localizado atrás do borne de alimentação de três vias seleciona o modo de operação do regulador:

  1. Com o jumper inserido: O regulador LM7805 interno reduz a tensão das baterias (7,4 extV…8,4 extV7,4\, ext{V} \dots 8,4\, ext{V} presentes no borne de entrada VMSVMS) para fornecer 5 extV5\, ext{V} estáveis no borne +5 extV+5\, ext{V}, alimentando os circuitos lógicos internos do próprio L298N e servindo como fonte de alimentação primária para a placa ESP32-CAM.
  2. Com o jumper removido: Obrigatório caso a tensão de alimentação dos motores ultrapasse 12 extV12\, ext{V} (para evitar queima do regulador por dissipação térmica excessiva), exigindo uma fonte externa de 5 extV5\, ext{V} no borne correspondente. No kit AD174, alimentado com duas baterias 18650 (∼7,4 extV\sim 7,4\, ext{V} nominais), o jumper deve permanecer obrigatoriamente inserido.

Os quatro motores TT do chassi são agrupados em pares elétricos paralelos: os dois motores do lado esquerdo são conectados em conjunto aos bornes OUT1 e OUT2 (Canal A), enquanto os dois motores do lado direito são conectados em conjunto aos bornes OUT3 e OUT4 (Canal B). A velocidade de rotação de cada lado é controlada pelos pinos de habilitação ENA e ENB, enquanto o sentido de rotação é determinado pelas entradas digitais IN1, IN2, IN3 e IN4.

A tabela abaixo apresenta a matriz completa de sinais de controle entre o microcontrolador ESP32-CAM e os bornes de potência do driver L298N:

Pino no ESP32-CAMEntrada no Driver L298NMapeamento no FirmwareFunção Técnica de ControleNível Lógico e Operação Resultante
GPIO 2ENA (Enable A)ENAHabilita e controla a velocidade dos motores do lado EsquerdoPWM (0…2550 \dots 255) via canal LEDC2 do ESP32
GPIO 12ENB (Enable B)ENBHabilita e controla a velocidade dos motores do lado DireitoPWM (0…2550 \dots 255) via canal LEDC12 do ESP32
GPIO 33IN1gpLb (Left Backward)Comanda a rotação reversa dos motores esquerdosNível lógico ALTO (HIGH) para ré do lado esquerdo
GPIO 15IN2gpLf (Left Forward)Comanda a rotação frontal dos motores esquerdosNível lógico ALTO (HIGH) para avanço do lado esquerdo
GPIO 14IN3gpRb (Right Backward)Comanda a rotação reversa dos motores direitosNível lógico ALTO (HIGH) para ré do lado direito
GPIO 13IN4gpRf (Right Forward)Comanda a rotação frontal dos motores direitosNível lógico ALTO (HIGH) para avanço do lado direito

Tabela-Mestre de Especificações Técnicas do Kit AD174

Parâmetro TécnicoEspecificação e Faixa Nominal de Operação
Modelo Comercial e SKUKit Robô Avançado 4WD com Câmera ESP32-CAM AD174 (Código RoboBuilders: RB2056)
Microcontrolador CentralESP32-CAM (SoC ESP32-D0WDQ6, Dual-Core 32-bit Xtensa LX6 @ 240 extMHz240\, ext{MHz})
Memória Volátil e Não-Volátil520 extKB520\, ext{KB} SRAM interna, 4 extMB4\, ext{MB} PSRAM externa QSPI, 4 extMB4\, ext{MB} Flash SPI
Sensor de ImagemOmniVision OV2640 (CMOS UXGA 2 MP, lente f=3,6 extmmf=3,6\, ext{mm}, campo de visão ∼65∘\sim 65^{\circ})
Formatos e Resoluções de VídeoJPEG nativo, resoluções QVGA (320imes240320 imes240), VGA (640imes480640 imes480) e SVGA (800imes600800 imes600)
Conectividade Sem FioWi-Fi 802.11 b/g/n (2,4 extGHz2,4\, ext{GHz}) com antena externa omnidirecional de 3 extdBi3\, ext{dBi} e conector IPEX/SMA
Modo de Operação de RádioPonto de Acesso Autônomo (SoftAP) com IP fixo padrão 192.168.4.1, canal 5 e DHCP interno
Estágio de Potência dos MotoresPonte H Dupla L298N (suporta até 2 extA2\, ext{A} contínuos e 3 extA3\, ext{A} de pico por canal, dissipador aletado)
Atuadores Eletromecânicos4 motores de corrente contínua com caixa de redução (TT Motor, redução 1:48, rotação ≈200 extRPM\approx 200\, ext{RPM})
Chassi EstruturalAcrílico usinado a laser de alta transparência e 3 extmm3\, ext{mm} de espessura, montagem em dois pavimentos
Rodas e Tração4 rodas de plástico ABS de 65 extmm65\, ext{mm} de diâmetro com pneus de borracha sintética frisada
Alimentação Elétrica2 baterias recarregáveis de íons de lítio formato 18650 (7,4 extV7,4\, ext{V} nominais, 8,4 extV8,4\, ext{V} plena carga)
Interface de ProgramaçãoPorta USB Tipo-C integrada na placa base com conversor serial CH340 de alta velocidade
Aplicativo de Controle RemotoAplicativo proprietário KUONGSHUN (disponível em formato APK para Android e App Store para iOS)

Inventário Detalhado do Kit (Packing List Oficial)

Antes de iniciar a montagem física do robô, realize a conferência minuciosa de todos os componentes fornecidos na embalagem oficial do kit Kuongshun AD174:

  • Plataforma Estrutural Acrílica:
    • 1x Chassi inferior de acrílico transparente de 3 extmm3\, ext{mm} com furação padrão para fixação dos suportes dos motores TT, colunas espaçadoras e módulo driver L298N;
    • 1x Chassi intermediário de suporte de componentes com recortes de ventilação e aberturas para passagem de cabos;
    • 2x Peças acrílicas para montagem do suporte angulado da câmera ESP32-CAM e antena WiFi.
  • Eletrônica de Controle e Sensores:
    • 1x Módulo microcontrolador ESP32-CAM com câmera OV2640 instalada no conector FPC de 24 pinos;
    • 1x Placa base de desenvolvimento e expansão para ESP32-CAM com conector USB Tipo-C e conversor USB-Serial CH340;
    • 1x Módulo driver de motor ponte H dupla L298N com dissipador de calor e bornes para conexão dos motores e bateria;
    • 1x Antena externa de 2,4 GHz com conector SMA fêmea e cabo pigtail coaxial com terminal IPEX miniatura.
  • Atuadores e Conjunto de Rodagem:
    • 4x Motores DC amarelos com caixa de redução plástica (TT Motors) de eixo duplo e relação de transmissão 1:48;
    • 4x Suportes metálicos usinados em liga de alumínio anodizado preto para fixação dos motores TT ao chassi;
    • 4x Rodas de plástico injetado de 65 extmm65\, ext{mm} com pneus de borracha de alta tração e encaixe com chaveta nos eixos dos motores.
  • Sistema de Alimentação e Fiação:
    • 1x Suporte plástico para 2 baterias de lítio padrão 18650 com chave gangorra liga/desliga de dois polos e cabos pré-estanhados;
    • 1x Conjunto completo de cabos jumpers coloridos com terminais macho-fêmea e fêmea-fêmea para interligação dos sinais de controle;
    • 1x Cabo de dados e alimentação padrão USB Tipo-A para USB Tipo-C.
  • Ferragens de Fixação e Ferramental:
    • 10x Espaçadores sextavados de latão fêmea-fêmea padrão M3 imes18 extmm imes 18\, ext{mm} para separação dos andares do chassi;
    • 18x Parafusos Philips de cabeça escareada M3 imes10 extmm imes 10\, ext{mm} em aço niquelado;
    • 8x Parafusos Philips longos de cabeça redonda M3 imes30 extmm imes 30\, ext{mm} para travamento dos suportes dos motores TT;
    • 9x Porcas sextavadas métricas padrão M3;
    • 4x Parafusos Philips de cabeça redonda M2 imes10 extmm imes 10\, ext{mm} para fixação da placa ESP32-CAM;
    • 4x Porcas sextavadas métricas padrão M2;
    • 4x Parafusos Philips autoatarraxantes de cabeça redonda M2 imes25 extmm imes 25\, ext{mm} para travamento central das rodas nos eixos dos motores;
    • 1x Chave de fenda Philips com cabo ergonômico para montagem integral do kit.

Somatória Geral: Mais de 60 elementos físicos perfeitamente balanceados compõem o kit robótico, formando um sistema mecatrônico completo, rígido e de altíssima confiabilidade operacional.

Guia de Montagem Mecânica (Assembly Guide)

A montagem estrutural do Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 constitui o alicerce fundamental para a estabilidade dinâmica, precisão de navegação e integridade dos sensores de visão. Um chassi montado com folgas mecânicas ou motores desalinhados induz forças parasitas de deriva lateral, sobrecarga nos enrolamentos e trepidações excessivas no fluxo de vídeo da câmera OV2640.

Fundamentos da Cinemática Diferencial e Tração 4WD

O robô opera através de um arranjo cinemático de tração diferencial por deslizamento (skid-steer mobile robot), no qual não há um mecanismo de esterçamento convencional com articulações de direção (geometria de Ackermann). Em vez disso, o controle angular e a rotação do veículo são gerados exclusivamente pela diferença relativa entre as velocidades angulares das rodas do lado esquerdo (ωL\omega_L) e do lado direito (ωR\omega_R).

Considerando que as quatro rodas possuem raio nominal idêntico r=32,5 extmmr = 32,5\, ext{mm} (0,0325 extm0,0325\, ext{m}) e que a bitola transversal do robô (distância entre os centros das rodas esquerdas e direitas) é denotada por W=145 extmmW = 145\, ext{mm} (0,145 extm0,145\, ext{m}), a velocidade linear longitudinal desenvolvida por cada lado do chassi é dada por:

vL=r⋅ωLevR=r⋅ωRv_L = r \cdot \omega_L \qquad \text{e} \qquad v_R = r \cdot \omega_R

A velocidade linear resultante de translação do centro de massa do robô (vv) corresponde à média aritmética simples das velocidades dos dois lados:

v=vR+vL2=r⋅(ωR+ωL)2v = \frac{v_R + v_L}{2} = \frac{r \cdot (\omega_R + \omega_L)}{2}

A velocidade angular de guinada do robô em torno de seu próprio eixo vertical (ωz\omega_z), responsável pela mudança de orientação azimutal, é obtida dividindo a diferença das velocidades tangenciais pela largura da bitola:

ωz=vR−vLW=r⋅(ωR−ωL)W\omega_z = \frac{v_R - v_L}{W} = \frac{r \cdot (\omega_R - \omega_L)}{W}

A trajetória curvilínea percorrida pelo chassi descreve um arco circular em torno de um Centro Instantâneo de Rotação (CIR). O raio desse círculo de manobra (RR), medido a partir do ponto central do chassi, é deduzido pela relação entre a velocidade linear de translação e a velocidade angular de rotação:

R=vωz=W2⋅(vR+vLvR−vL)R = \frac{v}{\omega_z} = \frac{W}{2} \cdot \left( \frac{v_R + v_L}{v_R - v_L} \right)

Analisando a equação do raio de curvatura, evidenciam-se três condições fundamentais de controle:

  1. Translação Retilínea Pura (vL=vRv_L = v_R): A diferença vR−vL→0v_R - v_L \to 0, resultando em velocidade angular nula (ωz=0\omega_z = 0) e raio de curvatura infinito (R→∞R \to \infty). O robô move-se em linha reta perfeitamente alinhada.
  2. Curva Suave em Movimento (vL≠vRv_L \neq v_R e ambos positivos): O robô translada para frente ao mesmo tempo em que gira em torno de um CIR externo ao chassi (R>W/2R > W/2), executando curvas suaves com velocidade regulada por PWM.
  3. Rotação no Próprio Eixo ou Giro em Pião (vL=−vRv_L = -v_R): As rodas de um lado giram para frente com velocidade +v+v, enquanto as rodas do lado oposto giram para trás com velocidade −v-v. Substituindo na equação:
v=v+(−v)2=0eR=W2⋅(v−vv−(−v))=0v = \frac{v + (-v)}{2} = 0 \qquad \text{e} \qquad R = \frac{W}{2} \cdot \left( \frac{v - v}{v - (-v)} \right) = 0

Nessa condição extrema, a velocidade linear de translação é estritamente zero e o raio de curvatura é nulo: o chassi gira estacionariamente sobre o centro geométrico de sua base, alcançando a taxa máxima de rotação angular para evasão de obstáculos em espaços confinados.

Para que a rotação estacionária ocorra com eficiência, o torque produzido pelos motores deve superar a força de atrito lateral gerada pelo arraste dos pneus sobre o solo. A força de atrito dinâmico lateral desenvolvida por cada pneu é regida pelo coeficiente de atrito cinético μk\mu_k e pela fração da força normal NiN_i sustentada pela roda:

Fat=μk⋅Ni=μk⋅(m⋅g4)F_{at} = \mu_k \cdot N_i = \mu_k \cdot \left( \frac{m \cdot g}{4} \right)

onde m≈0,65 extkgm \approx 0,65\, ext{kg} representa a massa total do robô montado e g≈9,81 extm/s2g \approx 9,81\, ext{m/s}^2 é a aceleração da gravidade. Assim, a distribuição equilibrada de massa entre a dianteira e a traseira do chassi é essencial para equalizar as cargas normais nos quatro pontos de contato.

A montagem física do kit Kuongshun AD174 é realizada em 8 passos lógicos numerados e sequenciais, ilustrados pelas imagens extraídas diretamente da engenharia do fabricante.


Passo 0 – Distinção de Orientação e Faces do Chassi Acrílico Inferior

Antes de aplicar qualquer parafuso, remova a película protetora de papel kraft marrom de todas as placas de acrílico para expor as superfícies transparentes límpidas. Em seguida, identifique a placa acrílica do chassi inferior e determine sua orientação correta no plano de trabalho.

A face superior e a extremidade dianteira da base acrílica são diferenciadas pela distribuição métrica das furações circulares de fixação: observe a distância entre o par de furos localizado na região frontal demarcada pelas setas do diagrama técnico. A distância entre os furos é mais ampla na porção superior e mais estreita na porção inferior. A extremidade com furação mais larga identifica indubitavelmente a parte frontal do robô.

Passo 0 – Orientação e distinção de faces do chassi inferiorPasso 0 – Detalhe do alinhamento dos furos guia frontal e traseiro

💡 Dica de bancada: Mantenha a placa com a extremidade frontal voltada para a parte superior de sua mesa de montagem. Marque sutilmente a face superior com uma etiqueta adesiva removível para assegurar que nenhum componente seja parafusado na face invertida.


Passo 1 – Fixação dos Espaçadores Sextavados de Latão M3

O chassi é sustentado por 10 colunas espaçadoras sextavadas de latão com rosca dupla fêmea padrão M3 imes18 extmm imes 18\, ext{mm}. Essas colunas elevam o pavimento superior, protegem os componentes eletrônicos contra impactos e servem como barreira estrutural para os cabos de potência.

Posicione os parafusos Philips de cabeça escareada M3 imes10 extmm imes 10\, ext{mm} inseridos a partir da face inferior (face de baixo) do chassi acrílico nos 10 orifícios de ancoragem designados. Na face superior, rosqueie manualmente cada espaçador de latão de 18 extmm18\, ext{mm} e efetue o aperto final moderado com a chave de fenda. A cabeça escareada do parafuso deve ficar perfeitamente embutida na chanfradura do acrílico para que a face inferior permaneça lisa.

Passo 1 – Instalação das colunas de latão M3*18 no chassi acrílico

⚠️ Atenção mecânica: O aperto dos parafusos em peças acrílicas deve ser firme, porém suave. O acrílico usinado possui alta rigidez, mas é susceptível a trincas radiais por concentração de tensão se for submetido a torque angular excessivo.


Passo 2 – Montagem dos Motores DC de Tração (TT Motors)

A tração do robô utiliza 4 motores DC com caixa de redução plástica integrados (motores amarelos padrão TT). Cada motor é fixado por um suporte metálico rígido em liga de alumínio em formato de L.

Subpasso 2.1 – Fixação dos Suportes Metálicos nos Motores TT

Pegue cada motor TT e observe suas duas faces laterais: uma das faces possui um ressalto plástico cilíndrico saliente (bump), enquanto a face oposta é plana com os pontos de solda dos fios expostos. O suporte metálico deve ser posicionado obrigatoriamente na face plana oposta ao ressalto cilíndrico.

Insira dois parafusos Philips longos de cabeça redonda M3 imes30 extmm imes 30\, ext{mm} atravessando o suporte de alumínio e o corpo plástico do motor. Na face oposta, rosqueie duas porcas sextavadas métricas M3 e aperte o conjunto. Repita o procedimento de maneira idêntica para os quatro motores.

Passo 2.1 – Fixação dos suportes metálicos angulados nos 4 motores TT

Subpasso 2.2 – Fixação dos Conjuntos de Motor no Chassi Acrílico

Com os quatro motores devidamente equipados com seus suportes metálicos, monte-os nas quatro extremidades laterais do chassi inferior.

Atente-se à orientação espacial dos motores: os ressaltos plásticos externos dos motores devem apontar para fora do chassi (lado em que o eixo do motor se projeta para receber as rodas), enquanto as soldas e terminais elétricos dos fios devem ficar voltados para a região interna central do chassi, protegidos de atritos laterais. Fixe a base de cada suporte metálico ao acrílico utilizando dois parafusos de cabeça escareada M3 imes10 extmm imes 10\, ext{mm} inseridos por baixo do chassi.

Passo 2.2 – Fixação dos motores TT ao chassi com parafusos M3*10

Passo 3 – Instalação do Módulo Driver de Motores L298N

O módulo driver de ponte H L298N é o componente eletrônico de maior peso e volume térmico do pavimento inferior. Ele deve ser posicionado centralizadamente sobre a base acrílica para otimizar o centro de gravidade e reduzir o comprimento dos cabos que vão aos motores.

Posicione o módulo L298N sobre os quatro furos de montagem correspondentes na placa acrílica. Alinhe a placa de modo que os bornes de potência de saída de dois terminais fiquem alinhados com as laterais do veículo: os bornes OUT1/OUT2 apontando para o par de motores esquerdos e os bornes OUT3/OUT4 apontando para o par de motores direitos. Fixe a placa de circuito impresso utilizando quatro parafusos Philips de cabeça escareada M3 imes10 extmm imes 10\, ext{mm} inseridos pela parte inferior do chassi.

Passo 3 – Fixação do módulo de potência L298N no chassi

Passo 4 – Instalação do Suporte de Baterias 18650 com Chave Geral

O sistema é alimentado por um suporte plástico moldado que acomoda duas baterias recarregáveis cilíndricas padrão 18650 ligadas em série, fornecendo uma tensão nominal de 7,4 extV7,4\, ext{V} (8,4 extV8,4\, ext{V} com carga máxima a 4,2 extV4,2\, ext{V} por célula).

Posicione o suporte de baterias na região traseira do chassi, garantindo que o interruptor de alavanca/gangorra liga/desliga permaneça voltado para a face posterior externa do robô, facilitando o acionamento e corte de emergência da alimentação pelo operador sem obstruções mecânicas. Fixe o suporte de baterias à base acrílica através de quatro parafusos Philips de cabeça escareada M3 imes10 extmm imes 10\, ext{mm}.

Passo 4 – Instalação do case de baterias 18650 com chave liga/desliga

Passo 5 – Montagem e Instalação do Suporte da Câmera ESP32-CAM

A câmera OV2640 deve ser sustentada em uma elevação angular ideal de visão frontal para fornecer horizonte visual limpo e sem oclusões no streaming de vídeo. O suporte é confeccionado em acrílico cortado a laser e parafusos de precisão.

Subpasso 5.1 – Junção das Partes da Torre de Suporte

Pegue as duas peças acrílicas que compõem a torre articulada de sustentação da câmera. Encaixe uma porca sextavada M3 no alojamento sextavado usinado da peça base e segure-a com a ponta do dedo. Em seguida, sobreponha a segunda peça acrílica e rosqueie um parafuso de cabeça escareada M3 imes10 extmm imes 10\, ext{mm} até fixar o suporte em ângulo rígido.

Passo 5.1 – Montagem da estrutura de suporte da câmera em acrílico

Subpasso 5.2 – Fixação da Placa ESP32-CAM no Suporte Acrílico

Com a torre de suporte montada, alinhe os quatro pequenos furos de fixação de canto da placa controladora ESP32-CAM com a furação da torre plástica. Utilize quatro parafusos de precisão de cabeça redonda M2 imes10 extmm imes 10\, ext{mm} e quatro porcas sextavadas métricas M2.

Certifique-se de que a lente cilíndrica da câmera OV2640 permaneça centralizada na abertura e voltada para a frente, e que o cabo flat FPC da câmera não sofra torções acentuadas contra a borda do circuito impresso.

Passo 5.2 – Fixação da placa ESP32-CAM com parafusos M2*10

Subpasso 5.3 – Acoplamento da Torre de Câmera ao Chassi Intermediário

Apoie o conjunto completo montado da câmera sobre a placa acrílica intermediária do robô e fixe-o firmemente utilizando dois parafusos de cabeça escareada M3 imes10 extmm imes 10\, ext{mm}. O conjunto deve ficar posicionado na extremidade frontal, apontando para a dianteira do veículo.

Passo 5.3 – Acoplamento e fixação da torre da câmera no chassi

Passo 6 – Instalação da Antena Externa Wi-Fi 2.4 GHz e Conector SMA

Para viabilizar uma transmissão de vídeo em alta definição com taxa de quadros estável sem perdas de pacotes ou latência induzida por reflexões eletromagnéticas do chassi, o robô utiliza uma antena externa omnidirecional de 2,4 GHz conectada via cabo pigtail coaxial de baixa perda.

Passe o cabo coaxial fino através do orifício guia usinado na placa acrílica superior. Conecte com extrema delicadeza o conector em miniatura IPEX macho no soquete receptor fêmea de rádiofrequência localizado na superfície da placa ESP32-CAM (pressione levemente até ouvir um estalo sutil de travamento mecânico). Em seguida, monte o conector rosqueável SMA fêmea na furação acrílica traseira, respeitando rigorosamente a ordem mecânica dos anéis de pressão: primeiro a arruela dentada estrela, seguida da porca sextavada de latão dourada. Rosqueie a antena flexível articulada externamente.

Passo 6 – Instalação do conector SMA e cabo pigtail IPEXPasso 6 – Ordem de arruelas e porcas de fixação da antena omni

Passo 7 – Instalação das 4 Rodas de Tração de Borracha

As quatro rodas são injetadas em plástico ABS reforçado com anéis externos de borracha sintética com sulcos transversais que maximizam o atrito estático com pisos lisos ou carpetes.

O cubo de cada roda possui uma cavidade com duplo chanfro em D, projetada para se acoplar com precisão cirúrgica aos eixos chatos dos motores TT. Alinhe a chaveta de cada roda com o chanfro do eixo do respectivo motor e empurre a roda firmemente até o batente. Para evitar desencaixes durante arrancadas ou reversões bruscas de torque, introduza um parafuso Philips autoatarraxante de cabeça redonda M2 imes25 extmm imes 25\, ext{mm} no centro do cubo de cada roda e aperte-o até encostar na rosca plástica do eixo do motor.

Passo 7 – Encaixe e fixação das rodas de tração nos eixos dos motores

Passo 8 – Esquema e Guia de Fiação Elétrica Completo (Wiring Guide)

Com todos os elementos mecânicos firmemente aparafusados e o segundo andar acrílico posicionado sobre os espaçadores de latão, execute a interligação elétrica do sistema de potência, do circuito de alimentação e dos barramentos lógicos de comando.

Passo 8 – Diagrama esquemático de fiação do Kit Kuongshun AD174

Siga estritamente a tabela de interconexão elétrica para evitar curto-circuitos ou polarizações invertidas:

Origem do Sinal / TerminalDestino Físico no CircuitoFunção Elétrica e Descrição
Cabo Vermelho (+Baterias 18650)Borne VMS (12V) do L298NEntrada de tensão não regulada das baterias (7,4 extV…8,4 extV7,4\, ext{V} \dots 8,4\, ext{V}) via chave geral
Cabo Preto (-Baterias 18650)Borne GND do L298NReferência de terra comum de potência
Borne +5V do L298NPino 5V da placa base ESP32-CAMSaída regulada do LM7805 que alimenta o ESP32
Borne GND do L298NPino GND da placa base ESP32-CAMReferência de terra comum lógica (essencial para retorno de sinais)
Motores Esquerdos (Fios Vermelho/Preto)Bornes OUT1 e OUT2 do L298NAlimentação dos dois motores de tração do lado esquerdo (em paralelo)
Motores Direitos (Fios Vermelho/Preto)Bornes OUT3 e OUT4 do L298NAlimentação dos dois motores de tração do lado direito (em paralelo)
Pino GPIO 2 do ESP32-CAMBorne ENA do L298NSinal PWM de controle de velocidade do lado esquerdo (remover jumper ENA)
Pino GPIO 12 do ESP32-CAMBorne ENB do L298NSinal PWM de controle de velocidade do lado direito (remover jumper ENB)
Pino GPIO 33 do ESP32-CAMBorne IN1 do L298NSinal de sentido de rotação ré da esteira esquerda (gpLb)
Pino GPIO 15 do ESP32-CAMBorne IN2 do L298NSinal de sentido de rotação avanço da esteira esquerda (gpLf)
Pino GPIO 14 do ESP32-CAMBorne IN3 do L298NSinal de sentido de rotação ré da esteira direita (gpRb)
Pino GPIO 13 do ESP32-CAMBorne IN4 do L298NSinal de sentido de rotação avanço da esteira direita (gpRf)

⚠️ Aviso de segurança elétrica: NUNCA conecte o cabo USB Tipo-C no computador com o interruptor das baterias ligado se houver dúvida sobre as conexões de terra (GND) e alimentação. Sempre revise a integridade dos cabos antes de fechar o circuito.

Preparação do Ambiente de Programação (Programming Preparation)

Para compilar e transferir os firmwares do robô para o módulo ESP32-CAM, é indispensável configurar com rigor o ecossistema de desenvolvimento da Arduino IDE, o driver de comunicação serial USB e o pacote de suporte às placas ESP32. Pequenas divergências de versão nos pacotes de suporte de placas podem impedir a compilação ou gerar falhas catastróficas em tempo de execução, como falhas no buffer de captura da câmera OV2640 ou travamentos no temporizador PWM dos motores.

Instalação da Arduino IDE e do Driver Serial CH340

A plataforma Arduino IDE é o ambiente de desenvolvimento integrado de código aberto utilizado para escrever, compilar e descarregar código nos microcontroladores. O kit é plenamente compatível tanto com a versão clássica estável (Arduino IDE 1.8.x) quanto com a versão moderna (Arduino IDE 2.x).

Instalação da Arduino IDE – Seleção do executávelInstalação da Arduino IDE – Aceite da licença

Durante o processo de instalação no Windows, selecione todas as opções de componentes padrão (incluindo o driver USB nativo do Arduino) e prossiga clicando sucessivamente em Next e Install. Quando a barra de progresso for concluída, encerre o instalador.

Instalação da Arduino IDE – Progresso da instalaçãoInstalação da Arduino IDE – Conclusão do processo

Instalação do Driver USB-Serial CH340 no Windows

A placa de desenvolvimento base do ESP32-CAM utiliza o chip conversor de protocolo CH340 (fabricado pela WCH - QinHeng Electronics) para intermediar os sinais entre a porta USB do computador e os pinos de transmissão/recepção assíncrona (UART0: GPIO 1 TX e GPIO 3 RX) do microcontrolador ESP32.

Se ao conectar a placa pela primeira vez através do cabo USB Tipo-C o Windows não atribuir uma porta de comunicação serial válida (exibindo o dispositivo no Gerenciador de Dispositivos com um ponto de exclamação amarelo ou rotulado como “Dispositivo Desconhecido”), instale o driver oficial:

  1. Acesse os arquivos do kit na pasta 2_Programming_Preparation/1. Installation of Arduino IDE and CH340 driver/CH340 Serial Driver/CH340 Driver File-Windows/USB_Drive_CH341_3_1;
  2. Execute o arquivo SETUP.EXE como Administrador;
  3. Na janela do assistente de instalação do driver, clique no botão INSTALL;
  4. Aguarde a mensagem de confirmação “Driver install success!” e reinicie o computador caso solicitado.
Instalação do Driver CH340 – Execução do SETUP.EXEInstalação do Driver CH340 – Confirmação de sucesso na instalação

Para confirmar o reconhecimento do hardware, conecte a placa ESP32-CAM via cabo USB Tipo-C, abra o Gerenciador de Dispositivos do Windows (devmgmt.msc) e expanda a seção Portas (COM e LPT). Uma nova porta serial será exibida com o nome USB-SERIAL CH340 (COMxx), onde xx representa o número atribuído pelo sistema operacional (por exemplo, COM3, COM5 ou COM12).

Confirmação do Driver CH340 no Gerenciador de Dispositivos do Windows

Instalação do Driver CH340 no macOS

Para usuários do sistema Apple macOS, acesse a pasta CH340 Driver File-MAC no pacote do fabricante e instale o pacote assinado CH34xVCPDriver.pkg. Acesse Ajustes do Sistema > Privacidade e Segurança e autorize a extensão de kernel caso o sistema bloqueie a execução. O dispositivo será identificado no terminal como /dev/cu.usbserial-xxxx ou /dev/cu.wchusbserialxxxx.


Instalação do Pacote de Placas ESP32 e Fixação Estrita da Versão 2.0.12

A arquitetura do ESP32 não faz parte da instalação nativa da Arduino IDE. Para habilitar o suporte às placas baseadas no silício Espressif, é necessário adicionar a URL oficial dos repositórios de placas nas preferências da IDE.

Abra a Arduino IDE, acesse o menu Arquivo > Preferências (ou Ctrl + Vírgula) e localize o campo denominado URLs Adicionais para o Gerenciadores de Placas. Insira a seguinte URL:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Preferências da Arduino IDE – Inserção da URL de placas ESP32Preferências da Arduino IDE – Confirmação da URL de pacotes

Clique em OK para salvar as configurações. Em seguida, acesse o menu Ferramentas > Placa > Gerenciador de Placas… (ou clique no ícone correspondente na barra lateral esquerda da Arduino IDE 2.x). Na caixa de pesquisa superior, digite esp32.

Localize o pacote oficial mantido pela Espressif Systems.

Gerenciador de Placas – Busca pelo pacote esp32 da Espressif

⛔ REGRA INVIOLÁVEL DE COMPATIBILIDADE — FIXAR NA VERSÃO 2.0.12: No menu suspenso de seleção de versões do pacote esp32, selecione obrigatoriamente a versão 2.0.12. NÃO instale versões da série 3.x (ex.: 3.0.0, 3.0.4 ou superiores).

Por que a versão 3.x falha no kit AD174? A série 3.0 do núcleo ESP32 migrou a base de compilação do ESP-IDF v4.4 para o ESP-IDF v5.1. Nessa grande reformulação estrutural, a Espressif alterou radicalmente as APIs de periféricos de hardware:

  1. As funções de temporização e modulação PWM ledcSetup(), ledcAttachPin() e ledcWrite() foram sumariamente extintas do cabeçalho de compatibilidade e substituídas por ledcAttach(pin, freq, res). Como os firmwares do kit AD174 utilizam os canais PWM dedicados para os motores e farol flash através dessas funções tradicionais, a compilação no core 3.x é abortada com erros fatais de símbolo indefinido (error: 'ledcSetup' was not declared in this scope).
  2. O driver da câmera OV2640 sofreu alterações no gerenciamento de DMA (Direct Memory Access) que provocam corrupção de fluxo em streams MJPEG de alta taxa quando associados à alocação em PSRAM.

Portanto, assegure-se de que a versão instalada seja rigorosamente a 2.0.12.

Gerenciador de Placas – Seleção e instalação da versão pinada 2.0.12

Método Alternativo: Instalador Offline Executável

Caso a sua conexão com a internet apresente lentidão ou o download das ferramentas pelo Gerenciador de Placas falhe repetidamente, o fabricante Kuongshun disponibiliza no pacote do kit um instalador offline direto para Windows:

  1. Feche completamente a Arduino IDE;
  2. Navegue até a pasta 2_Programming_Preparation/2. Install the ESP32 plugin in the Arduino IDE;
  3. Execute o instalador esp32_package_2.0.12_arduinome.exe;
  4. Siga as etapas na tela para descompactar e registrar todos os compiladores e cabeçalhos do ESP32 versão 2.0.12 diretamente na pasta %LOCALAPPDATA%\Arduino15\packages\esp32;
  5. Ao reabrir a Arduino IDE, as placas ESP32 estarão prontamente disponíveis no menu.
Instalador Offline ESP32 2.0.12 – Execução do pacote arduinome.exeVerificação das placas ESP32 instaladas no menu Ferramentas

Parâmetros Obrigatórios de Configuração da Placa na Arduino IDE

Antes de carregar qualquer código no robô, verifique e configure rigorosamente os seguintes parâmetros no menu Ferramentas da Arduino IDE:

Parâmetro no Menu FerramentasValor de Configuração ObrigatórioJustificativa Técnica de Engenharia
Placa (Board)ESP32 Dev ModuleMapeamento padrão com suporte aos pinos e periféricos do módulo AI-Thinker
Porta (Port)COMxx (Porta serial do CH340)Porta física USB associada à placa pelo sistema operacional
CPU Frequency240MHz (WiFi/BT)Frequência máxima de processamento para atender o encoder JPEG e o rádio
Flash Frequency80MHzClock de leitura e escrita da memória flash SPI
Flash ModeQIO (ou DIO)Modo de barramento de 4 vias paralelas de alta performance
Partition SchemeHuge APP (3MB No OTA/1MB SPIFFS)Garante espaço de memória suficiente para o binário do servidor web e Wi-Fi
Core Debug LevelNone (ou Error)Desativa mensagens de debug desnecessárias na UART0
PSRAMEnabledOBRIGATÓRIO: Ativa o acesso ao chip de 4 MB de PSRAM para buffer de vídeo
Upload Speed921600 (ou 115200 caso haja instabilidade)Velocidade de gravação da memória flash do ESP32

Tabela-Mestre de Bibliotecas do Curso

Todas as bibliotecas e cabeçalhos requeridos para compilar os projetos práticos do Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 já estão integralmente embutidos no pacote oficial de placas ESP32 versão 2.0.12. Não há necessidade de baixar bibliotecas avulsas de terceiros no Gerenciador de Bibliotecas, garantindo total repetibilidade e eliminando conflitos de dependências transitivas:

Biblioteca (#include)Função e Papel no ProjetoOrigem no Pacote ESP32 2.0.12Repositório Oficial EspressifLições em que é Utilizada
esp_camera.hDriver de controle de registradores, DMA e captura da câmera OV2640Integrada nativamente ao core ESP32espressif/esp32-cameraLição 2 e Lição 3
WiFi.hGerenciamento da pilha TCP/IP e rádio Wi-Fi nos modos Estação e SoftAPIntegrada nativamente ao core ESP32espressif/arduino-esp32Lição 2 e Lição 3
esp_http_server.hServidor HTTP multithreaded embarcado no FreeRTOS para streaming MJPEGIntegrada nativamente ao ESP-IDFespressif/esp-idfLição 2 e Lição 3
soc/soc.hDefinições de registradores básicos e barramentos do silício ESP32Integrada nativamente ao core ESP32espressif/arduino-esp32Lição 2 e Lição 3
soc/rtc_cntl_reg.hRegistradores de baixo nível do Real Time Clock e detector de brownoutIntegrada nativamente ao core ESP32espressif/arduino-esp32Lição 2 e Lição 3
Nativa do C++ / ArduinoFunções de GPIO (pinMode, digitalWrite, analogWrite, Serial)Nativas do compilador Xtensaarduino/ArduinoCore-APILição 1

💡 Conferência prévia: Para garantir que a toolchain esteja 100% funcional, abra a Arduino IDE, crie um sketch em branco (setup e loop vazios), selecione a placa ESP32 Dev Module e clique em Verificar (Ctrl + R). A compilação deve finalizar com a mensagem “Compilação terminada” e alocação mínima de memória flash.

Lição 1 – Primeiros Movimentos do Robô (Get The Car Moving)

Nesta primeira lição prática, iniciamos a programação do Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 explorando o controle eletromecânico fundamental dos quatro motores de tração através da ponte H dupla L298N. O objetivo é compreender como sinais digitais discretos (níveis lógicos ALTO e BAIXO) e sinais analógicos sintetizados por modulação em largura de pulso (PWM) comandam os transistores internos do circuito integrado para orientar o fluxo de corrente contínua, governando os sentidos de rotação, velocidade e frenagem do veículo.

Arquitetura de Acionamento e Tabela de Verdade dos Motores

O controle do chassi 4WD agrupa os quatro motores em dois canais de tração: o par de motores esquerdos (conectados em paralelo nos bornes OUT1 e OUT2 do L298N) e o par de motores direitos (conectados em paralelo nos bornes OUT3 e OUT4 do L298N). O microcontrolador ESP32-CAM utiliza seis pinos digitais de saída para governar esse estágio de potência:

  • GPIO 2 (ENA): Habilitação e modulação de velocidade do lado esquerdo;
  • GPIO 12 (ENB): Habilitação e modulação de velocidade do lado direito;
  • GPIO 33 (gpLb - Left Backward): Comanda o sentido reverso das rodas esquerdas;
  • GPIO 15 (gpLf - Left Forward): Comanda o sentido de avanço das rodas esquerdas;
  • GPIO 14 (gpRb - Right Backward): Comanda o sentido reverso das rodas direitas;
  • GPIO 13 (gpRf - Right Forward): Comanda o sentido de avanço das rodas direitas.

A lógica de acionamento das bobinas dos motores obedece estritamente à seguinte tabela de verdade:

ENA (GPIO 2)ENB (GPIO 12)gpLb (GPIO 33)gpLf (GPIO 15)gpRb (GPIO 14)gpRf (GPIO 13)Estado Cinemático Resultante do Robô
HIGHHIGHLOWHIGHLOWHIGHAvanço em Linha Reta (Forward): Ambos os lados giram para frente em velocidade máxima
HIGHHIGHHIGHLOWHIGHLOWMarcha a Ré (Backward): Ambos os lados giram para trás em velocidade máxima
HIGHHIGHHIGHLOWLOWHIGHConversão à Esquerda (Turn Left): Lado esquerdo gira para trás, lado direito para frente
HIGHHIGHLOWHIGHHIGHLOWConversão à Direita (Turn Right): Lado esquerdo gira para frente, lado direito para trás
HIGHHIGHLOWLOWLOWLOWParada Rápida por Frenagem Elétrica (Stop): Terminais dos motores em curto-circuito
HIGHHIGHHIGHHIGHHIGHHIGHParada por Curto-Circuito Lógico (Stop): Entradas idênticas em nível alto
LOWLOWN/AN/AN/AN/AParada por Desabilitação (Inércia / Coast): Canais da ponte H desligados

Fundamentos Teóricos da Modulação por Largura de Pulso (PWM)

Para variar a rotação dos motores sem dissipar energia em resistores em série, utiliza-se a técnica de Modulação por Largura de Pulso (PWM — Pulse-Width Modulation). Em vez de fornecer uma tensão contínua linear variável, o circuito entrega uma onda quadrada com frequência constante f=1/Tf = 1/T e alterna ciclicamente a saída entre a tensão máxima de saturação da bateria (Vcc≈7,4 extVV_{cc} \approx 7,4\, ext{V}) durante o tempo ativo tont_{on} e zero volts durante o tempo inativo tofft_{off}:

T=ton+toffT = t_{on} + t_{off}

A razão entre o tempo ativo e o período total é definida como o Ciclo de Trabalho ou Duty Cycle (DD):

D=tonT(0≤D≤1)D = \frac{t_{on}}{T} \qquad (0 \le D \le 1)

A tensão média eficaz resultante aplicada aos bornes do motor corresponde diretamente ao produto do Duty Cycle pela tensão da fonte:

Vmed=1T∫0Tv(t) dt=1T∫0tonVcc dt=D⋅VccV_{med} = \frac{1}{T} \int_{0}^{T} v(t)\,dt = \frac{1}{T} \int_{0}^{t_{on}} V_{cc}\,dt = D \cdot V_{cc}

No ambiente Arduino, a resolução padrão do PWM é de 8 bits, discretizando o intervalo em 28=2562^8 = 256 passos inteiros (de 00 a 255255). Assim, ao executar analogWrite(pino, 128), o duty cycle configurado é:

D=128255≈0,502(50,2%)  ⟹  Vmed≈0,502imes7,4 extV≈3,71 extVD = \frac{128}{255} \approx 0,502 \quad (50,2\%) \implies V_{med} \approx 0,502 imes 7,4\, ext{V} \approx 3,71\, ext{V}

Como a bobina de um motor de corrente contínua atua como uma carga indutiva em série com uma resistência de armadura (RaR_a) e uma força contraeletromotriz induzida (Efem=Ke⋅ω\mathcal{E}_{fem} = K_e \cdot \omega), a corrente elétrica não varia instantaneamente, mas é suavizada pela constante de tempo indutiva au=L/Ra au = L / R_a. O torque mecânico instantâneo desenvolvido no eixo do motor é linearmente proporcional à corrente média:

τmed=Kt⋅Imed \tau_{med} = K_t \cdot I_{med}

Contudo, todo motor DC com caixa de redução plástica apresenta um atrito estático mecânico interno nos dentes das engrenagens e no contato das escovas com o comutador. Existe, portanto, uma tensão mínima de partida (zona morta ou deadband), tipicamente correspondente a valores de PWM entre 8080 e 100100. Abaixo desse limiar de energia, o torque eletromagnético é insuficiente para romper a inércia estática e o motor apenas emite um zumbido característico de alta frequência sem produzir movimento mecânico.


Procedimento Geral de Gravação e Upload de Sketches

Para carregar os sketches desta lição na placa ESP32-CAM, siga o roteiro canônico do fabricante Kuongshun:

  1. Conecte a placa ESP32-CAM ao computador através do cabo USB Tipo-C;
  2. Na Arduino IDE, selecione o modelo de placa em Ferramentas > Placa > esp32 > ESP32 Dev Module;
  3. Selecione a porta de comunicação em Ferramentas > Porta > COMxx (identificada no Gerenciador de Dispositivos com o driver CH340);
  4. Abra o arquivo .ino desejado;
  5. Clique no botão Carregar (Upload, ícone de seta apontando para a direita na barra superior);
  6. Aguarde a compilação do código e o processo de gravação na memória flash. O console inferior exibirá as porcentagens de escrita (Writing at 0x00010000... (100 %)) e concluirá com a mensagem “Leaving… Hard resetting via RTS pin…”.
  7. Desconecte o cabo USB do computador, coloque o robô no chão, instale as duas baterias 18650 no suporte com a polaridade correta e ligue a chave geral. Caso o robô não inicialize o movimento de imediato, pressione uma vez o botão RST (Reset) localizado na placa base da ESP32-CAM.

Projeto 1.1 – Movimento de Avanço Contínuo (Forward)

O sketch Forward.ino configura todos os pinos de controle dos motores como saídas digitais e comuta os canais da ponte H para impor rotação de avanço com velocidade máxima em ambos os lados do chassi.

📦 Bibliotecas desta lição: nenhuma — o código utiliza apenas as funções nativas de GPIO (pinMode, digitalWrite, Serial) embutidas no compilador do núcleo ESP32. Nada a baixar ou instalar.

// ============================================================================
// Projeto 1.1: Movimento de Avanço Contínuo para Frente (Forward.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

// Definição dos pinos de interface com o módulo de potência L298N
#define ENA 2    // Pino GPIO 2 conectado à habilitação do Canal A (Velocidade Lado Esquerdo)
#define ENB 12   // Pino GPIO 12 conectado à habilitação do Canal B (Velocidade Lado Direito)
#define gpRb 14  // Pino GPIO 14: Entrada IN3 do L298N (Roda Direita para Trás / Backward)
#define gpRf 13  // Pino GPIO 13: Entrada IN4 do L298N (Roda Direita para Frente / Forward)
#define gpLb 33  // Pino GPIO 33: Entrada IN1 do L298N (Roda Esquerda para Trás / Backward)
#define gpLf 15  // Pino GPIO 15: Entrada IN2 do L298N (Roda Esquerda para Frente / Forward)

// Função de configuração de hardware executada uma única vez na inicialização
void setup() {
  // Inicializa a interface de comunicação serial a 9600 bps para telemetria
  Serial.begin(9600);
  
  // Configura todos os seis pinos de comando do L298N como saídas digitais ativas
  pinMode(gpLb, OUTPUT); // Configura o pino GPIO 33 como saída
  pinMode(gpLf, OUTPUT); // Configura o pino GPIO 15 como saída
  pinMode(gpRb, OUTPUT); // Configura o pino GPIO 14 como saída
  pinMode(gpRf, OUTPUT); // Configura o pino GPIO 13 como saída
  pinMode(ENA, OUTPUT);  // Configura o pino GPIO 2 como saída
  pinMode(ENB, OUTPUT);  // Configura o pino GPIO 12 como saída
}

// Loop de execução contínua do microcontrolador
void loop() {
  // Habilita os canais de potência A e B do driver L298N em nível alto (100% de tensão)
  digitalWrite(ENA, HIGH); // Ativa o canal de potência dos motores esquerdos
  digitalWrite(ENB, HIGH); // Ativa o canal de potência dos motores direitos
  
  // Configura o sentido de rotação dos motores do lado esquerdo para frente
  digitalWrite(gpLb, LOW);  // Desativa o comando reverso do lado esquerdo
  digitalWrite(gpLf, HIGH); // Ativa o comando de avanço do lado esquerdo
  
  // Configura o sentido de rotação dos motores do lado direito para frente
  digitalWrite(gpRb, LOW);  // Desativa o comando reverso do lado direito
  digitalWrite(gpRf, HIGH); // Ativa o comando de avanço do lado direito
  
  // Envia mensagem informativa para o Monitor Serial da Arduino IDE
  Serial.println("Forward");
}

Teste e Validação do Projeto 1.1

Após efetuar o upload do código e alimentar o robô pelas baterias, coloque-o sobre o chão. As quatro rodas devem girar sincronizadamente no sentido de avanço, impulsionando o robô em linha reta para frente. Caso o robô gire em torno do próprio eixo ou mova-se para trás, consulte o diagnóstico de inversão de fiação no final deste manual (Passo 8 / Troubleshooting).


Projeto 1.2 – Movimento de Marcha a Ré (Backward)

O sketch Backward.ino inverte a polaridade elétrica nas escovas dos quatro motores, fazendo com que o fluxo de corrente contínua atravesse as armaduras no sentido oposto, gerando torque reverso e deslocando o robô para trás.

📦 Bibliotecas desta lição: nenhuma — o código utiliza apenas as funções nativas de GPIO (pinMode, digitalWrite, Serial). Nada a baixar ou instalar.

// ============================================================================
// Projeto 1.2: Movimento de Marcha a Ré Contínua (Backward.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

// Definição dos pinos de interface com o módulo L298N
#define ENA 2    // Pino GPIO 2: Habilitação dos motores esquerdos
#define ENB 12   // Pino GPIO 12: Habilitação dos motores direitos
#define gpRb 14  // Pino GPIO 14: Sentido reverso dos motores direitos
#define gpRf 13  // Pino GPIO 13: Sentido de avanço dos motores direitos
#define gpLb 33  // Pino GPIO 33: Sentido reverso dos motores esquerdos
#define gpLf 15  // Pino GPIO 15: Sentido de avanço dos motores esquerdos

void setup() {
  // Inicializa o canal serial a 9600 bps para monitoramento
  Serial.begin(9600);
  
  // Configura os pinos de controle da ponte H como saídas digitais
  pinMode(gpLb, OUTPUT); // Saída do sentido ré esquerdo
  pinMode(gpLf, OUTPUT); // Saída do sentido frente esquerdo
  pinMode(gpRb, OUTPUT); // Saída do sentido ré direito
  pinMode(gpRf, OUTPUT); // Saída do sentido frente direito
  pinMode(ENA, OUTPUT);  // Saída de habilitação esquerda
  pinMode(ENB, OUTPUT);  // Saída de habilitação direita
}

void loop() {
  // Habilita as duas saídas de potência do L298N em condução máxima
  digitalWrite(ENA, HIGH); // Habilita canal A em saturação
  digitalWrite(ENB, HIGH); // Habilita canal B em saturação
  
  // Configura o lado esquerdo para rotação reversa
  digitalWrite(gpLb, HIGH); // Coloca IN1 em nível alto (ré ativada)
  digitalWrite(gpLf, LOW);  // Coloca IN2 em nível baixo (avanço desligado)
  
  // Configura o lado direito para rotação reversa
  digitalWrite(gpRb, HIGH); // Coloca IN3 em nível alto (ré ativada)
  digitalWrite(gpRf, LOW);  // Coloca IN4 em nível baixo (avanço desligado)
  
  // Imprime confirmação do comando no Monitor Serial
  Serial.println("Back");
}

Projeto 1.3 – Conversão à Esquerda (Turn Left)

Para realizar uma manobra de conversão fechada ou rotação no próprio eixo para a esquerda, o lado esquerdo do veículo deve girar para trás enquanto o lado direito gira para frente. O par de torques opostos gera um momento angular no sentido anti-horário (visto de cima), fazendo o robô girar sobre o centro de sua bitola.

📦 Bibliotecas desta lição: nenhuma — o código utiliza apenas comandos de GPIO nativos.

// ============================================================================
// Projeto 1.3: Conversão e Rotação à Esquerda (Turn_left.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

#define ENA 2    // Pino GPIO 2: Habilitação canal esquerdo
#define ENB 12   // Pino GPIO 12: Habilitação canal direito
#define gpRb 14  // Pino GPIO 14: Marcha ré direita
#define gpRf 13  // Pino GPIO 13: Avanço direito
#define gpLb 33  // Pino GPIO 33: Marcha ré esquerda
#define gpLf 15  // Pino GPIO 15: Avanço esquerdo

void setup() {
  Serial.begin(9600);
  
  pinMode(gpLb, OUTPUT);
  pinMode(gpLf, OUTPUT);
  pinMode(gpRb, OUTPUT);
  pinMode(gpRf, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  // Habilita potência máxima nas duas pontes H
  digitalWrite(ENA, HIGH);
  digitalWrite(ENB, HIGH);
  
  // Rodas esquerdas giram no sentido REVERSO (gpLb = HIGH, gpLf = LOW)
  digitalWrite(gpLb, HIGH);
  digitalWrite(gpLf, LOW);
  
  // Rodas direitas giram no sentido FRONTAL (gpRb = LOW, gpRf = HIGH)
  digitalWrite(gpRb, LOW);
  digitalWrite(gpRf, HIGH);
  
  Serial.println("Left");
}

Projeto 1.4 – Conversão à Direita (Turn Right)

Inversamente à manobra anterior, para girar no sentido horário para a direita, as rodas do lado esquerdo devem girar para frente enquanto as rodas do lado direito giram em marcha a ré.

📦 Bibliotecas desta lição: nenhuma — comandos nativos de GPIO do núcleo ESP32.

// ============================================================================
// Projeto 1.4: Conversão e Rotação à Direita (Turn_right.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

#define ENA 2    // Pino GPIO 2: Habilitação canal esquerdo
#define ENB 12   // Pino GPIO 12: Habilitação canal direito
#define gpRb 14  // Pino GPIO 14: Marcha ré direita
#define gpRf 13  // Pino GPIO 13: Avanço direito
#define gpLb 33  // Pino GPIO 33: Marcha ré esquerda
#define gpLf 15  // Pino GPIO 15: Avanço esquerdo

void setup() {
  Serial.begin(9600);
  
  pinMode(gpLb, OUTPUT);
  pinMode(gpLf, OUTPUT);
  pinMode(gpRb, OUTPUT);
  pinMode(gpRf, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  digitalWrite(ENA, HIGH);
  digitalWrite(ENB, HIGH);
  
  // Rodas esquerdas giram no sentido FRONTAL (gpLb = LOW, gpLf = HIGH)
  digitalWrite(gpLb, LOW);
  digitalWrite(gpLf, HIGH);
  
  // Rodas direitas giram no sentido REVERSO (gpRb = HIGH, gpRf = LOW)
  digitalWrite(gpRb, HIGH);
  digitalWrite(gpRf, LOW);
  
  Serial.println("Right");
}

Projeto 1.5 – Controle Suave de Velocidade via PWM (Speed Control)

O sketch Speed_control.ino demonstra o controle contínuo e progressivo de aceleração e frenagem suave através de sinais PWM gerados nos pinos ENA (GPIO 2) e ENB (GPIO 12). A rotina executa uma rampa linear ascendente de velocidade de 00 até 255255 em passos de 20 extms20\, ext{ms}, sustenta a velocidade de pico durante 1 extsegundo1\, ext{segundo} e em seguida executa uma rampa descendente de desaceleração até a imobilização completa.

📦 Bibliotecas desta lição: nenhuma — usa a função nativa analogWrite() suportada no núcleo ESP32 2.0.12.

// ============================================================================
// Projeto 1.5: Controle Dinâmico de Velocidade via Rampa PWM (Speed_control.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

#define ENA 2    // Pino GPIO 2: Controle de PWM do motor esquerdo
#define ENB 12   // Pino GPIO 12: Controle de PWM do motor direito
#define gpRb 14  // Pino GPIO 14: Ré direita
#define gpRf 13  // Pino GPIO 13: Avanço direito
#define gpLb 33  // Pino GPIO 33: Ré esquerda
#define gpLf 15  // Pino GPIO 15: Avanço esquerdo

void setup() {
  Serial.begin(9600);
  
  pinMode(gpLb, OUTPUT);
  pinMode(gpLf, OUTPUT);
  pinMode(gpRb, OUTPUT);
  pinMode(gpRf, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  // Configura a direção do movimento permanentemente para frente
  digitalWrite(gpLb, LOW);  // Desativa ré esquerda
  digitalWrite(gpLf, HIGH); // Ativa avanço esquerdo
  digitalWrite(gpRb, LOW);  // Desativa ré direita
  digitalWrite(gpRf, HIGH); // Ativa avanço direito
  
  // Rampa de Aceleração Suave: incrementa o ciclo de trabalho de 0 a 255
  for (int i = 0; i <= 255; i++) {
    analogWrite(ENB, i); // Aplica nível PWM nos motores direitos
    analogWrite(ENA, i); // Aplica nível PWM nos motores esquerdos
    delay(20);          // Pausa de 20 ms entre incrementos (~5,1 segundos de rampa)
  }
  
  // Mantém a velocidade máxima estabelecida durante 1 segundo
  delay(1000);
  
  // Rampa de Desaceleração Gradual: reduz o ciclo de trabalho de 255 a 0
  for (int i = 255; i >= 0; i--) {
    analogWrite(ENB, i); // Reduz nível PWM nos motores direitos
    analogWrite(ENA, i); // Reduz nível PWM nos motores esquerdos
    delay(20);          // Pausa de 20 ms entre decrementos (~5,1 segundos de rampa)
  }
  
  // Permanece em repouso durante 1 segundo antes de repetir o ciclo
  delay(1000);
}

Projeto 1.6 – Rotina Autônoma Integrada em Loop (AUTO_GO)

O sketch AUTO_GO.ino consolida todas as funções de locomoção em um código estruturado modularmente por funções independentes (forward(), back(), left(), right()), executando uma sequência de demonstração contínua: o robô avança durante 1 segundo, retrocede durante 1 segundo, gira à esquerda durante 1 segundo e gira à direita durante 1 segundo, repetindo o padrão indefinidamente.

📦 Bibliotecas desta lição: nenhuma — arquitetura em funções C++ nativas.

// ============================================================================
// Projeto 1.6: Ciclo Autônomo Completo de Movimentação (AUTO_GO.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM com Driver L298N | Tração 4WD
// ============================================================================

// Definição dos pinos de interface com o módulo L298N
#define ENA 2   // GPIO 2: Habilitação Lado Esquerdo
#define ENB 12  // GPIO 12: Habilitação Lado Direito
#define gpRb 14 // GPIO 14: Sentido Ré Direito
#define gpRf 13 // GPIO 13: Sentido Avanço Direito
#define gpLb 33 // GPIO 33: Sentido Ré Esquerdo
#define gpLf 15 // GPIO 15: Sentido Avanço Esquerdo

// Sub-rotina para movimentação retilínea para frente
void forward() {
  digitalWrite(ENA, HIGH);  // Habilita canal A em velocidade máxima
  digitalWrite(ENB, HIGH);  // Habilita canal B em velocidade máxima
  digitalWrite(gpLb, LOW);  // Desativa ré esquerda
  digitalWrite(gpLf, HIGH); // Ativa avanço esquerdo
  digitalWrite(gpRb, LOW);  // Desativa ré direita
  digitalWrite(gpRf, HIGH); // Ativa avanço direito
  Serial.println("Forward");// Transmite status na porta serial
}

// Sub-rotina para movimentação de marcha a ré
void back() {
  digitalWrite(ENA, HIGH);  // Habilita canal A
  digitalWrite(ENB, HIGH);  // Habilita canal B
  digitalWrite(gpLb, HIGH); // Ativa ré esquerda
  digitalWrite(gpLf, LOW);  // Desativa avanço esquerdo
  digitalWrite(gpRb, HIGH); // Ativa ré direita
  digitalWrite(gpRf, LOW);  // Desativa avanço direito
  Serial.println("Back");
}

// Sub-rotina para conversão e giro à esquerda
void left() {
  digitalWrite(ENA, HIGH);  // Habilita canal A
  digitalWrite(ENB, HIGH);  // Habilita canal B
  digitalWrite(gpLb, HIGH); // Lado esquerdo gira para trás
  digitalWrite(gpLf, LOW);
  digitalWrite(gpRb, LOW);  // Lado direito gira para frente
  digitalWrite(gpRf, HIGH);
  Serial.println("Left");
}

// Sub-rotina para conversão e giro à direita
void right() {
  digitalWrite(ENA, HIGH);  // Habilita canal A
  digitalWrite(ENB, HIGH);  // Habilita canal B
  digitalWrite(gpLb, LOW);  // Lado esquerdo gira para frente
  digitalWrite(gpLf, HIGH);
  digitalWrite(gpRb, HIGH); // Lado direito gira para trás
  digitalWrite(gpRf, LOW);
  Serial.println("Right");
}

// Rotina de inicialização e configuração de pinos
void setup() {
  Serial.begin(9600);     // Inicializa porta serial a 9600 baud
  pinMode(gpLb, OUTPUT);  // Configura todos os 6 pinos como saídas ativas
  pinMode(gpLf, OUTPUT);
  pinMode(gpRb, OUTPUT);
  pinMode(gpRf, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
}

// Loop principal de execução cíclica
void loop() {
  forward();   // Executa movimento para frente
  delay(1000); // Mantém o deslocamento ativo durante 1000 ms (1 segundo)
  
  back();      // Executa movimento de ré
  delay(1000); // Mantém o deslocamento ativo durante 1 segundo
  
  left();      // Executa conversão à esquerda
  delay(1000); // Mantém o giro ativo durante 1 segundo
  
  right();     // Executa conversão à direita
  delay(1000); // Mantém o giro ativo durante 1 segundo
}

Lição 2 – Controle do Robô via Interface Web e Streaming de Vídeo (WIFI Camera Car Code for Web)

Nesta lição, integramos a visão computacional embarcada e a teleoperação sem fio através de um servidor web autônomo executado inteiramente dentro da placa ESP32-CAM. O robô gera seu próprio ponto de acesso Wi-Fi (SoftAP), hospeda uma página web responsiva com botões interativos e transmite um fluxo ininterrupto de vídeo em tempo real no formato MJPEG (Motion JPEG). Qualquer dispositivo conectado à rede local — como um smartphone Android ou iOS, tablet ou notebook — pode abrir o navegador web, visualizar a transmissão da câmera OV2640 e pilotar o robô sem a necessidade de instalar aplicativos externos ou depender de roteadores domésticos.

Arquitetura de Rede e Protocolo de Streaming MJPEG

Ao ser inicializado, o firmware do robô coloca o rádio Wi-Fi do ESP32 no modo de Ponto de Acesso (Access Point), criando a rede sem fio com o identificador de serviço (SSID) KUONGSHUN-AD174 e chave de segurança WPA2-PSK 12345678. O microcontrolador atribui a si próprio o endereço IP estático padrão 192.168.4.1 e inicializa dois servidores de rede em paralelo:

  1. Servidor HTTP na Porta 80 (httpd_start): Gerencia requisições de página (/), comandos de movimentação e ajuste de parâmetros (/control), captura de foto instantânea (/capture) e o fluxo contínuo de vídeo (/stream);
  2. Servidor de Soquete TCP na Porta 100 (WiFiServer server(100)): Canal de comunicação raw para troca assíncrona de comandos de controle de baixa latência.

O streaming de vídeo utiliza o padrão aberto MJPEG através do tipo de conteúdo MIME multipart/x-mixed-replace. Quando o navegador solicita o endpoint http://192.168.4.1:81/stream (ou a rota /stream), o servidor responde com o cabeçalho HTTP:

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace;boundary=123456789000000000000987654321
Access-Control-Allow-Origin: *

A cada novo quadro de imagem capturado pelo sensor OV2640 e comprimido pelo circuito interno em formato JPEG, o ESP32 envia a linha delimitadora (boundary), o cabeçalho específico da imagem (Content-Type: image/jpeg e Content-Length) e o bloco binário comprimido de pixels:

--123456789000000000000987654321
Content-Type: image/jpeg
Content-Length: 14520

<bytes binários da imagem JPEG>

O navegador web interpreta essa resposta especial substituindo instantaneamente a imagem anterior na tela pela nova imagem recebida, sem nunca fechar a conexão HTTP e sem gerar sobrecarga de handshake de novas requisições.

Proteção Contra Afundamento de Tensão (Brownout Reset)

Ao transmitir sinais de rádio Wi-Fi em potência máxima (+19,5 extdBm+19,5\, ext{dBm}) e simultaneamente comutar os transistores da ponte H para acionar os motores DC, ocorrem picos instantâneos de corrente que podem ultrapassar 1,5 extA1,5\, ext{A}. Se as baterias 18650 apresentarem leve resistência interna ou não estiverem em plena carga, a tensão no barramento de 3,3 extV3,3\, ext{V} pode sofrer uma breve ondulação transitória (ripple) e cair abaixo do limiar do detector de brownout interno do ESP32 (≈2,43 extV\approx 2,43\, ext{V}), provocando um reset involuntário do processador.

Para conferir máxima resiliência e estabilidade ao robô em bancada, o firmware do fabricante desativa intencionalmente o detector de subtensão do subsistema RTC logo no início da função setup():

WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Desativa o detector de brownout

Código-Fonte Completo do Projeto Web

O projeto é estruturado em três arquivos de código: o sketch principal (ESP32CAM_L298N_Web.ino), o módulo de inicialização da câmera e rede (CameraWebServer.cpp) e o despachante de rotas e comandos HTTP (app_httpd.cpp).

📦 Bibliotecas desta lição:

  • esp_camera.h — driver nativo de câmera integrado no pacote de placas ESP32 2.0.12.
  • WiFi.h — biblioteca nativa de gerenciamento de rádio Wi-Fi.
  • soc/soc.h e soc/rtc_cntl_reg.h — cabeçalhos de registradores de baixo nível do chip ESP32.
  • Todas estão integradas nativamente ao pacote oficial de placas ESP32 versão 2.0.12. Nada a baixar separadamente.

Arquivo 1: ESP32CAM_L298N_Web.ino

// ============================================================================
// Projeto 2: Servidor Web e Streaming MJPEG (ESP32CAM_L298N_Web.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM | Câmera OV2640 | Driver L298N
// ============================================================================

#include "esp_camera.h"        // Driver oficial de controle da câmera OV2640
#include <WiFi.h>              // Biblioteca de rede Wi-Fi nativa do ESP32
#include "soc/soc.h"           // Definições de hardware e registradores do silício
#include "soc/rtc_cntl_reg.h"  // Registradores do controlador de baixo consumo e brownout

// Seleciona o perfil de pinagem para a placa AI-Thinker ESP32-CAM
#define CAMERA_MODEL_AI_THINKER

// Definições de pinos auxiliares
#define LED   4   // LED flash de alta potência no pino GPIO 4
#define RXD2 14   // Pino RX da segunda UART (caso seja utilizada ponte externa)
#define TXD2 13   // Pino TX da segunda UART

// Declaração da função externa de inicialização da câmera e do servidor HTTP
void CameraWebServer_init();

// Inicializa o servidor de soquete TCP na porta 100
WiFiServer server(100);

// Mapeamento dos pinos de interface com o módulo L298N (variáveis globais exportadas)
extern int gpLb = 14;  // Entrada IN3 do L298N (Ré do lado direito)
extern int gpLf = 13;  // Entrada IN4 do L298N (Avanço do lado direito)
extern int gpRb = 33;  // Entrada IN1 do L298N (Ré do lado esquerdo)
extern int gpRf = 15;  // Entrada IN2 do L298N (Avanço do lado esquerdo)
extern int gpLed = 4;  // LED flash no pino GPIO 4
extern int ENR = 2;    // Canal PWM de velocidade do lado direito
extern int ENL = 12;   // Canal PWM de velocidade do lado esquerdo

// Função de inicialização e configuração dos pinos de controle dos motores
void initMotors() {
  // Configura os terminais de controle de direção como saídas digitais
  pinMode(gpLb, OUTPUT);  // Ré Direita
  pinMode(gpLf, OUTPUT);  // Frente Direita
  pinMode(gpRb, OUTPUT);  // Ré Esquerda
  pinMode(gpRf, OUTPUT);  // Frente Esquerda
  pinMode(gpLed, OUTPUT); // Farol Flash LED
  pinMode(ENR, OUTPUT);   // Habilitação Direita
  pinMode(ENL, OUTPUT);   // Habilitação Esquerda

  // Configura os canais de modulação PWM via temporizador de hardware LEDC
  // Canal 2, frequência de 5000 Hz, resolução de 8 bits (valores de 0 a 255)
  ledcSetup(2, 5000, 8);
  // Canal 12, frequência de 5000 Hz, resolução de 8 bits
  ledcSetup(12, 5000, 8);
  
  // Vincula os pinos físicos ENR e ENL aos seus respectivos canais de hardware
  ledcAttachPin(ENR, 2);
  ledcAttachPin(ENL, 12);
  
  // Inicializa a velocidade com ciclo de trabalho em zero (motores imobilizados)
  ledcWrite(ENR, 0);
  ledcWrite(ENL, 0);
  
  // Garante que todas as entradas de direção inicializem em nível lógico baixo
  digitalWrite(gpLf, LOW);
  digitalWrite(gpRb, LOW);
  digitalWrite(gpRf, LOW);
  digitalWrite(gpLb, LOW);
}

void setup() {
  // Desativa o detector de brownout para prevenir reinicializações sob transientes de corrente
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // Inicializa a comunicação serial com o computador a 115200 bps
  Serial.begin(115200);
  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
  Serial.setDebugOutput(true); // Habilita logs detalhados do driver de câmera
  Serial.println();
    
  // Inicializa o sensor óptico OV2640 e sobe a rede Wi-Fi SoftAP
  CameraWebServer_init(); 

  // Inicializa e desliga os motores de tração
  initMotors();

  // Configura o canal PWM 7 para controle proporcional do LED flash
  ledcSetup(7, 5000, 8);
  ledcAttachPin(gpLed, 7); // Vincula o pino 4 ao canal 7

  // Inicializa a escuta no servidor TCP porta 100
  server.begin();

  // Executa uma sequência de 5 piscadas rápidas no LED flash para indicar boot bem-sucedido
  for (int i = 0; i < 5; i++) {
    ledcWrite(7, 10); // Liga o LED com intensidade moderada
    delay(50);
    ledcWrite(7, 0);  // Desliga o LED
    delay(50);
  }
}

void loop() {
  // O processamento principal do streaming e das rotas é gerenciado assincronamente
  // pelas tarefas do FreeRTOS iniciadas pela biblioteca esp_http_server.
}

Arquivo 2: CameraWebServer.cpp

// ============================================================================
// Módulo de Inicialização da Câmera OV2640 e do Access Point Wi-Fi
// ============================================================================

#include "esp_system.h"
#include "esp_camera.h"
#include <WiFi.h>

// Credenciais de fábrica do Ponto de Acesso gerado pelo robô
const char *ssid = "KUONGSHUN-AD174";  // Nome da rede Wi-Fi transmitida
const char *password = "12345678";      // Chave de autenticação WPA2-PSK
String wifi_name;

// Mapeamento dos pinos do barramento DVP do módulo AI-Thinker ESP32-CAM
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

// Função de registro e inicialização do servidor HTTP declarada em app_httpd.cpp
void startCameraServer();

void CameraWebServer_init() {
  camera_config_t config; // Estrutura de configuração do driver de câmera
  
  // Configuração dos temporizadores do sinal de clock mestre
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer   = LEDC_TIMER_0;
  
  // Atribuição dos pinos do barramento paralelo de 8 bits
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  
  // Atribuição das linhas de sincronismo e clock
  config.pin_xclk     = XCLK_GPIO_NUM;
  config.pin_pclk     = PCLK_GPIO_NUM;
  config.pin_vsync    = VSYNC_GPIO_NUM;
  config.pin_href     = HREF_GPIO_NUM;
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn     = PWDN_GPIO_NUM;
  config.pin_reset    = RESET_GPIO_NUM;
  
  // Frequência do sinal de clock XCLK em 20 MHz
  config.xclk_freq_hz = 20000000;
  config.frame_size   = FRAMESIZE_UXGA;    // Resolução máxima do sensor
  config.pixel_format = PIXFORMAT_JPEG;     // Fluxo comprimido JPEG nativo
  config.grab_mode    = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location  = CAMERA_FB_IN_PSRAM; // Aloca buffers na memória PSRAM
  config.jpeg_quality = 12;                 // Nível de qualidade (0 a 63; menor = melhor)
  config.fb_count     = 1;                  // Número de buffers alocados

  // Otimização de buffers caso o chip de PSRAM externa de 4 MB seja detectado
  if (config.pixel_format == PIXFORMAT_JPEG) {
    if (psramFound()) {
      config.jpeg_quality = 10;                // Qualidade superior de imagem
      config.fb_count     = 2;                 // Double-buffering para streaming fluído
      config.grab_mode    = CAMERA_GRAB_LATEST;// Sempre descarta quadros atrasados
    } else {
      // Caso a PSRAM falhe, reduz a resolução para SVGA e aloca na DRAM interna
      config.frame_size  = FRAMESIZE_SVGA;
      config.fb_location = CAMERA_FB_IN_DRAM;
    }
  }

  // Inicializa o hardware do sensor com a configuração definida
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Falha na inicializacao da camera! Codigo de erro: 0x%x
", err);
    return;
  }

  // Obtém ponteiro para a estrutura de registradores finos do sensor
  sensor_t *s = esp_camera_sensor_get();
  // Configura a resolução inicial padrão em QVGA (320x240) para streaming rápido
  s->set_framesize(s, FRAMESIZE_QVGA);
  
  // Ajuste de orientação óptica: espelhamento vertical e horizontal
  s->set_vflip(s, 1);   // Inverte verticalmente a imagem para corrigir a montagem física
  s->set_hmirror(s, 1); // Corrige a orientação horizontal em espelho

  // Ajusta a potência de transmissão do rádio Wi-Fi para o nível máximo estável
  WiFi.setTxPower(WIFI_POWER_19_5dBm);
  
  // Inicializa o ponto de acesso Wi-Fi local
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password, 5); // SSID, senha e canal de transmissão 5
  
  // Inicia o despachante de requisições HTTP
  startCameraServer();
  
  Serial.print("

Camera Pronta! Conecte-se em: http://");
  Serial.print(WiFi.softAPIP());
  Serial.println("

");
}

Arquivo 3: Fragmento do Despachante de Comandos em app_httpd.cpp

O arquivo app_httpd.cpp processa as requisições GET encaminhadas ao endpoint /control. Ao receber comandos com as chaves var e val, ele comuta os estados dos motores e ajusta os parâmetros de câmera:

// Função de acionamento unificado dos quatro motores e velocidade PWM
void WheelAct(int speed_R, int speed_L, int nLf, int nLb, int nRf, int nRb) {
  ledcWrite(ENR, speed_R);    // Aplica PWM no motor direito
  ledcWrite(ENL, speed_L);    // Aplica PWM no motor esquerdo
  digitalWrite(gpLf, nLf);    // Frente esquerda
  digitalWrite(gpLb, nLb);    // Ré esquerda
  digitalWrite(gpRf, nRf);    // Frente direita
  digitalWrite(gpRb, nRb);    // Ré direita
}

// Manipulador de requisições do endpoint /control
static esp_err_t cmd_handler(httpd_req_t *req) {
  char* buf;
  size_t buf_len;
  char variable[32] = {0,};
  char value[32] = {0,};

  buf_len = httpd_req_get_url_query_len(req) + 1;
  if (buf_len > 1) {
    buf = (char*)malloc(buf_len);
    if (!buf) {
      httpd_resp_send_500(req);
      return ESP_FAIL;
    }
    if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
      if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
          httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
      } else {
        free(buf);
        httpd_resp_send_404(req);
        return ESP_FAIL;
      }
    }
    free(buf);
  }

  int val = atoi(value);
  sensor_t * s = esp_camera_sensor_get();

  // Rota de alteração de resolução da câmera
  if (!strcmp(variable, "framesize")) {
    if (s->pixformat == PIXFORMAT_JPEG) s->set_framesize(s, (framesize_t)val);
  }
  // Rota de alteração do brilho do farol LED Flash
  else if (!strcmp(variable, "flash")) {
    ledcWrite(7, val); // Aplica duty cycle de 0 a 255 no GPIO 4
  }
  // Rota de ajuste da velocidade dos motores
  else if (!strcmp(variable, "speed")) {
    if (val > 255) val = 255;
    else if (val < 0) val = 0;
    speed = val;
  }
  // Rota de movimentação física do robô
  else if (!strcmp(variable, "car")) {
    if (val == 1) {      // Avanço (Forward)
      WheelAct(speed, speed, HIGH, LOW, HIGH, LOW);
    } else if (val == 2) { // Conversão à Direita (Turn Right)
      WheelAct(speed, speed, LOW, HIGH, HIGH, LOW);
    } else if (val == 3) { // Conversão à Esquerda (Turn Left)
      WheelAct(speed, speed, HIGH, LOW, LOW, HIGH);
    } else if (val == 4) { // Marcha a Ré (Backward)
      WheelAct(speed, speed, LOW, HIGH, LOW, HIGH);
    } else if (val == 0) { // Parada Imediata (Stop)
      WheelAct(0, 0, LOW, LOW, LOW, LOW);
    }
  }

  httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  return httpd_resp_send(req, "OK", 2);
}

Guia Passo a Passo de Operação da Interface Web

  1. Gravação do Firmware: Carregue o projeto ESP32CAM_L298N_Web na placa ESP32-CAM via cabo USB Tipo-C;
  2. Alimentação Autônoma: Desconecte o cabo USB, insira duas baterias 18650 carregadas no suporte traseiro e acione o interruptor liga/desliga. O farol LED flash piscará 5 vezes para sinalizar que o sistema está operacional;
  3. Conexão Wi-Fi: No smartphone ou computador, abra a lista de redes Wi-Fi disponíveis, selecione a rede KUONGSHUN-AD174 e digite a senha 12345678. Caso o sistema operacional informe que a rede não possui conexão com a internet, confirme e marque para “Permanecer Conectado”;
  4. Acesso ao Portal: Abra o navegador Google Chrome, Safari ou Mozilla Firefox e digite o endereço IP:
http://192.168.4.1
Conexão ao Ponto de Acesso WiFi KUONGSHUN-AD174 no smartphoneInterface Web de controle do robô e botões de teleoperação

A interface web apresenta os seguintes controles ergonômicos:

  • Botão de Streaming (Ícone de Câmera): Inicia a recepção contínua do fluxo de vídeo em tempo real na tela;
  • Botão Snapshot: Congela o quadro atual e salva uma fotografia da visualização;
  • Teclas Direcionais em Cruz (D-Pad Virtual): Botões para avançar, retroceder, virar à esquerda e virar à direita. O acionamento opera sob retenção contínua (press and hold): enquanto o botão for mantido pressionado, o robô se desloca; ao soltar, os motores são imediatamente desativados;
  • Slider de Velocidade: Ajusta dinamicamente o valor do PWM de 00 a 255255;
  • Slider de Iluminação Flash: Regula o brilho do LED branco do GPIO 4 para navegação em ambientes escuros;
  • Seletor de Resolução: Permite alternar instantaneamente entre resoluções QVGA (320imes240320 imes 240), VGA (640imes480640 imes 480) e SVGA (800imes600800 imes 600).
Ajuste de parâmetros e qualidade de imagem no portal webVisualização do streaming de vídeo em tempo real com controle de motores

Lição 3 – Controle do Robô via Aplicativo Mobile KUONGSHUN (WIFI Camera Car Code for APP)

Nesta lição avançada, exploramos a integração do Kit Robô Avançado 4WD com Câmera ESP32-CAM AD174 com o aplicativo móvel oficial KUONGSHUN. Ao invés de trafegar comandos baseados em strings de texto através de requisições HTTP individuais, o firmware implementa um servidor de soquetes TCP bruto na porta 100 e uma máquina de estados de alto desempenho capaz de decodificar pacotes binários compactados em tempo real. Isso reduz drasticamente a sobrecarga de cabeçalhos de rede e a latência de controle, proporcionando respostas instantâneas ao joystick virtual com transmissão simultânea de vídeo em alta taxa de quadros.


Download e Instalação do Aplicativo Mobile

O aplicativo oficial está hospedado e disponível para download direto e irrestrito para dispositivos Android:

📱 Download Direto do Aplicativo:

  • Pacote Android (APK): Baixar Aplicativo Oficial Android: KUONGSHUN.apk (Arquivo .apk oficial da Kuongshun, versão estável, tamanho ≈45,7 extMB\approx 45,7\, ext{MB}).
  • Instalação no Android: Transfira ou baixe o arquivo KUONGSHUN.apk diretamente no seu smartphone. Ao abrir o arquivo no gerenciador de arquivos, caso o sistema Android exiba um aviso de segurança sobre aplicativos de fontes desconhecidas, acesse as configurações do instalador e selecione “Permitir desta fonte”. Durante a inicialização, conceda integralmente as permissões de Localização (Location) e Dispositivos Próximos (Nearby Devices), essenciais para que o sistema operacional permita a varredura e conexão com pontos de acesso locais.
  • Dispositivos Apple iOS: No iPhone ou iPad, acesse a App Store, pesquise pelo termo kuongshun e realize a instalação gratuita do aplicativo oficial do fabricante.

Arquitetura de Comunicação e Protocolo de Pacotes Binários

A comunicação entre o smartphone e o ESP32-CAM ocorre sobre um fluxo contínuo de bytes TCP bidirecional na porta 100. Para garantir que nenhum ruído elétrico ou fragmentação de pacotes de rede provoque movimentos erráticos no chassi, o firmware implementa um protocolo estruturado com delimitadores fixos de sincronismo e identificadores de dispositivo.

Cada pacote de comando emitido pelo aplicativo possui a seguinte estrutura binária padronizada:

Byte do PacoteNome do CampoValor HexadecimalFunção Técnica no Protocolo
Byte 0Header 10xFFPrimeiro byte de sincronismo obrigatório da trama (Sync Byte 1)
Byte 1Header 20x55Segundo byte de sincronismo obrigatório da trama (Sync Byte 2)
Byte 2Data LengthVariávelComprimento em bytes dos dados que compõem o corpo da mensagem
Bytes 3 a 9Header Reservado0x00 ...Parâmetros de contexto e flags de roteamento interno
Byte 10Device ID0x0C / 0x05 / 0x0DIdentificador do subsistema acionado (Motores, LED Flash ou Velocidade)
Byte 11Sub-comando0x00Tipo de operação (escrita direta de registrador)
Byte 12Command Value0x00 ... 0xFFValor do comando (código da direção, nível de brilho ou valor de PWM)

Os identificadores de subsistema (Device ID) aceitos pelo decodificador são:

  • 0x0C (Controle dos Motores de Tração):
    • Valor 0x01: Movimento para Frente (Forward) o o WheelAct(speed, speed, HIGH, LOW, HIGH, LOW);
    • Valor 0x02: Marcha a Ré (Backward) o o WheelAct(speed, speed, LOW, HIGH, LOW, HIGH);
    • Valor 0x03: Giro à Esquerda (Turn Left) o o WheelAct(speed, speed, HIGH, LOW, LOW, HIGH);
    • Valor 0x04: Giro à Direita (Turn Right) o o WheelAct(speed, speed, LOW, HIGH, HIGH, LOW);
    • Valor 0x00: Parada Imediata (Stop) o o WheelAct(0, 0, LOW, LOW, LOW, LOW).
  • 0x05 (Farol Flash LED):
    • Valor 0 ... 255: Define o duty cycle no canal PWM do GPIO 4. Valores inferiores a 50 são automaticamente forçados para zero para poupar bateria e evitar aquecimento desnecessário.
  • 0x0D (Ajuste Global de Velocidade):
    • Valor 0 ... 255: Atualiza a variável global speed, determinando a potência com que os comandos direcionais serão executados.

Temporizador de Segurança (Watchdog de Conexão)

Se o usuário afastar-se do robô e o sinal Wi-Fi for interrompido enquanto o botão de avanço estiver acionado, o robô poderia continuar em movimento até colidir. Para prevenir acidentes, o firmware integra um temporizador de inatividade de 3 segundos (timeoutDuration = 3000). Se nenhum pacote válido for recebido dentro dessa janela temporal ou se a estação cliente desconectar-se do SoftAP, a função de segurança desativa imediatamente os motores através da chamada WheelAct(0, 0, LOW, LOW, LOW, LOW) e envia a trama de parada de emergência Stop[17].


Código-Fonte Completo do Projeto APP (ESP32CAM_L298N_APP.ino)

📦 Bibliotecas desta lição:

  • WiFi.h, esp_camera.h, soc/soc.h, soc/rtc_cntl_reg.h — todas integradas nativamente ao pacote de placas ESP32 versão 2.0.12.
  • Os arquivos auxiliares CameraWebServer.cpp e app_httpd.cpp são os mesmos da Lição 2, adaptados com as rotas de suporte à câmera do aplicativo.
// ============================================================================
// Projeto 3: Servidor TCP e Controle via Aplicativo (ESP32CAM_L298N_APP.ino)
// Fabricante: Kuongshun Electronic | Adaptado para RoboBuilders
// Placa: ESP32-CAM | Câmera OV2640 | Driver L298N | App KUONGSHUN
// ============================================================================

#include <WiFi.h>              // Suporte a redes Wi-Fi e pilha TCP/IP
#include "esp_camera.h"        // Driver de controle da câmera OV2640
#include "soc/soc.h"           // Definições de registradores do ESP32
#include "soc/rtc_cntl_reg.h"  // Desativação do brownout reset

// Instancia o servidor de soquete TCP escutando conexões na porta 100
WiFiServer server(100);

// Pacote binário pré-formatado de 17 bytes para comando de parada de emergência
byte Stop[17] = {0xff, 0x55, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00};

// Variáveis globais do analisador sintático de pacotes (parser)
char buffer[52];               // Buffer de armazenamento temporário da trama
byte RX_package[17] = {0};     // Pacote de recepção descompactado
byte dataLen, index_a = 0;     // Indicador de tamanho de dados e ponteiro de índice
unsigned char prevc = 0;       // Armazena o byte anterior para detectar o cabeçalho 0xFF 0x55
int dataIndex = 0;             // Índice do registrador de dados
int LED_mode = 0, LED_val = 0; // Modo e intensidade de brilho do LED Flash
int speed = 225;               // Velocidade PWM padrão de inicialização (faixa de 0 a 255)
String sendBuff;               // Buffer de transmissão serial/TCP
String Version = "Firmware Version is 0.12.21"; // Versão do firmware embarcado
bool ED_client = true;         // Flag de controle de desconexão de cliente
bool WA_en = false;            // Flag de habilitação de processamento
bool isStart = false;          // Sinalizador de detecção de início válido de pacote

#define gpLED  4               // Pino do LED flash branco de alta intensidade

// Declaração da rotina de inicialização de câmera e rede SoftAP
void CameraWebServer_init();

// Mapeamento dos pinos do L298N compartilhados com o módulo Web
extern int gpLb = 14; // Entrada IN3: Ré direita
extern int gpLf = 13; // Entrada IN4: Frente direita
extern int gpRb = 33; // Entrada IN1: Ré esquerda
extern int gpRf = 15; // Entrada IN2: Frente esquerda
extern int gpLed = 4; // Pino do LED Flash
extern int ENR = 2;   // PWM de velocidade direita
extern int ENL = 12;  // PWM de velocidade esquerda

bool st = false;
unsigned long lastDataTimes = 0;

// Sub-rotina de acionamento das pontes H e modulação PWM nos motores
void WheelAct(int speed_R, int speed_L, int nLf, int nLb, int nRf, int nRb) {
  ledcWrite(ENR, speed_R); // Atualiza duty cycle no canal PWM direito
  ledcWrite(ENL, speed_L); // Atualiza duty cycle no canal PWM esquerdo
  digitalWrite(gpLf, nLf); // Define nível lógico no avanço esquerdo
  digitalWrite(gpLb, nLb); // Define nível lógico no recuo esquerdo
  digitalWrite(gpRf, nRf); // Define nível lógico no avanço direito
  digitalWrite(gpRb, nRb); // Define nível lógico no recuo direito
}

// Configuração dos pinos dos motores e canais de hardware LEDC
void initMotors() {
  pinMode(gpLb, OUTPUT);
  pinMode(gpLf, OUTPUT);
  pinMode(gpRb, OUTPUT);
  pinMode(gpRf, OUTPUT);
  pinMode(gpLed, OUTPUT);
  pinMode(ENR, OUTPUT);
  pinMode(ENL, OUTPUT);

  // Configura canais LEDC 2 e 12 a 5 kHz e 8 bits de resolução
  ledcSetup(2, 5000, 8);
  ledcSetup(12, 5000, 8);
  ledcAttachPin(ENR, 2);
  ledcAttachPin(ENL, 12);
  ledcWrite(ENR, 0); // Inicia parado
  ledcWrite(ENL, 0);
  
  digitalWrite(gpLf, LOW);
  digitalWrite(gpRb, LOW);
  digitalWrite(gpRf, LOW);
  digitalWrite(gpLb, LOW);
}

// Funções de acesso ao buffer interno de telemetria
unsigned char readBuffer(int index_r) {
  return buffer[index_r]; 
}

void writeBuffer(int index_w, unsigned char c) {
  buffer[index_w] = c;
}

// Decodificador de comandos do aplicativo mobile
void parseData() { 
  isStart = false;            // Reseta a flag de busca de pacote
  int device = readBuffer(10);// Byte 10 identifica o subsistema
  int val    = readBuffer(12);// Byte 12 carrega o parâmetro de comando
  
  switch (device) {
    // Caso 0x0C: Comandos direcionais de locomoção
    case 0x0C: {   
      switch (val) {
        case 0x01: // Frente (Forward)
          WheelAct(speed, speed, HIGH, LOW, HIGH, LOW);
          break;
        case 0x02: // Ré (Backward)
          WheelAct(speed, speed, LOW, HIGH, LOW, HIGH);
          break;
        case 0x03: // Giro à Esquerda (Turn Left)
          WheelAct(speed, speed, HIGH, LOW, LOW, HIGH);
          break;
        case 0x04: // Giro à Direita (Turn Right)
          WheelAct(speed, speed, LOW, HIGH, HIGH, LOW);
          break;
        case 0x00: // Parada (Stop)
          WheelAct(0, 0, LOW, LOW, LOW, LOW);
          break;
        default:
          break;
      }
    } break;
    
    // Caso 0x05: Ajuste de luminosidade do Farol Flash
    case 0x05: {    
      if (val < 50) val = 0; // Limiar mínimo de corte para evitar brilho residual
      ledcWrite(7, val);     // Aplica duty cycle no GPIO 4
      delay(5);
    } break;
    
    // Caso 0x0D: Atualização da velocidade global
    case 0x0D: {
      speed = val;           // Atualiza a potência dos motores
    } break;
  }   
}

void setup() {
  // Desativa o circuito detector de brownout
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  Serial.begin(115200);
  Serial.setDebugOutput(true);

  // Inicializa o servidor web de vídeo e o Ponto de Acesso Wi-Fi KUONGSHUN-AD174
  CameraWebServer_init();
  
  // Abre o servidor TCP de comando na porta 100
  server.begin();
  delay(100);

  // Inicializa o hardware dos motores e configura o canal PWM 7 no LED Flash
  initMotors();
  ledcSetup(7, 5000, 8);
  ledcAttachPin(gpLed, 7);
  
  // Pisca o LED Flash 5 vezes confirmando prontidão de rede
  for (int i = 0; i < 5; i++) {
    ledcWrite(7, 20);
    delay(50);
    ledcWrite(7, 0);
    delay(50);
  }
}

// Sub-rotina de recepção, sincronismo e tratamento de pacotes TCP
void RXpack_func() {
  WiFiClient client = server.available(); // Verifica se há novo cliente conectado
  
  if (client) {
    WA_en = true;
    ED_client = true;
    unsigned long previousMillis = millis();     // Registra o tempo da conexão
    const unsigned long timeoutDuration = 3000;  // Watchdog de 3000 ms (3 segundos)
    Serial.println("[Cliente Conectado na Porta 100]");
    
    while (client.connected()) {
      // Interrompe caso o tempo de inatividade exceda 3 segundos com flag st ativa
      if ((millis() - previousMillis) > timeoutDuration && client.available() == 0 && st == true) {
        break;
      } 
      
      // Lê dados disponíveis no canal TCP
      if (client.available()) {
        previousMillis = millis(); // Reinicia o temporizador do watchdog
        unsigned char c = client.read() & 0xff;
        Serial.write(c);

        st = false;
        if (c == 200) st = true;

        // Máquina de estados: detecta o delimitador 0xFF seguido de 0x55
        if (c == 0x55 && isStart == false) {
          if (prevc == 0xff) {
            index_a = 1;
            isStart = true; // Início de pacote válido confirmado
          }
        } else {
          prevc = c;
          if (isStart) {
            if (index_a == 2) {
              dataLen = c; // Armazena o comprimento dos dados
            } else if (index_a > 2) {
              dataLen--;
            }
            writeBuffer(index_a, c); // Grava byte no buffer de comando
          }
        }
        
        index_a++;
        if (index_a > 120) { // Proteção contra overflow de buffer
          index_a = 0; 
          isStart = false;
        }
        
        // Quando a totalidade do pacote é recebida, dispara o decodificador
        if (isStart && dataLen == 0 && index_a > 3) { 
          isStart = false;
          parseData(); // Interpreta e executa o comando nos motores
          index_a = 0;
        }
      } else if ((millis() - previousMillis) > timeoutDuration && Serial.available() == 0 && st == true) {
        // Dispara parada de emergência por perda de telemetria
        WheelAct(0, 0, LOW, LOW, LOW, LOW);
      }   

      // Encaminha dados recebidos pela porta serial de volta ao cliente TCP
      if (Serial.available()) {
        char c = Serial.read();
        sendBuff += c;
        client.print(sendBuff);
        Serial.print(sendBuff);
        sendBuff = "";
      }
      
      // Monitora periodicamente a quantidade de estações conectadas ao SoftAP
      static unsigned long Test_time = 0;
      if (millis() - Test_time > 1000) {
        Test_time = millis();
        if (0 == (WiFi.softAPgetStationNum())) {
          Serial.write(Stop, 17);
          break; // Nenhum dispositivo associado ao Wi-Fi; encerra
        }
      }
    }
    
    // Finaliza a conexão do cliente e imobiliza o robô
    Serial.write(Stop, 17);
    client.stop();
    Serial.println("[Cliente Desconectado]");
  } else {
    // Se o cliente foi perdido, garante parada imediata dos motores
    if (ED_client == true) {
      ED_client = false;
      Serial.write(Stop, 17);
      WheelAct(0, 0, LOW, LOW, LOW, LOW);
    }
  }
}

void loop() {
  // Executa continuamente a rotina de recepção de pacotes na porta 100
  RXpack_func();
}

Guia de Operação e Pareamento com o Aplicativo Mobile

Para operar o robô através do smartphone ou tablet utilizando o aplicativo KUONGSHUN, siga os passos ilustrados:

  1. Gravação e Inicialização: Grave o firmware ESP32CAM_L298N_APP na placa ESP32-CAM. Desconecte o cabo USB e ligue as baterias 18650 na chave geral;
  2. Conexão à Rede Wi-Fi: No smartphone, abra as configurações de Wi-Fi, conecte-se à rede KUONGSHUN-AD174 com a senha 12345678 e confirme para manter a conexão mesmo sem internet;
Instalação do APK KUONGSHUN e concessão de permissões de redeConexão ao hotspot WiFi KUONGSHUN-AD174 no Android
  1. Abertura do Aplicativo: Abra o aplicativo KUONGSHUN instalado no dispositivo. Na tela inicial, selecione o idioma desejado (caso prefira, mantenha em inglês);
Tela inicial do aplicativo KUONGSHUN e seleção de idiomaSeleção do modelo de carro ESP32-CAM Two-wheel Drive
  1. Seleção do Modelo: Na galeria de veículos, toque na opção ESP32-CAM Two-wheel Drive (perfil correspondente aos modelos de tração diferencial com câmera da Kuongshun);
  2. Conexão TCP e Streaming: No canto superior direito da tela de pilotagem, toque no ícone de conexão (símbolo de plugue/antena). O aplicativo abrirá o soquete TCP na porta 100 e requisitará o stream de vídeo. A mensagem Connected Successfully surgirá na tela, exibindo imediatamente o vídeo ao vivo capturado pela câmera OV2640;
Tela de controle com streaming de vídeo e joystick virtualOperação do robô via botões direcionais no aplicativo mobile
  1. Pilotagem em Tempo Real:
    • Teclas Direcionais (D-Pad Virtual): Pressione e segure o botão de seta para frente, ré, esquerda ou direita. O botão se iluminará no app e o robô executará o movimento correspondente. Ao retirar o dedo da tela, o botão se apaga e os motores são imobilizados instantaneamente;
    • Controles de Vídeo: O botão Play inicia a renderização do vídeo, Pause congela o quadro e o botão de fechar desativa a tela de visualização;
    • Slider de Brilho do Farol: Deslize a barra para graduar a intensidade do LED flash no pino GPIO 4;
    • Slider de Velocidade: Ajuste a velocidade angular dos motores entre potência mínima e máxima.

⚠️ Solução para “Connected Fail”: Se ao tocar no ícone de conexão surgir o aviso “Connected Fail”, certifique-se de que o smartphone continua associado à rede Wi-Fi KUONGSHUN-AD174. Alguns sistemas Android desconectam-se automaticamente de redes sem acesso à internet para voltar aos dados móveis; desative os Dados Móveis temporariamente durante os ensaios de laboratório para assegurar tráfego exclusivo pela interface Wi-Fi.

Guia Diagnóstico de Falhas e Solução de Problemas (Troubleshooting)

A operação de sistemas robóticos complexos integrando rádiofrequência, vídeo em alta definição e atuadores indutivos de potência exige uma abordagem sistemática de diagnóstico. A tabela abaixo sintetiza os sintomas mais frequentes observados em bancada, suas causas raízes eletromecânicas e as soluções corretivas imediatas:

Sintoma ObservadoCausa Raiz Mais ProvávelAção Corretiva Recomendada
A rede Wi-Fi KUONGSHUN-AD174 não aparece na busca do smartphone1. Tensão insuficiente nas baterias 18650.
2. Chave geral na posição OFF.
3. Jumper regulador de 5V do L298N desconectado.
4. Mau contato no cabo de alimentação de 5V da placa ESP32.
1. Meça a tensão do pack de baterias com um multímetro; se for inferior a 7,0 extV7,0\, ext{V}, recarregue as duas células 18650 em carregador externo apropriado.
2. Verifique se o LED de energia do driver L298N acende em vermelho ao ligar a chave geral.
3. Certifique-se de que o jumper de 5V atrás do borne do L298N está inserido.
4. Pressione o botão RST da placa base da ESP32-CAM.
A imagem do vídeo aparece de cabeça para baixo ou espelhada horizontalmenteA orientação mecânica do sensor OV2640 varia conforme a revisão de fabricação do módulo (ESP32-CAM-V0.3 vs ESP32-CAM-V2.0).No arquivo CameraWebServer.cpp, localize as instruções de orientação óptica do sensor (s->set_vflip e s->set_hmirror). Se o seu módulo for a revisão V0.3, altere a chamada de s->set_vflip(s, 1); para s->set_vflip(s, 0);. Para desativar o espelhamento horizontal, altere s->set_hmirror(s, 1); para s->set_hmirror(s, 0); e recarregue o firmware.
O aplicativo mobile KUONGSHUN exibe o erro “Connected Fail”1. O smartphone desconectou do hotspot Wi-Fi do robô devido ao recurso de “troca inteligente para dados móveis”.
2. Permissões de Localização e Dispositivos Próximos negadas no Android.
1. Desative temporariamente os Dados Móveis (4G/5G) no celular durante o teste.
2. Acesse Configurações > Aplicativos > KUONGSHUN > Permissões e conceda permissão irrestrita para Localização e Dispositivos Próximos.
3. Reconecte o Wi-Fi em KUONGSHUN-AD174 e toque novamente no ícone de conexão do aplicativo.
O robô move-se em sentido contrário ao botão pressionado (ex.: avança quando deveria dar ré)Inversão física da fiação dos motores nos bornes de saída OUT1/OUT2 ou OUT3/OUT4 do driver L298N.1. Se apenas um dos lados estiver invertido (fazendo o robô girar em falso em vez de andar em linha reta), inverta fisicamente a posição dos dois fios correspondentes nos bornes OUT do L298N.
2. Alternativamente, ajuste o mapeamento lógico dos pinos gpLf/gpLb ou gpRf/gpRb diretamente no código-fonte.
O robô reinicia espontaneamente ou a conexão Wi-Fi cai assim que os motores aceleramQueda abrupta de tensão no barramento de alimentação (voltage dip) provocada pela alta corrente de partida indutiva dos 4 motores TT, disparando o reset do ESP32.1. Assegure-se de que as baterias 18650 possuem capacidade de corrente adequada e estão com mais de 7,4 extV7,4\, ext{V} sob carga.
2. Confirme que a instrução WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); está presente no início da função setup().
3. Conecte um capacitor eletrolítico de desacoplamento de 470 μextFimes16 extV470\,\mu ext{F} imes 16\, ext{V} diretamente entre os pinos 5V e GND da placa ESP32-CAM para absorver transientes de corrente.
O streaming de vídeo apresenta congelamentos frequentes ou alta latência (atraso)1. Resolução de imagem configurada em nível muito elevado para a banda de rádio local.
2. Conexão do pigtail IPEX da antena externa frouxa ou desconectada.
1. Reduza a resolução de captura para QVGA (320imes240320 imes 240) ou VGA (640imes480640 imes 480) na interface web ou via s->set_framesize(s, FRAMESIZE_QVGA).
2. Verifique o travamento mecânico do conector IPEX miniatura na placa ESP32-CAM e certifique-se de que a antena de 2,4 GHz externa esteja rosqueada com firmeza.
Erro de compilação na Arduino IDE: 'ledcSetup' was not declared in this scopeO pacote de placas ESP32 instalado no Gerenciador de Placas está na série 3.x (onde a API LEDC antiga foi extinta).Acesse Ferramentas > Placa > Gerenciador de Placas, busque por esp32 e faça o downgrade obrigatório para a versão oficial pinada 2.0.12, ou execute o instalador offline esp32_package_2.0.12_arduinome.exe fornecido no kit.

Diagnóstico Físico de Revisões da Câmera ESP32-CAM (V0.3 vs V2.0)

Durante o ciclo de vida do kit AD174, a Kuongshun adotou duas revisões principais do circuito impresso da placa controladora ESP32-CAM:

Comparativo de hardware – Placas ESP32-CAM revisão V0.3 e V2.0Ajuste de registradores de imagem e orientação de câmera no código
  • Revisão ESP32-CAM-V0.3: Utiliza montagem de sensor invertida mecanicamente em 180∘180^{\circ}. Para essa revisão, o arquivo CameraWebServer.cpp deve manter s->set_vflip(s, 0); para que o teto da sala não apareça na parte inferior da tela.
  • Revisão ESP32-CAM-V2.0: Possui o sensor soldado com orientação física direta. Requer a instrução s->set_vflip(s, 1); ativada por software para compensação de perspectiva da torre acrílica do chassi.

Ajuste de Resolução e Latência de Vídeo

Para aplicações que priorizem a taxa de atualização contínua de quadros por segundo (FPS) sobre a nitidez estática, o projetista pode fixar a resolução diretamente no momento da inicialização do sensor no arquivo CameraWebServer.cpp:

// Opção 1: Resolução QVGA (320x240 pixels) - Recomendada para pilotagem rápida de baixa latência
s->set_framesize(s, FRAMESIZE_QVGA); // ~25 a 30 FPS estáveis

// Opção 2: Resolução VGA (640x480 pixels) - Equilíbrio ótimo entre definição e taxa de atualização
// s->set_framesize(s, FRAMESIZE_VGA);  // ~15 a 20 FPS

// Opção 3: Resolução SVGA (800x600 pixels) - Alta nitidez, recomendada para inspeção estática detalhada
// s->set_framesize(s, FRAMESIZE_SVGA); // ~8 a 12 FPS

💡 Dica de engenharia: Quanto maior a resolução configurada, maior é o volume de bytes que o encoder JPEG precisa transferir pela memória PSRAM e pelo buffer do socket TCP. Em ambientes com interferência severa de outras redes Wi-Fi na faixa de 2,4 GHz, a resolução QVGA garante resposta imediata aos comandos do D-pad virtual, evitando atrasos que poderiam causar colisões do robô.

Solução de problemas

Olá! Sou o assistente técnico da RoboBuilders. Descreva seu problema com o Kit Robô Avançado 4wd Camera Tutoriais Esp32 Wifi App RB2056 AD174 – 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.