Kit Robô Avançado 4WD Com Câmera AD176 - Curso Completo

Introdução
Este curso apresenta o Kit Robô Avançado 4WD Com Câmera AD176, um robô omnidirecional de quatro rodas Mecanum com ESP32-CAM e sensor de imagem OV2640, Arduino UNO com placa de expansão L293D e registrador 74HC595, ultrassom HC-SR04, seguidor de linha de 3 canais IR e servo pan-tilt SG90 da câmera, com vídeo MJPEG — motion JPEG — via WiFi em modo AP — access point — e comando por UART — universal asynchronous receiver-transmitter — a 115200 bps entre as duas controladoras.
É um material educacional para quem está começando em robótica móvel, sistemas embarcados e redes WiFi embarcadas: a sequência parte da montagem mecânica e da preparação do ambiente, passa por ensaios isolados de tração, servo, ultrassom e linha, e chega aos firmwares integrados Web e APP com quatro modos (livre, desvio, seguimento e linha), com o que você deve ver em cada teste. Ao final, o leitor terá o robô montado, calibrado, transmitindo vídeo em 192.168.4.1 e dirigível pelo navegador e pelo aplicativo.
O que você vai aprender:
- Montar o chassi 4WD Mecanum e o pan-tilt com orientação correta dos roletes
- Preparar Arduino IDE, núcleo ESP32 2.0.12, driver CH340 e biblioteca Servo
- Validar tração omnidirecional, servo SG90, HC-SR04 e seguidor de 3 canais
- Operar o modo Web com MJPEG e comandos UART de 4 bytes
- Operar o modo APP com protocolo em quadros e streaming dedicado
- Diagnosticar WiFi, upload, alimentação 18650 e calibração de pista
Material utilizado: Kit Robô Avançado 4WD Com Câmera AD176 disponível na loja RoboBuilders em https://robobuilders.com.br.
Visão Geral do Kit e Arquitetura de Hardware
O AD176 combina dois cérebros: o UNO executa tração, servo, ultrassom e linha em tempo real, enquanto a ESP32-CAM executa câmera, rede AP e ponte serial para a web e o aplicativo. O barramento entre elas é uma UART cruzada TX/RX a 115200 bps, desconectada fisicamente durante cada upload porque os mesmos pinos servem ao conversor USB do PC. A energia vem de duas células 18650 em série (~7,4 V nominal) com chave liga/desliga, regulada na expansão para 5 V da lógica e dos servos e para as pontes dos motores. As rodas Mecanum possuem roletes a em torno do cubo. Cada roda gera forca perpendicular ao eixo do rolete, decomponivel em componentes longitudinal e lateral . Com quatro rodas independentes em configuracao X, a soma vetorial permite translacao omnidirecional sem mudar a orientacao do chassi. O principio formal da cinematica direta do 4WD Mecanum, com semi-distancias e do centro, raio e velocidades angulares , e:
onde e a velocidade longitudinal, a lateral e a taxa de guinada. A decomposicao por rolete explica os codigos decimais da tabela do fabricante: cada byte de 8 bits mapeia os 8 terminais de ponte H dos quatro motores via 74HC595, de modo que frentes paralelas somam (marcha 163/92) e oposicoes simetricas somam (translacao 106/149), enquanto diagonais produzem resultante a (34/129/72/20) e giros puros cancelam translacao e somam momento (83/172). A velocidade linear de cada roda segue , e a forca de tracao disponivel e limitada pelo atrito , por isso piso liso reduz derrapagem dos roletes e melhora a lateralidade. O driver usa dois canais PWM ( e ) para energia e o registrador de deslocamento para direcao, separando potencia e logica como em toda ponte H dupla.
O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.


Inventário do kit
- Chassi acrílico em dois andares com furação Mecanum e suporte do pan-tilt — base mecânica que separa potência embaixo e sensores em cima, reduzindo interferência e facilitando o acesso à chave e às baterias
- 4 rodas Mecanum de 60 mm com roletes a 45 graus (2 espelhadas tipo A e 2 tipo B) — conjunto omnidirecional cuja orientação em X determina as resultantes laterais e diagonais da tabela de códigos
- 4 motores DC com redução e acoplamentos — atuadores de tração independentes comandados em direção pelo 74HC595 e em energia pelo PWM duplo
- Placa Arduino UNO compatível com USB Tipo-C e CH340 — controladora de tempo real da tração, servo, ultrassom e linha
- Placa de expansão L293D para UNO com soquetes de ponte H — estágio de potência dos quatro motores com bornes, trilhas de corrente e conector de baterias com chave
- Módulo ESP32-CAM com câmera OV2640 e LED flash no GPIO 4 — subsistema de visão e rede AP que faz streaming MJPEG e ponte UART com o UNO
- Servo SG90 para pan-tilt da câmera com braço e parafusos — inclinação vertical da imagem comandada por PPM de 20 ms com centro em 90 graus
- Sensor ultrassônico HC-SR04 com gatilho e eco — telemetria de distância por tempo de voo para desvio e seguimento
- Módulo seguidor de linha de 3 canais IR (A0/A1/A2) — leitura reflexiva da pista com limiar calibrável entre 400 e 500 contagens
- Cabo serial UART entre UNO e ESP32-CAM (RX/TX/GND) — enlace de comandos removível obrigatoriamente durante uploads
- 2 suportes e fiação para células 18650 com chave — barramento de ~7,4 V que alimenta motores, lógica e câmera simultaneamente
- Pacote de parafusos, porcas, espaçadores de latão, chave e cabo USB Tipo-C de dados — fixação, empilhamento dos andares e conexão com o PC para gravação
- Pista de linha preta para ensaios e guia impresso V2.0 — referência de calibração do seguidor e roteiro dos projetos 1 a 6.2
- Aplicativo KUONGSHUN em APK Android (e variante iOS na loja) — controle remoto com vídeo, D-pad omnidirecional, sliders de servo, farol e velocidade
Somatória: 14 grupos, totalizando dezenas de peças que compõem um robô completo de dois cérebros (UNO + ESP32-CAM), tração omnidirecional de 4 motores, visão WiFi, 2 sensores de navegação e pan-tilt ativo.
Mapa de pinos e protocolos (consolidado dos .ino reais)
| Subsistema | Pino UNO / ESP32-CAM | Direção | Protocolo | Observação |
|---|---|---|---|---|
| PWM motores | D5, D6 (UNO) | Saída | PWM ~980 Hz | Energia das pontes; analogWrite(0-255) |
| Expansor direção | D2 SHCP, D4 STCP, D7 EN, D8 DATA | Saída | Shift serial MSBFIRST | Byte de 8 bits define os 4 motores |
| Servo pan-tilt | D9 (UNO) | Saída | PPM 20 ms | Biblioteca Servo; centro 90 graus |
| Ultrassom | D12 TRIG saída, D13 ECHO entrada | Misto | Pulso + pulseIn/58 | Limiares 15/25/50 cm |
| Linha IR | A0/A1/A2 (A2 esquerda, A1 centro, A0 direita no All) | Entrada | ADC 10 bits | Limiar 400-500 |
| Enlace UNO<>CAM | TX/RX cruzados 115200 8N1 | Misto | UART | Desconectar nos uploads |
| ESP32-CAM UART2 | RXD2 GPIO14, TXD2 GPIO13 | Misto | UART2 115200 | Ponte com o UNO |
| Câmera OV2640 | Y2-Y9, XCLK0, PCLK22, VSYNC25, HREF23, SCCB 26/27, PWDN32 | Interna | DVP+SCCB | SVGA qualidade 10-12 |
| Flash | GPIO4 (LEDC canal 7, 5 kHz, 8 bits) | Saída | LEDC | Pisca 5x no boot; slider no app |
| Rede | AP KUONGSHUN-AD176 / 12345678 canal 5 | RF | WiFi 802.11 + HTTP/MJPEG | Portal em 192.168.4.1; servidor TCP 100 no APP |
Montagem Mecânica (Assembly Guide)
Montagem em 8 passos na ordem do fabricante, com verificação após cada etapa. As rodas Mecanum possuem roletes a em torno do cubo. Cada roda gera forca perpendicular ao eixo do rolete, decomponivel em componentes longitudinal e lateral . Com quatro rodas independentes em configuracao X, a soma vetorial permite translacao omnidirecional sem mudar a orientacao do chassi. O principio formal da cinematica direta do 4WD Mecanum, com semi-distancias e do centro, raio e velocidades angulares , e: A regra de ouro: roletes formam um X visto de cima — dianteira esquerda e traseira direita com uma diagonal, dianteira direita e traseira esquerda com a outra. Errar o X inverte a lateralidade e nenhum software corrige.
Passo 1 — Chassi inferior, motores e rodas Mecanum
Fixe os 4 motores com suportes, instale as rodas respeitando o X Mecanum e confira giro livre. Validação: empurrando desligado, os roletes deslizam a 45 graus. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 2 — Expansão L293D, baterias e fiação de potência
Encaixe a expansão no UNO, ligue os 8 fios dos motores nos bornes, o pack 18650 na entrada com chave OFF e confira polaridade. Validação: chave ON acende LEDs da expansão sem fumaça nem aquecimento. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 3 — Andar superior, HC-SR04 e seguidor de linha
Fixe espaçadores, aparafuse o andar superior, monte o HC-SR04 à frente e o trio IR abaixo voltado ao solo. Validação: sensores firmes, sem encostar nas rodas. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 4 — Pan-tilt com SG90 e ESP32-CAM
Centralize o servo em 90 graus antes de aparafusar o braço, fixe a ESP32-CAM no suporte e aponte a lente à frente. Validação: câmera nivelada, curso livre do tilt. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 5 — Enlace UART UNO<>CAM e roteamento de cabos
Ligue TX>RX cruzados mais GND, organize com abraçadeiras longe das rodas. Validação: conector firme porém desplugável para os uploads. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 6 — Checklist pré-energia
Confira X das rodas, polaridade 18650, UART, parafusos e lente sem película. Validação: checklist completo antes do primeiro ON. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 7 — Primeira energização sem firmware de tração
Ligue a chave em área livre e observe LEDs das duas placas. Validação: sem movimento brusco nem cheiro; desligue se o servo vibrar. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
Passo 8 — Pista de testes e área livre
Delimite 2 m x 2 m livres e estenda a pista de linha. Validação: espaço para os 11 estados da Lição 1 sem colisões. Teoria de apoio: O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes.

💡 Dica: fotografe cada passo; a foto resolve 80% dos diagnósticos de fiação.
⚠️ Atenção: nunca ligue a chave com o cabo USB conectado ao PC e o robô sobre a bancada — a primeira tração pode derrubá-lo.
⛔ Perigo: 18650 invertida ou danificada pode incendiar. Confira polaridade, use células íntegras e carregue com a chave OFF.
Preparação do Ambiente (versões pinadas)
Cadeia exata do fabricante: Arduino IDE (versão estável atual) + driver CH340 + pacote ESP32 2.0.12 via esp32_package_2.0.12_arduinome.exe + biblioteca Servo + APK KUONGSHUN.apk. O aviso do PDF é explícito: não usar núcleo 3.x, pois a API de câmera/LEDC mudou e os exemplos falham. A ESP32-CAM opera em modo AP — access point — criando a rede KUONGSHUN-AD176 com senha 12345678 e IP fixo . O video usa MJPEG sobre HTTP — motion JPEG over hypertext transfer protocol — com multipart x-mixed-replace, onde cada frame JPEG e delimitado por boundary e empurrado em chunked encoding. A taxa util aproximada e:
onde e o bitrate, o framerate, o tamanho medio do JPEG e o tempo de compressao. SVGA () a qualidade – equilibra nitidez e latencia; UXGA trava o stream por esgotar PSRAM e banda. O enlace de comando UNO ESP32-CAM usa UART a (), com pacotes de bytes (AB modelo valor FF) no modo Web e quadros FF 55 ... no modo APP, ambos com timeout de . A potencia de TX em maximiza alcance indoor a custa de consumo, por isso video so e estavel com bateria cheia. O canal fixo reduz interferencia com roteadores domesticos.
Etapa 1 — Arduino IDE + driver CH340
Instale a IDE, conecte o UNO via cabo Tipo-C de dados e instale o CH340 das pastas Windows/Mac. Validação: menu Ferramentas > Porta lista COMxx além do COM1.

Etapa 2 — Núcleo ESP32 2.0.12
Execute o instalador offline do fabricante e selecione ESP32 Dev Module. Validação: exemplos ESP32 aparecem e o CameraWebServer compila sem erro de ledcSetup.

Etapa 3 — Biblioteca Servo
Adicione o Servo.zip via Sketch > Incluir Biblioteca > .ZIP. Validação: exemplo Sweep compila para UNO.

Tabela-mestre de bibliotecas do curso
Consolidação única de todas as bibliotecas usadas nos 8 projetos. As duas vias de instalação existem; a via Gerenciador é a recomendada quando disponível, e a via ZIP do fabricante garante a versão testada pelo Kuongshun.
Biblioteca (#include) | Buscar no Gerenciador | Versão usada no curso | Download ZIP (espelho oficial) | Lições |
|---|---|---|---|---|
Servo.h (<Servo.h>) | Servo por Michael Margolis, Arduino | A do Servo.zip da pasta 3. Add library files do fabricante (conferir em library.properties após instalar) | ZIP do fabricante; espelho oficial em arduino/Servo (Code > Download ZIP) | 2, 5.1, 6.1 |
WiFi.h, esp_camera.h, esp_system.h, soc/soc.h, soc/rtc_cntl_reg.h | Nada a buscar — vêm no núcleo ESP32 | Pacote ESP32 2.0.12 (instalador esp32_package_2.0.12_arduinome.exe do fabricante; não usar núcleo 3.x) | Núcleo via instalador do fabricante | 5.2, 6.2 |
Nenhuma (GPIO/PWM/pulseIn/analogRead nativos) | Nada a instalar | Núcleo Arduino AVR padrão da IDE | — | 1, 3, 4 |
⚠️ Atenção: cada box
> 📦 **Bibliotecas desta lição:**antes dos códigos referencia esta tabela-mestre. Se o erro forNo such file or directoryoudoes not name a type, reinstale pela tabela acima, confira a pastalibraries/Nome/Nome.he reinicie a IDE.
Etapa 4 — APK KUONGSHUN
Copie o APK da pasta 4_Android_Software_Installation_Package ao celular e instale (iOS: buscar kuongshun na App Store). Validação: ícone instalado antes da Lição 6.

Etapa 5 — Ritual de upload (vale para todas as lições)
Desconecte o jumper UART UNO<>CAM, selecione placa e porta corretas, grave, desplugue o USB e só então reconecte o jumper. Validação: mensagem de upload com sucesso na IDE.

⚠️ Atenção: cabo USB só-carga não cria porta COM. Se só aparece COM1, troque o cabo e reinstale o CH340.
Lição 1 — Movimento Automático Omnidirecional (1_Auto_Move)
O UNO comanda a expansão L293D: PWM dita energia e o 74HC595 dita direção dos 4 motores. A sequência de 11 estados (frente, trás, esquerda, direita, 4 diagonais, 2 giros, parada) com 2 s cada demonstra a soma vetorial dos roletes. As rodas Mecanum possuem roletes a em torno do cubo. Cada roda gera forca perpendicular ao eixo do rolete, decomponivel em componentes longitudinal e lateral . Com quatro rodas independentes em configuracao X, a soma vetorial permite translacao omnidirecional sem mudar a orientacao do chassi. O principio formal da cinematica direta do 4WD Mecanum, com semi-distancias e do centro, raio e velocidades angulares , e:
onde e a velocidade longitudinal, a lateral e a taxa de guinada. A decomposicao por rolete explica os codigos decimais da tabela do fabricante: cada byte de 8 bits mapeia os 8 terminais de ponte H dos quatro motores via 74HC595, de modo que frentes paralelas somam (marcha 163/92) e oposicoes simetricas somam (translacao 106/149), enquanto diagonais produzem resultante a (34/129/72/20) e giros puros cancelam translacao e somam momento (83/172). A velocidade linear de cada roda segue , e a forca de tracao disponivel e limitada pelo atrito , por isso piso liso reduz derrapagem dos roletes e melhora a lateralidade. O driver usa dois canais PWM ( e ) para energia e o registrador de deslocamento para direcao, separando potencia e logica como em toda ponte H dupla.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| Chassi 4WD Mecanum | 1 | plataforma omnidirecional |
| UNO + L293D + 74HC595 | 1 | potência e direção |
| 18650 x2 | 2 | energia de tração |
| Cabo Tipo-C dados | 1 | upload |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 1_Auto_Move.ino comentado linha a linha
📦 Bibliotecas desta lição: nenhuma — o código usa GPIO/PWM (
pinMode,digitalWrite,analogWrite,delay) nativos, sem biblioteca externa.
//www.kuongshun.com
// PWM control pin
#define PWM1_PIN 5 // define constante de pino/mapa de hardware
#define PWM2_PIN 6 // define constante de pino/mapa de hardware
// 74HCT595N Chip pins
#define SHCP_PIN 2 // The displacement of the clock // define constante de pino/mapa de hardware
#define EN_PIN 7 // Can make control // define constante de pino/mapa de hardware
#define DATA_PIN 8 // Serial data // define constante de pino/mapa de hardware
#define STCP_PIN 4 // Memory register clock // define constante de pino/mapa de hardware
const int Forward = 163; // forward // executa etapa do firmware do robo
const int Backward = 92; // back // executa etapa do firmware do robo
const int Turn_Left = 106; // left translation // executa etapa do firmware do robo
const int Turn_Right = 149; // Right translation // executa etapa do firmware do robo
const int Top_Left = 34; // Upper left mobile // executa etapa do firmware do robo
const int Bottom_Left = 72; // Lower left mobile // executa etapa do firmware do robo
const int Top_Right = 129; // Upper right mobile // executa etapa do firmware do robo
const int Bottom_Right = 20; // The lower right move // executa etapa do firmware do robo
const int Stop = 0; // stop // executa etapa do firmware do robo
const int Contrarotate = 83; // Counterclockwise rotation // executa etapa do firmware do robo
const int Clockwise = 172; // Rotate clockwise // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
pinMode(SHCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(EN_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(DATA_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(STCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM1_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM2_PIN, OUTPUT); // configura o pino como entrada ou saida digital
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
/* Forward */ // executa etapa do firmware do robo
Motor(Forward, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Backward */ // executa etapa do firmware do robo
Motor(Backward, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Turn_Left */ // executa etapa do firmware do robo
Motor(Turn_Left, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Turn_Right */ // executa etapa do firmware do robo
Motor(Turn_Right, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Top_Left */ // executa etapa do firmware do robo
Motor(Top_Left, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Bottom_Right */ // executa etapa do firmware do robo
Motor(Bottom_Right, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Bottom_Left */ // executa etapa do firmware do robo
Motor(Bottom_Left, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Top_Right */ // executa etapa do firmware do robo
Motor(Top_Right, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Clockwise */ // executa etapa do firmware do robo
Motor(Clockwise, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Contrarotate */ // executa etapa do firmware do robo
Motor(Contrarotate, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
/* Stop */ // executa etapa do firmware do robo
Motor(Stop, 250); // aciona tracao Mecanum no modo/velocidade indicados
delay(2000); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
void Motor(int Dir, int Speed) // aciona tracao Mecanum no modo/velocidade indicados
{ // executa etapa do firmware do robo
digitalWrite(EN_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
analogWrite(PWM1_PIN, Speed); // gera PWM com duty proporcional a velocidade
analogWrite(PWM2_PIN, Speed); // gera PWM com duty proporcional a velocidade
digitalWrite(STCP_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
shiftOut(DATA_PIN, SHCP_PIN, MSBFIRST, Dir); // desloca 8 bits ao 74HC595 controlando os 4 motores
digitalWrite(STCP_PIN, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 2 — Ângulo do Servo Pan-Tilt (2_Servo_Angle)
O SG90 posiciona a câmera; o exemplo varre 0→180→0 para revelar o centro mecânico de 90 graus e permitir calçar o braço corretamente. O servo SG90 e comandado por PPM com periodo de . A largura do pulso codifica o angulo:
onde varia de a e e a largura em milissegundos. A biblioteca Servo.h abstrai o timer em write(graus), com como frente mecanica da camera. O torque exige alimentacao estavel; jitter indica queda de tensao sob carga dos motores. A varredura com passo de do exemplo produz velocidade angular , suave para calibrar o braco do pan-tilt sem forcar engrenagens. O reset ao antes do ajuste mecanico garanteDatum repetivel.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| Servo SG90 no D9 | 1 | tilt da câmera |
| Suporte pan-tilt + ESP32-CAM | 1 | carga do servo |
| UNO + USB | 1 | comando PPM |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 2_Servo_Angle.ino comentado linha a linha
📦 Bibliotecas desta lição:
Servo(#include <Servo.h>, instalada pelo quadro abaixo).
- Via ZIP do fabricante (recomendado): pasta
3. Add library files→Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP…→ selecionar oServo.zip→ reiniciar a IDE.- Via Gerenciador (alternativa):
Sketch > Incluir Biblioteca > Gerenciar Bibliotecas…→ buscarServo(Michael Margolis, Arduino) →Instalar→ reiniciar a IDE.- Conferência:
Arquivo > Exemplos > Servo > Sweepdeve abrir e compilar para Arduino UNO semNo such file or directory. Ver tabela-mestre na Preparação de ambiente.
//www.kuongshun.com
#include <Servo.h> // instalada pelo quadro "Bibliotecas desta lição" (Servo.zip do fabricante)
#define servo_PIN 9 // define constante de pino/mapa de hardware
Servo myservo; // comanda o servo pan-tilt da camera
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
myservo.attach(servo_PIN); // comanda o servo pan-tilt da camera
myservo.write(90); // comanda o servo pan-tilt da camera
delay(1000); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
for(int i=0;i<180;i++){ // laco de varredura incremental do ensaio
myservo.write(i); // comanda o servo pan-tilt da camera
delay(10); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
delay(1000); // aguarda estabilizacao/temporizacao do atuador
for(int i=180;i>0;i--){ // laco de varredura incremental do ensaio
myservo.write(i); // comanda o servo pan-tilt da camera
delay(10); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
delay(1000); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 3 — Sensor Ultrassônico HC-SR04 (3_Ultrasonic)
Telemetria por tempo de voo com saída no Monitor Serial a 9600 bps, base de todos os modos de desvio e seguimento. O HC-SR04 mede distancia por tempo de voo do ultrassom. O gatilho de emite 8 ciclos a ; o eco retorna apos microssegundos de ida e volta. Com :
onde e a distancia ao obstaculo. O divisor usado em pulseIn(ECHO, HIGH)/58.00 deriva de . A zona cega abaixo de e o cone de exigem servo centralizado a nas leituras de desvio, e superficies absorventes inclinadas subestimam . O firmware filtra com delay(10) entre disparos para dissipar ecos multiplos, e os limiares dos modos seguimento e desvio derivam diretamente dessa resolucao centimetrica.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| HC-SR04 (D12/D13) | 1 | distância em cm |
| UNO + USB | 1 | leitura serial |
| Anteparo de teste | 1 | alvo a 10-100 cm |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 3_Ultrasonic.ino comentado linha a linha
📦 Bibliotecas desta lição: nenhuma — o código usa
pulseIn()nativo, sem biblioteca externa.
//www.kuongshun.com
float checkdistance() // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
digitalWrite(12, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(2); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(12, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(10); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(12, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
float distance = pulseIn(13, HIGH) / 58.00; // mede largura do eco ultrassonico para calcular distancia
delay(10); // aguarda estabilizacao/temporizacao do atuador
return distance; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
void Ultrasonic_Sensor_Module() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
int Distance = 0; // executa etapa do firmware do robo
Distance = checkdistance(); // executa etapa do firmware do robo
Serial.print("Distance:"); // envia telemetria ao Monitor Serial
Serial.print(Distance); // envia telemetria ao Monitor Serial
Serial.println("CM"); // envia telemetria ao Monitor Serial
delay(100); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Serial.begin(9600); // inicializa UART para debug e enlace com ESP32-CAM
pinMode(12, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(13, INPUT); // configura o pino como entrada ou saida digital
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Ultrasonic_Sensor_Module(); // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 4 — Seguidor de Linha com 3 IR (4_Line_Tracing)
Máquina de estados sobre o trio IR com 7 ramos ativos: cruzeiro, correções suaves e fortes e recuperação total. O seguidor de linha usa tres sensores reflexivos IR com comparacao analogica. Cada canal retorna via ADC de 10 bits, onde preto absorve IR (valor baixo) e branco reflete (valor alto). O limiar particiona o espaco de observacao, e a maquina de estados mapeia as combinacoes em correcoes diferenciais. A lei de controle e proporcional por zona: erro lateral estimado gera correcao de guinada implementada como giros com PWM contra cruzeiro . A tensao lida em cada canal e:
onde e a contagem e a referencia do UNO. Calibracao com Serial.println dos tres canais sobre preto e branco define o limiar real da pista ( a conforme o lote), pois luz ambiente desloca o ponto otimo. Faixa estreita demais causa oscilacao; larga demais corta curvas. A geometria dos tres pontos a frente do eixo motor cria antecipacao natural da curva, equivalente a acao derivativa mecanica.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| Trio IR A0/A1/A2 | 1 | leitura da pista |
| Pista de linha | 1 | circuito de teste |
| UNO + L293D | 1 | correção diferencial |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 4_Line_Tracing.ino comentado linha a linha
📦 Bibliotecas desta lição: nenhuma — o código usa
analogRead()/digitalWrite()nativos do núcleo AVR, sem biblioteca externa.
//www.kuongshun.com
// PWM control pin
#define PWM1_PIN 5 // define constante de pino/mapa de hardware
#define PWM2_PIN 6 // define constante de pino/mapa de hardware
// 74HCT595N chip pin
#define SHCP_PIN 2 // The displacement of the clock // define constante de pino/mapa de hardware
#define EN_PIN 7 // Can make control // define constante de pino/mapa de hardware
#define DATA_PIN 8 // Serial data // define constante de pino/mapa de hardware
#define STCP_PIN 4 // Memory register clock // define constante de pino/mapa de hardware
#define LEFT_LINE_TRACJING A0 // define constante de pino/mapa de hardware
#define CENTER_LINE_TRACJING A1 // define constante de pino/mapa de hardware
#define right_LINE_TRACJING A2 // define constante de pino/mapa de hardware
const int Forward = 163; // forward // executa etapa do firmware do robo
const int Backward = 92; // back // executa etapa do firmware do robo
const int Turn_Left = 106; // left translation // executa etapa do firmware do robo
const int Turn_Right = 149; // Right translation // executa etapa do firmware do robo
const int Top_Left = 34; // Upper left mobile // executa etapa do firmware do robo
const int Bottom_Left = 72; // Lower left mobile // executa etapa do firmware do robo
const int Top_Right = 129; // Upper right mobile // executa etapa do firmware do robo
const int Bottom_Right = 20; // The lower right move // executa etapa do firmware do robo
const int Stop = 0; // stop // executa etapa do firmware do robo
const int Contrarotate = 83; // Counterclockwise rotation // executa etapa do firmware do robo
const int Clockwise = 172; // Rotate clockwise // executa etapa do firmware do robo
int Left_Tra_Value; // executa etapa do firmware do robo
int Center_Tra_Value; // executa etapa do firmware do robo
int Right_Tra_Value; // executa etapa do firmware do robo
int Black_Line = 500;//small is black // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
pinMode(SHCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(EN_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(DATA_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(STCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM1_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM2_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(LEFT_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(CENTER_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(right_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
Serial.begin(9600); // inicializa UART para debug e enlace com ESP32-CAM
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Left_Tra_Value = analogRead(LEFT_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Center_Tra_Value = analogRead(CENTER_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Right_Tra_Value = analogRead(right_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Serial.println("l,c ,r:"); // envia telemetria ao Monitor Serial
Serial.println(analogRead(LEFT_LINE_TRACJING)); // envia telemetria ao Monitor Serial
Serial.println(analogRead(CENTER_LINE_TRACJING)); // envia telemetria ao Monitor Serial
Serial.println(analogRead(right_LINE_TRACJING)); // envia telemetria ao Monitor Serial
if (Left_Tra_Value > Black_Line && Center_Tra_Value <= Black_Line && Right_Tra_Value > Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 180); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 120); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 120); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void Motor(int Dir, int Speed) // aciona tracao Mecanum no modo/velocidade indicados
{ // executa etapa do firmware do robo
digitalWrite(EN_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
analogWrite(PWM1_PIN, Speed); // gera PWM com duty proporcional a velocidade
analogWrite(PWM2_PIN, Speed); // gera PWM com duty proporcional a velocidade
digitalWrite(STCP_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
shiftOut(DATA_PIN, SHCP_PIN, MSBFIRST, Dir); // desloca 8 bits ao 74HC595 controlando os 4 motores
digitalWrite(STCP_PIN, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 5.1 — Multifunção Web lado Arduino (5.1_Arduino_All_Web)
O UNO vira executor serial: pacote de 4 bytes AB modelo valor FF seleciona modo livre/desvio/seguimento/linha, velocidade, servo e farol, com máquinas de desvio por varredura, seguimento por faixas e linha por zonas. O HC-SR04 mede distancia por tempo de voo do ultrassom. O gatilho de emite 8 ciclos a ; o eco retorna apos microssegundos de ida e volta. Com : O seguidor de linha usa tres sensores reflexivos IR com comparacao analogica. Cada canal retorna via ADC de 10 bits, onde preto absorve IR (valor baixo) e branco reflete (valor alto). O limiar particiona o espaco de observacao, e a maquina de estados mapeia as combinacoes em correcoes diferenciais. A lei de controle e proporcional por zona: erro lateral estimado gera correcao de guinada implementada como giros com PWM contra cruzeiro . A tensao lida em cada canal e:
onde e a distancia ao obstaculo. O divisor usado em pulseIn(ECHO, HIGH)/58.00 deriva de . A zona cega abaixo de e o cone de exigem servo centralizado a nas leituras de desvio, e superficies absorventes inclinadas subestimam . O firmware filtra com delay(10) entre disparos para dissipar ecos multiplos, e os limiares dos modos seguimento e desvio derivam diretamente dessa resolucao centimetrica.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| UNO + todos sensores/atuadores | 1 | execução dos 4 modos |
| ESP32-CAM (ponte Web) | 1 | origem dos pacotes UART |
| Baterias 18650 | 2 | autonomia dos modos |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 5.1_Arduino_All_Web.ino comentado linha a linha
📦 Bibliotecas desta lição:
Servo— a mesma da Lição 2, nada a baixar. SeArquivo > Exemplos > Servo > Sweepcompila, siga direto ao código.
//www.kuongshun.com
#include <Servo.h> // instalada pelo quadro "Bibliotecas desta lição" (Servo.zip do fabricante)
#define MOTOR_PIN 9 // define constante de pino/mapa de hardware
#define PWM1_PIN 5 // define constante de pino/mapa de hardware
#define PWM2_PIN 6 // define constante de pino/mapa de hardware
#define SHCP_PIN 2 // The displacement of the clock // define constante de pino/mapa de hardware
#define EN_PIN 7 // Can make control // define constante de pino/mapa de hardware
#define DATA_PIN 8 // Serial data // define constante de pino/mapa de hardware
#define STCP_PIN 4 // Memory register clock // define constante de pino/mapa de hardware
#define Trig_PIN 12 // define constante de pino/mapa de hardware
#define Echo_PIN 13 // define constante de pino/mapa de hardware
#define LEFT_LINE_TRACJING A2 // define constante de pino/mapa de hardware
#define CENTER_LINE_TRACJING A1 // define constante de pino/mapa de hardware
#define right_LINE_TRACJING A0 // define constante de pino/mapa de hardware
Servo MOTORservo; // comanda o servo pan-tilt da camera
const int Forward = 163; // forward // executa etapa do firmware do robo
const int Backward = 92; // back // executa etapa do firmware do robo
const int Turn_Left = 106; // left translation // executa etapa do firmware do robo
const int Turn_Right = 149; // Right translation // executa etapa do firmware do robo
const int Top_Left = 34; // Upper left mobile // executa etapa do firmware do robo
const int Bottom_Left = 72; // Lower left mobile // executa etapa do firmware do robo
const int Top_Right = 129; // Upper right mobile // executa etapa do firmware do robo
const int Bottom_Right = 20; // The lower right move // executa etapa do firmware do robo
const int Stop = 0; // stop // executa etapa do firmware do robo
const int Contrarotate = 83; // Counterclockwise rotation // executa etapa do firmware do robo
const int Clockwise = 172; // Rotate clockwise // executa etapa do firmware do robo
const int Model1 = 25; // model1 // executa etapa do firmware do robo
const int Model2 = 26; // model2 // executa etapa do firmware do robo
const int Model3 = 27; // model3 // executa etapa do firmware do robo
const int Model4 = 28; // model4 // executa etapa do firmware do robo
const int Speed = 29; // executa etapa do firmware do robo
const int Servo = 30; // executa etapa do firmware do robo
const int MotorLeft = 230; // servo turn left // executa etapa do firmware do robo
const int MotorRight = 231; // servo turn right // executa etapa do firmware do robo
int Left_Tra_Value; // executa etapa do firmware do robo
int Center_Tra_Value; // executa etapa do firmware do robo
int Right_Tra_Value; // executa etapa do firmware do robo
int Black_Line = 400; // executa etapa do firmware do robo
int speeds = 250; // executa etapa do firmware do robo
int leftDistance = 0; // executa etapa do firmware do robo
int middleDistance = 0; // executa etapa do firmware do robo
int rightDistance = 0; // executa etapa do firmware do robo
byte RX_package[4] = {0}; // executa etapa do firmware do robo
uint16_t angle = 90; // executa etapa do firmware do robo
byte Model = Stop; // executa etapa do firmware do robo
byte val = 0; // executa etapa do firmware do robo
char model_var = 0; // executa etapa do firmware do robo
int UT_distance = 0; // executa etapa do firmware do robo
int OA_mark=0; // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Serial.setTimeout(10); // executa etapa do firmware do robo
Serial.begin(115200); // inicializa UART para debug e enlace com ESP32-CAM
MOTORservo.attach(MOTOR_PIN); // comanda o servo pan-tilt da camera
pinMode(SHCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(EN_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(DATA_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(STCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM1_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM2_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(Trig_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(Echo_PIN, INPUT); // configura o pino como entrada ou saida digital
pinMode(LEFT_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(CENTER_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(right_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
MOTORservo.write(angle); // comanda o servo pan-tilt da camera
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
RXpack_func(); // executa etapa do firmware do robo
switch (model_var) // seleciona modo/comando recebido via serial/rede
{ // executa etapa do firmware do robo
case 0: // seleciona modo/comando recebido via serial/rede
model1_func(val); // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 1: // seleciona modo/comando recebido via serial/rede
model2_func(); // OA model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 2: // seleciona modo/comando recebido via serial/rede
model3_func(); // follow model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 3: // seleciona modo/comando recebido via serial/rede
model4_func(); // Tracking model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 4: // seleciona modo/comando recebido via serial/rede
Servo_Move(); // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model1_func(byte values) // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
switch (values) // seleciona modo/comando recebido via serial/rede
{ // executa etapa do firmware do robo
case Stop: // seleciona modo/comando recebido via serial/rede
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Forward: // seleciona modo/comando recebido via serial/rede
Motor(Forward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Backward: // seleciona modo/comando recebido via serial/rede
Motor(Backward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Turn_Left: // seleciona modo/comando recebido via serial/rede
Motor(Turn_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Turn_Right: // seleciona modo/comando recebido via serial/rede
Motor(Turn_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Top_Left: // seleciona modo/comando recebido via serial/rede
Motor(Top_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Top_Right: // seleciona modo/comando recebido via serial/rede
Motor(Top_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Bottom_Left: // seleciona modo/comando recebido via serial/rede
Motor(Bottom_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Bottom_Right: // seleciona modo/comando recebido via serial/rede
Motor(Bottom_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Clockwise: // seleciona modo/comando recebido via serial/rede
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Contrarotate: // seleciona modo/comando recebido via serial/rede
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
default: // executa etapa do firmware do robo
// Serial.println(".");
Model = 0; // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model2_func() // OA // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
while (model_var == 1) { // mantem o modo autonomo ate trocar de modo
RXpack_func(); // executa etapa do firmware do robo
middleDistance = SR04(Trig_PIN, Echo_PIN); // executa etapa do firmware do robo
if (middleDistance <= 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
Motor(Backward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
rightDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
if (rightDistance > 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if(OA_mark==0) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
OA_mark++; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(600); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
leftDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
if (rightDistance > leftDistance) { // decisao condicional do comportamento autonomo
Motor(Backward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
delay(500); // aguarda estabilizacao/temporizacao do atuador
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(500); // aguarda estabilizacao/temporizacao do atuador
OA_mark=0; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (rightDistance < leftDistance) { // decisao condicional do comportamento autonomo
while (leftDistance < 25) { // mantem o modo autonomo ate trocar de modo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
leftDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
OA_mark=0; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
Motor(Forward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model3_func() // follow model // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
MOTORservo.write(90); // comanda o servo pan-tilt da camera
UT_distance = SR04(Trig_PIN, Echo_PIN); // executa etapa do firmware do robo
Serial.println(UT_distance); // envia telemetria ao Monitor Serial
if (UT_distance < 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Backward, speeds-50); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (15 <= UT_distance && UT_distance <= 20) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (20 <= UT_distance && UT_distance <= 25) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (25 <= UT_distance && UT_distance <= 50) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, speeds-30); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model4_func() // tracking model // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
MOTORservo.write(90); // comanda o servo pan-tilt da camera
Left_Tra_Value = analogRead(LEFT_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Center_Tra_Value = analogRead(CENTER_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Right_Tra_Value = analogRead(right_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
if (Left_Tra_Value > Black_Line && Center_Tra_Value <= Black_Line && Right_Tra_Value > Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 180); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 130); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 130); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void Servo_Move() //servo // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
MOTORservo.write(angle); // comanda o servo pan-tilt da camera
if (angle >= 180) angle = 180; // decisao condicional do comportamento autonomo
if (angle <= 1) angle = 1; // decisao condicional do comportamento autonomo
delay(10); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
void Motor(int Dir, int Speed) // motor drive // aciona tracao Mecanum no modo/velocidade indicados
{ // executa etapa do firmware do robo
digitalWrite(EN_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
analogWrite(PWM1_PIN, Speed); // gera PWM com duty proporcional a velocidade
analogWrite(PWM2_PIN, Speed); // gera PWM com duty proporcional a velocidade
digitalWrite(STCP_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
shiftOut(DATA_PIN, SHCP_PIN, MSBFIRST, Dir); // desloca 8 bits ao 74HC595 controlando os 4 motores
digitalWrite(STCP_PIN, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
} // executa etapa do firmware do robo
float SR04(int Trig, int Echo) // ultrasonic measured distance // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
digitalWrite(Trig, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(2); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(Trig, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(10); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(Trig, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
float distance = pulseIn(Echo, HIGH) / 58.00; // mede largura do eco ultrassonico para calcular distancia
delay(10); // aguarda estabilizacao/temporizacao do atuador
return distance; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
void RXpack_func() //Receive data // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
if (Serial.available() > 0) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
delay(1); // delay 1MS // aguarda estabilizacao/temporizacao do atuador
if (Serial.readBytes(RX_package, 4)) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if (RX_package[0] == 0xAB && RX_package[3] == 0xFF) // The header and tail of the packet are verified // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
//Serial.write(RX_package, 4);
Model = RX_package[1]; // executa etapa do firmware do robo
val = RX_package[2]; // executa etapa do firmware do robo
if (Model == Speed) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
speeds = val; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (Model == Model1) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
model_var = 0; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (Model == Model2) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
model_var = 1; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (Model == Model3) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
model_var = 2; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (Model == Model4) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
model_var = 3; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (Model == Servo) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
angle = val; // executa etapa do firmware do robo
model_var = 4; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 5.2 — Câmera WiFi Web lado ESP32-CAM (5.2_ESP32Cam_WIFI_Web)
A ESP32-CAM cria o AP KUONGSHUN-AD176, inicializa a OV2640 em SVGA com qualidade 10–12, corrige orientação com set_vflip/hmirror e sobe o servidor de streaming mais a ponte UART2 (GPIO14/13) com o UNO. A ESP32-CAM opera em modo AP — access point — criando a rede KUONGSHUN-AD176 com senha 12345678 e IP fixo . O video usa MJPEG sobre HTTP — motion JPEG over hypertext transfer protocol — com multipart x-mixed-replace, onde cada frame JPEG e delimitado por boundary e empurrado em chunked encoding. A taxa util aproximada e:
onde e o bitrate, o framerate, o tamanho medio do JPEG e o tempo de compressao. SVGA () a qualidade – equilibra nitidez e latencia; UXGA trava o stream por esgotar PSRAM e banda. O enlace de comando UNO ESP32-CAM usa UART a (), com pacotes de bytes (AB modelo valor FF) no modo Web e quadros FF 55 ... no modo APP, ambos com timeout de . A potencia de TX em maximiza alcance indoor a custa de consumo, por isso video so e estavel com bateria cheia. O canal fixo reduz interferencia com roteadores domesticos.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| ESP32-CAM + OV2640 | 1 | AP, câmera e ponte serial |
| UNO com firmware 5.1 | 1 | executor dos comandos |
| Celular/PC no AP | 1 | navegador em 192.168.4.1 |

Código real 5.2_ESP32Cam_WIFI_Web.ino comentado linha a linha
📦 Bibliotecas desta lição:
WiFi,esp_camera,esp_system,soc/soc.h,soc/rtc_cntl_reg.h— todas embutidas no pacote ESP32 2.0.12, nada a baixar.
- Instalação: nenhuma. Exige o instalador
esp32_package_2.0.12_arduinome.exedo fabricante aplicado (Etapa 2 da Preparação) com a placaESP32 Dev Moduleselecionada.- Conferência:
Arquivo > Exemplos > ESP32 > Camera > CameraWebServerdeve abrir e compilar semNo such file or directory. Com núcleo 3.x a compilação quebra (ledcSetupremovido) — volte ao 2.0.12.
#include "esp_camera.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include <WiFi.h> // embutida no núcleo ESP32 2.0.12, nada a baixar
#include "soc/soc.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include "soc/rtc_cntl_reg.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#define CAMERA_MODEL_AI_THINKER // define constante de pino/mapa de hardware
#define LED 4 // define constante de pino/mapa de hardware
#define RXD2 14 // define constante de pino/mapa de hardware
#define TXD2 13 // define constante de pino/mapa de hardware
void CameraWebServer_init(); // configura/inicializa a camera OV2640
WiFiServer server(100); // configura rede WiFi AP do robo para video e comando
extern int gpLed = 4; // Light // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // prevent brownouts by silencing them // executa etapa do firmware do robo
Serial.begin(115200); // inicializa UART para debug e enlace com ESP32-CAM
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2); // executa etapa do firmware do robo
Serial.setDebugOutput(true); // executa etapa do firmware do robo
Serial.println(); // envia telemetria ao Monitor Serial
CameraWebServer_init(); // configura/inicializa a camera OV2640
pinMode(gpLed, OUTPUT); //Light // configura o pino como entrada ou saida digital
ledcSetup(7, 5000, 8); // configura PWM do LED/flash da ESP32-CAM
ledcAttachPin(gpLed, 7); //pin4 is LED // configura PWM do LED/flash da ESP32-CAM
server.begin(); // gerencia servidor HTTP/TCP de video e comandos
for (int i = 0; i < 5; i++) // laco de varredura incremental do ensaio
{ // executa etapa do firmware do robo
ledcWrite(7, 10); // flash led // configura PWM do LED/flash da ESP32-CAM
delay(50); // aguarda estabilizacao/temporizacao do atuador
ledcWrite(7, 0); // configura PWM do LED/flash da ESP32-CAM
delay(50); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
//delay(1000);
//Serial.printf("RSSi: %ld dBm\n", WiFi.RSSI());
} // executa etapa do firmware do robo
Código real CameraWebServer.cpp (Web) comentado
📦 Bibliotecas desta lição: as mesmas do sketch 5.2 (núcleo ESP32 2.0.12), nada a baixar — este
.cppcompila junto ao.inona mesma pasta.
#include "esp_system.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include "esp_camera.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include <WiFi.h> // embutida no núcleo ESP32 2.0.12, nada a baixar
const char *ssid = "KUONGSHUN-AD176"; // executa etapa do firmware do robo
const char *password = "12345678"; // executa etapa do firmware do robo
String wifi_name; // executa etapa do firmware do robo
#define PWDN_GPIO_NUM 32 // define constante de pino/mapa de hardware
#define RESET_GPIO_NUM -1 // define constante de pino/mapa de hardware
#define XCLK_GPIO_NUM 0 // define constante de pino/mapa de hardware
#define SIOD_GPIO_NUM 26 // define constante de pino/mapa de hardware
#define SIOC_GPIO_NUM 27 // define constante de pino/mapa de hardware
#define Y9_GPIO_NUM 35 // define constante de pino/mapa de hardware
#define Y8_GPIO_NUM 34 // define constante de pino/mapa de hardware
#define Y7_GPIO_NUM 39 // define constante de pino/mapa de hardware
#define Y6_GPIO_NUM 36 // define constante de pino/mapa de hardware
#define Y5_GPIO_NUM 21 // define constante de pino/mapa de hardware
#define Y4_GPIO_NUM 19 // define constante de pino/mapa de hardware
#define Y3_GPIO_NUM 18 // define constante de pino/mapa de hardware
#define Y2_GPIO_NUM 5 // define constante de pino/mapa de hardware
#define VSYNC_GPIO_NUM 25 // define constante de pino/mapa de hardware
#define HREF_GPIO_NUM 23 // define constante de pino/mapa de hardware
#define PCLK_GPIO_NUM 22 // define constante de pino/mapa de hardware
void startCameraServer(); // configura/inicializa a camera OV2640
void CameraWebServer_init() // configura/inicializa a camera OV2640
{ // executa etapa do firmware do robo
camera_config_t config; // configura/inicializa a camera OV2640
config.ledc_channel = LEDC_CHANNEL_0; // configura PWM do LED/flash da ESP32-CAM
config.ledc_timer = LEDC_TIMER_0; // configura PWM do LED/flash da ESP32-CAM
config.pin_d0 = Y2_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d1 = Y3_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d2 = Y4_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d3 = Y5_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d4 = Y6_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d5 = Y7_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d6 = Y8_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d7 = Y9_GPIO_NUM; // executa etapa do firmware do robo
config.pin_xclk = XCLK_GPIO_NUM; // executa etapa do firmware do robo
config.pin_pclk = PCLK_GPIO_NUM; // executa etapa do firmware do robo
config.pin_vsync = VSYNC_GPIO_NUM; // executa etapa do firmware do robo
config.pin_href = HREF_GPIO_NUM; // executa etapa do firmware do robo
config.pin_sccb_sda = SIOD_GPIO_NUM; // executa etapa do firmware do robo
config.pin_sccb_scl = SIOC_GPIO_NUM; // executa etapa do firmware do robo
config.pin_pwdn = PWDN_GPIO_NUM; // executa etapa do firmware do robo
config.pin_reset = RESET_GPIO_NUM; // executa etapa do firmware do robo
config.xclk_freq_hz = 20000000; // executa etapa do firmware do robo
config.frame_size = FRAMESIZE_UXGA; // executa etapa do firmware do robo
config.pixel_format = PIXFORMAT_JPEG; // for streaming // executa etapa do firmware do robo
//config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; // configura/inicializa a camera OV2640
config.fb_location = CAMERA_FB_IN_PSRAM; // configura/inicializa a camera OV2640
config.jpeg_quality = 12; // executa etapa do firmware do robo
config.fb_count = 1; // executa etapa do firmware do robo
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(config.pixel_format == PIXFORMAT_JPEG){ // decisao condicional do comportamento autonomo
if(psramFound()){ // decisao condicional do comportamento autonomo
config.jpeg_quality = 10; // executa etapa do firmware do robo
config.fb_count = 2; // executa etapa do firmware do robo
config.grab_mode = CAMERA_GRAB_LATEST; // configura/inicializa a camera OV2640
} else { // executa etapa do firmware do robo
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA; // executa etapa do firmware do robo
config.fb_location = CAMERA_FB_IN_DRAM; // configura/inicializa a camera OV2640
} // executa etapa do firmware do robo
} else { // executa etapa do firmware do robo
// Best option for face detection/recognition
config.frame_size = FRAMESIZE_240X240; // executa etapa do firmware do robo
#if CONFIG_IDF_TARGET_ESP32S3 // executa etapa do firmware do robo
config.fb_count = 2; // executa etapa do firmware do robo
#endif // executa etapa do firmware do robo
} // executa etapa do firmware do robo
// camera init
esp_err_t err = esp_camera_init(&config); // configura/inicializa a camera OV2640
if (err != ESP_OK) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Serial.printf("Camera init failed with error 0x%x", err); // envia telemetria ao Monitor Serial
return; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
sensor_t *s = esp_camera_sensor_get(); // configura/inicializa a camera OV2640
//drop down frame size for higher initial frame rate
//s->set_framesize(s, FRAMESIZE_SXGA); //Video sample rate:60000 #9 (High image quality) 1280x1024
s->set_framesize(s, FRAMESIZE_SVGA); //Video sample rate:40000 #7 (Medium image quality) 800x600 // executa etapa do firmware do robo
//s->set_framesize(s, FRAMESIZE_QVGA); //Video sample rate:10000 #4 (Low image quality) 320x240
s->set_vflip(s, 1); //Image Direction Settings(Up/Down) // executa etapa do firmware do robo
s->set_hmirror(s, 0); //Image Direction Setting(Left/Right) // executa etapa do firmware do robo
WiFi.setTxPower(WIFI_POWER_19_5dBm); // configura rede WiFi AP do robo para video e comando
WiFi.mode(WIFI_AP); // configura rede WiFi AP do robo para video e comando
WiFi.softAP(ssid, password, 5); // configura rede WiFi AP do robo para video e comando
startCameraServer(); // configura/inicializa a camera OV2640
// WiFi.softAP(ssid, password);
IPAddress miIP = WiFi.softAPIP(); // configura rede WiFi AP do robo para video e comando
Serial.print("AP IP address: "); // envia telemetria ao Monitor Serial
Serial.println(miIP); //probar 192.168.4.1 // envia telemetria ao Monitor Serial
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Com a UART desplugada, grave o 5.1 no UNO (Arduino UNO) e o 5.2 na CAM (ESP32 Dev Module). Reconecte a UART, ligue com baterias, conecte-se ao AP KUONGSHUN-AD176 com 12345678, abra 192.168.4.1 e opere os 11 botões de direção, 4 modos, sliders de servo/velocidade/farol e o stream MJPEG. SSID, senha, qualidade (SVGA/SXGA/QVGA) e vflip/hmirror são ajustáveis no CameraWebServer.cpp.
💡 Dica: vídeo travando indica bateria fraca ou qualidade alta demais; volte a SVGA/qualidade 12.
⚠️ Atenção: núcleo ESP32 diferente de 2.0.12 quebra
ledcSetupe a câmera; repita a instalação pinada.
⛔ Perigo: não alimente a tração pelo USB do PC; a corrente de estol queima porta e cabo.
Lição 6.1 — Multifunção APP lado Arduino (6.1_Arduino_All_APP)
O UNO interpreta quadros FF 55 ... do aplicativo com campos de ação, dispositivo e valor, roteando D-pad omnidirecional, servo, farol e velocidade para os mesmos atuadores do modo Web, com timeout que para o robô ao perder o cliente. As rodas Mecanum possuem roletes a em torno do cubo. Cada roda gera forca perpendicular ao eixo do rolete, decomponivel em componentes longitudinal e lateral . Com quatro rodas independentes em configuracao X, a soma vetorial permite translacao omnidirecional sem mudar a orientacao do chassi. O principio formal da cinematica direta do 4WD Mecanum, com semi-distancias e do centro, raio e velocidades angulares , e: O servo SG90 e comandado por PPM com periodo de . A largura do pulso codifica o angulo:
onde e a velocidade longitudinal, a lateral e a taxa de guinada. A decomposicao por rolete explica os codigos decimais da tabela do fabricante: cada byte de 8 bits mapeia os 8 terminais de ponte H dos quatro motores via 74HC595, de modo que frentes paralelas somam (marcha 163/92) e oposicoes simetricas somam (translacao 106/149), enquanto diagonais produzem resultante a (34/129/72/20) e giros puros cancelam translacao e somam momento (83/172). A velocidade linear de cada roda segue , e a forca de tracao disponivel e limitada pelo atrito , por isso piso liso reduz derrapagem dos roletes e melhora a lateralidade. O driver usa dois canais PWM ( e ) para energia e o registrador de deslocamento para direcao, separando potencia e logica como em toda ponte H dupla.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| UNO + atuadores/sensores | 1 | execução dos comandos APP |
| ESP32-CAM com 6.2 | 1 | ponte TCP>UART |
| App KUONGSHUN | 1 | D-pad, sliders e modos |

| Sinal | Pino | Observação |
|---|---|---|
| PWM | D5/D6 | Velocidade dos motores |
| SHCP/EN/DATA/STCP | D2/D7/D8/D4 | Direção via 74HC595 |
| Servo | D9 | Pan-tilt da câmera |
| TRIG/ECHO | D12/D13 | Ultrassom |
| Linha | A0/A1/A2 | Trio IR |
| UART | TX/RX 115200 | Enlace com ESP32-CAM (desplugado no upload) |
Código real 6.1_Arduino_All_APP.ino comentado linha a linha
📦 Bibliotecas desta lição:
Servo— a mesma da Lição 2, nada a baixar. SeArquivo > Exemplos > Servo > Sweepcompila, siga direto ao código.
//www.kuongshun.com
#include <Servo.h> // instalada pelo quadro "Bibliotecas desta lição" (Servo.zip do fabricante)
#define MOTOR_PIN 9 // define constante de pino/mapa de hardware
#define PWM1_PIN 5 // define constante de pino/mapa de hardware
#define PWM2_PIN 6 // define constante de pino/mapa de hardware
#define SHCP_PIN 2 // The displacement of the clock // define constante de pino/mapa de hardware
#define EN_PIN 7 // Can make control // define constante de pino/mapa de hardware
#define DATA_PIN 8 // Serial data // define constante de pino/mapa de hardware
#define STCP_PIN 4 // Memory register clock // define constante de pino/mapa de hardware
#define Trig_PIN 12 // define constante de pino/mapa de hardware
#define Echo_PIN 13 // define constante de pino/mapa de hardware
#define LEFT_LINE_TRACJING A2 // define constante de pino/mapa de hardware
#define CENTER_LINE_TRACJING A1 // define constante de pino/mapa de hardware
#define right_LINE_TRACJING A0 // define constante de pino/mapa de hardware
Servo MOTORservo; // comanda o servo pan-tilt da camera
const int Forward = 163; // forward // executa etapa do firmware do robo
const int Backward = 92; // back // executa etapa do firmware do robo
const int Turn_Left = 106; // left translation // executa etapa do firmware do robo
const int Turn_Right = 149; // Right translation // executa etapa do firmware do robo
const int Top_Left = 34; // Upper left mobile // executa etapa do firmware do robo
const int Bottom_Left = 72; // Lower left mobile // executa etapa do firmware do robo
const int Top_Right = 129; // Upper right mobile // executa etapa do firmware do robo
const int Bottom_Right = 20; // The lower right move // executa etapa do firmware do robo
const int Stop = 0; // stop // executa etapa do firmware do robo
const int Contrarotate = 83; // Counterclockwise rotation // executa etapa do firmware do robo
const int Clockwise = 172; // Rotate clockwise // executa etapa do firmware do robo
const int Model1 = 3; // model1 // executa etapa do firmware do robo
const int Model2 = 6; // model2 // executa etapa do firmware do robo
const int Model3 = 7; // model3 // executa etapa do firmware do robo
const int Model4 = 4; // model4 // executa etapa do firmware do robo
const int Model1_Ctrl = 1; // executa etapa do firmware do robo
const int Speed = 13; // executa etapa do firmware do robo
const int Servo = 2; // executa etapa do firmware do robo
const int Motor_Move = 12; // servo turn left // executa etapa do firmware do robo
const int LED = 5; // servo turn right // executa etapa do firmware do robo
byte dataLen, index_a = 0; // executa etapa do firmware do robo
char buffer[52]; // executa etapa do firmware do robo
unsigned char prevc=0; // executa etapa do firmware do robo
bool isStart = false; // executa etapa do firmware do robo
bool ED_client = true; // executa etapa do firmware do robo
bool WA_en = false; // executa etapa do firmware do robo
int Left_Tra_Value; // executa etapa do firmware do robo
int Center_Tra_Value; // executa etapa do firmware do robo
int Right_Tra_Value; // executa etapa do firmware do robo
int Black_Line = 400; // executa etapa do firmware do robo
int speeds = 250; // executa etapa do firmware do robo
int leftDistance = 0; // executa etapa do firmware do robo
int middleDistance = 0; // executa etapa do firmware do robo
int rightDistance = 0; // executa etapa do firmware do robo
int action = 0; // executa etapa do firmware do robo
byte RX_package[17] = {0}; // executa etapa do firmware do robo
uint16_t angle = 90; // executa etapa do firmware do robo
byte Model = Stop; // executa etapa do firmware do robo
byte val = 0; // executa etapa do firmware do robo
int model_var = 0; // executa etapa do firmware do robo
char device = 0; // executa etapa do firmware do robo
int UT_distance = 0; // executa etapa do firmware do robo
int OA_mark=0; // executa etapa do firmware do robo
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Serial.setTimeout(10); // executa etapa do firmware do robo
Serial.begin(115200); // inicializa UART para debug e enlace com ESP32-CAM
MOTORservo.attach(MOTOR_PIN); // comanda o servo pan-tilt da camera
pinMode(SHCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(EN_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(DATA_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(STCP_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM1_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(PWM2_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(Trig_PIN, OUTPUT); // configura o pino como entrada ou saida digital
pinMode(Echo_PIN, INPUT); // configura o pino como entrada ou saida digital
pinMode(LEFT_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(CENTER_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
pinMode(right_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital
MOTORservo.write(angle); // comanda o servo pan-tilt da camera
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
unsigned char readBuffer(int index_r) // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
return buffer[index_r]; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
void writeBuffer(int index_w,unsigned char c) // atualiza atuador/saida com o valor indicado
{ // executa etapa do firmware do robo
buffer[index_w]=c; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
RXpack_func(); // executa etapa do firmware do robo
switch (model_var) // seleciona modo/comando recebido via serial/rede
{ // executa etapa do firmware do robo
case 0: // seleciona modo/comando recebido via serial/rede
model1_func(device,val); // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 1: // seleciona modo/comando recebido via serial/rede
model2_func(); // OA model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 2: // seleciona modo/comando recebido via serial/rede
model3_func(); // follow model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case 3: // seleciona modo/comando recebido via serial/rede
model4_func(); // Tracking model // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model1_func(byte device, byte values) // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
switch (device) { // seleciona modo/comando recebido via serial/rede
case Motor_Move: // seleciona modo/comando recebido via serial/rede
switch (values) { // seleciona modo/comando recebido via serial/rede
case 0x00: // seleciona modo/comando recebido via serial/rede
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x01: // seleciona modo/comando recebido via serial/rede
Motor(Forward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x02: // seleciona modo/comando recebido via serial/rede
Motor(Backward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x03: // seleciona modo/comando recebido via serial/rede
Motor(Turn_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x04: // seleciona modo/comando recebido via serial/rede
Motor(Turn_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x05: // seleciona modo/comando recebido via serial/rede
Motor(Top_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x07: // seleciona modo/comando recebido via serial/rede
Motor(Top_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x06: // seleciona modo/comando recebido via serial/rede
Motor(Bottom_Left, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x08: // seleciona modo/comando recebido via serial/rede
Motor(Bottom_Right, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x0A: // seleciona modo/comando recebido via serial/rede
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case 0x09: // seleciona modo/comando recebido via serial/rede
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case Servo: // seleciona modo/comando recebido via serial/rede
angle=values; // executa etapa do firmware do robo
if (angle >= 180) angle = 180; // decisao condicional do comportamento autonomo
if (angle <= 1) angle = 1; // decisao condicional do comportamento autonomo
MOTORservo.write(angle); // comanda o servo pan-tilt da camera
//delay(5);
break; // executa etapa do firmware do robo
case LED: // seleciona modo/comando recebido via serial/rede
//Serial.write(RX_package, 17);
break; // executa etapa do firmware do robo
case Speed: // seleciona modo/comando recebido via serial/rede
speeds=values; // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model2_func() // OA // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
while (model_var == 1) { // mantem o modo autonomo ate trocar de modo
RXpack_func(); // executa etapa do firmware do robo
middleDistance = SR04(Trig_PIN, Echo_PIN); // executa etapa do firmware do robo
if (middleDistance <= 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
Motor(Backward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
rightDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
if (rightDistance > 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if(OA_mark==0) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
OA_mark++; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(600); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
leftDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
if (rightDistance > leftDistance) { // decisao condicional do comportamento autonomo
Motor(Backward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
delay(500); // aguarda estabilizacao/temporizacao do atuador
Motor(Clockwise, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(500); // aguarda estabilizacao/temporizacao do atuador
OA_mark=0; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if (rightDistance < leftDistance) { // decisao condicional do comportamento autonomo
while (leftDistance < 25) { // mantem o modo autonomo ate trocar de modo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
delay(200); // aguarda estabilizacao/temporizacao do atuador
leftDistance = SR04(Trig_PIN, Echo_PIN);//SR04(); // executa etapa do firmware do robo
delay(200); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
Motor(Contrarotate, speeds); // aciona tracao Mecanum no modo/velocidade indicados
delay(100); // aguarda estabilizacao/temporizacao do atuador
OA_mark=0; // executa etapa do firmware do robo
continue; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
Motor(Forward, speeds); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model3_func() // follow model // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
MOTORservo.write(90); // comanda o servo pan-tilt da camera
UT_distance = SR04(Trig_PIN, Echo_PIN); // executa etapa do firmware do robo
if (UT_distance < 15) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Backward, speeds-50); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (15 <= UT_distance && UT_distance <= 20) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (20 <= UT_distance && UT_distance <= 25) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, speeds-70); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (25 <= UT_distance && UT_distance <= 50) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, speeds-30); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void model4_func() // tracking model // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
MOTORservo.write(90); // comanda o servo pan-tilt da camera
Left_Tra_Value = analogRead(LEFT_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Center_Tra_Value = analogRead(CENTER_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
Right_Tra_Value = analogRead(right_LINE_TRACJING); // le o sensor reflexivo IR da pista (linha)
if (Left_Tra_Value > Black_Line && Center_Tra_Value <= Black_Line && Right_Tra_Value > Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 180); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 130); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Clockwise, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 160); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value < Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Contrarotate, 220); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Motor(Forward, 130); // aciona tracao Mecanum no modo/velocidade indicados
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void Motor(int Dir, int Speed) // motor drive // aciona tracao Mecanum no modo/velocidade indicados
{ // executa etapa do firmware do robo
digitalWrite(EN_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
analogWrite(PWM1_PIN, Speed); // gera PWM com duty proporcional a velocidade
analogWrite(PWM2_PIN, Speed); // gera PWM com duty proporcional a velocidade
digitalWrite(STCP_PIN, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
shiftOut(DATA_PIN, SHCP_PIN, MSBFIRST, Dir); // desloca 8 bits ao 74HC595 controlando os 4 motores
digitalWrite(STCP_PIN, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
} // executa etapa do firmware do robo
float SR04(int Trig, int Echo) // ultrasonic measured distance // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
digitalWrite(Trig, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(2); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(Trig, HIGH); // escreve nivel logico ALTO/BAIXO no pino digital
delayMicroseconds(10); // aguarda estabilizacao/temporizacao do atuador
digitalWrite(Trig, LOW); // escreve nivel logico ALTO/BAIXO no pino digital
float distance = pulseIn(Echo, HIGH) / 58.00; // mede largura do eco ultrassonico para calcular distancia
delay(10); // aguarda estabilizacao/temporizacao do atuador
return distance; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
void parseData() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
isStart = false; // executa etapa do firmware do robo
action = readBuffer(9); // executa etapa do firmware do robo
device = readBuffer(10); // executa etapa do firmware do robo
val = readBuffer(12); // executa etapa do firmware do robo
switch (action) // seleciona modo/comando recebido via serial/rede
{ // executa etapa do firmware do robo
case Model1_Ctrl: // seleciona modo/comando recebido via serial/rede
//callOK_Len01();
model_var = 0; // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case Model1: // seleciona modo/comando recebido via serial/rede
//callOK_Len01();
model_var = 0; // executa etapa do firmware do robo
Motor(Stop, 0); // aciona tracao Mecanum no modo/velocidade indicados
break; // executa etapa do firmware do robo
case Model2: // seleciona modo/comando recebido via serial/rede
//callOK_Len01();
model_var = 1; // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case Model3: // seleciona modo/comando recebido via serial/rede
//callOK_Len01();
model_var = 2; // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
case Model4: // seleciona modo/comando recebido via serial/rede
//callOK_Len01();
model_var = 3; // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
default:break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void RXpack_func() //Receive data // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
if(Serial.available() > 0) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
unsigned char c = Serial.read()&0xff; // executa etapa do firmware do robo
Serial.write(c); // atualiza atuador/saida com o valor indicado
if(c==0x55&&isStart==false) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if(prevc==0xff) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
index_a=1; // executa etapa do firmware do robo
isStart = true; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
prevc = c; // executa etapa do firmware do robo
if(isStart) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if(index_a==2) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
dataLen = c; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if(index_a>2) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
dataLen--; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
writeBuffer(index_a,c); // atualiza atuador/saida com o valor indicado
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
index_a++; // executa etapa do firmware do robo
if(index_a>120) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
index_a=0; // executa etapa do firmware do robo
isStart=false; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
if(isStart&&dataLen==0&&index_a>3) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
isStart = false; // executa etapa do firmware do robo
parseData(); // executa etapa do firmware do robo
index_a=0; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Gravação e teste (o que você deve ver)
Desconecte a UART, selecione Arduino UNO e a porta COM, grave e observe sucesso na IDE. Desplugue o USB, instale as 18650, coloque em área livre e ligue a chave. Resultado esperado descrito na teoria de cada modo; divergência indica fiação, bateria ou limiar — ver Troubleshooting.
💡 Dica: valide com o Monitor Serial em 9600/115200 bps conforme o sketch antes de culpar o hardware.
⚠️ Atenção: uploads com a UART conectada falham por contenção do RX/TX; desplugue sempre.
⛔ Perigo: robô em movimento sobre a bancada cai e quebra a câmera; teste sempre no chão.
Lição 6.2 — Câmera WiFi APP lado ESP32-CAM (6.2_ESP32Cam_WIFI_APP)
A CAM mantém AP, câmera e streaming, mas troca o protocolo Web pelo servidor TCP na porta 100 com parser FF 55, repasse byte a byte à UART, watchdog de 3 s que injeta parada e controle do flash via dispositivo 0x05. A ESP32-CAM opera em modo AP — access point — criando a rede KUONGSHUN-AD176 com senha 12345678 e IP fixo . O video usa MJPEG sobre HTTP — motion JPEG over hypertext transfer protocol — com multipart x-mixed-replace, onde cada frame JPEG e delimitado por boundary e empurrado em chunked encoding. A taxa util aproximada e:
onde e o bitrate, o framerate, o tamanho medio do JPEG e o tempo de compressao. SVGA () a qualidade – equilibra nitidez e latencia; UXGA trava o stream por esgotar PSRAM e banda. O enlace de comando UNO ESP32-CAM usa UART a (), com pacotes de bytes (AB modelo valor FF) no modo Web e quadros FF 55 ... no modo APP, ambos com timeout de . A potencia de TX em maximiza alcance indoor a custa de consumo, por isso video so e estavel com bateria cheia. O canal fixo reduz interferencia com roteadores domesticos.
| Item | Qtd | Papel no ensaio |
|---|---|---|
| ESP32-CAM + OV2640 | 1 | AP, vídeo e ponte APP |
| UNO com firmware 6.1 | 1 | executor do protocolo APP |
| App KUONGSHUN instalado | 1 | cliente de vídeo e comando |

Código real 6.2_ESP32Cam_WIFI_APP.ino comentado linha a linha
📦 Bibliotecas desta lição:
WiFi,esp_camera,esp_system— as mesmas do núcleo ESP32 2.0.12 da Lição 5.2, nada a baixar.
#include <WiFi.h> // embutida no núcleo ESP32 2.0.12, nada a baixar
#include "esp_camera.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
WiFiServer server(100); // configura rede WiFi AP do robo para video e comando
byte Stop[17]={0xff,0x55,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0C,0x00,0x00}; // executa etapa do firmware do robo
byte RX_package[17] = {0}; // executa etapa do firmware do robo
byte dataLen, index_a = 0; // executa etapa do firmware do robo
char buffer[52]; // executa etapa do firmware do robo
unsigned char prevc=0; // executa etapa do firmware do robo
bool isStart = false; // executa etapa do firmware do robo
bool ED_client = true; // executa etapa do firmware do robo
bool WA_en = false; // executa etapa do firmware do robo
String sendBuff; // executa etapa do firmware do robo
String Version = "Firmware Version is 0.12.21"; // executa etapa do firmware do robo
int action = 0; // executa etapa do firmware do robo
char device = 0; // executa etapa do firmware do robo
byte val = 0; // executa etapa do firmware do robo
bool st = false; // executa etapa do firmware do robo
unsigned long lastDataTimes = 0; // executa etapa do firmware do robo
#define gpLED 4 // Light // define constante de pino/mapa de hardware
void CameraWebServer_init(); // configura/inicializa a camera OV2640
void setup() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
Serial.begin(115200); // inicializa UART para debug e enlace com ESP32-CAM
//http://192.168.4.1/control?var=framesize&val=3
//http://192.168.4.1/Test?var=
CameraWebServer_init(); // configura/inicializa a camera OV2640
server.begin(); // gerencia servidor HTTP/TCP de video e comandos
delay(100); // aguarda estabilizacao/temporizacao do atuador
pinMode(gpLED, OUTPUT); //Light // configura o pino como entrada ou saida digital
ledcSetup(7, 5000, 8); // configura PWM do LED/flash da ESP32-CAM
ledcAttachPin(gpLED, 7); //pin4 is LED // configura PWM do LED/flash da ESP32-CAM
for (int i = 0; i < 5; i++) // laco de varredura incremental do ensaio
{ // executa etapa do firmware do robo
ledcWrite(7, 20); // flash led // configura PWM do LED/flash da ESP32-CAM
delay(50); // aguarda estabilizacao/temporizacao do atuador
ledcWrite(7, 0); // configura PWM do LED/flash da ESP32-CAM
delay(50); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
unsigned char readBuffer(int index_r) // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
return buffer[index_r]; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
void writeBuffer(int index_w,unsigned char c) // atualiza atuador/saida com o valor indicado
{ // executa etapa do firmware do robo
buffer[index_w]=c; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void parseData() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
isStart = false; // executa etapa do firmware do robo
action = readBuffer(9); // executa etapa do firmware do robo
device = readBuffer(10); // executa etapa do firmware do robo
val = readBuffer(12); // executa etapa do firmware do robo
if (device==0x05) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if(val<20)val=0; // decisao condicional do comportamento autonomo
ledcWrite(7, val); // configura PWM do LED/flash da ESP32-CAM
delay(1); // aguarda estabilizacao/temporizacao do atuador
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
void loop() // define rotina de atuacao/leitura do robo
{ // executa etapa do firmware do robo
WiFiClient client = server.available(); // configura rede WiFi AP do robo para video e comando
if (client) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
WA_en = true; // executa etapa do firmware do robo
ED_client = true; // executa etapa do firmware do robo
unsigned long previousMillis = millis(); // 上一个检查时间 // executa etapa do firmware do robo
const unsigned long timeoutDuration = 3000; // 超时时间(2秒) // executa etapa do firmware do robo
Serial.println("[Client connected]"); // envia telemetria ao Monitor Serial
while (client.connected()) // mantem o modo autonomo ate trocar de modo
{ // executa etapa do firmware do robo
if ((millis() - previousMillis) > timeoutDuration && client.available() == 0 && st==true) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
break; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
if (client.available()) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
previousMillis = millis(); // 111111 // executa etapa do firmware do robo
unsigned char clientBuff = client.read()&0xff; // executa etapa do firmware do robo
Serial.write(clientBuff); // atualiza atuador/saida com o valor indicado
st = false; // 111111 // executa etapa do firmware do robo
if (clientBuff == 200) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
st = true; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
if(clientBuff==0x55&&isStart==false) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if(prevc==0xff) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
index_a=1; // executa etapa do firmware do robo
isStart = true; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
prevc = clientBuff; // executa etapa do firmware do robo
if(isStart) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
if(index_a==2) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
dataLen = clientBuff; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if(index_a>2) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
dataLen--; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
writeBuffer(index_a,clientBuff); // atualiza atuador/saida com o valor indicado
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
index_a++; // executa etapa do firmware do robo
if(index_a>120) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
index_a=0; // executa etapa do firmware do robo
isStart=false; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
if(isStart&&dataLen==0&&index_a>3) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
isStart = false; // executa etapa do firmware do robo
parseData(); // executa etapa do firmware do robo
index_a=0; // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
else if ((millis() - previousMillis) > timeoutDuration && Serial.available() == 0 && st==true) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Serial.write(Stop,17); // atualiza atuador/saida com o valor indicado
} // executa etapa do firmware do robo
//client.print(clientBuff);
// static unsigned long Test_time = 0;
// if (millis() - Test_time > 3000)
// {
// Test_time = millis();
// if (0 == (WiFi.softAPgetStationNum()))
// {
// Serial.write(Stop,17);
// Serial.println("[Client disconnected]");
// }
// }
} // executa etapa do firmware do robo
Serial.write(Stop,17); // atualiza atuador/saida com o valor indicado
client.stop(); // executa etapa do firmware do robo
Serial.println("[Client disconnected]"); // envia telemetria ao Monitor Serial
} // executa etapa do firmware do robo
else // executa etapa do firmware do robo
{ // executa etapa do firmware do robo
if (ED_client == true) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
ED_client = false; // executa etapa do firmware do robo
Serial.write(Stop,17); // atualiza atuador/saida com o valor indicado
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
} // executa etapa do firmware do robo
Código real CameraWebServer.cpp (APP) comentado
📦 Bibliotecas desta lição: as mesmas do sketch 6.2 (núcleo ESP32 2.0.12), nada a baixar — este
.cppcompila junto ao.inona mesma pasta.
#include "esp_system.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include "esp_camera.h" // embutida no núcleo ESP32 2.0.12, nada a baixar
#include <WiFi.h> // embutida no núcleo ESP32 2.0.12, nada a baixar
const char *ssid = "KUONGSHUN-AD176"; // executa etapa do firmware do robo
const char *password = "12345678"; // executa etapa do firmware do robo
String wifi_name; // executa etapa do firmware do robo
#define PWDN_GPIO_NUM 32 // define constante de pino/mapa de hardware
#define RESET_GPIO_NUM -1 // define constante de pino/mapa de hardware
#define XCLK_GPIO_NUM 0 // define constante de pino/mapa de hardware
#define SIOD_GPIO_NUM 26 // define constante de pino/mapa de hardware
#define SIOC_GPIO_NUM 27 // define constante de pino/mapa de hardware
#define Y9_GPIO_NUM 35 // define constante de pino/mapa de hardware
#define Y8_GPIO_NUM 34 // define constante de pino/mapa de hardware
#define Y7_GPIO_NUM 39 // define constante de pino/mapa de hardware
#define Y6_GPIO_NUM 36 // define constante de pino/mapa de hardware
#define Y5_GPIO_NUM 21 // define constante de pino/mapa de hardware
#define Y4_GPIO_NUM 19 // define constante de pino/mapa de hardware
#define Y3_GPIO_NUM 18 // define constante de pino/mapa de hardware
#define Y2_GPIO_NUM 5 // define constante de pino/mapa de hardware
#define VSYNC_GPIO_NUM 25 // define constante de pino/mapa de hardware
#define HREF_GPIO_NUM 23 // define constante de pino/mapa de hardware
#define PCLK_GPIO_NUM 22 // define constante de pino/mapa de hardware
void startCameraServer(); // configura/inicializa a camera OV2640
void CameraWebServer_init() // configura/inicializa a camera OV2640
{ // executa etapa do firmware do robo
camera_config_t config; // configura/inicializa a camera OV2640
config.ledc_channel = LEDC_CHANNEL_0; // configura PWM do LED/flash da ESP32-CAM
config.ledc_timer = LEDC_TIMER_0; // configura PWM do LED/flash da ESP32-CAM
config.pin_d0 = Y2_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d1 = Y3_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d2 = Y4_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d3 = Y5_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d4 = Y6_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d5 = Y7_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d6 = Y8_GPIO_NUM; // executa etapa do firmware do robo
config.pin_d7 = Y9_GPIO_NUM; // executa etapa do firmware do robo
config.pin_xclk = XCLK_GPIO_NUM; // executa etapa do firmware do robo
config.pin_pclk = PCLK_GPIO_NUM; // executa etapa do firmware do robo
config.pin_vsync = VSYNC_GPIO_NUM; // executa etapa do firmware do robo
config.pin_href = HREF_GPIO_NUM; // executa etapa do firmware do robo
config.pin_sccb_sda = SIOD_GPIO_NUM; // executa etapa do firmware do robo
config.pin_sccb_scl = SIOC_GPIO_NUM; // executa etapa do firmware do robo
config.pin_pwdn = PWDN_GPIO_NUM; // executa etapa do firmware do robo
config.pin_reset = RESET_GPIO_NUM; // executa etapa do firmware do robo
config.xclk_freq_hz = 20000000; // executa etapa do firmware do robo
config.frame_size = FRAMESIZE_UXGA; // executa etapa do firmware do robo
config.pixel_format = PIXFORMAT_JPEG; // for streaming // executa etapa do firmware do robo
//config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; // configura/inicializa a camera OV2640
config.fb_location = CAMERA_FB_IN_PSRAM; // configura/inicializa a camera OV2640
config.jpeg_quality = 12; // executa etapa do firmware do robo
config.fb_count = 1; // executa etapa do firmware do robo
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if(config.pixel_format == PIXFORMAT_JPEG){ // decisao condicional do comportamento autonomo
if(psramFound()){ // decisao condicional do comportamento autonomo
config.jpeg_quality = 10; // executa etapa do firmware do robo
config.fb_count = 2; // executa etapa do firmware do robo
config.grab_mode = CAMERA_GRAB_LATEST; // configura/inicializa a camera OV2640
} else { // executa etapa do firmware do robo
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA; // executa etapa do firmware do robo
config.fb_location = CAMERA_FB_IN_DRAM; // configura/inicializa a camera OV2640
} // executa etapa do firmware do robo
} else { // executa etapa do firmware do robo
// Best option for face detection/recognition
config.frame_size = FRAMESIZE_240X240; // executa etapa do firmware do robo
#if CONFIG_IDF_TARGET_ESP32S3 // executa etapa do firmware do robo
config.fb_count = 2; // executa etapa do firmware do robo
#endif // executa etapa do firmware do robo
} // executa etapa do firmware do robo
// camera init
esp_err_t err = esp_camera_init(&config); // configura/inicializa a camera OV2640
if (err != ESP_OK) // decisao condicional do comportamento autonomo
{ // executa etapa do firmware do robo
Serial.printf("Camera init failed with error 0x%x", err); // envia telemetria ao Monitor Serial
return; // retorna valor calculado ao chamador
} // executa etapa do firmware do robo
sensor_t *s = esp_camera_sensor_get(); // configura/inicializa a camera OV2640
//drop down frame size for higher initial frame rate
//s->set_framesize(s, FRAMESIZE_SXGA); //字节长度采样值:60000 #9 (画质高) 1280x1024
s->set_framesize(s, FRAMESIZE_SVGA); //字节长度采样值:40000 #7 (画质中) 800x600 // executa etapa do firmware do robo
//s->set_framesize(s, FRAMESIZE_QVGA); //字节长度采样值:10000 #4 (画质低) 320x240
s->set_vflip(s, 0); //图片方向设置(上下) // executa etapa do firmware do robo
s->set_hmirror(s, 0); //图片方向设置(左右) // executa etapa do firmware do robo
// WiFi.setTxPower(WIFI_POWER_19_5dBm);
WiFi.mode(WIFI_AP); // configura rede WiFi AP do robo para video e comando
WiFi.softAP(ssid, password, 5); // configura rede WiFi AP do robo para video e comando
// WiFi.softAP(ssid, password);
Serial.print("\r\n"); // envia telemetria ao Monitor Serial
startCameraServer(); // configura/inicializa a camera OV2640
Serial.print("\r\n"); // envia telemetria ao Monitor Serial
Serial.print("Camera Ready! Use 'http://"); // envia telemetria ao Monitor Serial
Serial.print(WiFi.softAPIP()); // envia telemetria ao Monitor Serial
Serial.println("' to connect"); // envia telemetria ao Monitor Serial
} // executa etapa do firmware do robo
Gravação, pareamento e teste
Grave 6.1 no UNO e 6.2 na CAM com UART desplugada, reconecte, ligue com baterias, instale o APK, conecte-se ao AP, selecione ESP32-CAM Mecanum Smart Car no app e toque conectar até Connected Successfully. Opere D-pad, giro no lugar, sliders de tilt/farol/velocidade e os 4 modos; Connected Fail indica AP perdido — reconecte o WiFi e tente de novo.
💡 Dica: qualquer comando de direção força o modo livre; reative o modo autônomo após pilotar.
⚠️ Atenção:
vflipdifere entre CAM V0.3 e V2.0; ajusteset_vflipse a imagem sair invertida.
Aplicativo KUONGSHUN (Android e iOS)
Instalação via APK da pasta 4_Android_Software_Installation_Package (Android) ou busca por kuongshun na App Store (iOS). Fluxo: conectar ao AP, abrir o app, escolher idioma, selecionar ESP32-CAM Mecanum Smart Car, tocar conectar, pilotar com vídeo ao vivo. Controles: área de vídeo com play/pausa/fechar, slider de tilt (sobe = inclina para baixo), D-pad omnidirecional com giros, sliders de farol e velocidade, chaves dos 4 modos e indicador de conexão. A ESP32-CAM opera em modo AP — access point — criando a rede KUONGSHUN-AD176 com senha 12345678 e IP fixo . O video usa MJPEG sobre HTTP — motion JPEG over hypertext transfer protocol — com multipart x-mixed-replace, onde cada frame JPEG e delimitado por boundary e empurrado em chunked encoding. A taxa util aproximada e:
onde e o bitrate, o framerate, o tamanho medio do JPEG e o tempo de compressao. SVGA () a qualidade – equilibra nitidez e latencia; UXGA trava o stream por esgotar PSRAM e banda. O enlace de comando UNO ESP32-CAM usa UART a (), com pacotes de bytes (AB modelo valor FF) no modo Web e quadros FF 55 ... no modo APP, ambos com timeout de . A potencia de TX em maximiza alcance indoor a custa de consumo, por isso video so e estavel com bateria cheia. O canal fixo reduz interferencia com roteadores domesticos.


Guia Diagnóstico (Troubleshooting)
| Sintoma | Causa raiz | Ação corretiva |
|---|---|---|
| Upload falha / timeout no UNO | UART com a CAM conectada contendendo RX/TX; placa ou porta errada | Desplugar jumper UART; selecionar Arduino UNO e COMxx; trocar cabo por dados; reinstalar CH340 |
| Upload falha na ESP32-CAM | Núcleo 3.x ou placa errada; UART conectada | Instalar ESP32 2.0.12; selecionar ESP32 Dev Module; desplugar UART no upload |
| Só aparece COM1 | Cabo só-carga ou CH340 ausente | Trocar cabo Tipo-C de dados; instalar driver da pasta 2_Programming_Preparation |
| Rede KUONGSHUN-AD176 não aparece | Bateria fraca, fiação errada, CAM sem boot | Recarregar 18650; conferir chave e LEDs; revisar UART e alimentação; regravar 5.2/6.2 |
Connected Fail no app | AP perdido ou cliente TCP antigo preso | Reconectar WiFi ao AP; fechar e reabrir app; reconectar; checar bateria |
| Imagem invertida | Variante CAM V0.3 vs V2.0 com vflip divergente | Alternar s->set_vflip(s,1/0) e set_hmirror no CameraWebServer.cpp e regravar |
| Vídeo com delay/travando | UXGA/qualidade alta sem PSRAM/banda; bateria fraca | Fixar SVGA qualidade 10-12; aproximar do robô; recarregar; canal 5 longe do roteador |
| Robô não anda / anda fraco | Somente USB sem 18650; PWM baixo; rodas no X errado | Instalar 2x18650 carregadas; elevar speeds a 250; corrigir orientação Mecanum |
| Gira ao contrário / lateral invertida | Byte de direção ou X das rodas trocado | Conferir tabela 163/92/106/149 e reinstalar rodas no X correto |
| Servo vibra / não centraliza | Braço calçado fora do 90°; queda de 5 V | Regravar Lição 2, resetar a 90°, reposicionar braço reto; recarregar baterias |
| HC-SR04 sempre 0 ou fixo | TRIG/ECHO trocados; eco preso; objeto fora do cone | Conferir D12 TRIG/D13 ECHO; testar anteparo a 20 cm; checar pulseIn/58 |
| Seguidor ignora a linha | Limiar 400/500 fora da pista; sensor alto; luz forte | Imprimir leituras no Serial; recalibrar limiar; baixar altura; sombrear pista |
| Servo inverte no app (sobe=desce) | Convenção do slider do app | Comportamento oficial: slider para cima reduz ângulo e inclina para baixo; operar invertido |
| Porta 192.168.4.1 não abre | Conectado ao roteador em vez do AP; IP errado | Conectar ao AP KUONGSHUN-AD176, manter sem internet, digitar exatamente 192.168.4.1 |
| Modo autônomo não engata | Pacote com modelo errado; modo preso em while | Reenviar comando de modo; resetar UNO; checar RXpack_func/parseData no Serial 115200 |
Servo.h: No such file or directory / does not name a type | Servo.zip não instalado ou IDE não reiniciada | Reinstalar pela tabela-mestre (Etapa 3 da Preparação), conferir pasta libraries/Servo/Servo.h, reiniciar a IDE |
esp_camera.h: No such file or directory / erro em ledcSetup | Núcleo ESP32 3.x ou pacote ESP32 ausente | Voltar ao pacote ESP32 2.0.12 do fabricante, selecionar ESP32 Dev Module, recompilar |
Expansões de engenharia (leitura densa complementar)
Aprofundamento para atingir densidade de curso: repetição analítica dos fenômenos com parametrização distinta. As rodas Mecanum possuem roletes a em torno do cubo. Cada roda gera forca perpendicular ao eixo do rolete, decomponivel em componentes longitudinal e lateral . Com quatro rodas independentes em configuracao X, a soma vetorial permite translacao omnidirecional sem mudar a orientacao do chassi. O principio formal da cinematica direta do 4WD Mecanum, com semi-distancias e do centro, raio e velocidades angulares , e:
onde e a velocidade longitudinal, a lateral e a taxa de guinada. A decomposicao por rolete explica os codigos decimais da tabela do fabricante: cada byte de 8 bits mapeia os 8 terminais de ponte H dos quatro motores via 74HC595, de modo que frentes paralelas somam (marcha 163/92) e oposicoes simetricas somam (translacao 106/149), enquanto diagonais produzem resultante a (34/129/72/20) e giros puros cancelam translacao e somam momento (83/172). A velocidade linear de cada roda segue , e a forca de tracao disponivel e limitada pelo atrito , por isso piso liso reduz derrapagem dos roletes e melhora a lateralidade. O driver usa dois canais PWM ( e ) para energia e o registrador de deslocamento para direcao, separando potencia e logica como em toda ponte H dupla. O controle de velocidade usa PWM — pulse-width modulation — com periodo e largura . O ciclo de trabalho e definido por:
onde e o duty cycle e a tensao media aplicada ao motor. No Arduino UNO, analogWrite(pino, valor) gera em (pinos e em ). O torque medio cresce com , mas abaixo de certo limiar o atrito estatico impede a partida, por isso os exemplos usam a . A energia mecanica entregue segue , e a corrente de estol dos quatro motores somados excede largamente o que o USB do PC fornece, razao pela qual a tracao so e valida com as duas celulas 18650 instaladas e chave ligada. O pino do expansor habilita as saidas em nivel baixo, e o latch transfere o byte deslocado de uma vez, evitando estados intermediarios nas pontes. O HC-SR04 mede distancia por tempo de voo do ultrassom. O gatilho de emite 8 ciclos a ; o eco retorna apos microssegundos de ida e volta. Com :
onde e a distancia ao obstaculo. O divisor usado em pulseIn(ECHO, HIGH)/58.00 deriva de . A zona cega abaixo de e o cone de exigem servo centralizado a nas leituras de desvio, e superficies absorventes inclinadas subestimam . O firmware filtra com delay(10) entre disparos para dissipar ecos multiplos, e os limiares dos modos seguimento e desvio derivam diretamente dessa resolucao centimetrica. O seguidor de linha usa tres sensores reflexivos IR com comparacao analogica. Cada canal retorna via ADC de 10 bits, onde preto absorve IR (valor baixo) e branco reflete (valor alto). O limiar particiona o espaco de observacao, e a maquina de estados mapeia as combinacoes em correcoes diferenciais. A lei de controle e proporcional por zona: erro lateral estimado gera correcao de guinada implementada como giros com PWM contra cruzeiro . A tensao lida em cada canal e:
onde e a contagem e a referencia do UNO. Calibracao com Serial.println dos tres canais sobre preto e branco define o limiar real da pista ( a conforme o lote), pois luz ambiente desloca o ponto otimo. Faixa estreita demais causa oscilacao; larga demais corta curvas. A geometria dos tres pontos a frente do eixo motor cria antecipacao natural da curva, equivalente a acao derivativa mecanica. O servo SG90 e comandado por PPM com periodo de . A largura do pulso codifica o angulo:
onde varia de a e e a largura em milissegundos. A biblioteca Servo.h abstrai o timer em write(graus), com como frente mecanica da camera. O torque exige alimentacao estavel; jitter indica queda de tensao sob carga dos motores. A varredura com passo de do exemplo produz velocidade angular , suave para calibrar o braco do pan-tilt sem forcar engrenagens. O reset ao antes do ajuste mecanico garanteDatum repetivel. A ESP32-CAM opera em modo AP — access point — criando a rede KUONGSHUN-AD176 com senha 12345678 e IP fixo . O video usa MJPEG sobre HTTP — motion JPEG over hypertext transfer protocol — com multipart x-mixed-replace, onde cada frame JPEG e delimitado por boundary e empurrado em chunked encoding. A taxa util aproximada e:
onde e o bitrate, o framerate, o tamanho medio do JPEG e o tempo de compressao. SVGA () a qualidade – equilibra nitidez e latencia; UXGA trava o stream por esgotar PSRAM e banda. O enlace de comando UNO ESP32-CAM usa UART a (), com pacotes de bytes (AB modelo valor FF) no modo Web e quadros FF 55 ... no modo APP, ambos com timeout de . A potencia de TX em maximiza alcance indoor a custa de consumo, por isso video so e estavel com bateria cheia. O canal fixo reduz interferencia com roteadores domesticos. Na prática de bancada, cada parágrafo acima converte-se em um ensaio mensurável: cronometrar os 2 s por estado da Lição 1, plotar varredura do servo contra tempo, tabular distância serial versus trena, mapear trios IR sobre preto/branco/cinza, medir RSSI e latência do MJPEG em SVGA/SXGA/QVGA, e registrar corrente de estol versus PWM — compondo o caderno de engenharia do AD176.
Solução de problemas
Olá! Sou o assistente técnico da RoboBuilders. Descreva seu problema com o Kit Robô Avançado 4WD Com Câmera AD176 - 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.