Kit Robô Tartaruga ESP32 WiFi AD177 - Curso Completo

Introdução
Este curso apresenta o Kit Robô Tartaruga ESP32 WiFi AD177, um robô móvel diferencial 2WD com ESP32 e placa de expansão, driver de motores L298N, motores N20 com redução metálica, sensor ultrassônico HC-SR04 montado sobre servo, seguidor de linha de 3 canais IR, receptor infravermelho com controle remoto e comando sem fio por WiFi em modo AP — access point — com portal em 192.168.4.1 e aplicativo KUONGSHUN, programado na IDE do Arduino — integrated development environment — com o núcleo esp32 2.0.12. É 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 do chassi em acrílico e da preparação do ambiente com driver CH340, passa por ensaios isolados de tração, ultrassom, servo e linha, avança para comportamentos autônomos de seguimento e desvio de obstáculos e controle infravermelho, e chega aos firmwares integrados de comando Web e APP com quatro modos selecionáveis, sempre com o resultado esperado de cada teste. Ao final, o leitor terá o robô montado, calibrado, navegando por linha, desviando de obstáculos, seguindo objetos e dirigível pelo navegador e pelo aplicativo.
O que você vai aprender:
- Montar o chassi tartaruga 2WD com motores N20, roda boba, servo do ultrassom e torre de acrílico
- Preparar IDE do Arduino, núcleo ESP32 2.0.12, driver CH340 e bibliotecas ESP32Servo 1.1.2 e IRremote 4.1.2
- Validar tração diferencial, telemetria HC-SR04, centragem do servo e calibração do seguidor de 3 canais
- Programar seguimento de objeto, desvio com varredura e controle por infravermelho com timeout
- Operar o modo Web em 192.168.4.1 e o modo APP com protocolo em quadros na porta 100
- Diagnosticar alimentação 18650, WiFi, upload, biblioteca e pista com matriz de sintomas e causas
Material utilizado: Kit Robô Tartaruga ESP32 WiFi AD177 disponível na loja RoboBuilders em https://robobuilders.com.br.
Visão Geral do Kit e Arquitetura de Hardware
O AD177 é um robô diferencial de duas rodas motrizes com uma terceira roda boba universal para apoio, no formato que o fabricante chama de tartaruga pelo casco em acrílico em dois andares. Um único ESP32 comanda tudo: gera os dois PWMs de velocidade, os quatro sinais de sentido da ponte H dupla L298N, o PPM do servo do ultrassom, lê o eco por tempo de voo, lê os três canais analógicos da linha e decodifica o infravermelho, além de manter o rádio WiFi em modo AP com servidor HTTP e servidor TCP. A energia vem de duas células 18650 em série com chave, alimentando em paralelo a lógica do ESP32 pela expansão e o estágio de potência do L298N. A separação mecânica em dois andares isola vibração e fiação de potência embaixo da eletrônica de sinal em cima, reduzindo ruído no ADC da linha e no eco do ultrassom.
A cinemática diferencial do tartaruga relaciona as velocidades lineares das rodas direita e esquerda com a velocidade do centro e a taxa de guinada. Com distância entre rodas e raio de roda , e velocidades angulares e , o modelo direto é:
onde é a velocidade de avanço do centro e a taxa de guinada. Marcha à frente soma velocidades iguais, giro puro usa velocidades opostas de mesmo módulo, e curva usa módulos diferentes. A velocidade linear de cada roda segue e . A força de tração disponível é limitada pelo atrito , por isso piso liso com poeira reduz aderência e o robô patina em arrancadas com duty alto. O raio de curvatura instantâneo é , e quando o robô gira em torno do próprio centro, manobra usada no desvio após ré de segurança. O código implementa as combinações como funções discretas: ambas as pontes avante para positivo, ambas a ré para negativo, pontes opostas para puro, e uma ponte parada com a outra avante para curva fechada de raio mínimo.


Inventário do kit
A lista abaixo consolida o guia de montagem em 14 passos do fabricante com os códigos reais. Cada grupo indica a função eletromecânica no conjunto, para conferência antes de apertar o primeiro parafuso.
- Placas de acrílico superior e inferior com furação do tartaruga — casco em dois andares que separa potência embaixo de sinal em cima e define frente estreita e traseira larga para orientação
- 2 motores N20 com redução metálica e suportes com porcas M2 — atuadores de tração diferencial com torque elevado em baixa rotação e giro suave característico do passeio da tartaruga
- 2 rodas de tração com pneus de borracha — conversão de torque em deslocamento com raio que entra na cinemática diferencial e na velocidade de cruzeiro
- Roda boba universal com esferas — terceiro apoio livre que permite giro puro sem arrasto e sustenta a frente do chassi
- Placa controladora ESP32 com USB Tipo-C e chip serial CH340C — cérebro único com WiFi, ADC de 12 bits, LEDC para PWM e portas para servo, ultrassom, linha e infravermelho
- Placa de expansão para ESP32 — distribuição de alimentação e sinais com barras de pinos que recebem a controladora e organizam a fiação de sensores e do L298N
- Módulo driver de motores L298N — ponte H dupla que recebe dois PWMs de velocidade e quatro sinais de sentido e entrega corrente aos dois N20
- Sensor ultrassônico HC-SR04 com suporte e braço do servo — telemetria de distância por tempo de voo montada sobre varredura para desvio e seguimento
- Servo com braço em forma de 1 e parafusos — pan de um eixo que aponta o ultrassom a 90 graus à frente, 30 graus à direita e 150 graus à esquerda na varredura
- Módulo seguidor de linha de 3 canais IR com cabo XH2.54 de 5 vias para Dupont — leitura reflexiva da pista sob o bico dianteiro com trimpot de sensibilidade por canal
- Módulo receptor infravermelho com controle remoto — comando sem fio por rajadas de 38 kHz com mapa de códigos NEC e parada por timeout
- Caixa de baterias para 2 células 18650 com chave — barramento de cerca de 7,4 V nominal que alimenta lógica e potência em paralelo
- Jogo de colunas de cobre M3 simples e duplas, parafusos M2, M3 e M1.6 com porcas e parafusos autorroscantes M1.4 — fixação e empilhamento dos andares com alturas que acomodam driver, expansão e torre
- Chicotes XH2.54, jumpers Dupont, cabo de bateria e cabo USB Tipo-C de dados — interligação de sinal e potência com distinção obrigatória entre cabo de carga e cabo de dados
- Fita preta para pista de testes e pacote de aplicativo KUONGSHUN em APK para Android com variante na App Store — ambiente de ensaio de linha e comando remoto por navegador e por aplicativo
Somatória: 15 grupos, totalizando dezenas de peças que compõem um robô diferencial completo com um ESP32, driver duplo, 2 motores com redução, 3 sensores de navegação, servo de varredura, comando infravermelho e comando WiFi em dois firmwares integrados.
Mapa de pinos e protocolos (consolidado dos .ino reais)
A tabela abaixo foi extraída dos dez sketches do fabricante. É a referência única de fiação: qualquer fio fora dela impede o modo correspondente sem acusar erro de compilação.
| Subsistema | Pino ESP32 | Direção | Protocolo | Observação |
|---|---|---|---|---|
| PWM velocidade A | GPIO 25 via canal LEDC 3 | Saída | LEDC 5 kHz 8 bits | ledcWrite(ENA, 0-255) com duty |
| PWM velocidade B | GPIO 13 via canal LEDC 4 | Saída | LEDC 5 kHz 8 bits | Mesmo duty do canal A no cruzeiro |
| Sentido ponte A | GPIO 26 IN1 e GPIO 27 IN2 | Saída | Digital | Avante LOW/HIGH, ré HIGH/LOW, freio HIGH/HIGH |
| Sentido ponte B | GPIO 14 IN3 e GPIO 12 IN4 | Saída | Digital | Mesma convenção do canal A |
| Gatilho ultrassom | GPIO 19 TRIG | Saída | Pulso 10-20 us | Dispara trem de 8 ciclos a 40 kHz |
| Eco ultrassom | GPIO 18 ECHO | Entrada | pulseIn/58 | Largura em us dividida por 58 resulta em cm |
| Servo do ultrassom | GPIO 16 | Saída | PPM 20 ms | ESP32Servo com pulsos de 500 a 2500 us, centro 90 graus |
| Linha esquerda | GPIO 32 | Entrada | ADC1 12 bits | analogRead de 0 a 4095, referência 3,3 V |
| Linha centro | GPIO 35 | Entrada | ADC1 12 bits | Canal central da decisão de marcha |
| Linha direita | GPIO 34 | Entrada | ADC1 12 bits | Canal direito da decisão de curva |
| Receptor infravermelho | GPIO 15 nos modos 7 e 10 e GPIO 5 no modo 9 | Entrada | NEC 38 kHz | Conferir fiação do passo 11 antes de gravar o modo 9; ajustar #define ao fio real |
| Rede de comando | AP KUONGSHUN-AD177 senha 12345678 | RF | WiFi 802.11 + HTTP e TCP 100 | Portal em 192.168.4.1; canal 9 no Web e 5 no APP |
O controle de velocidade usa PWM — pulse-width modulation — com período e largura . O ciclo de trabalho e a tensão média no motor são:
onde é o duty cycle, a tensão do pack 18650 e a queda de cerca de na ponte L298N. No ESP32, ledcSetup(canal, 5000, 8) cria em . O torque médio cresce com , mas abaixo do limiar de atrito estático o motor zumbe sem partir, por isso os exemplos usam a . A potência elétrica entregue é , e a corrente de estol dos dois N20 somada excede o que o USB fornece, razão pela qual tração só se valida com as duas células instaladas e chave ligada. A Lei de Ohm explica a queda nos enrolamentos e nos transistores da ponte, que aquecem em marcha lenta prolongada.
Montagem Mecânica (Assembly Guide)
A montagem segue os 14 passos do guia do fabricante na ordem original, da distinção de frente e traseira até as rodas. A regra de ouro é mecânica antes de energia: nenhum teste com bateria antes do passo da fiação conferido fio a fio, e nenhum aperto final antes da validação de giro livre e curso do servo. Cada passo indica peças, cuidados e validação, com a imagem oficial correspondente.
Passo 0 — Distinguir frente e traseira das placas
As duas placas de acrílico têm extremidade estreita e extremidade larga. A frente é o lado estreito, onde ficam o seguidor de linha e a torre do ultrassom. Monte sempre com a face da frente para cima para que a furação dos suportes coincida. Validação: sobreponha as duas placas com as frentes alinhadas e confira que os furos das colunas batem sem forçar. Teoria de apoio: a geometria define o centro de massa à frente do eixo motor, o que estabiliza a marcha e reduz empinamento em arrancada, pois o momento de reação com altura baixa gera pouca transferência de carga para trás.


💡 Dica: fotografe cada passo com o celular. A foto resolve a maioria dos diagnósticos de fiação e orientação.
Passo 1 — Fixar os motores N20 no chassi inferior
Encaixe cada N20 no suporte metálico com a porca M2 pré-alojada na cavidade do furo antes de passar o parafuso M2 por 10 de cabeça chata, e fixe o conjunto na placa inferior. Observe a orientação dos suportes para que os eixos fiquem coaxiais e as caixas de redução para dentro. Validação: gire cada eixo com o dedo e sinta a redução suave sem pontos duros. Teoria de apoio: a redução multiplica o torque pelo inverso da relação e divide a rotação na mesma proporção, com potência mecânica conservada a menos do rendimento das engrenagens. O N20 metálico entrega passeio lento e forte, ideal para seguimento fino a baixa velocidade sem trepidação.

⚠️ Atenção: porca fora da cavidade espana o suporte. Aloje a porca primeiro e aperte com firmeza moderada para não trincar o acrílico.
Passo 2 — Montar o seguidor de linha de 3 canais
Fixe quatro colunas de cobre M3 por 7 com parafusos M3 por 6 de cabeça chata na região do bico, alinhe o módulo de três vias sobre as colunas e trave com mais quatro parafusos, e conecte o chicote XH2.54 de 5 vias ao conector do módulo. Validação: módulo paralelo à placa a cerca de um dedo de altura do solo futuro, sem inclinação lateral. Teoria de apoio: cada canal tem um LED emissor infravermelho e um fototransistor receptor. O preto absorve e o branco reflete, de modo que a tensão do divisor varia com a refletância . A leitura do ESP32 é:
onde é a contagem de 12 bits. O limiar particiona preto e branco, e o trimpot desloca o ponto de transição. Altura excessiva dilui o contraste e exige recalibração.

Passo 3 — Montar a roda boba universal
Fixe duas colunas M3 por 7 na furação dianteira com quatro parafusos M3 por 6 e aparafuse a roda boba sobre elas. Validação: esfera gira livre em qualquer direção e a placa fica nivelada quando apoiada nos dois eixos traseiros mais a boba. Teoria de apoio: o apoio em três pontos define um plano estável, e a boba universal impõe restrição holonômica nula, permitindo giro puro com e sem arrasto lateral. Folga excessiva aqui vira oscilação de guinada na linha, corrigida com coluna bem travada.

Passo 4 — Montar o módulo driver L298N
Fixe quatro colunas M3 por 7 na região central inferior, alinhe o L298N sobre elas respeitando a orientação com bornes de motores para os lados e borne de alimentação para trás, e trave com oito parafusos. Validação: dissipador sem encostar no acrílico e bornes acessíveis para a fiação do passo 11. Teoria de apoio: cada ponte H tem quatro chaves em H que invertem a polaridade no motor. A queda nos Darlingtons converte-se em calor , por isso marcha lenta prolongada com duty alto aquece o dissipador e exige pausas entre ensaios.

⛔ Perigo: nunca alimente o L298N invertido. Inversão de bateria destrói a ponte e a expansão em segundos. Confira polaridade duas vezes antes do primeiro ON.
Passo 5 — Montar a controladora ESP32 e a expansão
Fixe quatro colunas M3 por 7 na placa inferior, alinhe a expansão sobre elas e trave, e encaixe a controladora ESP32 nos barramentos da expansão até o fundo sem pinos tortos. Validação: placa paralela, sem folga, com USB Tipo-C acessível pela lateral para upload. Teoria de apoio: a expansão é um distribuidor passivo de alimentação e sinal. O contato intermitente em barra de pinos gera reset espúrio por queda de durante pico de corrente dos motores, sintoma clássico de placa mal assentada que se confunde com defeito de firmware.

Passo 6 — Montar as colunas de sustentação de 40 mm
Fixe as quatro colunas longas M3 por 40 nos cantos da placa inferior com parafusos M3 por 10. Elas definem o vão entre andares que acomoda driver, expansão e chicotes. Validação: quatro topos no mesmo plano, sem coluna bamba. Teoria de apoio: o vão adequado garante convecção ao redor do L298N e raio de curvatura suave aos chicotes, evitando fadiga por dobra fechada que rompe cobre com a vibração da marcha.

Passo 7 — Montar a caixa de baterias na placa superior
Fixe a caixa de 2 células 18650 na placa superior com quatro parafusos M3 por 10 e porcas M3, respeitando a orientação com fios para trás e frente da placa alinhada com a frente inferior. Não instale as células ainda. Validação: caixa firme, sem tocar as colunas, com chave e fios livres. Teoria de apoio: duas células em série somam tensão nominal e mantêm a capacidade em ampère-hora. Chave desligada durante a fiação evita curto acidental de ferramenta sobre os bornes.

⚠️ Atenção: use apenas células 18650 íntegras, sem amassados ou capa rasgada, e sempre em par com cargas semelhantes. Célula danificada é risco de incêndio.
Passo 8 — Montar o servo do ultrassom
Fixe o servo na furação da placa superior com dois parafusos M2 por 10 de cabeça redonda e porcas M2, com o eixo para cima e a face do eixo voltada para a frente. Validação: servo perpendicular, sem folga rotacional na caixa. Teoria de apoio: o servo será o pan do ultrassom. O centro mecânico a 90 graus deve coincidir com a frente geométrica, e qualquer desalinhamento aqui vira erro sistemático de na varredura de desvio, que o firmware não compensa.

Passo 9 — Montar o ultrassom sobre o servo em três subetapas
Primeiro fixe o HC-SR04 no suporte em U com quatro parafusos M1.6 por 10 e porcas M1.6 com as cápsulas para frente e sem tocar os pinos. Depois fixe o braço em forma de 1 no eixo do servo com dois parafusos autorroscantes M1.4 por 5. Por fim una o suporte ao braço com o parafuso pequeno do kit do servo. Validação: conjunto gira solidário ao eixo sem escorregar e sem cabo tracionando. Teoria de apoio: o ultrassom mede por tempo de voo com . O suporte rígido garante que o eixo acústico acompanhe o ângulo comandado, e folga no braço espalha o cone de e degrada a comparação direita-esquerda do desvio.



Passo 10 — Montar o receptor infravermelho
Fixe o módulo receptor na lateral dianteira com dois parafusos M2 por 10 e porcas M2, com o olho receptor para frente e sem obstrução do casco. Validação: LED do módulo visível e olho desobstruído em 180 graus frontais. Teoria de apoio: o receptor usa fotodiodo com filtro de 38 kHz e decodificador NEC. Obstrução parcial reduz o alcance de metros para centímetros e gera quadros corrompidos que o firmware descarta, sintoma que se confunde com pilha fraca do controle.

Passo 11 — Fiação completa de sinal e potência
Com a chave desligada e sem baterias, ligue os motores aos bornes do L298N, os enables e sentidos à expansão conforme o mapa de pinos, o TRIG e o ECHO do ultrassom, o sinal do servo, os três canais da linha e o sinal do receptor IR, e o cabo de bateria em paralelo na expansão e no L298N. Distinga o chicote XH2.54 com trava do jumper Dupont avulso. Validação: cada fio puxado de leve sem soltar, polaridade da bateria conferida com multímetro, e USB Tipo-C de dados separado do cabo de carga. Teoria de apoio: a malha de potência carrega ampères com queda nos contatos, enquanto a malha de sinal carrega microampères sensível a ruído. Trançar sinal longe dos fios de motor reduz diafonia no ADC da linha e no eco.

⛔ Perigo: confira duas vezes o paralelo da bateria na expansão e no L298N antes de inserir as células. Curto no barramento funde trilhas e pode inflar células 18650.
Passo 12 — Unir os andares superior e inferior
Apoie a placa superior sobre as quatro colunas de 40 mm, passe os chicotes pelo vão sem prensar, e trave com quatro parafusos M3 por 10. Validação: vão uniforme, nenhum fio esmagado, torre do ultrassom livre acima do casco. Teoria de apoio: a compressão de chicote contra coluna cria falha intermitente por vibração, o defeito mais difícil de diagnosticar porque some com o robô parado na bancada e reaparece em marcha.

Passo 13 — Montar as rodas de tração
Encaixe as duas rodas nos eixos dos N20 até o fundo com pressão firme e simétrica. Validação: rodas coplanares, sem bamboleio, com giro livre e sem roçar no acrílico. Teoria de apoio: excentricidade de roda injeta oscilação periódica na odometria com frequência , que o seguidor de linha interpreta como erro de pista e corrige com zigue-zague. Roda bem centrada é pré-requisito de linha lisa.


Preparação do Ambiente (Programming Preparation)
A preparação instala a cadeia completa de gravação antes do primeiro upload: IDE do Arduino, driver do conversor serial CH340, núcleo ESP32 e bibliotecas do kit. Nenhuma lição compila sem as quatro camadas, e a maioria dos erros de porta e de biblioteca nasce aqui. Reserve uma hora calma, com cabo Tipo-C de dados conhecido e internet estável para o gerenciador de placas.
IDE do Arduino e driver CH340
Baixe a IDE no site oficial do Arduino e instale a versão estável para Windows ou macOS conforme o guia do fabricante. Conecte a ESP32 com cabo Tipo-C de dados e observe se o sistema cria uma porta serial. Se aparecer apenas COM1 no Windows ou nenhum dispositivo USB com VID 0x1A86 no macOS, instale manualmente o pacote CH340 da pasta de recursos do kit e reinicie. Validação: Gerenciador de Dispositivos mostra a porta sem triângulo amarelo, e a IDE lista a COM correspondente em Ferramentas e Porta. Teoria de apoio: o CH340 converte USB em UART TTL para o bootloader do ESP32. Cabo de carga sem fios de dados alimenta a placa sem criar porta, o erro mais comum do primeiro upload, que se resolve trocando o cabo e não o driver.


⚠️ Atenção: use cabo Tipo-C de dados, não cabo de carga. Sem fios D+ e D-, a placa acende mas a porta nunca aparece.
Núcleo ESP32 2.0.12 na IDE
Abra Arquivo e Preferências e adicione a URL do gerenciador da Espressif em URLs Adicionais para Gerenciadores de Placas. Em Ferramentas, Placa e Gerenciador de Placas, busque esp32 e instale a versão 2.0.12, sem aceitar a latest automaticamente. Selecione ESP32 Dev Module em Ferramentas e Placa. Validação: o menu mostra ESP32 Dev Module e o exemplo WiFiScan compila sem erro. Teoria de apoio: o núcleo entrega compilador Xtensa, bootloader, WiFi, LEDC e ADC. A versão 2.0.12 preserva a API ledcSetup e ledcAttachPin usada em todos os sketches do kit. O núcleo 3.x removeu essas funções e quebra 100 por cento dos códigos do AD177 com erro de compilação, por isso fixar a versão é inegociável e o primeiro item do troubleshooting.


⛔ Perigo: núcleo ESP32 3.x não compila os sketches do kit. Se a compilação acusar
ledcSetup was not declared, volte o núcleo para 2.0.12 no Gerenciador de Placas.
Tabela-mestre de bibliotecas do curso
Todas as dependências externas do curso estão consolidadas abaixo com versão pinada e duas vias de instalação. Instale uma vez e confira antes de cada lição pelo quadro da lição.
Biblioteca (#include) | Buscar no Gerenciador | Versão usada no curso | Download ZIP (espelho oficial) | Lições |
|---|---|---|---|---|
ESP32Servo por Kevin Harrington | ESP32Servo | 1.1.2 | ESP32Servo no GitHub madhephaestus/ESP32Servo | 3, 5, 6, 10 |
IRremote por shirriff, z3t0, ArminJo | IRremote | 4.1.2 | IRremote no GitHub Arduino-IRremote/Arduino-IRremote | 7, 9, 10 |
WiFi do núcleo ESP32 | embutida no núcleo 2.0.12, nada a instalar | 2.0.12 | acompanha o pacote ESP32 da Espressif | 8, 9, 10 |
esp_http_server do IDF | embutida no núcleo, nada a instalar | 2.0.12 | acompanha o pacote ESP32 | 8, 9 |
Via Gerenciador, recomendada: Sketch, Incluir Biblioteca, Gerenciar Bibliotecas, buscar o nome exato, selecionar a versão pinada no seletor, Instalar e reiniciar a IDE. Via ZIP: baixar o ZIP no espelho oficial, Sketch, Incluir Biblioteca, Adicionar Biblioteca .ZIP, selecionar o arquivo e reiniciar a IDE. Conferência: Arquivo, Exemplos, ESP32Servo, Sweep deve abrir e compilar para ESP32 Dev Module sem No such file or directory, e Arquivo, Exemplos, IRremote, SimpleReceiver deve abrir e compilar. Dependências transitivas: a 4.1.2 do IRremote não exige bibliotecas auxiliares no ESP32. Erro típico ESP32Servo.h: No such file or directory indica pasta libraries/ESP32Servo ausente ou IDE aberta durante a cópia sem reiniciar.

💡 Dica: copie a pasta
librariesdo kit para a pasta de sketches sem alterar o caminho do Sketchbook, ou instale pelas versões pinadas acima. Nunca misture as duas vias com versões diferentes.
Primeiro upload e Monitor Serial
Com a placa conectada, selecione ESP32 Dev Module e a COM correta, abra o sketch da lição, clique em Verificar e depois em Carregar, e aguarde a barra de progresso com pontos e o aviso de sucesso. Abra o Monitor Serial com o baud rate do sketch, 9600 na maioria das lições e 115200 no modo APP, com retorno de linha adequado. Validação: mensagens de telemetria aparecem sem lixo de caracteres, o que confirma cristal, baud e aterramento íntegros. Teoria de apoio: o upload usa o bootloader ROM via RTS e DTR para reset automático. Falha de conexão com Failed to connect pede BOOT segurado na placa, cabo de dados e porta correta, nessa ordem, antes de suspeitar de driver.
Lições na Ordem do Tutorial do Fabricante
As dez lições abaixo seguem a ordem do PDF ESP32 WiFi Intelligent Turtle Car V2.0.24.6.24, sem reordenar nem fundir. Cada lição mantém o padrão interno: teoria do fenômeno com equações, componentes, conexões, bibliotecas, firmware comentado linha a linha, gravação com resultado esperado e avisos. Grave uma lição por vez e valide antes de avançar, porque os modos integrados 9 e 10 pressupõem tração, ultrassom, servo, linha e infravermelho já funcionais isoladamente.
Lição 1 — Colocar o carro em movimento
A primeira lição valida a cadeia completa de potência: ESP32, L298N, dois N20 e baterias. O sketch aciona as quatro combinações de ponte em sequência de dois segundos: avante, ré, esquerda e direita, com parada. É o ensaio de fumaça do robô: se ele anda nas quatro direções, a fiação de potência e os sentidos estão corretos. A teoria central é a ponte H: cada motor tem dois terminais comandados por IN1/IN2 e IN3/IN4, com enables em nível alto liberando corrente. A tabela de verdade implementada é avante LOW/HIGH em ambas as pontes, ré HIGH/LOW, esquerda com pontes opostas em um sentido e direita com o oposto, e parada com todos em HIGH. A velocidade aqui é plena porque os enables vão a HIGH digital, sem PWM, o que entrega com . A potência dissipada na ponte segue e o aquecimento é normal em bancada curta. O período de dois segundos por estado deriva de delay(2000), tempo suficiente para observar o sentido sem o robô sair da mesa se elevado no suporte. A mensagem de cada estado no Monitor Serial a 9600 bps confirma a máquina de estados mesmo sem ver o robô andar.
onde é a tensão plena no motor nesta lição sem PWM. Nas lições seguintes o LEDC modulará entre 0 e 1 para controlar velocidade com a mesma ponte e os mesmos sentidos validados aqui. A cinemática diferencial prevê que avante soma , ré soma negativa, e giros usam para puro com . Se uma roda gira invertida, inverta os dois fios dela no borne do L298N com a bateria removida, nunca no código, para preservar o mapa de sentidos das lições integradas.
| Componente necessário | Função no ensaio |
|---|---|
| Chassi montado com 2 N20 e rodas | Planta de tração diferencial sob teste |
| ESP32 com expansão | Geração dos sentidos e enables |
| Driver L298N | Estágio de potência das duas pontes |
| 2 células 18650 com chave | Barramento de potência da tração |
| Cabo Tipo-C de dados | Upload do sketch de marcha |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Enable A | GPIO 25 | Saída HIGH |
| IN1/IN2 | GPIO 26/27 | Saída digital |
| IN3/IN4 | GPIO 14/12 | Saída digital |
| Enable B | GPIO 13 | Saída HIGH |
📦 Bibliotecas desta lição: nenhuma — o código usa
digitalWrite()edelay()nativos, sem biblioteca externa.
//www.kuongshun.com
// The direction of the car's movement
// ENA ENB IN1 IN2 IN3 IN4 Description
// HIGH HIGH HIGH LOW LOW HIGH Car is runing forward
// HIGH HIGH LOW HIGH HIGH LOW Car is runing back
// HIGH HIGH LOW HIGH LOW HIGH Car is turning left
// HIGH HIGH HIGH LOW HIGH LOW Car is turning right
// HIGH HIGH LOW LOW LOW LOW Car is stoped
// HIGH HIGH HIGH HIGH HIGH HIGH Car is stoped
// LOW LOW N/A N/A N/A N/A Car is stoped
//define L298n module IO Pin
#define ENA 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 13 // cria constante simbolica para pino ou parametro do hardware
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(ENA,HIGH); //enable L298n A channel
digitalWrite(ENB,HIGH); //enable L298n B channel
digitalWrite(IN1,LOW); //set IN1 LOW level
digitalWrite(IN2,HIGH); //set IN2 HIGH level
digitalWrite(IN3,LOW); //set IN3 low level
digitalWrite(IN4,HIGH); //set IN4 hight level
Serial.println("Forward");//send message to serial monitor
}
void Back(){ // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(ENA,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(ENB,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN1,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right(){ // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(ENA,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(ENB,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN1,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Left"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left(){ // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(ENA,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(ENB,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN1,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4,LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop(){ // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(IN1,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4,HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Stop"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
//before execute loop() function,
//setup() function will execute first and only execute once
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
Serial.begin(9600);//open serial and set the baudrate
pinMode(IN1,OUTPUT);//before useing io pin, pin mode must be set first
pinMode(IN2,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
}
//Repeat execution
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
Forward(); //go forward
delay(2000);//delay 2000 ms
Back(); //go back
delay(2000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Left(); //turning left
delay(2000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Right(); //turning right
delay(2000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Stop(); //Stop
delay(2000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
Gravação: conecte o Tipo-C de dados, selecione ESP32 Dev Module e a COM, clique em Carregar e aguarde o sucesso. Desconecte o USB, apoie o robô com as rodas livres ou leve ao chão livre, instale as duas 18650 e ligue a chave. Resultado esperado: avante por 2 s, ré por 2 s, esquerda por 2 s, direita por 2 s, parada por 2 s, em ciclo, com mensagens Forward, Back, Left, Right e Stop no Monitor a 9600 quando conectado. Se uma direção sai trocada, desligue, remova as baterias e inverta os dois fios do motor correspondente no borne. Se nada anda mas o Serial avança, suspeite de bateria fraca ou chave desligada, porque o USB sozinho não sustenta os N20.
⚠️ Atenção: primeiro teste sempre no chão livre ou com o robô suspenso. Tração plena em bancada derruba o robô e rompe a torre do ultrassom.
Lição 2 — Módulo sensor ultrassônico e Monitor Serial
A segunda lição isola a telemetria de distância que alimentará o seguimento e o desvio. O sketch dispara o TRIG, mede o ECHO com pulseIn e imprime a distância em centímetros a 9600 bps. O princípio é o tempo de voo: o módulo emite 8 ciclos a 40 kHz e o eco retorna após ida e volta até o obstáculo. Com velocidade do som , a distância é metade do percurso total. O divisor 58 converte microssegundos em centímetros porque . O período de medição acima de 60 ms evita que o eco tardio de um disparo contamine o seguinte, e o delay(10) entre leituras mais o delay(100) do laço garantem janela limpa. A zona morta abaixo de 2 cm e o cone de cerca de 15 graus exigem alvo plano e perpendicular na bancada para leitura estável. Superfície absorvente como tecido ou inclinada subestima a distância ou perde o eco, fenômeno que reaparecerá como leitura zero ou máxima nos modos autônomos.
onde é a distância e a largura do pulso de eco. A resolução de do fabricante deriva do clock de microssegundos do ESP32, e o alcance de 2 cm a 450 cm cobre da mesa ao corredor. A precisão prática em sala é de poucos centímetros até 2 m, degradando com vento de ventilador e ruído ultrassônico de impacto. O pino TRIG em GPIO 19 como saída e o ECHO em GPIO 18 como entrada dedicam o par ultrassônico sem conflito com PWM e servo, e a leitura bloqueante de pulseIn impõe que os modos autônomos intercalem medição e movimento em fatias curtas.
| Componente necessário | Função no ensaio |
|---|---|
| HC-SR04 na torre | Emissor e receptor do trem ultrassônico |
| ESP32 com expansão | Gatilho, cronometria e cálculo |
| Cabo USB de dados | Telemetria no Monitor Serial |


| Conexão validada | Pino | Sentido |
|---|---|---|
| TRIG | GPIO 19 | Saída |
| ECHO | GPIO 18 | Entrada |
| VCC/GND | 5 V e GND da expansão | Alimentação |
📦 Bibliotecas desta lição: nenhuma — o código usa
pulseIn()nativo, sem biblioteca externa.
//www.kuongshun.com
float checkdistance() // define rotina de atuacao, leitura ou protocolo do robo
{
digitalWrite(19, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(2); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(19, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(10); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(19, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
float distance = pulseIn(18, HIGH) / 58.00; // mede a largura do pulso de eco para calcular a distancia por tempo de voo
delay(10); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
return distance; // devolve o valor calculado ao chamador da funcao
}
void Ultrasonic_Sensor_Module() // define rotina de atuacao, leitura ou protocolo do robo
{
int Distance = 0; // define rotina de atuacao, leitura ou protocolo do robo
Distance = checkdistance(); // executa etapa do firmware do robo tartaruga
Serial.print("Distance:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.print(Distance); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println("CM"); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
void setup() // define rotina de atuacao, leitura ou protocolo do robo
{
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
pinMode(19, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(18, INPUT); // configura o pino como entrada ou saida digital antes do uso
}
void loop() // define rotina de atuacao, leitura ou protocolo do robo
{
Ultrasonic_Sensor_Module(); // executa etapa do firmware do robo tartaruga
}
Gravação: selecione placa e porta, carregue e abra o Monitor Serial a 9600 bps. Resultado esperado: linhas Distance: XX CM atualizando cerca de dez vezes por segundo, caindo ao aproximar a mão e subindo ao afastar. Aponte para parede lisa a 30 cm e confira leitura entre 28 e 32. Se a leitura trava em zero, confira TRIG e ECHO trocados. Se oscila sem alvo, afaste de ventilador e de outro ultrassom na bancada. Se mostra lixo de caracteres, ajuste o baud do Monitor para 9600 exatamente.
💡 Dica: valide com régua na bancada antes de ir ao chão. Telemetria calibrada aqui evita seguimento nervoso e desvio cego nas lições 5 e 6.
Lição 3 — Servo pan e correção do ângulo
A terceira lição domina o pan que carrega o ultrassom e corrige o zero mecânico do braço. O sketch centraliza a 90 graus por um segundo e varre de 0 a 180 e de volta com passo de um grau a cada 10 ms. A teoria é o PPM de 20 ms: a largura do pulso entre cerca de 0,5 ms e 2,5 ms codifica o ângulo, com 1,5 ms ao centro. A biblioteca ESP32Servo abstrai os timers LEDC do ESP32 em attach com pulsos de 500 a 2500 us e write em graus. A velocidade de varredura resultante é de cerca de 100 graus por segundo, suave para observar simetria sem forçar engrenagens. O ajuste mecânico usa o reset: com o servo comandado a 90 graus, desliga-se o sinal, solta-se o braço, realinha-se à frente e reencaixa-se, eliminando erro sistemático que deslocaria a varredura do desvio.
onde é o ângulo e a largura do pulso. O centro de 90 graus corresponde a e define a frente do robô. O torque de cerca de exige 5 V estável, e jitter com motores ligados indica queda de barramento, não defeito do servo. O pino GPIO 16 dedicado evita conflito com os PWMs de tração nos canais 3 e 4 e com o ADC da linha. A repetibilidade do zero mecânico determina a simetria das leituras a 30 e 150 graus no desvio, e erro aqui vira preferência espúria por um lado.
| Componente necessário | Função no ensaio |
|---|---|
| Servo com braço em 1 | Pan do ultrassom com centro a 90 graus |
| ESP32 com expansão | Geração do PPM de 20 ms |
| 2 células 18650 | Corrente de pico do servo sob carga |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Sinal do servo | GPIO 16 | Saída PPM |
| Alimentação | 5 V e GND | Alimentação |
📦 Bibliotecas desta lição:
ESP32Servopor Kevin Harrington, John K. Bennett (versão 1.1.2).
- Via Gerenciador (recomendado):
Sketch > Incluir Biblioteca > Gerenciar Bibliotecas…→ buscarESP32Servo→ selecionar1.1.2→Instalar→ reiniciar a IDE.- Via ZIP: baixar em madhephaestus/ESP32Servo (
Code > Download ZIP) →Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP…→ reiniciar a IDE.- Conferência:
Arquivo > Exemplos > ESP32Servo > Sweepdeve abrir e compilar semNo such file or directory.
//www.kuongshun.com
#include <ESP32Servo.h> // inclui a biblioteca necessaria ao projeto
#define servo_PIN 16 // cria constante simbolica para pino ou parametro do hardware
Servo myservo; // executa etapa do firmware do robo tartaruga
void setup() // define rotina de atuacao, leitura ou protocolo do robo
{
myservo.attach(servo_PIN,500,2500); // associa o objeto servo ao pino de sinal com pulsos de 500 a 2500 microssegundos
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(1000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
void loop() // define rotina de atuacao, leitura ou protocolo do robo
{
for(int i=0;i<180;i++){ // laco de varredura incremental do ensaio ou da vigilância de modo
myservo.write(i); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(10); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
delay(1000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i=180;i>0;i--){ // laco de varredura incremental do ensaio ou da vigilância de modo
myservo.write(i); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(10); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
delay(1000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
Gravação: carregue, desconecte o USB, instale as baterias e ligue. Resultado esperado: torre vai a 90 graus, pausa um segundo e varre de lado a lado simetricamente. Se a varredura é assimétrica, pressione reset na ESP32 para voltar a 90 graus, desligue, solte o braço, alinhe à frente e reencaixe. Para alterar curso, edite os limites do for e o delay(10) e recarregue. Se treme com motor ligado, recarregue as 18650, porque queda de barramento gera jitter antes de qualquer defeito mecânico.
⚠️ Atenção: nunca force o braço com a mão ligada. O torque da redução quebra dentes com facilidade. Ajuste sempre com o servo comandado a 90 graus e desligado no instante do reencaixe.
Lição 4 — Seguidor de linha de 3 canais
A quarta lição fecha a primeira malha sensorial completa: três sensores reflexivos comandando a tração diferencial para permanecer sobre a fita preta. O sketch lê os três ADCs, compara com o limiar e aplica a máquina de estados: só o centro preto avança, preto à direita corrige à direita, preto à esquerda corrige à esquerda, tudo branco conforme a variante para ou avança, e tudo preto avança sobre cruzamento. A teoria é a refletância: o preto absorve infravermelho e devolve contagem baixa, o branco reflete e devolve contagem alta, com o trimpot deslocando a curva de transição. O ADC do ESP32 tem 12 bits de 0 a 4095 com referência de 3,3 V, o que explica limiares na casa das centenas nesta lição isolada e de 2000 na integrada, conforme iluminação e altura. A lei de controle é proporcional por zona com duas intensidades: correção forte travando uma roda e correção suave com turnSpeed de 120 contra cruzeiro de 200, o que suaviza a entrada em curva sem perder a linha. A geometria com três pontos à frente do eixo cria antecipação natural equivalente a ação derivativa mecânica.
onde é a contagem e a máquina de oito combinações. A calibração imprime os três canais sobre branco e sobre preto e posiciona o limiar no meio do vão, tipicamente entre 400 e 600 nesta lição. Curva fechada demais para a velocidade estoura a pista por inércia com , e a correção é reduzir cruzeiro ou suavizar o raio com fita sem quina. Luz solar direta satura os fototransistores e apaga o contraste, exigindo ensaio em sombra.
| Componente necessário | Função no ensaio |
|---|---|
| Seguidor de 3 canais com trimpots | Leitura reflexiva da pista |
| Fita preta sobre fundo claro | Pista de contraste calibrável |
| ESP32, L298N, N20 e 18650 | Malha sensor-motora completa |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Linha esquerda | GPIO 32 | Entrada analógica |
| Linha centro | GPIO 35 | Entrada analógica |
| Linha direita | GPIO 34 | Entrada analógica |
| Tração | GPIOs 25/26/27/14/12/13 | Saída LEDC e digital |
📦 Bibliotecas desta lição: nenhuma — o código usa
analogRead()e LEDC nativos do núcleo ESP32, sem biblioteca externa.
//www.kuongshun.com
//Line Tracking IO define
#define LEFT_LINE_TRACJING 32 // cria constante simbolica para pino ou parametro do hardware
#define CENTER_LINE_TRACJING 35 // cria constante simbolica para pino ou parametro do hardware
#define right_LINE_TRACJING 34 // cria constante simbolica para pino ou parametro do hardware
int Left_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Center_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Right_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Black_Line = 500;//small is black
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define carSpeed 200 // cria constante simbolica para pino ou parametro do hardware
#define turnSpeed 120 // cria constante simbolica para pino ou parametro do hardware
void Forward() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); //set IN1 LOW level
digitalWrite(IN2, HIGH); //set IN2 HIGH level
digitalWrite(IN3, LOW); //set IN3 low level
digitalWrite(IN4, HIGH); //set IN4 hight level
Serial.println("go forward!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("go back!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("go left!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left_small() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, turnSpeed); //enable L298n A channel
ledcWrite(ENB, turnSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("go left!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Right_small() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, turnSpeed); //enable L298n A channel
ledcWrite(ENB, turnSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("go right!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
pinMode(LEFT_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(CENTER_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(right_LINE_TRACJING, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN1, OUTPUT); //before useing io pin, pin mode must be set first
pinMode(IN2, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
Left_Tra_Value = analogRead(LEFT_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
Center_Tra_Value = analogRead(CENTER_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
Right_Tra_Value = analogRead(right_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
/*Serial.println("l,c,r:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Left_Tra_Value); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Center_Tra_Value); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Right_Tra_Value);*/ // envia telemetria ao Monitor Serial para validacao do ensaio
if (Left_Tra_Value > Black_Line && Center_Tra_Value <= Black_Line && Right_Tra_Value > Black_Line) // decisao condicional que seleciona o comportamento autonomo
{
Forward(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value < Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Right(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Right_small(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value >= Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Left_small(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value < Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Left(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Stop(); // executa etapa do firmware do robo tartaruga
}
else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) // ramo alternativo da decisao de navegacao autonoma
{
Forward(); // executa etapa do firmware do robo tartaruga
}
}
Gravação e calibração: carregue, desconecte o USB e ligue com baterias. Com o robô suspenso, aproxime cada sonda da fita preta e confira o LED correspondente acendendo, ajustando o trimpot até apagar no branco e acender no preto. Faça pista oval sem quina com fita de 19 mm sobre piso claro. Resultado esperado: centro preto avança, desvios laterais corrigem para o lado do preto, e o robô completa voltas sem sair. Se oscila, reduza carSpeed de 200 para 150. Se ignora a linha, refaça a calibração sob a luz do ensaio, pois limiar de bancada não vale para sala iluminada.
💡 Dica: desative temporariamente as impressões de debug para ganhar ciclo, mas mantenha o bloco comentado de
Serial.printlndos três canais para recalibrar sempre que trocar de piso.
Lição 5 — Carro seguidor de objeto
A quinta lição transforma a telemetria em comportamento: manter distância de um alvo móvel à frente usando apenas o ultrassom fixo a 90 graus. O sketch centra o servo, mede a distância e aplica quatro faixas: abaixo de 15 cm recua devagar, entre 15 e 20 para, entre 20 e 25 avança devagar, entre 25 e 50 avança pleno, e fora disso para por perda de alvo. A teoria é o controle por zonas com histerese implícita: a faixa morta de 15 a 20 cm evita oscilação de caça ao redor do ponto, e as velocidades reduzidas a 60 e 70 por cento do cruzeiro de 255 suavizam aproximação e afastamento sem solavanco. O tempo de ciclo com medição bloqueante de pulseIn mais LEDC contínuo cria amostragem de cerca de 10 Hz, suficiente para alvo a passo humano. Alvo pequeno ou absorvente subestima a distância e o robô aproxima demais, enquanto parede lateral no cone gera leitura fantasma que paralisa o avanço. A equação de malha mostra que o erro de distância comanda diretamente o duty, sem integrador, o que elimina windup mas deixa erro residual de poucos centímetros aceitável para brinquedo seguidor.
onde é a leitura em centímetros e a velocidade comandada com de duty 255. A faixa de 20 cm é o ponto de equilíbrio programado, e a perda acima de 50 cm trava por segurança em vez de acelerar ao infinito. A física do ultrassom impõe que o alvo tenha pelo menos a largura do cone a cada distância, com diâmetro iluminado . Mão aberta a 30 cm funciona, dedo isolado falha intermitente. O servo fixo a 90 graus elimina variável de apontamento e isola o teste de controle longitudinal antes da varredura lateral da lição seguinte.
| Componente necessário | Função no ensaio |
|---|---|
| HC-SR04 centrado a 90 graus | Medição frontal contínua |
| Servo travado à frente | Eliminação da variável de pan |
| ESP32, L298N, N20 e 18650 | Atuação proporcional por zonas |
| Alvo móvel como caixa ou mão | Referência de distância |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Servo | GPIO 16 | Saída PPM |
| TRIG/ECHO | GPIO 19/18 | Saída/Entrada |
| Tração | LEDC 3/4 com IN1/IN2/IN3/IN4 | Saída |
📦 Bibliotecas desta lição:
ESP32Servopor Kevin Harrington, John K. Bennett (versão 1.1.2, mesma da Lição 3, nada a baixar).
- Conferência:
Arquivo > Exemplos > ESP32Servo > Sweepcompila. Se o erro forESP32Servo.h: No such file, reinstale pela tabela-mestre e reinicie a IDE.
//www.kuongshun.com
#include <ESP32Servo.h> //servo library
Servo myservo; // create servo object to control servo
#define Echo 18 // cria constante simbolica para pino ou parametro do hardware
#define Trig 19 // cria constante simbolica para pino ou parametro do hardware
#define servoPIN 16 // cria constante simbolica para pino ou parametro do hardware
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define carSpeed 255 // cria constante simbolica para pino ou parametro do hardware
int rightDistance = 0, leftDistance = 0, middleDistance = 0; // define rotina de atuacao, leitura ou protocolo do robo
int UT_distance = 0; // define rotina de atuacao, leitura ou protocolo do robo
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Forward"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Left"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Forward_slow(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.6*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.6*carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Back_slow() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.7*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.7*carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
//Ultrasonic distance measurement Sub function
int Distance_detection() { // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(2); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(20); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
float Fdistance = pulseIn(Echo, HIGH); // mede a largura do pulso de eco para calcular a distancia por tempo de voo
Fdistance= Fdistance / 58; // executa etapa do firmware do robo tartaruga
return (int)Fdistance; // devolve o valor calculado ao chamador da funcao
}
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
myservo.attach(servoPIN,500,2500); // associa o objeto servo ao pino de sinal com pulsos de 500 a 2500 microssegundos
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
pinMode(Echo, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(Trig, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN1, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN2, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
Stop(); // executa etapa do firmware do robo tartaruga
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
UT_distance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.println(UT_distance); // envia telemetria ao Monitor Serial para validacao do ensaio
if (UT_distance < 15) { // decisao condicional que seleciona o comportamento autonomo
Back_slow(); // executa etapa do firmware do robo tartaruga
} else if (15 <= UT_distance && UT_distance <= 20) { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
} else if (20 <= UT_distance && UT_distance <= 25) { // ramo alternativo da decisao de navegacao autonoma
Forward_slow(); // executa etapa do firmware do robo tartaruga
} else if (25 <= UT_distance && UT_distance <= 50) { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
} else { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
}
}
Gravação: carregue, leve ao chão livre com baterias e ligue. Resultado esperado: com caixa a 40 cm o robô avança, a 22 cm avança devagar, a 18 cm para, e a 10 cm recua devagar até estabilizar perto de 18 cm. Afaste a caixa além de 60 cm e ele para por perda. Se avança sem parar, confira ECHO solto que lê zero convertido em marcha. Se recua sem alvo, confiraeco preso em HIGH por curto. Ajuste os limiares 15, 20, 25 e 50 no loop para sala pequena ou corredor longo, mantendo a faixa morta de pelo menos 5 cm.
⚠️ Atenção: teste de seguimento exige área livre de 3 m. Recuo inesperado contra parede derruba a torre se houver obstáculo atrás fora do cone frontal.
Lição 6 — Carro com desvio de obstáculos e varredura
A sexta lição adiciona percepção lateral: ao detectar parede à frente abaixo de 25 cm, o robô para, gira o ultrassom a 30 e 150 graus, compara os lados e escapa para o mais livre com ré de segurança e giro. O sketch implementa a máquina clássica de desvio com três medidas por ciclo: centro, direita e esquerda, com pausas de acomodação do servo entre elas. A teoria é a amostragem espacial com sensor único multiplexado no tempo: em vez de três sonares, um sonar varrido emula três direções ao custo de latência de cerca de um segundo por decisão. A comparação usa máximo de espaço livre, e o empate com ambos os lados bloqueados comanda ré adicional. A ré antes do giro descola o para-choque da parede e evita arrasto lateral da roda boba, com negativo curto seguido de puro. O limiar de 25 cm equilibra antecipação e falsos positivos: menor trava em porta estreita, maior desvia de sombra acústica sem obstáculo real.
onde , e são as leituras a 90, 30 e 150 graus. Os ângulos assimétricos em torno do centro compensam a montagem espelhada do suporte, e os delay de 200 a 500 ms acomodam o transitório mecânico antes de cada Distance_detection. A física do cone exige que a parede tenha largura suficiente nas três direções, e quina viva espalha o eco e subestima o lado real. A velocidade de cruzeiro com duty 255 garante torque para escapar de tapete alto, mas em piso liso causa derrapagem no giro que se corrige reduzindo para 200 sem alterar a lógica.
| Componente necessário | Função no ensaio |
|---|---|
| HC-SR04 na torre varrida | Sonar multiplexado em três direções |
| Servo de pan | Apontamento sequencial 90, 30 e 150 graus |
| ESP32, L298N, N20 e 18650 | Decisão e escape diferencial |
| Corredor com caixas | Labirinto de validação do desvio |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Servo | GPIO 16 | Saída PPM |
| TRIG/ECHO | GPIO 19/18 | Saída/Entrada |
| Tração | LEDC com INs | Saída |
📦 Bibliotecas desta lição:
ESP32Servopor Kevin Harrington, John K. Bennett (versão 1.1.2, mesma da Lição 3, nada a baixar).
//www.kuongshun.com
#include <ESP32Servo.h> //servo library
Servo myservo; // create servo object to control servo
#define Echo 18 // cria constante simbolica para pino ou parametro do hardware
#define Trig 19 // cria constante simbolica para pino ou parametro do hardware
#define servoPIN 16 // cria constante simbolica para pino ou parametro do hardware
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define carSpeed 255 // cria constante simbolica para pino ou parametro do hardware
int rightDistance = 0, leftDistance = 0, middleDistance = 0; // define rotina de atuacao, leitura ou protocolo do robo
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Forward"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Left"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
//Ultrasonic distance measurement Sub function
int Distance_detection() { // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(2); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(20); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
float Fdistance = pulseIn(Echo, HIGH); // mede a largura do pulso de eco para calcular a distancia por tempo de voo
Fdistance= Fdistance / 58; // executa etapa do firmware do robo tartaruga
return (int)Fdistance; // devolve o valor calculado ao chamador da funcao
}
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
myservo.attach(servoPIN,500,2500); // associa o objeto servo ao pino de sinal com pulsos de 500 a 2500 microssegundos
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
pinMode(Echo, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(Trig, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN1, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN2, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
Stop(); // executa etapa do firmware do robo tartaruga
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
myservo.write(90); //setservo position according to scaled value
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
middleDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("M:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(middleDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(500); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
if(middleDistance <= 25) { // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(30); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(300); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
rightDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("R:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(rightDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(300); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(150); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(400); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
leftDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("L:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(leftDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(300); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
if(rightDistance > leftDistance) { // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Back(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Right(); // executa etapa do firmware do robo tartaruga
delay(400); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else if(rightDistance < leftDistance) { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Back(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Left(); // executa etapa do firmware do robo tartaruga
delay(400); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else if((rightDistance <= 25) || (leftDistance <= 25)) { // ramo alternativo da decisao de navegacao autonoma
Back(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
}
}
else { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
}
}
Gravação: carregue e solte em corredor com caixas. Resultado esperado: avança até 25 cm da parede, para, olha à direita e à esquerda com a torre, gira para o lado mais livre após curta ré e retoma. Com corredor sem saída nos três lados, dá ré extra. Acompanhe no Serial a 9600 as marcas M, R e L para auditar cada decisão. Se gira sempre para o mesmo lado, recalibre o zero do servo da Lição 3, porque braço torto viesa a comparação. Se bate antes de parar, reduza o cruzeiro de 255 para 200. Se a torre vibra sem medir, recarregue as baterias, pois servo faminto consome o pico e corrompe o eco.
💡 Dica: filme a torre em câmera lenta. A sequência 90, 30, 90, 150 e 90 deve ser nítida. Salto direto de 30 para 150 sem centrar indica bateria fraca que reinicia o movimento.
Lição 7 — Carro com controle remoto infravermelho
A sétima lição entrega comando humano sem fio com o controle do kit. O sketch inicializa o receptor, decodifica quadros NEC, mapeia setas em marcha e usa timeout de 200 ms para parar ao soltar o botão. A teoria é a modulação a 38 kHz com código de endereço e comando mais repetição enquanto o botão fica pressionado. O receptor filtra a portadora e entrega o quadro decodificado com flag de repetição, que o firmware trata reutilizando o último código válido para marcha contínua sem trancos. O timeout implementa homem-morto: sem quadro novo em 200 ms, a tração para, o que protege contra perda de enlace e contra botão preso. Os códigos do fabricante para este lote são UP 0xB946FF00, DOWN 0xEA15FF00, LEFT 0xBB44FF00, RIGHT 0xBC43FF00 e OK 0xBF40FF00, com dígitos e asterisco apenas reportados no Serial. Lote diferente de controle pode trocar os códigos sem trocar o protocolo, e a calibração se faz lendo o Serial e atualizando os case.
onde é o tempo desde o último quadro válido. A taxa de repetição do controle em cerca de 110 ms garante pelo menos um quadro por janela de 200 ms com botão pressionado, e a ausência confirma soltura ou sombra. A óptica exige visada ao olho receptor sem obstrução do casco, e luz solar direta com componente de 38 kHz eleva o piso de ruído e encurta o alcance. A pilha CR2025 ou CR2032 fraca gera quadros corrompidos descartados que se manifestam como marcha picotada, indistinguível de sombra parcial sem o diagnóstico do Serial.
| Componente necessário | Função no ensaio |
|---|---|
| Receptor IR no chassi | Decodificação dos quadros de 38 kHz |
| Controle remoto com pilha botão | Transmissor de setas e OK |
| ESP32, L298N, N20 e 18650 | Marcha comandada com parada segura |


| Conexão validada | Pino | Sentido |
|---|---|---|
| Sinal do receptor | GPIO 15 | Entrada digital |
| Tração | LEDC 3/4 com INs | Saída |
📦 Bibliotecas desta lição:
IRremotepor shirriff, z3t0, ArminJo (versão 4.1.2).
- Via Gerenciador (recomendado):
Sketch > Incluir Biblioteca > Gerenciar Bibliotecas…→ buscarIRremote→ selecionar4.1.2→Instalar→ reiniciar a IDE.- Via ZIP: baixar em Arduino-IRremote/Arduino-IRremote (
Code > Download ZIP) →Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP…→ reiniciar a IDE.- Conferência:
Arquivo > Exemplos > IRremote > SimpleReceiverdeve abrir e compilar. ErroIRremote.h: No such fileindica versão errada ou pasta duplicada emlibraries.
//www.kuongshun.com
#include <IRremote.h> // inclui a biblioteca necessaria ao projeto
int receiver = 15; // define rotina de atuacao, leitura ou protocolo do robo
/*define channel enable output pins*/ // executa etapa do firmware do robo tartaruga
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define carSpeed 200 // initial speed of car >=0 to <=255
IRrecv irrecv(receiver); // executa etapa do firmware do robo tartaruga
uint32_t last_decodedRawData = 0; // executa etapa do firmware do robo tartaruga
unsigned long lastCommandTime; // Record the time of the last received command
const unsigned long commandTimeout = 200; // Set the timeout period (milliseconds)
void translateIR() // takes action based on IR code received
{
if (irrecv.decodedIRData.flags)// Check if it is a repeat IR code
{
irrecv.decodedIRData.decodedRawData = last_decodedRawData; //set the current decodedRawData to the last decodedRawData
Serial.println("REPEAT!"); // envia telemetria ao Monitor Serial para validacao do ensaio
} else//output the IR code on the serial monitor
{
Serial.print("IR code:0x"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(irrecv.decodedIRData.decodedRawData, HEX); // envia telemetria ao Monitor Serial para validacao do ensaio
}
switch (irrecv.decodedIRData.decodedRawData)//map the IR code to the remote key
{
case 0xB946FF00: Serial.println("UP"); Forward();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xEA15FF00: Serial.println("DOWN"); Back();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBB44FF00: Serial.println("LEFT"); Left();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBC43FF00: Serial.println("RIGHT"); Right(); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBF40FF00: Serial.println("OK"); Stop(); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xAD52FF00: Serial.println("0"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE916FF00: Serial.println("1"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE619FF00: Serial.println("2"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF20DFF00: Serial.println("3"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF30CFF00: Serial.println("4"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE718FF00: Serial.println("5"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA15EFF00: Serial.println("6"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF708FF00: Serial.println("7"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE31CFF00: Serial.println("8"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA55AFF00: Serial.println("9"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBD42FF00: Serial.println("*"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xB54AFF00: Serial.println("#"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
default: // executa etapa do firmware do robo tartaruga
Serial.println(" other button "); // envia telemetria ao Monitor Serial para validacao do ensaio
}// End Case
last_decodedRawData = irrecv.decodedIRData.decodedRawData;//store the last decodedRawData
//delay(500); // Do not get immediate repeat
} //END translateIR
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); //set IN1 LOW level
digitalWrite(IN2, HIGH); //set IN2 HIGH level
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Forward"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Left"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
pinMode(IN1,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN2,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(13, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
Stop(); // executa etapa do firmware do robo tartaruga
irrecv.enableIRIn();// Start the receiver
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
if (irrecv.decode()) // have we received an IR signal?
{
lastCommandTime = millis(); // Update the last command time
translateIR(); // executa etapa do firmware do robo tartaruga
irrecv.resume(); // receive the next value
}
if (millis() - lastCommandTime > commandTimeout) { // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
// If no new IR signal within 100 milliseconds, stop the robot
}
}
Gravação: instale a CR2025 ou CR2032 no controle, carregue o sketch e ligue o robô no chão. Resultado esperado: seta para cima avança, para baixo recua, esquerda e direita giram, tudo apenas enquanto o botão fica pressionado, e OK ou soltura para em até 200 ms, com códigos impressos no Serial a 9600. Se nenhum botão responde, confira visada, pilha e GPIO 15 no fio real. Se responde com códigos diferentes dos case, anote os códigos do seu Serial e atualize os cinco case de direção sem alterar a lógica de timeout. Se anda sozinho sem tocar, há fonte de 38 kHz próxima como TV ou sol direto no receptor.
⚠️ Atenção: timeout de 200 ms é segurança, não atraso. Não aumente para suavizar marcha, pois o robô passa a andar metros após soltar o botão em velocidade plena.
Lição 8 — Carro WiFi via página Web
A oitava lição corta o fio do USB e coloca o comando no navegador do celular. O ESP32 sobe em modo AP com SSID KUONGSHUN-AD177 e senha 12345678, anuncia o IP 192.168.4.1 e serve uma página com botões de marcha que disparam requisições com parâmetros de comando. A teoria é o WiFi em modo AP com servidor HTTP embarcado: o ESP32 é o roteador da sua própria célula sem internet, o celular associa e mantém a conexão mesmo com aviso de sem internet, e cada toque no botão gera um GET com variável e valor que o handler converte em marcha. O canal 9 fixo reduz disputa com roteadores domésticos nos canais 1 e 6, e a potência de 19,5 dBm maximiza alcance indoor ao custo de consumo que exige bateria cheia. A latência de toque a roda é a soma do tempo de ida do HTTP com o tempo de atuação da ponte, na casa de centenas de milissegundos, e soltar o botão envia o comando de parada, o mesmo homem-morto do infravermelho agora sobre TCP. O aviso de sem internet no celular deve ser mantido conectado, nunca alternado para dados móveis, senão o comando cai no meio da curva.
onde é a ida e volta na célula AP e a comutação do L298N. O throughput necessário é mínimo porque comandos têm bytes, sem vídeo neste kit, o que torna o enlace robusto mesmo com sinal fraco. A segurança é física: sem senha não há comando, e sem associação o robô fica parado aguardando cliente. O firmware divide-se em dois arquivos: o .ino configura WiFi, imprime o IP e delega ao servidor, e o app_httpd.cpp implementa Car_init, as marchas e o cmd_handler que interpreta var=car com val de 1 a 5. A velocidade é plena com duty 255, adequada para demonstração em quadra lisa.
| Componente necessário | Função no ensaio |
|---|---|
| ESP32 com rádio WiFi | Ponto de acesso e servidor HTTP |
| Celular ou tablet | Navegador com botões de marcha |
| ESP32, L298N, N20 e 18650 | Marcha comandada pela página |



| Conexão validada | Parâmetro | Valor |
|---|---|---|
| SSID do AP | KUONGSHUN-AD177 | Rede aberta pelo robô |
| Senha | 12345678 | Oito dígitos fixos do firmware |
| Portal | 192.168.4.1 | Página com avante, ré, esquerda e direita |
| Tração | Duty 255 | Marcha plena com parada ao soltar |
📦 Bibliotecas desta lição:
WiFieesp_http_server— embutidas no núcleo ESP32 2.0.12, nada a baixar.
- Instalação: nenhuma. Confira em
Arquivo > Exemplos > WiFi > WiFiScanque o exemplo abre e compila para ESP32 Dev Module.
//www.kuongshun.com
#include <WiFi.h> // inclui a biblioteca necessaria ao projeto
const char* ssid = "KUONGSHUN-AD177"; // executa etapa do firmware do robo tartaruga
const char* password = "12345678"; // executa etapa do firmware do robo tartaruga
void startServer(); // inicializa o servidor HTTP ou TCP que atende o navegador e o aplicativo
void Car_init(); // define rotina de atuacao, leitura ou protocolo do robo
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
WiFi.setTxPower(WIFI_POWER_19_5dBm); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.mode(WIFI_AP); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.softAP(ssid, password, 9); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
IPAddress myIP = WiFi.softAPIP(); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
Serial.print("AP IP address: "); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(myIP); //probar 192.168.4.1
Car_init(); // executa etapa do firmware do robo tartaruga
startServer(); // inicializa o servidor HTTP ou TCP que atende o navegador e o aplicativo
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
}
Arquivo complementar app_httpd.cpp do modo Web, com servidor, marchas e interpretador de comandos da página:
#include "Arduino.h" // inclui a biblioteca necessaria ao projeto
#include "esp_http_server.h" // inclui a biblioteca necessaria ao projeto
#include <ESP32Servo.h> // inclui a biblioteca necessaria ao projeto
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define carSpeed 255 // initial speed of car >=0 to <=255
#define LED 4 // cria constante simbolica para pino ou parametro do hardware
int val=0; // define rotina de atuacao, leitura ou protocolo do robo
bool state = LOW; // executa etapa do firmware do robo tartaruga
typedef struct { // executa etapa do firmware do robo tartaruga
httpd_req_t *req; // executa etapa do firmware do robo tartaruga
size_t len; // executa etapa do firmware do robo tartaruga
} jpg_chunking_t;
httpd_handle_t camera_httpd = NULL; // executa etapa do firmware do robo tartaruga
void stateChange(){ // define rotina de atuacao, leitura ou protocolo do robo
state = !state; // executa etapa do firmware do robo tartaruga
digitalWrite(4, state); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Light"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Car_init(){ // define rotina de atuacao, leitura ou protocolo do robo
pinMode(LED, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN1,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN2,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
}
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Forward"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Left"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
static esp_err_t cmd_handler(httpd_req_t *req) // executa etapa do firmware do robo tartaruga
{
char* buf; // executa etapa do firmware do robo tartaruga
size_t buf_len; // executa etapa do firmware do robo tartaruga
char variable[32] = {0,}; // executa etapa do firmware do robo tartaruga
char value[32] = {0,}; // executa etapa do firmware do robo tartaruga
buf_len = httpd_req_get_url_query_len(req) + 1; // executa etapa do firmware do robo tartaruga
if (buf_len > 1) { // decisao condicional que seleciona o comportamento autonomo
buf = (char*)malloc(buf_len); // executa etapa do firmware do robo tartaruga
if(!buf){ // decisao condicional que seleciona o comportamento autonomo
httpd_resp_send_500(req); // executa etapa do firmware do robo tartaruga
return ESP_FAIL; // devolve o valor calculado ao chamador da funcao
}
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { // decisao condicional que seleciona o comportamento autonomo
if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK && // decisao condicional que seleciona o comportamento autonomo
httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) { // executa etapa do firmware do robo tartaruga
} else { // ramo alternativo da decisao de navegacao autonoma
free(buf); // executa etapa do firmware do robo tartaruga
httpd_resp_send_404(req); // executa etapa do firmware do robo tartaruga
return ESP_FAIL; // devolve o valor calculado ao chamador da funcao
}
} else { // ramo alternativo da decisao de navegacao autonoma
free(buf); // executa etapa do firmware do robo tartaruga
httpd_resp_send_404(req); // executa etapa do firmware do robo tartaruga
return ESP_FAIL; // devolve o valor calculado ao chamador da funcao
}
free(buf); // executa etapa do firmware do robo tartaruga
} else { // ramo alternativo da decisao de navegacao autonoma
httpd_resp_send_404(req); // executa etapa do firmware do robo tartaruga
return ESP_FAIL; // devolve o valor calculado ao chamador da funcao
}
val = atoi(value); // executa etapa do firmware do robo tartaruga
int res = 0; // define rotina de atuacao, leitura ou protocolo do robo
if(!strcmp(variable, "car")) // decisao condicional que seleciona o comportamento autonomo
{
if (val==1) // decisao condicional que seleciona o comportamento autonomo
{
Serial.println("claw_x"); // envia telemetria ao Monitor Serial para validacao do ensaio
Forward(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==2) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("claw_y"); // envia telemetria ao Monitor Serial para validacao do ensaio
Back(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==3) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("Stop"); // envia telemetria ao Monitor Serial para validacao do ensaio
Stop(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==4) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("turn_x"); // envia telemetria ao Monitor Serial para validacao do ensaio
Left(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==5) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("turn_y"); // envia telemetria ao Monitor Serial para validacao do ensaio
Right(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==6) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("upper_arm_x"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==7) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("upper_arm_y"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==8) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("lower_arm_x"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==9) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("lower_arm_y"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==10) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("Reset"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
Stop(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
else if (val==11) // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("Reset"); // envia telemetria ao Monitor Serial para validacao do ensaio
stateChange(); // executa etapa do firmware do robo tartaruga
Stop(); // executa etapa do firmware do robo tartaruga
//httpd_resp_set_type(req, "text/html");
//return httpd_resp_send(req, "OK", 2);
}
}
else // ramo alternativo da decisao de navegacao autonoma
{
Serial.println("variable"); // envia telemetria ao Monitor Serial para validacao do ensaio
res = -1; // executa etapa do firmware do robo tartaruga
}
if(res){ return httpd_resp_send_500(req); } // decisao condicional que seleciona o comportamento autonomo
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); // executa etapa do firmware do robo tartaruga
return httpd_resp_send(req, NULL, 0); // devolve o valor calculado ao chamador da funcao
}
static const char PROGMEM INDEX_HTML[] = R"rawliteral( // executa etapa do firmware do robo tartaruga
<!doctype html> // executa etapa do firmware do robo tartaruga
<html> // executa etapa do firmware do robo tartaruga
<head> // executa etapa do firmware do robo tartaruga
<meta charset="utf-8"> // executa etapa do firmware do robo tartaruga
<meta name="viewport" content="width=device-width,initial-scale=1"> // executa etapa do firmware do robo tartaruga
<title>KUONGSHUN Turtle ROBOT</title> // executa etapa do firmware do robo tartaruga
<style> // executa etapa do firmware do robo tartaruga
*{ // executa etapa do firmware do robo tartaruga
padding: 0; margin: 0; // executa etapa do firmware do robo tartaruga
font-family:monospace; // executa etapa do firmware do robo tartaruga
}
*{ // executa etapa do firmware do robo tartaruga
-webkit-touch-callout:none; // executa etapa do firmware do robo tartaruga
-webkit-user-select:none; // executa etapa do firmware do robo tartaruga
-khtml-user-select:none; // executa etapa do firmware do robo tartaruga
-moz-user-select:none; // executa etapa do firmware do robo tartaruga
-ms-user-select:none; // executa etapa do firmware do robo tartaruga
user-select:none; // executa etapa do firmware do robo tartaruga
}
canvas { // executa etapa do firmware do robo tartaruga
margin: auto; // executa etapa do firmware do robo tartaruga
display: block; // executa etapa do firmware do robo tartaruga
}
.tITULO{ // executa etapa do firmware do robo tartaruga
text-align: center; // executa etapa do firmware do robo tartaruga
color: rgb(97, 97, 97); // executa etapa do firmware do robo tartaruga
}
.LINK{ // executa etapa do firmware do robo tartaruga
color: red; // executa etapa do firmware do robo tartaruga
width: 60px; // executa etapa do firmware do robo tartaruga
margin: auto; // executa etapa do firmware do robo tartaruga
display: block; // executa etapa do firmware do robo tartaruga
font-size: 14px; // executa etapa do firmware do robo tartaruga
}
.cont_flex{ // executa etapa do firmware do robo tartaruga
margin: 20px auto 20px; // executa etapa do firmware do robo tartaruga
width: 70%; // executa etapa do firmware do robo tartaruga
max-width: 400px; // executa etapa do firmware do robo tartaruga
display: flex; // executa etapa do firmware do robo tartaruga
flex-wrap: wrap; // executa etapa do firmware do robo tartaruga
justify-content: space-around; // executa etapa do firmware do robo tartaruga
}
.cont_flex_model{ // executa etapa do firmware do robo tartaruga
margin: 20px auto 20px; // executa etapa do firmware do robo tartaruga
width: 78%; // executa etapa do firmware do robo tartaruga
max-width: 400px; // executa etapa do firmware do robo tartaruga
display: flex; // executa etapa do firmware do robo tartaruga
flex-wrap: wrap; // executa etapa do firmware do robo tartaruga
justify-content: space-around; // executa etapa do firmware do robo tartaruga
}
.cont_flex button{ // executa etapa do firmware do robo tartaruga
width: 70px; // executa etapa do firmware do robo tartaruga
height: 30px; // executa etapa do firmware do robo tartaruga
border: none; // executa etapa do firmware do robo tartaruga
background-color: red; // executa etapa do firmware do robo tartaruga
border-radius: 10px; // executa etapa do firmware do robo tartaruga
color: white; // executa etapa do firmware do robo tartaruga
}
.cont_flex_model button{ // executa etapa do firmware do robo tartaruga
width: 100px; // executa etapa do firmware do robo tartaruga
height: 30px; // executa etapa do firmware do robo tartaruga
border: none; // executa etapa do firmware do robo tartaruga
background-color: yellow; // executa etapa do firmware do robo tartaruga
border-radius: 10px; // executa etapa do firmware do robo tartaruga
color: black; // executa etapa do firmware do robo tartaruga
}
.cont_flex button:active{ // executa etapa do firmware do robo tartaruga
background-color: green; // executa etapa do firmware do robo tartaruga
}
.cont_flex_model button:active{ // executa etapa do firmware do robo tartaruga
background-color: green; // executa etapa do firmware do robo tartaruga
}
input{-webkit-user-select:auto;} // executa etapa do firmware do robo tartaruga
input[type=range]{-webkit-appearance:none;width:300px;height:25px;background:#cecece;cursor:pointer;margin:0} // executa etapa do firmware do robo tartaruga
input[type=range]:focus{outline:0} // executa etapa do firmware do robo tartaruga
input[type=range]::-webkit-slider-runnable-track{width:100%;height:2px;cursor:pointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF} // executa etapa do firmware do robo tartaruga
input[type=range]::-webkit-slider-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer;-webkit-appearance:none;margin-top:-10px} // executa etapa do firmware do robo tartaruga
</style> // executa etapa do firmware do robo tartaruga
</head> // executa etapa do firmware do robo tartaruga
<body> // executa etapa do firmware do robo tartaruga
<h1 class="tITULO">KUONGSHUN Turtle ROBOT</h1> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<button type="button" id="Forward" ontouchstart="fetch(document.location.origin+'/control?var=car&val=1');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">Forward</button> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<button type="button" id="TurnLeft" ontouchstart="fetch(document.location.origin+'/control?var=car&val=4');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">Turnleft</button> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="stop" ontouchstart="fetch(document.location.origin+'/control?var=car&val=10');">Reset</button> --> // executa etapa do firmware do robo tartaruga
<button type="button" id="TurnRight" ontouchstart="fetch(document.location.origin+'/control?var=car&val=5');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">TurnRight</button> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<button type="button" id="Backward" ontouchstart="fetch(document.location.origin+'/control?var=car&val=2');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">Backward</button> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<p><br></p> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="upper_arm_x" ontouchstart="fetch(document.location.origin+'/control?var=car&val=6');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">upper_arm_x</button> --> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="lower_arm_x" ontouchstart="fetch(document.location.origin+'/control?var=car&val=8');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">lower_arm_x</button> --> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="stop" ontouchstart="fetch(document.location.origin+'/control?var=car&val=11');">Reset</button> --> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="lower_arm_y" ontouchstart="fetch(document.location.origin+'/control?var=car&val=9');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">lower_arm_y</button> --> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex_model"> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="model1" onmousedown="fetch(document.location.origin+'/control?var=car&val=6');">Free Control</button>--> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="model2" onmousedown="fetch(document.location.origin+'/control?var=model&val=7');">Obstacle Avoidance</button>--> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex_model"> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="model3" onmousedown="fetch(document.location.origin+'/control?var=model&val=8');">Object Following</button>--> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="model4" onmousedown="fetch(document.location.origin+'/control?var=model&val=9');">Line Tracing</button>--> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<div class="cont_flex"> // executa etapa do firmware do robo tartaruga
<!-- <button type="button" id="upper_arm_y" ontouchstart="fetch(document.location.origin+'/control?var=car&val=7');"ontouchend="fetch(document.location.origin+'/control?var=car&val=3');">upper_arm_y</button> --> // executa etapa do firmware do robo tartaruga
</div> // executa etapa do firmware do robo tartaruga
<script> // executa etapa do firmware do robo tartaruga
window.onload = function(){ // executa etapa do firmware do robo tartaruga
var canvas = document.getElementById("canvas"); // executa etapa do firmware do robo tartaruga
var ctx = canvas.getContext("2d"); // executa etapa do firmware do robo tartaruga
ctx.fillStyle = "rgb(255,0,0)"; // executa etapa do firmware do robo tartaruga
ctx.fillRect(73,25,60,35); // executa etapa do firmware do robo tartaruga
ctx.clearRect(78,30,50,25); // executa etapa do firmware do robo tartaruga
ctx.fillRect(93,20,20,5); // executa etapa do firmware do robo tartaruga
ctx.fillRect(68,35,5,15); // executa etapa do firmware do robo tartaruga
ctx.fillRect(133,35,5,15); // executa etapa do firmware do robo tartaruga
ctx.beginPath(); // executa etapa do firmware do robo tartaruga
ctx.arc(92,42,6,0,2*Math.PI,true); // executa etapa do firmware do robo tartaruga
ctx.fill(); // executa etapa do firmware do robo tartaruga
ctx.beginPath(); // executa etapa do firmware do robo tartaruga
ctx.arc(117,42,6,0,2*Math.PI,true); // executa etapa do firmware do robo tartaruga
ctx.fill(); // executa etapa do firmware do robo tartaruga
Gravação e operação: carregue com USB, desconecte, ligue com baterias e aguarde o LED do ESP32 aceso. No celular, abra o WiFi, conecte em KUONGSHUN-AD177 com 12345678 e mantenha mesmo com aviso de sem internet. Abra o navegador em 192.168.4.1. Resultado esperado: a página mostra os quatro botões, pressionar avança e soltar para, com a mesma resposta das lições com fio. Se a rede não aparece, confira bateria e fiação de alimentação da ESP32 e do L298N, pois rádio sem corrente não anuncia SSID. Se abre a página mas não anda, confira se outro sketch com servidor ficou gravado antes e recarregue este modo. Se o celular alterna para dados móveis, desative dados durante o ensaio.
⚠️ Atenção: mantenha o aviso de sem internet conectado. Trocar para dados móveis no meio do ensaio derruba o comando e o robô segue na última marcha até o timeout.
Lição 9 — Carro Web multifunção com modos autônomos
A nona lição funde tudo em um portal único: comando livre mais botões de linha, seguimento, desvio e infravermelho, com sliders de servo e velocidade. O sketch mantém o mesmo AP e portal, mas o app_httpd.cpp ampliado interpreta comandos de modo além de marcha, e o laço principal executa a máquina do modo ativo enquanto atende a rede e o infravermelho em paralelo. A teoria é a multiplexação cooperativa: cada modo autônomo roda em fatias de 50 ms intercaladas com leitura de rede, de modo que um toque de modo troca o comportamento sem regravar. O modo livre obedece aos botões direcionais, o desvio executa a varredura da Lição 6, o seguimento executa as zonas da Lição 5, e a linha executa a máquina da Lição 4, tudo com o mesmo mapa de pinos. O slider de servo ajusta o pan manualmente no modo livre para mirar o ultrassom, e o slider de velocidade reescreve carSpeed em tempo real, o que demonstra o efeito de sem recompilar. A atenção crítica é o pino do receptor neste sketch do fabricante, declarado como 5 em vez de 15: confira o fio real do passo 11 e iguale o #define ao hardware antes de culpar o controle.
onde é o duty comandado pelo controle deslizante de 0 a 255. A transição de modo preserva a segurança com parada intermediária, e a vigilância de rede a cada 50 ms impede travamento em modo autônomo sem comando. A latência de troca é de uma a duas fatias, imperceptível em demonstração. A telemetria no Serial a 9600 registra modo e comando, auditoria útil quando o robô parece ignorar o botão porque está em modo autônomo diferente do imaginado.
| Componente necessário | Função no ensaio |
|---|---|
| Todos os sensores calibrados | Entradas dos quatro modos |
| Celular com navegador | Portal multifunção com sliders |
| Controle IR com pilha | Comando redundante ao Web |


| Conexão e modo | Valor | Observação |
|---|---|---|
| AP e portal | KUONGSHUN-AD177 em 192.168.4.1 | Mesmo acesso da Lição 8 |
| Modo livre | Botões direcionais | Marcha com parada ao soltar |
| Modo desvio | Botão de obstáculo | Varredura 90, 30 e 150 graus |
| Modo seguimento | Botão de follow | Zonas 15, 20, 25 e 50 cm |
| Modo linha | Botão de tracking | Máquina de três canais |
| Receptor IR | GPIO 5 no código, 15 no chassi típico | Igualar código ao fio real |
📦 Bibliotecas desta lição:
IRremote4.1.2 por shirriff, z3t0, ArminJo maisWiFiembutida no núcleo 2.0.12.
- Via Gerenciador: conferir
IRremoteem3selecionada em4.1.2instalada.WiFidispensa instalação.- Divergência de pino: o sketch declara receptor em 5. Se seu chicote está em 15 do passo 11, altere o
#definepara 15 antes de carregar e anote na tampa com caneta.
//www.kuongshun.com
#include <WiFi.h> // inclui a biblioteca necessaria ao projeto
#include <IRremote.h> // inclui a biblioteca necessaria ao projeto
const char* ssid = "KUONGSHUN-AD177"; // executa etapa do firmware do robo tartaruga
const char* password = "12345678"; // executa etapa do firmware do robo tartaruga
int receiver = 5; // define rotina de atuacao, leitura ou protocolo do robo
IRrecv irrecv(receiver); // executa etapa do firmware do robo tartaruga
uint32_t last_decodedRawData = 0; // executa etapa do firmware do robo tartaruga
void startServer(); // inicializa o servidor HTTP ou TCP que atende o navegador e o aplicativo
void Car_init(); // define rotina de atuacao, leitura ou protocolo do robo
void Line_Tracing_mode(); // define rotina de atuacao, leitura ou protocolo do robo
void Obstacles_Avoidance_mode(); // define rotina de atuacao, leitura ou protocolo do robo
void Object_Following_mode(); // define rotina de atuacao, leitura ou protocolo do robo
void Forward(); // define rotina de atuacao, leitura ou protocolo do robo
void Back(); // define rotina de atuacao, leitura ou protocolo do robo
void Left(); // define rotina de atuacao, leitura ou protocolo do robo
void Right(); // define rotina de atuacao, leitura ou protocolo do robo
void Stop(); // define rotina de atuacao, leitura ou protocolo do robo
void getIRData() // takes action based on IR code received
{
if (irrecv.decode()) // have we received an IR signal?
{
if (irrecv.decodedIRData.flags)// Check if it is a repeat IR code
{
irrecv.decodedIRData.decodedRawData = last_decodedRawData; //set the current decodedRawData to the last decodedRawData
Serial.println("REPEAT!"); // envia telemetria ao Monitor Serial para validacao do ensaio
} else//output the IR code on the serial monitor
{
Serial.print("IR code:0x"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(irrecv.decodedIRData.decodedRawData, HEX); // envia telemetria ao Monitor Serial para validacao do ensaio
}
switch (irrecv.decodedIRData.decodedRawData)//map the IR code to the remote key
{
case 0xB946FF00: Serial.println("UP"); Forward();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xEA15FF00: Serial.println("DOWN"); Back();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBB44FF00: Serial.println("LEFT"); Left();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBC43FF00: Serial.println("RIGHT"); Right(); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBF40FF00: Serial.println("OK"); Stop(); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xAD52FF00: Serial.println("0"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE916FF00: Serial.println("1"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE619FF00: Serial.println("2"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF20DFF00: Serial.println("3"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF30CFF00: Serial.println("4"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE718FF00: Serial.println("5"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA15EFF00: Serial.println("6"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF708FF00: Serial.println("7"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE31CFF00: Serial.println("8"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA55AFF00: Serial.println("9"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBD42FF00: Serial.println("*"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xB54AFF00: Serial.println("#"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
default: // executa etapa do firmware do robo tartaruga
Serial.println(" other button "); // envia telemetria ao Monitor Serial para validacao do ensaio
}// End Case
last_decodedRawData = irrecv.decodedIRData.decodedRawData;//store the last decodedRawData
delay(100); // Do not get immediate repeat
}
irrecv.resume(); // receive the next value
} //END translateIR
void setup() { // define rotina de atuacao, leitura ou protocolo do robo
Serial.begin(9600); // inicializa a UART de depuracao para o Monitor Serial
WiFi.setTxPower(WIFI_POWER_19_5dBm); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.mode(WIFI_AP); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.softAP(ssid, password, 9); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
IPAddress myIP = WiFi.softAPIP(); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
Serial.print("AP IP address: "); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(myIP); //probar 192.168.4.1
Car_init(); // executa etapa do firmware do robo tartaruga
startServer(); // inicializa o servidor HTTP ou TCP que atende o navegador e o aplicativo
irrecv.enableIRIn();// Start the receiver
}
void loop() { // define rotina de atuacao, leitura ou protocolo do robo
getIRData(); // executa etapa do firmware do robo tartaruga
Object_Following_mode(); // executa etapa do firmware do robo tartaruga
Obstacles_Avoidance_mode(); // executa etapa do firmware do robo tartaruga
Line_Tracing_mode(); // executa etapa do firmware do robo tartaruga
}
Gravação e operação: carregue, conecte no AP, abra 192.168.4.1 e teste cada botão em sequência com espaço livre. Resultado esperado: setas movem com parada ao soltar, cada modo assume o comportamento da lição isolada correspondente, o slider do servo move a torre no modo livre e o slider de velocidade altera visivelmente o passo. Se o IR não responde só neste modo mas responde na Lição 7, o culpado é o pino 5 contra 15: ajuste e recarregue. Se um modo parece morto, confira se outro modo ficou ativo e volte ao livre antes de concluir defeito. Se a página carrega mas os sliders não atuam, recarregue sem cache do navegador.
💡 Dica: demonstre nesta ordem: livre, linha, seguimento e desvio. Cada modo pressupõe a calibração da lição isolada, e a ordem revela qual calibração falta quando um modo falha e os anteriores passam.
Lição 10 — Carro APP multifunção com protocolo em quadros
A décima lição troca o navegador pelo aplicativo KUONGSHUN com protocolo binário dedicado na porta TCP 100. O ESP32 mantém o mesmo AP, mas agora atende quadros FF 55 comprimento … com ação e dispositivo, o que permite D-pad analógico, sliders e troca de modo com menor overhead que HTTP. A teoria é o enquadramento com sincronismo: os bytes FF 55 marcam início, o comprimento delimita, e o parser só executa quadro completo, descartando ruído de rádio sem travar. As ações incluem correr com dispositivo de marcha, girar servo, ajustar velocidade e trocar func_mode entre 1 livre, 2 desvio, 3 seguimento e 4 linha. O laço atende o socket, o infravermelho e a máquina do modo ativo em paralelo, com vigilância de 50 fatias de 1 ms que aborta o modo ao chegar comando novo. O limiar de linha aqui é 2000 contagens no ADC de 12 bits, adequado à iluminação do ensaio do fabricante, e deve ser recalibrado ao seu piso sem tratar como defeito. O include residual de câmera neste sketch compila sem câmera e pode ser mantido para fidelidade ao kit.
onde delimita o quadro e seleciona o comportamento. A taxa de quadros do APP em dezenas por segundo supera o clique do Web, o que suaviza o D-pad proporcional e justifica o modo APP para demonstração dinâmica. A porta 100 dedicada evita disputa com o HTTP da Lição 8, e a reconexão exige apenas reassociar no WiFi e tocar em conectar no APP, sem regravar. A segurança mantém o homem-morto: sem quadro em 200 ms no IR e sem cliente no socket, a tração para. A versão de firmware 0.12.21 impressa no Serial identifica este lote e ajuda no suporte.
| Componente necessário | Função no ensaio |
|---|---|
| Aplicativo KUONGSHUN instalado | D-pad, modos e sliders no protocolo em quadros |
| Celular com WiFi | Transporte TCP na porta 100 |
| Robô completo calibrado | Execução dos quatro modos pelo APP |




| Conexão e comando | Valor | Observação |
|---|---|---|
| AP | KUONGSHUN-AD177 com 12345678, canal 5 | Reassociar a cada ligada |
| APP | KUONGSHUN com tartaruga ESP32 | Android por APK da pasta do kit, iOS pela loja |
| Porta | TCP 100 | Toque em conectar se mostrar desconectado |
| Modos | Livre, desvio, seguimento e linha | Mesmos comportamentos das lições isoladas |
📦 Bibliotecas desta lição:
ESP32Servo1.1.2 eIRremote4.1.2 por shirriff, z3t0, ArminJo, maisWiFiembutida no núcleo 2.0.12.
- Via Gerenciador: conferir as duas versões pinadas instaladas. Nada novo a baixar se as Lições 3 e 7 passaram.
- Conferência:
Arquivo > Exemplos > ESP32Servo > SweepeIRremote > SimpleReceivercompilam. Receptor no GPIO 15 como na Lição 7.
#include <WiFi.h> // inclui a biblioteca necessaria ao projeto
#include "esp_camera.h" // inclui a biblioteca necessaria ao projeto
#include <ESP32Servo.h> // inclui a biblioteca necessaria ao projeto
#include <Arduino.h> // inclui a biblioteca necessaria ao projeto
#include <IRremote.h> // inclui a biblioteca necessaria ao projeto
Servo myservo; // executa etapa do firmware do robo tartaruga
#define Echo 18 // cria constante simbolica para pino ou parametro do hardware
#define Trig 19 // cria constante simbolica para pino ou parametro do hardware
#define servoPIN 16 // cria constante simbolica para pino ou parametro do hardware
#define ENA 3 // cria constante simbolica para pino ou parametro do hardware
#define ENA_PIN 25 // cria constante simbolica para pino ou parametro do hardware
#define IN1 26 // cria constante simbolica para pino ou parametro do hardware
#define IN2 27 // cria constante simbolica para pino ou parametro do hardware
#define IN3 14 // cria constante simbolica para pino ou parametro do hardware
#define IN4 12 // cria constante simbolica para pino ou parametro do hardware
#define ENB 4 // cria constante simbolica para pino ou parametro do hardware
#define ENB_PIN 13 // cria constante simbolica para pino ou parametro do hardware
#define LEFT_LINE_TRACJING 32 // cria constante simbolica para pino ou parametro do hardware
#define CENTER_LINE_TRACJING 35 // cria constante simbolica para pino ou parametro do hardware
#define right_LINE_TRACJING 34 // cria constante simbolica para pino ou parametro do hardware
#define CMD_RUN 1 // cria constante simbolica para pino ou parametro do hardware
#define CMD_GET 2 // cria constante simbolica para pino ou parametro do hardware
#define CMD_STANDBY 3 // cria constante simbolica para pino ou parametro do hardware
#define CMD_TRACK_1 4 // cria constante simbolica para pino ou parametro do hardware
#define CMD_TRACK_2 5 // cria constante simbolica para pino ou parametro do hardware
#define CMD_AVOID 6 // cria constante simbolica para pino ou parametro do hardware
#define CMD_FOLLOW 7 // cria constante simbolica para pino ou parametro do hardware
const char* ssid = "KUONGSHUN-AD177"; // executa etapa do firmware do robo tartaruga
const char* password = "12345678"; // executa etapa do firmware do robo tartaruga
WiFiServer server(100); // executa etapa do firmware do robo tartaruga
WiFiClient client; // executa etapa do firmware do robo tartaruga
int receiver = 15; // define rotina de atuacao, leitura ou protocolo do robo
IRrecv irrecv(receiver); // executa etapa do firmware do robo tartaruga
uint32_t last_decodedRawData = 0; // executa etapa do firmware do robo tartaruga
unsigned long lastCommandTime; // Record the time of the last received command
const unsigned long commandTimeout = 200; // Set the timeout period (milliseconds)
int Left_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Center_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Right_Tra_Value; // define rotina de atuacao, leitura ou protocolo do robo
int Black_Line = 2000;//small is black
int Model1 = 25; // 模式1
int Model2 = 26; // 模式2
int Model3 = 27; // 模式3
int Model4 = 28; // 模式4
int carSpeed = 200; // 速度
int Servo = 90; // 舵机
int rightDistance = 0, leftDistance = 0, middleDistance = 0; // define rotina de atuacao, leitura ou protocolo do robo
unsigned long IR_PreMillis; // define rotina de atuacao, leitura ou protocolo do robo
unsigned long LT_PreMillis; // define rotina de atuacao, leitura ou protocolo do robo
int func_mode =0; // define rotina de atuacao, leitura ou protocolo do robo
String sendBuff; // executa etapa do firmware do robo tartaruga
String Version = "Firmware Version is 0.12.21"; // executa etapa do firmware do robo tartaruga
byte dataLen, index_a = 0; // executa etapa do firmware do robo tartaruga
char buffer[52]; // executa etapa do firmware do robo tartaruga
unsigned char prevc=0; // define rotina de atuacao, leitura ou protocolo do robo
bool isStart = false; // executa etapa do firmware do robo tartaruga
bool ED_client = true; // executa etapa do firmware do robo tartaruga
bool WA_en = false; // executa etapa do firmware do robo tartaruga
byte RX_package[17] = {0}; // executa etapa do firmware do robo tartaruga
uint16_t angle = 90; // executa etapa do firmware do robo tartaruga
byte action =0; // executa etapa do firmware do robo tartaruga
byte val = 0; // executa etapa do firmware do robo tartaruga
char model_var = 0; // executa etapa do firmware do robo tartaruga
int UT_distance = 0; // define rotina de atuacao, leitura ou protocolo do robo
void Car_init(){ // define rotina de atuacao, leitura ou protocolo do robo
myservo.attach(servoPIN,500,2500); // associa o objeto servo ao pino de sinal com pulsos de 500 a 2500 microssegundos
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
pinMode(IN1,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN2,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN3,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(IN4,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENA,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(ENB,OUTPUT); // configura o pino como entrada ou saida digital antes do uso
ledcSetup(ENA,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcSetup(ENB,5000,8); // configura canal LEDC do ESP32 com frequencia e resolucao para PWM dos motores
ledcAttachPin(ENA_PIN,ENA); // associa o pino fisico de enable ao canal LEDC configurado
ledcAttachPin(ENB_PIN,ENB); // associa o pino fisico de enable ao canal LEDC configurado
pinMode(Echo, INPUT); // configura o pino como entrada ou saida digital antes do uso
pinMode(Trig, OUTPUT); // configura o pino como entrada ou saida digital antes do uso
}
void Forward(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Forward_slow(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.6*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.6*carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Back() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Back_slow() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.7*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.7*carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Back"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Left() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Left_single() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Left_single_small() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.6*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.6*carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Left_turn(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.5*carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Right() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
Serial.println("Right"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void Right_single() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Right_single_small() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.6*carSpeed); //enable L298n A channel
ledcWrite(ENB, 0.6*carSpeed); //enable L298n B channel
digitalWrite(IN1, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Right_turn(){ // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0.5*carSpeed); //enable L298n A channel
ledcWrite(ENB, carSpeed); //enable L298n B channel
digitalWrite(IN1, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN2, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN3, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
digitalWrite(IN4, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
}
void Stop() { // define rotina de atuacao, leitura ou protocolo do robo
ledcWrite(ENA, 0); //enable L298n A channel
ledcWrite(ENB, 0); //enable L298n B channel
Serial.println("Stop!"); // envia telemetria ao Monitor Serial para validacao do ensaio
}
void getIRData() // takes action based on IR code received
{
if (irrecv.decode()) // have we received an IR signal?
{
lastCommandTime = millis(); // Update the last command time
if (irrecv.decodedIRData.flags)// Check if it is a repeat IR code
{
irrecv.decodedIRData.decodedRawData = last_decodedRawData; //set the current decodedRawData to the last decodedRawData
Serial.println("REPEAT!"); // envia telemetria ao Monitor Serial para validacao do ensaio
} else//output the IR code on the serial monitor
{
Serial.print("IR code:0x"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(irrecv.decodedIRData.decodedRawData, HEX); // envia telemetria ao Monitor Serial para validacao do ensaio
}
switch (irrecv.decodedIRData.decodedRawData)//map the IR code to the remote key
{
case 0xB946FF00: Serial.println("UP"); Forward();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xEA15FF00: Serial.println("DOWN"); Back();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBB44FF00: Serial.println("LEFT"); Left();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBC43FF00: Serial.println("RIGHT"); Right();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBF40FF00: Serial.println("OK"); Stop();break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xAD52FF00: Serial.println("0"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE916FF00: Serial.println("1"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE619FF00: Serial.println("2"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF20DFF00: Serial.println("3"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF30CFF00: Serial.println("4"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE718FF00: Serial.println("5"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA15EFF00: Serial.println("6"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xF708FF00: Serial.println("7"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xE31CFF00: Serial.println("8"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xA55AFF00: Serial.println("9"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xBD42FF00: Serial.println("*"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
case 0xB54AFF00: Serial.println("#"); break; // envia telemetria ao Monitor Serial para validacao do ensaio
default: // executa etapa do firmware do robo tartaruga
Serial.println(" other button "); // envia telemetria ao Monitor Serial para validacao do ensaio
}// End Case
last_decodedRawData = irrecv.decodedIRData.decodedRawData;//store the last decodedRawData
//delay(100); // Do not get immediate repeat
irrecv.resume(); // receive the next value
}
if ((millis() - lastCommandTime > commandTimeout)&&(lastCommandTime>0)){ // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
lastCommandTime=0; // executa etapa do firmware do robo tartaruga
// If no new IR signal within 100 milliseconds, stop the robot
}
} //END translateIR
int Distance_detection() { // define rotina de atuacao, leitura ou protocolo do robo
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(2); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, HIGH); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
delayMicroseconds(20); // gera temporizacao fina em microssegundos exigida pelo gatilho do ultrassom
digitalWrite(Trig, LOW); // escreve nivel logico ALTO ou BAIXO definindo o sentido da ponte H
float Fdistance = pulseIn(Echo, HIGH); // mede a largura do pulso de eco para calcular a distancia por tempo de voo
Fdistance= Fdistance / 58; // executa etapa do firmware do robo tartaruga
return (int)Fdistance; // devolve o valor calculado ao chamador da funcao
}
void Line_Tracing_mode() { // define rotina de atuacao, leitura ou protocolo do robo
if (func_mode == 4) { // decisao condicional que seleciona o comportamento autonomo
Left_Tra_Value = analogRead(LEFT_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
Center_Tra_Value = analogRead(CENTER_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
Right_Tra_Value = analogRead(right_LINE_TRACJING); // le o conversor AD do ESP32 no canal do sensor reflexivo de linha
/*Serial.println("l,c,r:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Left_Tra_Value); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Center_Tra_Value); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(Right_Tra_Value);*/ // envia telemetria ao Monitor Serial para validacao do ensaio
if (Left_Tra_Value > Black_Line && Center_Tra_Value <= Black_Line && Right_Tra_Value > Black_Line) { // decisao condicional que seleciona o comportamento autonomo
Forward(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value < Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Right_single(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value >= Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Right_turn(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value >= Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Left_turn(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value < Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Left_single(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value >= Black_Line && Center_Tra_Value >= Black_Line && Right_Tra_Value >= Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
} else if (Left_Tra_Value < Black_Line && Center_Tra_Value < Black_Line && Right_Tra_Value < Black_Line) { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
}
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 4) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
}
}
void Obstacles_Avoidance_mode() { // define rotina de atuacao, leitura ou protocolo do robo
if (func_mode == 2) { // decisao condicional que seleciona o comportamento autonomo
myservo.write(90); //setservo position according to scaled value
delay(300); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
middleDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("M:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(middleDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
if(middleDistance <= 25) { // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(30); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
rightDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("R:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(rightDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(150); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(300); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
leftDistance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.print("L:"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println(leftDistance); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
if(rightDistance > leftDistance) { // decisao condicional que seleciona o comportamento autonomo
Stop(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Back(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Right(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else if(rightDistance < leftDistance) { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Back(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Left(); // executa etapa do firmware do robo tartaruga
delay(200); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else if((rightDistance <= 25) || (leftDistance <= 25)) { // ramo alternativo da decisao de navegacao autonoma
Back(); // executa etapa do firmware do robo tartaruga
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
else { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
}
}
else { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
}
delay(50); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 2) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
delay(50); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
}
void Object_Following_mode() { // define rotina de atuacao, leitura ou protocolo do robo
if (func_mode == 3) { // decisao condicional que seleciona o comportamento autonomo
myservo.write(90); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
UT_distance = Distance_detection(); // executa etapa do firmware do robo tartaruga
Serial.println(UT_distance); // envia telemetria ao Monitor Serial para validacao do ensaio
if (UT_distance < 15) { // decisao condicional que seleciona o comportamento autonomo
Back_slow(); // executa etapa do firmware do robo tartaruga
} else if (15 <= UT_distance && UT_distance <= 20) { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
} else if (20 <= UT_distance && UT_distance <= 25) { // ramo alternativo da decisao de navegacao autonoma
Forward_slow(); // executa etapa do firmware do robo tartaruga
} else if (25 <= UT_distance && UT_distance <= 50) { // ramo alternativo da decisao de navegacao autonoma
Forward(); // executa etapa do firmware do robo tartaruga
} else { // ramo alternativo da decisao de navegacao autonoma
Stop(); // executa etapa do firmware do robo tartaruga
}
for(int i = 0;i < 50;i++) // laco de varredura incremental do ensaio ou da vigilância de modo
{
delay(1); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
Receive_data(); // executa etapa do firmware do robo tartaruga
if(func_mode != 3) // decisao condicional que seleciona o comportamento autonomo
return ; // devolve o valor calculado ao chamador da funcao
}
}
}
unsigned char readBuffer(int index_r) // define rotina de atuacao, leitura ou protocolo do robo
{
return buffer[index_r]; // devolve o valor calculado ao chamador da funcao
}
void writeBuffer(int index_w,unsigned char c) // define rotina de atuacao, leitura ou protocolo do robo
{
buffer[index_w]=c; // executa etapa do firmware do robo tartaruga
}
void setup() // define rotina de atuacao, leitura ou protocolo do robo
{
Serial.setTimeout(10); // executa etapa do firmware do robo tartaruga
Serial.begin(115200); // inicializa a UART de depuracao para o Monitor Serial
Car_init(); // executa etapa do firmware do robo tartaruga
//ESP32PWM::allocateTimer(1);
delay(1000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
WiFi.setTxPower(WIFI_POWER_19_5dBm); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.mode(WIFI_AP); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
WiFi.softAP(ssid, password, 5); // configura o radio WiFi do ESP32 em modo ponto de acesso para comando
Serial.print("\r\n"); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.softAPIP()); // envia telemetria ao Monitor Serial para validacao do ensaio
Serial.println("' to connect"); // envia telemetria ao Monitor Serial para validacao do ensaio
delay(100); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
server.begin(); // inicializa o servidor HTTP ou TCP que atende o navegador e o aplicativo
delay(1000); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
irrecv.enableIRIn();// Start the receiver
}
void loop() // define rotina de atuacao, leitura ou protocolo do robo
{
RXpack_func(); // executa etapa do firmware do robo tartaruga
getIRData(); // executa etapa do firmware do robo tartaruga
//model4_func();
}
void functionMode() // define rotina de atuacao, leitura ou protocolo do robo
{
switch (func_mode) // seleciona o comando recebido via infravermelho ou rede
{
case 3: // executa etapa do firmware do robo tartaruga
{
Object_Following_mode(); // follow model
}
break; // executa etapa do firmware do robo tartaruga
case 4: // executa etapa do firmware do robo tartaruga
{
Line_Tracing_mode(); // Tracking model1
}
break; // executa etapa do firmware do robo tartaruga
case 2: // executa etapa do firmware do robo tartaruga
{
Obstacles_Avoidance_mode(); // OA model
}
break; // executa etapa do firmware do robo tartaruga
default:break; // executa etapa do firmware do robo tartaruga
}
}
void Receive_data() //Receive data
{
if (client.available()) // gerencia a conexao do cliente movel no protocolo de comando em quadros
{
unsigned char c = client.read()&0xff; // gerencia a conexao do cliente movel no protocolo de comando em quadros
Serial.write(c); // executa etapa do firmware do robo tartaruga
if(c==0x55&&isStart==false) // decisao condicional que seleciona o comportamento autonomo
{
if(prevc==0xff) // decisao condicional que seleciona o comportamento autonomo
{
index_a=1; // executa etapa do firmware do robo tartaruga
isStart = true; // executa etapa do firmware do robo tartaruga
}
}
else // ramo alternativo da decisao de navegacao autonoma
{
prevc = c; // executa etapa do firmware do robo tartaruga
if(isStart) // decisao condicional que seleciona o comportamento autonomo
{
if(index_a==2) // decisao condicional que seleciona o comportamento autonomo
{
dataLen = c; // executa etapa do firmware do robo tartaruga
}
else if(index_a>2) // ramo alternativo da decisao de navegacao autonoma
{
dataLen--; // executa etapa do firmware do robo tartaruga
}
writeBuffer(index_a,c); // executa etapa do firmware do robo tartaruga
}
}
index_a++; // executa etapa do firmware do robo tartaruga
if(index_a>120) // decisao condicional que seleciona o comportamento autonomo
{
index_a=0; // executa etapa do firmware do robo tartaruga
isStart=false; // executa etapa do firmware do robo tartaruga
}
if(isStart&&dataLen==0&&index_a>3) // decisao condicional que seleciona o comportamento autonomo
{
isStart = false; // executa etapa do firmware do robo tartaruga
parseData(); // executa etapa do firmware do robo tartaruga
index_a=0; // executa etapa do firmware do robo tartaruga
}
}
}
void Servo_Move(int angles) //servo
{
myservo.write(angles); // posiciona o servo no angulo indicado para varredura ou centragem do sensor
if (angles >= 179) angles = 179; // decisao condicional que seleciona o comportamento autonomo
if (angles <= 1) angles = 1; // decisao condicional que seleciona o comportamento autonomo
delay(10); // aguarda estabilizacao mecanica ou garante janela de observacao do fenomeno
}
void runModule(int device) // define rotina de atuacao, leitura ou protocolo do robo
{
val = readBuffer(12); // executa etapa do firmware do robo tartaruga
switch(device) // seleciona o comando recebido via infravermelho ou rede
{
case 0x0C: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
switch (val) // seleciona o comando recebido via infravermelho ou rede
{
case 0x01: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Forward(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x02: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Back(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x03: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Left(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x04: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Right(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x05: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Left_single(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x06: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
break; // executa etapa do firmware do robo tartaruga
case 0x07: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Right_single(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case 0x08: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
break; // executa etapa do firmware do robo tartaruga
case 0x0A: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
break; // executa etapa do firmware do robo tartaruga
case 0x09: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
break; // executa etapa do firmware do robo tartaruga
case 0x00: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
Stop(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
default: // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
}
}break;
case 0x02: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
Servo_Move(val); // executa etapa do firmware do robo tartaruga
}break;
case 0x03: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
}break;
case 0x05: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
}break;
case 0x08: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
}break;
case 0x0D: // mapeia o codigo hexadecimal do botao do controle ao movimento correspondente
{
carSpeed = val; // executa etapa do firmware do robo tartaruga
}break;
}
}
void parseData() // define rotina de atuacao, leitura ou protocolo do robo
{
isStart = false; // executa etapa do firmware do robo tartaruga
int action = readBuffer(9); // define rotina de atuacao, leitura ou protocolo do robo
int device = readBuffer(10); // define rotina de atuacao, leitura ou protocolo do robo
switch (action) // seleciona o comando recebido via infravermelho ou rede
{
case CMD_RUN: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 1; // executa etapa do firmware do robo tartaruga
runModule(device); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case CMD_STANDBY: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 1; // executa etapa do firmware do robo tartaruga
Stop(); // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case CMD_TRACK_1: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 4; // executa etapa do firmware do robo tartaruga
//Serial.write(0x01);
break; // executa etapa do firmware do robo tartaruga
case CMD_TRACK_2: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 4; // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case CMD_AVOID: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 2; // executa etapa do firmware do robo tartaruga
break; // executa etapa do firmware do robo tartaruga
case CMD_FOLLOW: // executa etapa do firmware do robo tartaruga
//callOK_Len01();
func_mode = 3; // executa etapa do firmware do robo tartaruga
Instalação do aplicativo: no Android, copie o APK da pasta do kit para o celular e instale permitindo fonte do kit; no iOS, busque kuongshun na loja e instale. Operação: ligue o robô com baterias, conecte o WiFi em KUONGSHUN-AD177, abra o APP, selecione o tartaruga ESP32 e toque em conectar. Resultado esperado: o D-pad move com parada ao soltar e já alterna para o modo livre, os botões de modo assumem desvio, seguimento e linha, o slider ajusta velocidade em tempo real, e o indicador mostra conectado. Nas próximas ligadas, basta reassociar no WiFi e abrir o APP, sem regravar. Se o APP mostra WiFi conectado mas robô desconectado, toque no indicador para reconectar o socket na porta 100. Se o D-pad anda invertido, confira IN1/IN2 e IN3/IN4 nos bornes antes de culpar o APP.
⚠️ Atenção: instale o APK apenas da pasta do kit. APK de terceiros com mesmo nome pode implementar protocolo diferente e mover o robô de forma imprevisível.
Guia Diagnóstico (Troubleshooting)
A matriz abaixo parte dos sintomas reais do kit AD177 na bancada e no chão, com causa raiz e ação corretiva sem chute. Diagnostique sempre nesta ordem: alimentação, fiação pelo mapa de pinos, versão de núcleo e biblioteca, e por fim pista e ambiente. A maioria dos chamados se resolve nos três primeiros sem trocar peça.
| Sintoma | Causa raiz provável | Ação corretiva |
|---|---|---|
| Nenhuma porta COM além de COM1 | Cabo de carga sem dados ou CH340 ausente | Trocar por cabo Tipo-C de dados conhecido e instalar o CH340 da pasta do kit, reiniciar e reconectar |
Failed to connect no upload | Bootloader sem reset automático ou porta errada | Selecionar a COM correta, segurar BOOT na placa durante o início do upload, soltar após os pontos |
ledcSetup was not declared | Núcleo ESP32 3.x instalado | Voltar o núcleo para 2.0.12 no Gerenciador de Placas e recompilar |
ESP32Servo.h: No such file | Biblioteca ausente ou IDE sem reiniciar | Instalar ESP32Servo 1.1.2 pela tabela-mestre, conferir libraries/ESP32Servo, reiniciar a IDE |
IRremote.h: No such file | Biblioteca ausente ou duplicada | Instalar IRremote 4.1.2, remover pasta duplicada com nome parecido, reiniciar |
| Robô não anda mas Serial avança | Bateria fraca, chave desligada ou fio de motor solto | Medir pack acima de 7 V, ligar a chave, repuxar bornes do L298N |
| Uma roda gira invertida | Fios do motor invertidos no borne | Desligar, remover baterias e inverter os dois fios daquele motor no L298N |
| Servo com jitter ou varredura assimétrica | Bateria fraca ou braço desalinhado | Recarregar 18650 e refazer o zero a 90 graus com reset e reencaixe do braço |
| Ultrassom trava em zero ou oscila | TRIG e ECHO trocados ou eco contaminado | Conferir GPIO 19 TRIG e 18 ECHO, afastar de ventilador, medir com alvo plano a 30 cm |
| Linha ignora a fita ou oscila | Limiar e trimpot fora do ponto da sala | Recalibrar com Serial dos três canais e trimpots, reduzir cruzeiro de 200 para 150, ensaiar em sombra |
| IR não responde em nenhum modo | Sem visada, pilha fraca ou GPIO errado | Trocar CR2025/CR2032, apontar ao olho sem obstrução, conferir GPIO 15 no fio real |
| IR funciona na Lição 7 mas não na 9 | Código declara receptor em 5 e fio está em 15 | Alterar o pino para o fio real e recarregar o modo 9 |
Rede KUONGSHUN-AD177 não aparece | Alimentação insuficiente do rádio | Recarregar 18650, conferir paralelo da bateria na expansão e no L298N, religar e aguardar 10 s |
Conecta no WiFi mas 192.168.4.1 não abre | Celular pulou para dados móveis ou modo errado gravado | Desativar dados móveis, manter sem internet conectado, recarregar o sketch Web correspondente |
| APP mostra WiFi ok mas robô desconectado | Socket TCP 100 caiu | Tocar no indicador do APP para reconectar, reassociar no WiFi se trocou de rede |
| Desvio bate antes de parar | Cruzeiro alto ou servo descentralizado | Reduzir de 255 para 200 e refazer o zero do servo da Lição 3 |
| Seguimento avança sem parar | ECHO solto lendo zero | Reconectar ECHO no GPIO 18 e validar telemetria antes de soltar no chão |
| Página Web carrega mas slider não atua | Cache do navegador com JS antigo | Recarregar sem cache e retestar os sliders de servo e velocidade |
💡 Dica: mantenha um caderno de bancada com pack medido, limiar de linha do dia, códigos IR do seu controle e versão de núcleo. O diagnóstico cai pela metade quando o ponto de partida está anotado.
Solução de problemas
Olá! Sou o assistente técnico da RoboBuilders. Descreva seu problema com o Kit Robô Tartaruga ESP32 WiFi AD177 - 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.