Kit Robô Inteligente 4WD Completo AD118

Kit Robô Inteligente 4WD AD118 — Curso Completo com Projetos Práticos

Introdução

Este curso profissional apresenta uma formação técnica completa, progressiva e aprofundada em robótica móvel, cinemática de veículos terrestres não tripulados (AGVs / UGVs) e sistemas embarcados utilizando a plataforma microcontrolada Arduino Uno R3 e o Kit Robô Inteligente 4WD Completo AD118. Ao longo de módulos estruturados, são explorados desde a fundamentação mecânica e elétrica do chassi de acrílico duplo com quatro motores de tração independente (Four-Wheel Drive) até o desenvolvimento de algoritmos avançados de navegação autônoma, teleoperação sem fio via Bluetooth Low Energy (BLE), decodificação de pacotes infravermelhos em tempo real e fusão de sensores ópticos e ultrassônicos.

Projetado sob rigorosos padrões de engenharia mecatrônica, este material foi elaborado para capacitar estudantes, hobbistas, técnicos e engenheiros no domínio de pontes H de potência, modulação por largura de pulso (PWM — Pulse Width Modulation), protocolos de comunicação assíncrona (UART), filtragem de ruídos em sinais acústicos e infravermelhos e arquitetura de firmware concorrente com Máquinas de Estados Finitos (FSM).

Kit Robô Inteligente 4WD AD118 totalmente montado e integrado com sensores e atuadores

O que você vai aprender:

  • Compreender a cinemática diferencial e de deslizamento lateral (Skid Steering) de robôs móveis com 4 rodas de tração independente
  • Realizar a montagem estrutural mecânica precisa do chassi de acrílico duplo, caixas de redução e suportes pan-tilt
  • Dominar a integração elétrica e de potência utilizando a placa de expansão Sensor Shield V5.0 e a Ponte H Dupla L298N
  • Implementar controle de torque, velocidade e frenagem regenerativa via sinais PWM analógicos
  • Estabelecer comunicação sem fio bidirecional via transceptor Bluetooth BLE HC-08 e protocolo serial UART a 9600 bps
  • Decodificar pulsos infravermelhos modulados a 38 kHz no protocolo NEC com controle remoto de 21 teclas
  • Projetar sistemas de sensoriamento espacial com transdutores ultrassônicos HC-SR04 montados em servomotores angulares SG90
  • Programar robôs seguidores de linha autônomos com matriz óptica reflexiva de 3 canais TCRT5000 e condicionamento LM393
  • Desenvolver uma arquitetura de software unificada e escalável com máquina de estados finitos hierárquica e rotinas não-bloqueantes com millis()

Material utilizado: Kit Robô Inteligente 4WD Completo AD118


Visão Geral da Arquitetura de Hardware e Kit AD118

O Kit Robô Inteligente 4WD AD118 é uma plataforma robótica educacional de alto nível baseada no microcontrolador ATmega328P (Arduino Uno R3). A estrutura física adota um chassi de acrílico duplo transparente de 3 mm com furação padrão para fixação rígida de atuadores, placas lógicas, baterias de lítio e módulos de sensoriamento. A tração integral é realizada por quatro motores DC com caixa de redução interna 1:48, permitindo manobras rápidas de translação, curvas suaves e rotação em torno do próprio eixo central (Zero-Radius Pivot Turn).

Placa de expansão Arduino Sensor Shield V5.0 Módulo Driver de Potência com Ponte H Dupla L298N

Especificações Técnicas do Microcontrolador Arduino Uno R3

Parâmetro de EngenhariaEspecificação TécnicaObservações de Operação
Microcontrolador PrincipalATmega328P (8-bit AVR RISC)Arquitetura Harvard modificada com execução de 1 ciclo por instrução
Tensão Lógica de Operação5,0 VDCNível TTL padrão de entrada/saída
Tensão de Alimentação do Sistema (VIN / Jack)7,4 V a 8,4 VDC (2x Baterias 18650)Alimentado através da saída regulada do L298N ou barramento VIN
Pinos de Entrada/Saída Digital (GPIO)14 pinos (D0 a D13)6 pinos suportam PWM nativo de 8 bits por hardware (D3, D5, D6, D9, D10, D11)
Pinos de Entrada Analógica6 canais (A0 a A5)Resolução de 10 bits (0 a 1023 passos com VREF = 5V)
Corrente Máxima por Pino de I/O20 mA (típico), 40 mA (limite absoluto)Barramento total limitado a 200 mA
Memória Flash de Programa32 KB0,5 KB ocupados pelo bootloader Optiboot
Memória SRAM de Dados Voláteis2 KBArmazenamento dinâmico de variáveis e buffers seriais
Memória EEPROM Não-Volátil1 KBArmazenamento de parâmetros de calibração
Frequência de Clock do Núcleo16 MHz (±0,5%)Oscilador a cristal externo de alta estabilidade
Interface USB-SerialConversor CH340G / ATmega16U2Comunicação UART assíncrona full-duplex com PC e módulos

Especificações dos Módulos, Atuadores e Sensores do Robô

Subsistema / MóduloCircuito Integrado / ComponenteFaixa de OperaçãoFunção no Sistema Robótico
Driver de Potência dos MotoresCircuito Integrado Ponte H Dupla L298N5V a 35V / 2A por canal (pico 3A)Controle bidirecional de sentido e velocidade PWM dos 4 motores DC
Motores de Tração (4 unidades)Motor DC TT com caixa de redução 1:483V a 6V DC (Torque 0,8 kg·cm a 4,5V)Acionamento das 4 rodas de borracha com alta aderência
Placa de Expansão de E/SArduino Sensor Shield V5.05V DC (com barramento de alimentação externa)Roteamento facilitado dos pinos GPIO em padrão Signal-VCC-GND (SVG)
Transceptor Bluetooth Sem FioMódulo HC-08 BLE (Chip CC2540/CC2541)3,3V a 5V / UART 9600 bpsComunicação sem fio teleoperada com smartphone / aplicativo mobile
Receptor de InfravermelhoMódulo Sensor AX-1838HS (38 kHz)2,7V a 5,5V / Filtro de luz visívelRecepção e demodulação de comandos do controle remoto NEC
Sensor de Distância UltrassônicoMódulo HC-SR04 (Transdutor Piezoelétrico)5V DC / Alcance de 2 cm a 400 cm (15° de abertura)Medição telemétrica de obstáculos por eco acústico de 40 kHz
Mecanismo Pan-Tilt de VarreduraMicro Servomotor Analógico SG90 de 9g4,8V a 6,0V / Curso angular de 0° a 180°Rotação do sensor ultrassônico para varredura angular frontal e lateral
Módulo Seguidor de Linha (3 canais)Sensores Ópticos Reflexivos TCRT5000 + LM3933,3V a 5V / Distância focal de 1 mm a 25 mmDetecção de contraste óptico (pista preta / fundo reflexivo claro)
Fonte de Alimentação PrimáriaSuporte Duplo para Baterias de Íon de Lítio 186507,4V nominal (8,4V em carga plena)Fornecimento de energia com alta densidade de corrente para motores e lógica

Inventário Completo de Componentes (Packing List do Kit AD118)

O Kit Robô Inteligente 4WD AD118 acompanha todos os componentes mecânicos, fixadores metálicos, placas eletrônicas e cabeamento necessários para a construção completa do sistema:

Inventário de peças e componentes mecânicos e eletrônicos do Kit Robô 4WD AD118
  • 1x Placa microcontroladora compatível com Arduino Uno R3 (ATmega328P + CH340)
  • 1x Placa de expansão de entradas e saídas Arduino Sensor Shield V5.0
  • 1x Módulo Driver de Motor Ponte H Dupla L298N com dissipador de calor em alumínio anodizado
  • 1x Módulo Transceptor Bluetooth Low Energy HC-08 (BLE V4.0)
  • 1x Módulo Sensor Receptor Infravermelho integrado AX-1838HS (38 kHz)
  • 1x Controle remoto infravermelho de 21 teclas (com bateria CR2025/CR2032 inclusa)
  • 1x Módulo Sensor Telemétrico Ultrassônico de Distância HC-SR04
  • 1x Micro Servomotor SG90 de 9g com acessórios de fixação e cruzetas
  • 3x Módulos Sensores Ópticos Reflexivos Seguidores de Linha TCRT5000 com comparador LM393
  • 4x Motores DC TT com caixa de redução interna 1:48 e fios pré-soldados
  • 4x Rodas de borracha de alta tração e diâmetro de 65 mm com cubo de acoplamento chanfrado tipo D
  • 1x Chassi estrutural inferior em acrílico cortado a laser com película protetora
  • 1x Chassi estrutural superior em acrílico cortado a laser com furação para servo e bateria
  • 1x Conjunto de suporte de acrílico para montagem do servo pan-tilt e sensor ultrassônico
  • 4x Discos encoders ópticos de velocidade com 20 fendas
  • 8x Suportes metálicos / acrílicos de fixação rápida para os motores TT no chassi
  • 1x Suporte para 2 baterias de lítio 18650 com plug conector e chave liga/desliga
  • 6x Espaçadores sextavados de latão M3 × 30 mm (macho-fêmea e fêmea-fêmea) para união dos chassis
  • 4x Espaçadores de latão M3 × 10 mm / M3 × 15 mm para elevação das placas
  • 1x Conjunto de parafusos mecânicos M3 (comprimentos variados: 8mm, 10mm, 30mm) e porcas sextavadas M3
  • 1x Conjunto de parafusos finos autorroscantes e parafusos para montagem do servo SG90
  • 1x Cabo de comunicação e programação USB Tipo A para Tipo B (50 cm)
  • 20x Cabos jumper fêmea-fêmea de 20 cm para interconexão dos sensores e atuadores
  • 10x Cabos jumper macho-fêmea de 20 cm
  • 1x Rolo de fita isolante preta de alta aderência para montagem de pista de testes
  • 1x Chave de fenda / Philips para montagem mecânica

📦 Somatória Geral do Kit: 84 componentes individuais (englobando elementos de estrutura mecânica, caixas de redução, placas de circuito impresso, cablagem, sensores e fixadores).


Módulo 0 — Montagem Mecânica Passo a Passo e Arquitetura Elétrica

Lição 0.1: Montagem Estrutural Mecânica do Robô 4WD

A montagem do Kit Robô Inteligente 4WD AD118 deve ser realizada com precisão e atenção aos torques de aperto para evitar tensões mecânicas excessivas sobre as placas de acrílico. Antes de iniciar, remova a película protetora de papel kraft de todas as peças acrílicas.

Passos 1 a 4: Fixação dos Motores TT e Rodas no Chassi Inferior

  1. Instalação dos Suportes dos Motores: Posicione os 4 motores DC TT no chassi inferior de acrílico, alinhando os eixos de tração para o lado externo. Utilize os suportes de fixação em conjunto com os parafusos longos M3 e porcas sextavadas para prender firmemente cada motor.
  2. Instalação dos Discos Encoders: Encaixe os discos perfurados de encoder nos eixos traseiros dos quatro motores TT.
Passo 1: Fixação dos suportes dos motores DC no chassi inferior Passo 2: Montagem dos quatro motores TT e discos encoders
Passo 3: Fixação estrutural dos motores com parafusos M3 Passo 4: Verificação do alinhamento dos 4 motores de tração

Passos 5 a 8: Montagem do Módulo Ponte H L298N e Sensores de Linha

  1. Fixação do Driver L298N: Fixe o módulo driver Ponte H L298N na parte superior do chassi inferior utilizando parafusos M3 e porcas, com os bornes de saída de potência voltados para as laterais do veículo.
  2. Instalação dos 3 Sensores de Linha: Fixe os três módulos ópticos TCRT5000 na extremidade dianteira da face inferior do chassi acrílico, alinhando os emissores infravermelhos voltados diretamente para o solo (a uma distância focal recomendada de 5 mm a 12 mm da pista).
Passo 5: Fixação do módulo driver Ponte H L298N no chassi inferior Passo 6: Instalação e alinhamento dos 3 módulos seguidores de linha TCRT5000
Passo 7: Fixação dos espaçadores sextavados de latão M3 no chassi inferior Passo 8: Fiação dos motores direito e esquerdo aos bornes do L298N

Passos 9 a 14: Montagem do Suporte Pan-Tilt, Servomotor e Sensor Ultrassônico

  1. Montagem do Suporte do Servo SG90: Encaixe o micro servomotor SG90 no suporte de acrílico frontal superior e trave com os parafusos autorroscantes inclusos.
  2. Fixação do Sensor HC-SR04: Encaixe o sensor ultrassônico HC-SR04 no suporte facial de acrílico correspondente e una a cruzeta do servo motor à haste de rotação para permitir varredura angular livre de 0° a 180°.
Passo 9: Encaixe do servomotor SG90 na base do suporte pan-tilt Passo 10: Acoplamento do sensor ultrassônico HC-SR04 no suporte
Passo 11: Fixação do suporte ultrassônico articulado no chassi superior Passo 12: Instalação da placa Arduino Uno R3 no chassi superior

Passos 15 a 20: União dos Chassis, Shield V5.0, Bateria e Rodas

  1. Instalação do Arduino Uno e Sensor Shield V5.0: Fixe a placa Arduino Uno R3 no chassi superior com parafusos M3 e acople o Sensor Shield V5.0 firmemente sobre seus barramentos de pinos fêmea.
  2. Instalação do Suporte de Bateria 18650: Posicione o suporte de baterias na traseira do chassi superior para equilibrar o centro de gravidade do robô.
  3. União Estrutural e Acoplamento das Rodas: Una os dois chassis através dos 6 espaçadores de latão M3 × 30 mm, encaixe as quatro rodas de borracha nos eixos chanfrados dos motores e fixe o módulo receptor IR e Bluetooth HC-08.
Passo 13: Encaixe da placa Sensor Shield V5.0 sobre o Arduino Uno R3 Passo 14: Fixação do suporte de baterias 18650 com chave liga/desliga
Passo 15: Conexão dos chicotes de cabos jumpers entre o shield e os atuadores Passo 16: Conexão do módulo Bluetooth BLE HC-08 na porta serial
Passo 17: Conexão do módulo receptor infravermelho AX-1838HS Passo 18: União mecânica dos chassis com espaçadores sextavados M3
Passo 19: Encaixe sob pressão das quatro rodas de borracha 65mm Passo 20: Inspeção final do conjunto robótico 4WD totalmente montado

Lição 0.3: Configuração da IDE Arduino, Instalação de Drivers USB e Gravação

Antes de testar a movimentação autônoma do robô, o ambiente de compilação da IDE Arduino e os drivers de comunicação USB do microcontrolador devem ser corretamente configurados no computador.

Seleção do modelo da placa Arduino Uno e porta de comunicação COM na IDE Arduino Assistente de instalação do driver USB do Arduino Uno no sistema operacional Windows

Toolchain oficial pinada deste curso (versões usadas na bancada)

A documentação do fabricante KUONGSHUN (pastas Lesson 0 a Lesson 5, PDFs de 2019, códigos forward_back, AUTO_GO, bluetooth_car, Infrared_remote_control_car, Obstacle_Avoidance_Car, Line_tracking_car e APK KUONGSHUN BLE Tool.apk) foi escrita para a linha Arduino IDE 1.8 com núcleo AVR clássico. Para reproduzir os 11 sketches do pacote sem erro de compilação, fixe exatamente estas versões antes do primeiro upload:

Ferramenta / PacoteVersão usada no cursoOnde obter (oficial)Observação de bancada
Arduino IDE1.8.19 (série 1.8)arduino.cc — Software 1.8.19Última 1.8 estável; 100% compatível com IRremote 2.0.1 e AVR. IDE 2.x compila, mas muda telas e mensagens — o passo a passo abaixo usa a 1.8.
Arduino AVR Boards (núcleo)1.8.6Ferramentas > Placa > Gerenciador de Placas… → buscar Arduino AVR Boards → selecionar 1.8.6 → InstalarDefine digitalWrite, analogWrite, pulseIn, Serial do ATmega328P. Núcleo errado é a causa nº 1 de not declared in scope.
Driver USB-serial CH3403.8 (2023)wch.cn — CH341SERA placa do kit usa conversor CH340G. Sem ele, a porta COM não aparece. Cabo precisa ser de dados, não só de carga.
Biblioteca IRremote2.0.1 (shirriff) — OBRIGATÓRIAZIP IRremote.zip dentro da pasta Lesson 3 do fabricanteAPI antiga (decode(&results), results.value, códigos decimais como 16736925). NUNCA instalar a latest (3.x/4.x quebra 100% dos sketches IR do kit).
Biblioteca ServoEmbutida na IDE 1.8.19Nenhum download — Arquivo > Exemplos > ServoControla o SG90 no pino D3. Nada a instalar.
APP de pilotagemKUONGSHUN BLE Tool.apk (pasta Lesson 2 do fabricante)APK dentro do pacote do kitApp Android do fabricante; pareia com o HC-08 e envia f/b/l/r/s/a. iOS usa app BLE genérico.

⚠️ Atenção: se você já tem IRremote 3.x ou 4.x instalada, desinstale antes (Sketch > Incluir Biblioteca > Gerenciar Bibliotecas… → IRremote → Remover), instale a 2.0.1 via ZIP (Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP… → apontar para o IRremote.zip da Lesson 3), feche e reabra a IDE. Misturar majors causa error: 'class IRrecv' has no member named 'decodedIRData' ou o inverso ('decode_results' does not name a type).

Tabela-mestre de bibliotecas do curso

Consolidada de todos os #include dos 11 sketches do fabricante. Cada lição referencia esta tabela no seu box > 📦 **Bibliotecas desta lição:**.

Biblioteca (#include)Buscar no GerenciadorVersão usada no cursoDownload ZIP (espelho oficial)Lições que usam
IRremote.hIRremote por shirriff — fixar 2.0.1, nunca latest2.0.1ZIP IRremote.zip da pasta Lesson 3 do fabricante; espelho oficial shirriff/Arduino-IRremote (tag 2.0.1)3.1 (infrared_Blink), 3.2 (Infrared_remote_control_car), Apêndice SmartCar_Core
Servo.hEmbutida — nada a instalarIDE 1.8.19—4.1 (Servo_debug), 4.2 (Obstacle_Avoidance_Car), Apêndice SmartCar_Core
(nenhuma — nativo)—Núcleo AVR 1.8.6—1.1 (forward_back), 1.2 (left_wheel_rotation), 1.3 (right_wheel_rotation), 1.4 (AUTO_GO), 1.5 (speed_control), 2.1 (bluetooth_blink), 2.2 (bluetooth_car), 5 (Line_tracking_car: usa só digitalRead/analogWrite/Serial)

📦 Bibliotecas desta lição: nenhuma — preparação de ambiente; se o próximo sketch pedir IRremote ou Servo, volte a esta tabela-mestre e confira a versão antes de compilar.

Passo a Passo para Instalação e Primeiro Upload:

  1. Instalar a IDE 1.8.19: baixe no site oficial, instale com a opção de drivers marcada. Abra e confira em Ajuda > Sobre o Arduino que exibe 1.8.19.
  2. Fixar o núcleo AVR 1.8.6: Ferramentas > Placa > Gerenciador de Placas… → Arduino AVR Boards → 1.8.6 → Instalar. Selecione depois Ferramentas > Placa > Arduino Uno.
  3. Instalar o driver CH340: execute o CH341SER.EXE oficial, conecte o cabo USB de dados tipo A/B na Uno. No Gerenciador de Dispositivos do Windows deve aparecer USB-SERIAL CH340 (COM[X]).
  4. Instalar as bibliotecas pela tabela-mestre: IRremote 2.0.1 via ZIP da Lesson 3; Servo já vem na IDE — confira em Arquivo > Exemplos > Servo > Sweep que compila (✓ Verificar) sem No such file or directory.
  5. Conexão Física: conecte o cabo USB tipo A/B da placa à porta USB do computador, com o robô desligado (chave OFF) e o jumper do Bluetooth fora de D0/D1.
  6. Seleção de Placa e Porta: Ferramentas → Placa → Arduino Uno e Ferramentas → Porta → COM[X] (a COM do CH340).
  7. Primeiro upload de validação: abra Arquivo > Exemplos > 01.Basics > Blink, clique em Carregar. O LED L (D13) deve piscar a 1 Hz. Se falhar com stk500_recv(), volte ao passo 5 (Bluetooth fora de D0/D1) e confira cabo de dados vs. só-carga.
  8. Monitor Serial: Ferramentas > Monitor Serial, fixar 9600 baud e Ambos NL & CR. Todo sketch do kit usa Serial.begin(9600) — baud errado exibe lixo.
Confirmação de gravação concluída com sucesso na barra de status da IDE Arduino

💡 Dica: grave o Blink antes de qualquer sketch do robô. Ele prova que IDE + núcleo + driver + cabo + porta estão íntegros. Só então passe ao forward_back (Lição 1.1) com as rodas livres (robô suspenso) e a chave do suporte 18650 em OFF durante o upload, ligando-a só após desconectar o USB.


Lição 0.2: Tabela Mestra de Pinagem e Interconexão Elétrica

Para garantir o perfeito funcionamento de todos os subsistemas sem conflitos de portas digitais ou barramentos analógicos, a conexão elétrica entre o Arduino Uno R3 (através do Sensor Shield V5.0), o driver L298N, os sensores e atuadores deve seguir rigorosamente a matriz padronizada de fiação:

Diagrama esquemático oficial de ligações e cabeamento do Robô 4WD AD118

Matriz Completa de Pinagem do Sistema Robótico AD118

Porta Arduino / Shield V5.0Tipo de SinalMódulo ou Atuador ConectadoPino de Destino no DispositivoFunção e Observações Técnicas
D0 (RX)Entrada Digital / UARTMódulo Bluetooth HC-08TXDRecepção serial de dados do smartphone (9600 baud)
D1 (TX)Saída Digital / UARTMódulo Bluetooth HC-08RXDTransmissão serial de telemetria para o smartphone
D2 (S2)Entrada DigitalSeguidor de Linha #3 (Esquerdo)OUT / D0Leitura digital do sensor infravermelho esquerdo
D3 (S3)Saída Digital / PWMMicro Servomotor SG90Sinal (Fio Laranja / Amarelo)Controle angular de 0° a 180° via modulação por pulsos de 50 Hz
D4 (S4)Entrada DigitalSeguidor de Linha #2 (Centro)OUT / D0Leitura digital do sensor infravermelho central de pista
D5 (S5)Saída Digital / PWMDriver Ponte H L298NENA (Enable A)Controle de velocidade PWM dos Motores Direitos (0 a 255)
D6 (S6)Saída Digital / PWMDriver Ponte H L298NENB (Enable B)Controle de velocidade PWM dos Motores Esquerdos (0 a 255)
D7 (S7)Saída DigitalDriver Ponte H L298NIN1Controle de direção do Motor Direito (Canal A)
D8 (S8)Saída DigitalDriver Ponte H L298NIN2Controle de direção do Motor Direito (Canal A)
D9 (S9)Saída DigitalDriver Ponte H L298NIN3Controle de direção do Motor Esquerdo (Canal B)
D10 (S10)Entrada DigitalSeguidor de Linha #1 (Direito)OUT / D0Leitura digital do sensor infravermelho direito
D11 (S11)Saída DigitalDriver Ponte H L298NIN4Controle de direção do Motor Esquerdo (Canal B)
D12 (S12)Entrada DigitalMódulo Receptor IR AX-1838HSDAT / S (Sinal)Recepção dos pulsos de onda portadora demodulada em 38 kHz
D13Saída DigitalLED Onboard da Placa UnoAnodo LEDIndicador de status de firmware e depuração visual
A4Entrada DigitalSensor Ultrassônico HC-SR04ECHORecepção do pulso de eco proporcional à distância
A5Saída DigitalSensor Ultrassônico HC-SR04TRIGDisparo do trem de 8 pulsos ultrassônicos de 40 kHz
5V / VCCAlimentação LógicaBarramentos VCC dos MódulosVCC / V+Linha de 5,0 V regulada para sensores e microcontrolador
GNDReferência / TerraBarramentos GND dos MódulosGND / G / -Potencial de referência comum para lógica e potência

Conexão de Potência dos Motores no Driver L298N

  • Borne OUT1 & OUT2 (Canal Direito): Conectados em paralelo aos cabos dos 2 Motores Direitos (Frente Direito + Traseiro Direito). Fio vermelho em OUT1 e fio preto em OUT2.
  • Borne OUT3 & OUT4 (Canal Esquerdo): Conectados em paralelo aos cabos dos 2 Motores Esquerdos (Frente Esquerdo + Traseiro Esquerdo). Fio preto em OUT3 e fio vermelho em OUT4.
  • Borne VCC (+12V Power In): Conectado ao polo positivo (+7,4V / +8,4V) do suporte de baterias 18650 através da chave geral.
  • Borne GND (Power Ground): Conectado ao polo negativo (-) do suporte de baterias e interligado ao pino GND do Arduino Uno.
  • Borne +5V (Saída Regulada 5V LDO): Fornece alimentação estável de 5V para o Sensor Shield e o microcontrolador quando o jumper regulador 5V do L298N estiver fechado.

[!IMPORTANT] O pino GND da bateria, o GND do módulo driver L298N e o GND do Arduino Uno / Sensor Shield V5.0 devem estar obrigatoriamente interligados. A ausência de um plano de terra comum causa oscilações lógicas severas e impede o acionamento correto dos transistores da ponte H.


Módulo 1 — Cinemática e Controle de Tração Diferencial 4WD

Neste módulo, você compreenderá os fundamentos físicos e matemáticos da tração diferencial em veículos robóticos de quatro rodas (Skid-Steering Kinematics), a operação em nível de comutação da Ponte H L298N e o controle de velocidade proporcional por modulação PWM.

Módulo Driver Ponte H L298N com terminais de controle e potência Pinagem dos conectores de sinal de controle IN1 a IN4 e ENA/ENB

Fundamentação Teórica da Ponte H Dupla L298N

A ponte H é uma topologia de circuito eletrônico de chaveamento composta por quatro chaves semicondutoras de potência dispostas em formato de ‘H’, permitindo a aplicação de uma diferença de potencial reversível sobre os enrolamentos indutivos dos motores de corrente contínua:

Diagrama de blocos interno e circuito equivalente da Ponte H L298N
  1. Sentido Horário (Avanço): As chaves S1S_1 e S4S_4 são saturadas (fechadas), enquanto S2S_2 e S3S_3 permanecem em corte (abertas). A corrente flui do terminal positivo para o negativo através do enrolamento do motor.
  2. Sentido Anti-Horário (Recuo): As chaves S3S_3 e S2S_2 são saturadas, enquanto S1S_1 e S4S_4 permanecem abertas. O sentido da corrente é invertido, invertendo instantaneamente o vetor de densidade de fluxo magnético no rotor e o torque eletromecânico gerado.
  3. Frenagem Eletrodinâmica: As chaves superiores (S1S_1 e S3S_3) ou inferiores (S2S_2 e S4S_4) são fechadas simultaneamente, curto-circuitando os terminais do motor e dissipando a energia cinética gerada pela força contra-eletromotriz (FCEM) através dos diodos de recirculação (flyback).

Tabela Lógica de Comutação da Ponte H

ENA / ENBIN1 / IN3IN2 / IN4Estado do MotorComportamento Cinemático
0 (LOW)X (Indiferente)X (Indiferente)Desativado (Coast)Motor desenergizado, gira livre por inércia
1 (HIGH / PWM)1 (HIGH)0 (LOW)Rotação Direta (Forward)Eixo gira no sentido de avanço à velocidade definida pelo PWM
1 (HIGH / PWM)0 (LOW)1 (HIGH)Rotação Reversa (Reverse)Eixo gira no sentido de recuo à velocidade definida pelo PWM
1 (HIGH)1 (HIGH)1 (HIGH)Freio Ativo (Brake)Terminais em curto-circuito lógico, frenagem rápida
1 (HIGH)0 (LOW)0 (LOW)Freio Ativo (Brake)Terminais no potencial de terra, frenagem rápida

Modulação por Largura de Pulso (PWM) e Cálculo de Tensão Eficaz

Para controlar a velocidade angular ω\omega dos motores sem dissipar calor excessivo em transistores lineares, o microcontrolador ATmega328P modula a largura de pulso de uma onda quadrada de frequência fixa (≈490 Hz\approx 490\,\text{Hz} nos pinos D5 e D6 do Timer0) variando a razão cíclica (Duty Cycle DD). A tensão média eficaz (VMEDIOV_{\text{MEDIO}}) entregue à carga é expressa por:

D=TONTON+TOFF=TONTPERIODO×100%D = \frac{T_{ON}}{T_{ON} + T_{OFF}} = \frac{T_{ON}}{T_{PERIODO}} \times 100\% VMEDIO=VIN⋅(Duty255)V_{\text{MEDIO}} = V_{IN} \cdot \left( \frac{\text{Duty}}{255} \right)

Onde:

  • Duty\text{Duty} é o valor inteiro de 8 bits fornecido à função analogWrite(pino, Duty), variando no intervalo fechado de 00 (0%0\%, motor imobilizado) a 255255 (100%100\%, tensão plena de VINV_{IN}).
  • VINV_{IN} é a tensão nominal do barramento de potência suprido pelas células de íons de lítio 18650 (VIN≈7,4 VV_{IN} \approx 7,4\,\text{V} a 8,4 V8,4\,\text{V}).

Modelagem Cinemática de Robôs Móveis 4WD (Skid-Steering Kinematics)

Diferente de veículos convencionais que utilizam direção geométrica de Ackermann (esterçamento angular das rodas dianteiras) ou robôs diferenciais clássicos com duas rodas e um rodízio esférico (caster), o Kit Robô AD118 emprega uma arquitetura de tração integral em quatro rodas por deslizamento lateral (SSMR — Skid-Steer Mobile Robot).

Como as quatro rodas são mecanicamente paralelas e não possuem juntas de esterçamento, qualquer rotação ou curva é executada impondo velocidades tangenciais distintas entre os pares de rodas esquerdas e direitas, forçando um escorregamento transversal controlado (tyre scrubbing) contra o piso.

Diagrama cinemático de velocidades e vetores de tração do robô 4WD Modelo geométrico de coordenadas e Centro Instantâneo de Curvatura (ICC)

1. Definição dos Sistemas de Coordenadas (Frames de Referência)

Para descrever a cinemática do robô no plano bidimensional R2\mathbb{R}^2, definimos dois referenciais ortogonais:

  1. Referencial Global / Inercial {XI,YI}\{X_I, Y_I\}: Fixado no plano de navegação (estático no ambiente).
  2. Referencial Local / Robô {XR,YR}\{X_R, Y_R\}: Fixado rigidamente no centro geométrico e de massa do chassi robótico, onde o eixo +XR+X_R aponta na direção frontal de avanço e o eixo +YR+Y_R aponta lateralmente para o lado esquerdo.

O vetor de postura (estado cinemático) do robô no referencial global é definido pela tripla:

q=[xyθ]∈R3\mathbf{q} = \begin{bmatrix} x \\ y \\ \theta \end{bmatrix} \in \mathbb{R}^3

Onde:

  • x,yx, y: Posição cartesiana do centro do robô em metros (m\text{m}).
  • θ\theta: Ângulo de orientação (heading / yaw) em relação ao eixo +XI+X_I global, medido em radianos (rad\text{rad}).

2. Parâmetros Físicos e Geométricos do Kit AD118

Os cálculos cinemáticos do robô dependem das seguintes constantes construtivas dimensionais:

Parâmetro GeométricoSímboloValor no Kit AD118Descrição Construtiva
Raio Nominal das Rodasrr33 mm=0,033 m33\,\text{mm} = 0,033\,\text{m}Diâmetro externo do pneu emborrachado =66 mm= 66\,\text{mm}
Bitola Lateral (Track Gauge)LL150 mm=0,150 m150\,\text{mm} = 0,150\,\text{m}Distância transversal entre os centros de contato das rodas esquerda e direita
Distância entre Eixos (Wheelbase)BB140 mm=0,140 m140\,\text{mm} = 0,140\,\text{m}Distância longitudinal entre os centros dos eixos dianteiro e traseiro
Relação de Redução da Caixa de EngrenagensGG1:481:48Relação de engrenamento mecânico dos motores DC amarelos
Velocidade Angular Máxima do Motorωmotor_max\omega_{\text{motor\_max}}≈200 RPM≈20,94 rad/s\approx 200\,\text{RPM} \approx 20,94\,\text{rad/s}Rotação do eixo de saída em 6 V6\,\text{V} com caixa 1:48

3. Cinemática Direta no Referencial Local (Forward Kinematics)

Sejam ωE\omega_E e ωD\omega_D as velocidades angulares das rodas esquerdas e direitas, respectivamente (rad/s\text{rad/s}). As velocidades lineares tangenciais correspondentes de cada lado do veículo são:

vE=r⋅ωEv_E = r \cdot \omega_E vD=r⋅ωDv_D = r \cdot \omega_D

A velocidade linear longitudinal de translação do robô (vv) e a velocidade angular de guinada (ω=θ˙\omega = \dot{\theta}) no referencial local da estrutura são obtidas pela média e pela diferença diferencial das velocidades de cada esteira/roda:

v=vD+vE2=r(ωD+ωE)2v = \frac{v_D + v_E}{2} = \frac{r (\omega_D + \omega_E)}{2} ω=θ˙=vD−vELefetivo=r(ωD−ωE)Lefetivo\omega = \dot{\theta} = \frac{v_D - v_E}{L_{\text{efetivo}}} = \frac{r (\omega_D - \omega_E)}{L_{\text{efetivo}}}

Em notação matricial com a Matriz Jacobiana Cinemática Direta:

[vω]=[r2r2−rLefetivorLefetivo][ωEωD]\begin{bmatrix} v \\ \omega \end{bmatrix} = \begin{bmatrix} \frac{r}{2} & \frac{r}{2} \\ -\frac{r}{L_{\text{efetivo}}} & \frac{r}{L_{\text{efetivo}}} \end{bmatrix} \begin{bmatrix} \omega_E \\ \omega_D \end{bmatrix}

4. Transformação de Coordenadas para o Referencial Global Inercial

Para mapear as velocidades do referencial móvel {XR,YR}\{X_R, Y_R\} para o referencial de navegação {XI,YI}\{X_I, Y_I\}, aplica-se a matriz de rotação R(θ)R(\theta):

q˙=[x˙y˙θ˙]=[cos⁡θ0sin⁡θ001][vω]=[vcos⁡θvsin⁡θω]\dot{\mathbf{q}} = \begin{bmatrix} \dot{x} \\ \dot{y} \\ \dot{\theta} \end{bmatrix} = \begin{bmatrix} \cos\theta & 0 \\ \sin\theta & 0 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} v \\ \omega \end{bmatrix} = \begin{bmatrix} v \cos\theta \\ v \sin\theta \\ \omega \end{bmatrix}

Expandindo em termos das velocidades angulares individuais das rodas (ωE,ωD\omega_E, \omega_D):

[x˙y˙θ˙]=[r2cos⁡θr2cos⁡θr2sin⁡θr2sin⁡θ−rLefetivorLefetivo][ωEωD]\begin{bmatrix} \dot{x} \\ \dot{y} \\ \dot{\theta} \end{bmatrix} = \begin{bmatrix} \frac{r}{2}\cos\theta & \frac{r}{2}\cos\theta \\ \frac{r}{2}\sin\theta & \frac{r}{2}\sin\theta \\ -\frac{r}{L_{\text{efetivo}}} & \frac{r}{L_{\text{efetivo}}} \end{bmatrix} \begin{bmatrix} \omega_E \\ \omega_D \end{bmatrix}

5. Cinemática Inversa (Inverse Kinematics)

A cinemática inversa calcula as velocidades lineares (vE,vDv_E, v_D) e angulares (ωE,ωD\omega_E, \omega_D) que o microcontrolador deve exigir de cada conjunto de motores para que o robô atinja uma velocidade de translação linear vv (m/s\text{m/s}) e uma taxa de giro ω\omega (rad/s\text{rad/s}) arbitrárias:

vE=v−ω⋅Lefetivo2  ⟹  ωE=1r(v−ω⋅Lefetivo2)v_E = v - \frac{\omega \cdot L_{\text{efetivo}}}{2} \implies \omega_E = \frac{1}{r} \left( v - \frac{\omega \cdot L_{\text{efetivo}}}{2} \right) vD=v+ω⋅Lefetivo2  ⟹  ωD=1r(v+ω⋅Lefetivo2)v_D = v + \frac{\omega \cdot L_{\text{efetivo}}}{2} \implies \omega_D = \frac{1}{r} \left( v + \frac{\omega \cdot L_{\text{efetivo}}}{2} \right)

6. Centro Instantâneo de Curvatura (ICC) e Regimes de Manobra

Durante qualquer movimento sobre o plano, o robô descreve uma trajetória circular instantânea em torno de um ponto geométrico denominado Centro Instantâneo de Curvatura (ICC — Instantaneous Center of Curvature).

O raio de curvatura da trajetória (RR), medido do centro do robô ao ICC, é dado por:

R=vω=Lefetivo2⋅(vD+vEvD−vE)R = \frac{v}{\omega} = \frac{L_{\text{efetivo}}}{2} \cdot \left( \frac{v_D + v_E}{v_D - v_E} \right)

As coordenadas globais do ponto ICC no espaço são calculadas por:

ICC=[ICCxICCy]=[x−Rsin⁡θy+Rcos⁡θ]\mathbf{ICC} = \begin{bmatrix} ICC_x \\ ICC_y \end{bmatrix} = \begin{bmatrix} x - R \sin\theta \\ y + R \cos\theta \end{bmatrix}

Analisando a equação do raio RR, identificamos três regimes cinemáticos fundamentais executados pelo Kit AD118:

  1. Translação Retilínea Pura:
    • Condição (velocidades iguais nos dois lados):
ωE=ωD  ⟹  vD−vE=0\omega_E = \omega_D \implies v_D - v_E = 0
  • Resultado: R→∞R \to \infty e ω=0\omega = 0. O robô desloca-se em linha reta com velocidade v=r⋅ωDv = r \cdot \omega_D.
  1. Giro Pivot em Torno do Eixo Central (Zero-Radius Turn):
    • Condição (velocidades opostas nos dois lados):
ωE=−ωD  ⟹  vE=−vD\omega_E = -\omega_D \implies v_E = -v_D
  • Resultado: R=0R = 0 e v=0v = 0. O ICC coincide perfeitamente com o centro geométrico do robô. O veículo gira no próprio local com velocidade angular máxima:
ω=2vDLefetivo\omega = \frac{2 v_D}{L_{\text{efetivo}}}
  1. Curva Diferencial com Raio Finito RR:
    • Condição: ωE≠ωD\omega_E \neq \omega_D (ambos com mesmo sinal)
    • Resultado: O robô executa trajetória curvilínea suave. O lado com maior velocidade orbita no raio externo:
Rext=R+L2R_{\text{ext}} = R + \frac{L}{2}
 E o lado mais lento percorre o raio interno:
Rint=R−L2R_{\text{int}} = R - \frac{L}{2}

7. Dinâmica de Deslizamento Lateral (Skid-Steering e Bitola Efetiva)

Nos robôs móveis 4WD com quatro rodas coplanares, as rodas dianteiras e traseiras de um mesmo lado giram na mesma velocidade (ωE1=ωE2=ωE\omega_{E1} = \omega_{E2} = \omega_E). Como a distância longitudinal entre eixos (B=140 mmB = 140\,\text{mm}) não é nula, as rodas obrigatoriamente sofrem escorregamento lateral (skid) ao realizar rotações.

As forças de atrito transversal geram um conjugado resistente ao giro MatritoM_{\text{atrito}} proporcional ao coeficiente de atrito pneu-solo (μ\mu) e à massa total do robô (mm):

Matrito≈μ⋅m⋅g⋅B4M_{\text{atrito}} \approx \frac{\mu \cdot m \cdot g \cdot B}{4}

Para compensar esse efeito de dissipação por atrito na modelagem cinemática sem recorrer a modelos dinâmicos complexos, a literatura de robótica móvel introduz o conceito de Bitola Efetiva (LefetivoL_{\text{efetivo}}):

Lefetivo=χ⋅LL_{\text{efetivo}} = \chi \cdot L

Onde χ≥1,0\chi \ge 1,0 é o coeficiente empírico de derrapagem. Em pisos lisos como cerâmica ou madeira polida, χ≈1,15\chi \approx 1,15 a 1,251,25. Em carpetes de alto atrito, χ≈1,4\chi \approx 1,4 a 1,61,6, exigindo maior torque dos motores para vencer a resistência ao giro.

8. Mapeamento de Velocidade Cinemática para Registradores PWM no Arduino

O firmware do microcontrolador ATmega328P mapeia as velocidades lineares desejadas vEv_E e vDv_D para os valores inteiros do conversor PWM de 8 bits (0 a 255).

Devido ao atrito estático dos mancais e das engrenagens plásticas da caixa de redução 1:48, os motores DC não entram em movimento até que a tensão aplicada supere a tensão de zona morta (deadband), correspondente a PWMmin≈60\text{PWM}_{\text{min}} \approx 60. O algoritmo de conversão linear proporcional implementado no microcontrolador é expresso por:

PWMi={0,se vi=0constrain(PWMmin+∣vi∣vmax⋅(255−PWMmin), 0, 255),se ∣vi∣>0\text{PWM}_i = \begin{cases} 0, & \text{se } v_i = 0 \\ \text{constrain}\left( \text{PWM}_{\text{min}} + \frac{|v_i|}{v_{\text{max}}} \cdot (255 - \text{PWM}_{\text{min}}),\, 0,\, 255 \right), & \text{se } |v_i| > 0 \end{cases}

Onde i∈{E,D}i \in \{E, D\}:

vmax=r⋅ωmax≈0,033 m×20,94 rad/s≈0,69 m/s≈2,5 km/hv_{\text{max}} = r \cdot \omega_{\text{max}} \approx 0,033\,\text{m} \times 20,94\,\text{rad/s} \approx 0,69\,\text{m/s} \approx 2,5\,\text{km/h}

Lição 1.1: Movimentação Básica e Teste Unitário dos Motores

Este primeiro programa de validação (forward_back da Lesson 1 do fabricante) executa uma rotina contínua de movimentação, acionando o robô para frente por 2 segundos e para trás por 2 segundos, com parada eletrodinâmica entre inversões para aliviar as engrenagens 1:48.

📦 Bibliotecas desta lição: nenhuma — o código usa digitalWrite(), analogWrite(), delay() e pinMode() nativos do núcleo AVR 1.8.6, sem biblioteca externa. Se der not declared in scope, reinstale o núcleo pela tabela-mestre da Lição 0.3.

Código-Fonte Completo Comentado: forward_back.ino

💡 Dica: primeiro upload com o robô suspenso (rodas livres, sem contato com o piso) e baterias em OFF. Resultado esperado: 2 s frente → 0,5 s parado → 2 s ré → 0,5 s parado, em loop. Se um lado girar invertido, inverta os fios do borne correspondente (OUT1/OUT2 ou OUT3/OUT4), nunca o código primeiro.

/*
 * =====================================================================================
 * Projeto: Movimentacao Basica de Avanco e Recuo (Robo 4WD AD118)
 * Autor: Engenharia RoboBuilders
 * Plataforma: Arduino Uno R3 + Sensor Shield V5.0 + Driver L298N
 * Descricao: Aciona os 4 motores DC em velocidade constante para frente e para tras
 * =====================================================================================
 */

// Definicao dos pinos de controle de velocidade PWM (Enable)
#define ENA 5 // Pino PWM D5 conectado ao ENA do driver L298N (Motores Direitos)
#define ENB 6 // Pino PWM D6 conectado ao ENB do driver L298N (Motores Esquerdos)

// Definicao dos pinos de controle direcional da Ponte H
#define IN1 7  // Pino Digital D7 -> Sentido Motor Direito (Fase A)
#define IN2 8  // Pino Digital D8 -> Sentido Motor Direito (Fase B)
#define IN3 9  // Pino Digital D9 -> Sentido Motor Esquerdo (Fase A)
#define IN4 11 // Pino Digital D11 -> Sentido Motor Esquerdo (Fase B)

// Constante de velocidade operacional do veiculo (faixa de 0 a 255)
const int carSpeed = 200;

// Funcao de translacao para frente (Forward)
void forward() {
  // Define o nivel de potencia PWM para ambos os lados
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);

  // Configuracao das pontes H para rotacao horaria dos motores
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

// Funcao de translacao para tras (Backward)
void back() {
  // Define o nivel de potencia PWM para ambos os lados
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);

  // Inversao logica dos polos da ponte H para rotacao anti-horaria
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

// Funcao de parada eletrodinamica (Stop)
void stop() {
  // Desativa os sinais de habilitacao ENA e ENB
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  
  // Zera todos os pinos de controle de direcao
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

void setup() {
  // Configura todas as portas de controle do L298N como saidas digitais
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  // Garante que o robo inicie completamente imobilizado
  stop();
}

void loop() {
  // Avanca para frente durante 2000 milissegundos (2 segundos)
  forward();
  delay(2000);

  // Parada momentanea para alivio de tensao mecanica nas engrenagens
  stop();
  delay(500);

  // Recua para tras durante 2000 milissegundos (2 segundos)
  back();
  delay(2000);

  // Parada momentanea antes de reiniciar o ciclo
  stop();
  delay(500);
}

Lição 1.2: Teste unitário do motor esquerdo (left_wheel_rotation)

O fabricante valida cada lado isoladamente antes do 4WD combinado. O sketch original left_wheel_rotation.ino (pasta Lesson 1) aciona somente o canal ENA/IN1/IN2 em 4 estados (frente → freio → ré → freio, 500 ms cada), permitindo ouvir cada caixa 1:48 sem acoplamento do outro lado.

📦 Bibliotecas desta lição: nenhuma — digitalWrite()/delay() nativos do núcleo AVR 1.8.6. Mesma conferência da Lição 1.1, nada a baixar.

Código-fonte do fabricante (original, comentado linha a linha): left_wheel_rotation.ino

// www.kuongshun.com — Lesson 1: teste unitario do motor ESQUERDO
// Tabela-verdade do canal ENA/IN1/IN2:
//   ENA=LOW  (qualquer IN)            -> motor desligado (coast)
//   ENA=HIGH, IN1=LOW,  IN2=LOW       -> freio (brakes)
//   ENA=HIGH, IN1=HIGH, IN2=LOW       -> frente (forwards)
//   ENA=HIGH, IN1=LOW,  IN2=HIGH      -> re (backwards)
//   ENA=HIGH, IN1=HIGH, IN2=HIGH      -> freio (brakes)

// Pinos do canal esquerdo (conforme Wire connect table v3.0.pdf)
#define ENA 5  // Enable PWM do canal esquerdo
#define IN1 7  // Fase A do canal esquerdo
#define IN2 8  // Fase B do canal esquerdo

void setup() {
  pinMode(IN1, OUTPUT);    // configura fase A como saida
  pinMode(IN2, OUTPUT);    // configura fase B como saida
  pinMode(ENA, OUTPUT);    // configura enable como saida
  digitalWrite(ENA, HIGH); // habilita o canal (potencia maxima, sem PWM)
}

void loop() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);  // roda esquerda para frente
  delay(500);              // mantem 500 ms
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);  // freio (ambos LOW)
  delay(500);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH); // roda esquerda para tras
  delay(500);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, HIGH); // freio (ambos HIGH)
  delay(500);
}

💡 Dica: resultado esperado — só as 2 rodas esquerdas giram (frente 0,5 s → parada 0,5 s → ré 0,5 s → parada 0,5 s); as direitas ficam imóveis. Se as esquerdas não girarem, meça o borne OUT correspondente do L298N e confira o jumper de 5 V.

Lição 1.3: Teste unitário do motor direito (right_wheel_rotation)

Espelho do anterior para o canal ENB/IN3/IN4. O sketch original right_wheel_rotation.ino valida o lado direito isolado na mesma sequência de 4 estados.

📦 Bibliotecas desta lição: nenhuma — nativo do núcleo AVR 1.8.6 (mesma da Lição 1.2, nada a baixar).

Código-fonte do fabricante (original, comentado linha a linha): right_wheel_rotation.ino

// www.kuongshun.com — Lesson 1: teste unitario do motor DIREITO
// Tabela-verdade do canal ENB/IN3/IN4:
//   ENB=LOW  (qualquer IN)            -> motor desligado (coast)
//   ENB=HIGH, IN3=LOW,  IN4=LOW       -> freio (brakes)
//   ENB=HIGH, IN3=LOW,  IN4=HIGH      -> frente (forwards)
//   ENB=HIGH, IN3=HIGH, IN4=LOW       -> re (backwards)
//   ENB=HIGH, IN3=HIGH, IN4=HIGH      -> freio (brakes)

// Pinos do canal direito (conforme Wire connect table v3.0.pdf)
#define ENB 6  // Enable PWM do canal direito
#define IN3 9  // Fase A do canal direito
#define IN4 11 // Fase B do canal direito

void setup() {
  pinMode(IN3, OUTPUT);    // configura fase A como saida
  pinMode(IN4, OUTPUT);    // configura fase B como saida
  pinMode(ENB, OUTPUT);    // configura enable como saida
  digitalWrite(ENB, HIGH); // habilita o canal (potencia maxima, sem PWM)
}

void loop() {
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH); // roda direita para frente
  delay(500);              // mantem 500 ms
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);  // freio (ambos LOW)
  delay(500);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);  // roda direita para tras
  delay(500);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, HIGH); // freio (ambos HIGH)
  delay(500);
}

⚠️ Atenção: os comentários originais do fabricante trocam os rótulos (“Right wheel” num arquivo do lado esquerdo e vice-versa). O que vale é o pino: ENA/IN1/IN2 = canal esquerdo, ENB/IN3/IN4 = canal direito (Wire connect table v3.0.pdf). Valide um lado por vez antes de juntar no AUTO_GO.

Lição 1.4: Rotação diferencial combinada e curvas pivot (4WD)

Com os dois lados validados isoladamente, este sketch de integração aciona os 4 motores juntos para o giro pivot no próprio eixo (Zero-Radius Pivot Turn): um lado traciona para frente enquanto o outro traciona para trás com o mesmo torque.

Execução do giro pivot pelo robô 4WD AD118 através de rotação diferencial dos motores

📦 Bibliotecas desta lição: nenhuma — analogWrite()/digitalWrite() nativos (mesma das Lições 1.1–1.3, nada a baixar).

Código-Fonte Completo Comentado: giro pivot à esquerda (derivado de left_wheel_rotation.ino + AUTO_GO.ino)

/*
 * =====================================================================================
 * Projeto: Rotacao Pivot para a Esquerda (Robo 4WD AD118)
 * Autor: Engenharia RoboBuilders
 * Plataforma: Arduino Uno R3 + Driver L298N
 * Descricao: Executa o giro no proprio eixo para a esquerda tracionando o lado direito
 *            para frente e o lado esquerdo para tras.
 * =====================================================================================
 */

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11

const int carSpeed = 200;

// Funcao de giro no proprio eixo para a esquerda (Pivot Left)
void left() {
  analogWrite(ENA, carSpeed); // Aplica potencia nos motores direitos
  analogWrite(ENB, carSpeed); // Aplica potencia nos motores esquerdos

  // Lado Direito gira para frente
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);

  // Lado Esquerdo gira para tras
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

// Funcao de parada
void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
}

void setup() {
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  stop();
}

void loop() {
  // Executa o giro para a esquerda por 2 segundos
  left();
  delay(2000);

  // Permanece parado por 1 segundo
  stop();
  delay(1000);
}

Lição 1.5: Demonstração autônoma completa (AUTO_GO)

O sketch AUTO_GO.ino (pasta Lesson 1 do fabricante) é a primeira demonstração 4WD completa: frente 1 s → ré 1 s → esquerda 1 s → direita 1 s, em loop, com telemetria no Monitor Serial a 9600 baud. É o teste de aceitação da Lição 1 — se ele passar com as 4 rodas livres, a tração está íntegra.

📦 Bibliotecas desta lição: nenhuma — Serial, digitalWrite(), delay() nativos do núcleo AVR 1.8.6 (mesma das Lições 1.1–1.4, nada a baixar).

Código-fonte do fabricante (original, comentado linha a linha): AUTO_GO.ino

// www.kuongshun.com — Lesson 1 AUTO_GO: demonstracao autonoma frente/re/esquerda/direita
// Tabela de movimento do cabecalho original:
//   ENA=HIGH, ENB=HIGH, IN1=HIGH, IN2=LOW,  IN3=LOW,  IN4=HIGH -> frente
//   ENA=HIGH, ENB=HIGH, IN1=LOW,  IN2=HIGH, IN3=HIGH, IN4=LOW  -> re
//   ENA=HIGH, ENB=HIGH, IN1=LOW,  IN2=HIGH, IN3=LOW,  IN4=HIGH -> esquerda
//   ENA=HIGH, ENB=HIGH, IN1=HIGH, IN2=LOW,  IN3=HIGH, IN4=LOW  -> direita

// Pinos do driver L298N (Wire connect table v3.0.pdf)
#define ENA 5  // Enable canal esquerdo
#define ENB 6  // Enable canal direito
#define IN1 7  // Fase A esquerda
#define IN2 8  // Fase B esquerda
#define IN3 9  // Fase A direita
#define IN4 11 // Fase B direita

void forward(){ // frente: ambos os lados para frente
  digitalWrite(ENA,HIGH); // habilita canal esquerdo
  digitalWrite(ENB,HIGH); // habilita canal direito
  digitalWrite(IN1,HIGH); // esquerda fase A HIGH
  digitalWrite(IN2,LOW);  // esquerda fase B LOW
  digitalWrite(IN3,LOW);  // direita fase A LOW
  digitalWrite(IN4,HIGH); // direita fase B HIGH
  Serial.println("Forward"); // telemetria no Monitor Serial
}

void back(){ // re: ambos os lados para tras
  digitalWrite(ENA,HIGH);
  digitalWrite(ENB,HIGH);
  digitalWrite(IN1,LOW);
  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,LOW);
  Serial.println("Back");
}

void left(){ // esquerda pivot: esquerda re + direita frente
  digitalWrite(ENA,HIGH);
  digitalWrite(ENB,HIGH);
  digitalWrite(IN1,LOW);
  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,LOW);
  digitalWrite(IN4,HIGH);
  Serial.println("Left");
}

void right(){ // direita pivot: esquerda frente + direita re
  digitalWrite(ENA,HIGH);
  digitalWrite(ENB,HIGH);
  digitalWrite(IN1,HIGH);
  digitalWrite(IN2,LOW);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,LOW);
  Serial.println("Right");
}

void setup() {
  Serial.begin(9600); // abre a serial a 9600 baud (fixar o Monitor Serial em 9600)
  pinMode(IN1,OUTPUT); // configura cada pino como saida antes de usar
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
}

void loop() {
  forward();  // frente por 1 s
  delay(1000);
  back();     // re por 1 s
  delay(1000);
  left();     // esquerda por 1 s
  delay(1000);
  right();    // direita por 1 s
  delay(1000);
}

💡 Dica: resultado esperado no Monitor Serial (9600 baud): Forward → Back → Left → Right repetindo a cada 4 s, com as 4 rodas mudando de sentido juntas. É o último teste com USB conectado; a partir do Módulo 2 o Bluetooth ocupa D0/D1 e o USB precisa sair.

Lição 1.6: Controle Gradual de Velocidade via Modulação PWM

Nesta prática (speed_control.ino da Lesson 1 do fabricante), a velocidade do robô é incrementada e decrementada de forma linear e contínua, demonstrando a aplicação prática da modulação por largura de pulso nos pinos ENA e ENB — a base física da equação de tensão eficaz deduzida acima.

📦 Bibliotecas desta lição: nenhuma — analogWrite()/digitalWrite() nativos do núcleo AVR 1.8.6 (mesma das Lições 1.1–1.5, nada a baixar).

Código-Fonte Completo Comentado: speed_control.ino (original do fabricante + comentários linha a linha)

/*
 * =====================================================================================
 * Projeto: Controle de Aceleracao Linear por PWM (Robo 4WD AD118)
 * Autor: Engenharia RoboBuilders
 * Plataforma: Arduino Uno R3 + Driver L298N
 * Descricao: Incrementa a velocidade de 0 a 255 e desacelera gradualmente
 * =====================================================================================
 */

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11

void setup() {
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  // Configura a direcao dos motores para avanco constante para frente
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void loop() {
  // Rampa de aceleracao progressiva (0 ate 255)
  for (int pwmVal = 0; pwmVal <= 255; pwmVal += 5) {
    analogWrite(ENA, pwmVal); // Ajusta velocidade do lado direito
    analogWrite(ENB, pwmVal); // Ajusta velocidade do lado esquerdo
    delay(40);                // Taxa de variacao da aceleracao (40ms por degrau)
  }

  // Mantem velocidade maxima durante 1 segundo
  delay(1000);

  // Rampa de desaceleracao progressiva (255 ate 0)
  for (int pwmVal = 255; pwmVal >= 0; pwmVal -= 5) {
    analogWrite(ENA, pwmVal);
    analogWrite(ENB, pwmVal);
    delay(40);
  }

  // Permanece imobilizado por 1 segundo antes do proximo ciclo
  delay(1000);
}

Módulo 2 — Comunicação Sem Fio e Controle Teleoperado via Bluetooth BLE

O controle remoto sem fio em média distância é um recurso essencial em plataformas robóticas de exploração e inspeção. Neste módulo, integraremos o módulo transceptor Bluetooth Low Energy HC-08 à porta serial por hardware do microcontrolador Arduino Uno para receber comandos direcionais emitidos por um aplicativo mobile.

Módulo transceptor Bluetooth Low Energy HC-08 Pinagem de comunicação serial UART do módulo Bluetooth HC-08

Teoria da Comunicação Serial UART e Protocolo Bluetooth Low Energy (BLE)

O módulo HC-08 baseia-se no circuito integrado Texas Instruments CC2540/CC2541, operando na banda ISM de 2,4 GHz sob a especificação Bluetooth 4.0 BLE. Diferente do Bluetooth clássico (SPP), o BLE utiliza perfis GATT (Generic Attribute Profile) com consumo elétrico ultra-baixo (corrente em repouso inferior a 0,5 mA).

A comunicação com o Arduino ocorre através da interface assíncrona UART (Universal Asynchronous Receiver-Transmitter):

  • Linha TXD do HC-08 →\rightarrow Pino D0 (RX) do Arduino: Transmite dados recebidos pelo rádio Bluetooth para o buffer serial do microcontrolador.
  • Linha RXD do HC-08 ←\leftarrow Pino D1 (TX) do Arduino: Envia caracteres de telemetria do microcontrolador para o ar.
  • Baud Rate Padrão: 9600 bps9600\,\text{bps} (8 bits de dados, sem paridade, 1 stop bit — 8-N-1).
Tela inicial de busca de dispositivos Bluetooth no aplicativo Kuongshun Interface de controle por volante virtual no aplicativo móvel

Protocolo de Comandos ASCII Transmitidos pelo Aplicativo

Caractere ASCII RecebidoCódigo HexAção Executada pelo FirmwareComportamento Cinemático
'f'0x66forward()Todos os 4 motores giram para frente na velocidade padrão
'b'0x62back()Todos os 4 motores giram para trás
'l'0x6Cleft()Giro no próprio eixo para a esquerda (Pivot Left)
'r'0x72right()Giro no próprio eixo para a direita (Pivot Right)
's'0x73stop()Motores desenergizados instantaneamente
'1'0x31Modo Seguidor de LinhaChaveia a máquina de estados para modo autônomo de pista
'2'0x32Modo Desvio de ObstáculosChaveia para navegação ultrassônica autônoma

[!WARNING] Como os pinos digitais D0 (RX) e D1 (TX) são compartilhados fisicamente com a interface USB do conversor CH340, desconecte temporariamente o cabo jumper do pino RX do Bluetooth durante o processo de gravação do código (Upload). Caso contrário, haverá contenção de barramento e a IDE Arduino retornará erro avrdude: stk500_recv(): programmer is not responding.


Antes de mover 4 motores por rádio, o fabricante valida o enlace com 1 LED. O sketch bluetooth_blink.ino (pasta Lesson 2) lê a UART a 9600 baud e alterna o LED L (D13) a cada caractere 'a' recebido do app KUONGSHUN BLE Tool.apk. É o “Hello World” do HC-08: se o LED não alternar, o problema é pareamento/APP/permissão — nunca a ponte H.

📦 Bibliotecas desta lição: nenhuma — Serial.read(), digitalWrite() nativos do núcleo AVR 1.8.6. O APP é o KUONGSHUN BLE Tool.apk da pasta Lesson 2 (Android; conceda permissão de Localização/Dispositivos Próximos, senão o scan BLE retorna vazio e parece Connected Fail).

Código-fonte do fabricante (original, comentado linha a linha): bluetooth_blink.ino

// www.kuongshun.com — Lesson 2 bluetooth_blink: valida o enlace HC-08 com o LED L
#define LED 13    // LED onboard (pino D13) como indicador de enlace
bool state = LOW; // estado atual do LED (comeca apagado)
char getstr;      // ultimo caractere recebido pela UART via HC-08

void setup() {
  pinMode(LED, OUTPUT); // configura D13 como saida
  Serial.begin(9600);   // abre a UART a 9600 baud (mesmo baud do HC-08)
}

// Alterna o LED (toggle) a cada comando valido
void stateChange() {
  state = !state; // inverte o estado logico
  digitalWrite(LED, state); // aplica no LED
}

void loop() {
  getstr = Serial.read(); // le 1 byte da UART (retorna -1 se vazio)
  if(getstr == 'a'){ // o botao de teste do app envia 'a'
    stateChange(); // alterna o LED
  }
}

💡 Dica: ritual de pareamento que funciona — 1) HC-08 alimentado (LED vermelho piscando = buscando); 2) Bluetooth e Localização do celular ligados; 3) abrir o KUONGSHUN BLE Tool, Scan, tocar no HC-08, Connect (LED do módulo passa a aceso fixo); 4) tocar no botão que envia 'a' e ver o LED L alternar. Resultado esperado: cada toque = 1 toggle do LED + nenhum movimento das rodas (motores nem entram aqui).

Lição 2.2: Pilotagem 4WD por Bluetooth (bluetooth_car)

Com o enlace validado, o bluetooth_car.ino (pasta Lesson 2) mapeia f/b/l/r/s/a para as 4 funções de tração da Lição 1 mais o LED. É o firmware de teleoperação que o Apêndice SmartCar_Core reaproveita no modo Bluetooth.

📦 Bibliotecas desta lição: nenhuma — UART + GPIO nativos (mesma da Lição 2.1, nada a baixar).

Código-Fonte Completo Comentado: bluetooth_car.ino (original do fabricante + comentários linha a linha)

/*
 * =====================================================================================
 * Projeto: Controle Teleoperado via Bluetooth BLE (Robo 4WD AD118)
 * Autor: Engenharia RoboBuilders
 * Plataforma: Arduino Uno R3 + Modulo HC-08 BLE + Driver L298N
 * Descricao: Decodifica comandos seriais ASCII recebidos via Bluetooth e comanda
 *            a cinematica de tracao e manobra do veiculo 4WD.
 * =====================================================================================
 */

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11

// Velocidade constante de movimentacao teleoperada
#define carSpeed 200

// Variavel global para armazenar o caractere recebido pelo buffer serial
char comandoBluetooth = 's';

void forward() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println(F("[BLE] Comando: Avancar Frente"));
}

void back() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println(F("[BLE] Comando: Recuar"));
}

void left() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println(F("[BLE] Comando: Girar Esquerda"));
}

void right() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println(F("[BLE] Comando: Girar Direita"));
}

void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  Serial.println(F("[BLE] Comando: Parada Total"));
}

void setup() {
  // Inicializa a interface UART a 9600 bps para comunicacao com o modulo HC-08
  Serial.begin(9600);

  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  stop();
  Serial.println(F("Sistema de Controle Bluetooth HC-08 Pronto."));
}

void loop() {
  // Verifica se ha bytes disponiveis no buffer serial da UART
  if (Serial.available() > 0) {
    comandoBluetooth = Serial.read(); // Realiza a leitura de 1 byte

    // Estrutura de decisao para decodificacao de comandos direcionais
    switch (comandoBluetooth) {
      case 'f':
        forward();
        break;

      case 'b':
        back();
        break;

      case 'l':
        left();
        break;

      case 'r':
        right();
        break;

      case 's':
        stop();
        break;

      default:
        // Ignora quebras de linha ou caracteres nao reconhecidos
        break;
    }
  }
}

Módulo 3 — Controle Remoto Infravermelho (IR)

O controle infravermelho é uma tecnologia sem fio amplamente disseminada na indústria eletrônica devido à sua alta imunidade a interferências de radiofrequência e baixo custo de implementação. Neste módulo, integraremos o receptor AX-1838HS e decodificaremos o protocolo NEC de 38 kHz.

Diagrama em blocos e pinagem do módulo receptor infravermelho AX-1838HS Mapeamento dos botões do controle remoto infravermelho multifunção de 21 teclas

Teoria da Transmissão Óptica Infravermelha e Protocolo NEC

O controle remoto emite pulsos de luz invisível no espectro infravermelho (λ≈940 nm\lambda \approx 940\,\text{nm}) modulados em uma onda portadora de alta frequência (38 kHz38\,\text{kHz}). O receptor AX-1838HS possui lente com filtro passa-faixa para luz visível, fotodiodo receptor, circuito de ganho automático (AGC) e demodulador interno, entregando diretamente na saída digital um sinal em nível TTL ativo em nível baixo (ativo em LOW).

Estrutura do Frame de Dados do Protocolo NEC

O protocolo NEC transmite 32 bits de dados seriais utilizando modulação por distância de pulso (Pulse Distance Modulation):

  1. Leader Code: Pulso de rajada contínua de 9 ms seguido por uma pausa de 4,5 ms em nível alto.
  2. Endereço do Dispositivo (8 bits): Identificador exclusivo do controle remoto.
  3. Endereço Invertido (~Endereço, 8 bits): Verificação de integridade (checksum por complemento de um).
  4. Comando da Tecla (8 bits): Identificador da tecla pressionada.
  5. Comando Invertido (~Comando, 8 bits): Validação contra erros de transmissão.
  6. Bit Lógico ‘0’: Pulso de 562,5 μ\mus seguido por pausa de 562,5 μ\mus (tempo total de 1,125 ms).
  7. Bit Lógico ‘1’: Pulso de 562,5 μ\mus seguido por pausa de 1687,5 μ\mus (tempo total de 2,25 ms).
Forma de onda do protocolo NEC e temporização dos pulsos lógicos

Tabela de códigos decimais do controle (IRremote 2.0.1 — results.value)

O IRremote.zip da Lesson 3 é a versão 2.0.1 (shirriff), cuja API entrega results.value em decimal via irrecv.decode(&results). O controle do kit transmite em NEC com duas famílias de códigos (o receptor alterna entre elas conforme o lote do controle — por isso o fabricante testa os dois com || lógico via case F: case UNKNOWN_F:):

Tecla do controleFamília 1 (F/B/L/R/S)Família 2 (UNKNOWN_*)Ação no Infrared_remote_control_car.ino
Frente (UP)167369255316027forward()
Ré (DOWN)167547752747854299back()
Esquerda167206051386468383left()
Direita16761405553536955right()
STOP / OK167124453622325019stop() + freio 500 ms

⚠️ Atenção: NUNCA instale IRremote 3.x/4.x neste curso. A API nova (decode() sem argumento, decodedIRData.decodedRawData, hex 0xB946FF00) não compila com os sketches do fabricante (error: no matching function for call to 'IRrecv::decode(decode_results*)' no sentido inverso). Fixe a 2.0.1 via ZIP da Lesson 3 (tabela-mestre da Lição 0.3) e confira em Arquivo > Exemplos > IRremote > IRrecvDemo que abre e compila.

💡 Dica: outros botões do controle de 21 teclas (1, 2, 3, 0, *, #) enviam outros decimais que o infrared_Blink exibe no Serial — anote os seus, pois variam por lote. O Apêndice SmartCar_Core usa 1/2/0 do seu controle para chavear modos autônomos; ajuste os case aos valores que você capturou na Lição 3.1.


Este sketch (infrared_Blink.ino da Lesson 3 do fabricante) acende o LED L (D13) ao receber o código da tecla programada e imprime todo results.value decimal no Monitor Serial a 9600 baud. É o passo de calibração obrigatório: você anota os decimais do seu controle antes de pilotar o robô.

📦 Bibliotecas desta lição: IRremote por shirriff, versão 2.0.1 (ZIP IRremote.zip da pasta Lesson 3 do fabricante — ver tabela-mestre da Lição 0.3).

  • Via ZIP (única via válida aqui): Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP… → apontar para o IRremote.zip da Lesson 3 → reiniciar a IDE.
  • NUNCA pelo Gerenciador latest: o Gerenciador oferece 3.x/4.x, que quebram este sketch ('decode_results' does not name a type / no matching function for call to 'IRrecv::decode(decode_results*)'). Fixe a 2.0.1.
  • Conferência: Arquivo > Exemplos > IRremote > IRrecvDemo deve abrir e compilar sem No such file or directory.

Código-fonte do fabricante (original 2.0.1, comentado linha a linha): infrared_Blink.ino

// www.kuongshun.com — Lesson 3 infrared_Blink (IRremote 2.0.1, API antiga)
#include <IRremote.h> // biblioteca de recepcao IR (FIXAR 2.0.1 via ZIP da Lesson 3)

#define RECV_PIN  12        // pino de sinal do receptor AX-1838HS
#define LED       13        // LED onboard para feedback visual
#define L         16738455 // codigo da tecla de teste (familia do lote de referencia)
#define UNKNOWN_L 1386468383 // mesmo botao na familia alternativa de codigos

bool state = LOW;           // estado atual do LED (comeca apagado)
unsigned long val; // ultimo valor decimal decodificado (results.value)

IRrecv irrecv(RECV_PIN);   // objeto receptor no pino D12
decode_results results;   // ESTRUTURA da API 2.x (nao existe na 3.x/4.x — por isso fixar 2.0.1)

void stateChange() { // alterna o LED (toggle)
  state = !state; // inverte o estado logico
  digitalWrite(LED, state); // aplica no pino D13
}

void setup() {
  pinMode(LED, OUTPUT); // configura D13 como saida
  Serial.begin(9600);  // abre debug a 9600 baud (fixar o Monitor Serial em 9600)
  irrecv.enableIRIn();  // inicia o receptor (liga o timer de captura IR)
}

void loop() {
  if (irrecv.decode(&results)) { // TRUE quando um frame NEC valido chegou (&results = API 2.x)
    val = results.value; // copia o decimal decodificado (ex.: 16738455)
    Serial.println(val); // imprime o decimal — ANOTE os do seu controle
    irrecv.resume();      // libera o buffer para o proximo frame
    delay(150); // debounce de 150 ms contra repeticao do controle
    if(val == L || val == UNKNOWN_L) { // aceita as duas familias de codigo
      stateChange(); // alterna o LED L
    }
  }
}

💡 Dica: resultado esperado — cada tecla pressionada imprime 1 decimal por linha no Monitor Serial (9600 baud, Ambos NL & CR); a tecla de teste alterna o LED L. Se sair 4294967295 repetido, é código de repetição (tecla segurada) — solte e pressione de novo. Anote frente/ré/esquerda/direita/STOP do seu controle: a Lição 3.2 e o Apêndice usam esses valores.


Lição 3.2: Pilotagem 4WD pelo controle IR (Infrared_remote_control_car)

Com os decimais do seu controle anotados na Lição 3.1, o Infrared_remote_control_car.ino (pasta Lesson 3) mapeia frente/ré/esquerda/direita/STOP nas duas famílias de códigos, com parada de segurança 500 ms após o último comando (se o controle sair do alcance, o robô freia sozinho em vez de fugir).

📦 Bibliotecas desta lição: IRremote 2.0.1 (mesma da Lição 3.1, nada a baixar — só conferir que continua a 2.0.1 antes de compilar).

Código-fonte do fabricante (original 2.0.1, comentado linha a linha): Infrared_remote_control_car.ino

// www.kuongshun.com — Lesson 3 Infrared_remote_control_car (IRremote 2.0.1)
#include <IRremote.h> // FIXAR 2.0.1 via ZIP da Lesson 3 (API decode(&results)/results.value)

////////// IR REMOTE CODES //////////
#define F 16736925  // frente — familia 1 (se o seu der outro decimal, troque aqui)
#define B 16754775  // re — familia 1
#define L 16720605  // esquerda — familia 1
#define R 16761405  // direita — familia 1
#define S 16712445  // STOP — familia 1
#define UNKNOWN_F 5316027     // frente — familia 2 (lote alternativo)
#define UNKNOWN_B 2747854299  // re — familia 2
#define UNKNOWN_L 1386468383  // esquerda — familia 2
#define UNKNOWN_R 553536955   // direita — familia 2
#define UNKNOWN_S 3622325019  // STOP — familia 2

#define RECV_PIN  12 // sinal do AX-1838HS

/*define channel enable output pins*/
#define ENA 5   // velocidade canal esquerdo (PWM)
#define ENB 6   // velocidade canal direito (PWM)
/*define logic control output pins*/
#define IN1 7   // fase A esquerda
#define IN2 8   // fase B esquerda
#define IN3 9   // fase A direita
#define IN4 11  // fase B direita
#define carSpeed 150  // velocidade inicial (0 a 255; fabricante usa 150 no IR)

IRrecv irrecv(RECV_PIN); // receptor no D12 (API 2.x)
decode_results results; // estrutura 2.x com .value decimal
unsigned long val; // ultimo codigo recebido
unsigned long preMillis; // timestamp do ultimo comando (para parada de seguranca)

/**
 * BEGIN DEFINE FUNCTIONS
 */

 void forward(){ // frente 4WD
  digitalWrite(ENA,HIGH); // habilita canal esquerdo (potencia maxima)
  digitalWrite(ENB,HIGH); // habilita canal direito
  digitalWrite(IN1,HIGH); // esquerda fase A HIGH
  digitalWrite(IN2,LOW);  // esquerda fase B LOW
  digitalWrite(IN3,LOW);  // direita fase A LOW
  digitalWrite(IN4,HIGH); // direita fase B HIGH
  Serial.println("go forward!"); // telemetria
}
void back(){ // re 4WD
  digitalWrite(ENA,HIGH);
  digitalWrite(ENB,HIGH);
  digitalWrite(IN1,LOW);
  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,LOW);
  Serial.println("go back!");
}
void left(){ // pivot esquerda (com PWM a carSpeed)
  analogWrite(ENA,carSpeed); // velocidade PWM esquerda
  analogWrite(ENB,carSpeed); // velocidade PWM direita
  digitalWrite(IN1,LOW);
  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,LOW);
  digitalWrite(IN4,HIGH);
  Serial.println("go left!");
}
void right(){ // pivot direita (com PWM a carSpeed)
  analogWrite(ENA,carSpeed);
  analogWrite(ENB,carSpeed);
  digitalWrite(IN1,HIGH);
  digitalWrite(IN2,LOW);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,LOW);
  Serial.println("go right!");
}
void stop(){ // parada (desabilita ENA/ENB)
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("STOP!");
}

void setup() {
  Serial.begin(9600); // debug a 9600 baud
  pinMode(IN1,OUTPUT); // configura saidas da ponte H
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
  stop(); // inicia freado
  irrecv.enableIRIn(); // liga o receptor IR
}

void loop() {
  if (irrecv.decode(&results)){ // frame valido? (API 2.x com &results)
    preMillis = millis(); // marca o instante do comando
    val = results.value; // copia o decimal
    Serial.println(val); // imprime para conferir com a tabela
    irrecv.resume(); // libera para o proximo frame
    switch(val){ // aceita as duas familias por botao
      case F:
      case UNKNOWN_F: forward(); break;
      case B:
      case UNKNOWN_B: back(); break;
      case L:
      case UNKNOWN_L: left(); break;
      case R:
      case UNKNOWN_R: right();break;
      case S:
      case UNKNOWN_S: stop(); break;
      default: break; // tecla fora do mapa: ignora
    }
  }
  else{ // sem frame: watchdog de 500 ms
    if(millis() - preMillis > 500){ // 500 ms sem comando
      stop(); // freia por seguranca (controle fora de alcance/bateria fraca)
      preMillis = millis(); // rearma o watchdog
    }
  }
}

💡 Dica: resultado esperado — cada botão move o robô imediatamente e o Serial imprime o decimal; soltando o controle por 0,5 s, o robô para sozinho (watchdog preMillis). Se um botão não mover, compare o decimal impresso com os #define e ajuste o lote do seu controle. Pilha CR2025 fraca encurta o alcance para menos de 2 m — troque antes de culpar o código.


Módulo 4 — Navegação Autônoma com Desvio Inteligente de Obstáculos

A navegação autônoma em ambientes desconhecidos requer que o robô seja capaz de mapear obstáculos espaciais e tomar decisões de evasão em tempo real. Neste módulo, integraremos o transdutor ultrassônico HC-SR04 montado sobre o micro servomotor SG90 em um suporte articulado pan-tilt.

Transdutor ultrassônico HC-SR04 com pinos VCC, Trig, Echo e GND Mecanismo de montagem do servomotor SG90 com suporte pan-tilt

Teoria do Transdutor Ultrassônico HC-SR04 e Equações de Propagação

O sensor HC-SR04 baseia-se na emissão e recepção de ondas de pressão acústica de alta frequência (f=40 kHzf = 40\,\text{kHz}). O processo telemétrico ocorre em quatro etapas:

  1. O microcontrolador envia um pulso em nível alto (HIGH) de pelo menos 10 μs10\,\mu\text{s} no pino TRIG.
  2. O módulo gera internamente um trem de 8 pulsos ultrassônicos senoidais a 40 kHz.
  3. O pino ECHO comuta para nível alto (HIGH) e permanece nesse estado até que o eco refletido seja captado pelo transdutor receptor.
  4. A largura temporal do pulso (Δt\Delta t) no pino ECHO é diretamente proporcional ao dobro da distância percorrida pela onda mecânica (ida e volta).
Diagrama de temporização dos pulsos de Trigger e Echo do sensor HC-SR04

Dedução Matemática da Distância Telemétrica

Considerando a velocidade de propagação do som no ar à temperatura ambiente (T≈20∘CT \approx 20^\circ\text{C}):

vsom≈340 m/s=0,0340 cm/\musv_{\text{som}} \approx 340\,\text{m/s} = 0,0340\,\text{cm/\mu s} d=vsom⋅Δt2d = \frac{v_{\text{som}} \cdot \Delta t}{2} d=0,0340 cm/\mus⋅Δt2=Δt58,82≈Δt58 cmd = \frac{0,0340\,\text{cm/\mu s} \cdot \Delta t}{2} = \frac{\Delta t}{58,82} \approx \frac{\Delta t}{58}\,\text{cm}

Onde:

  • dd é a distância calculada do obstáculo em centímetros (cm\text{cm}).
  • Δt\Delta t é a duração do pulso em microssegundos (μs\mu\text{s}) mensurada pela função nativa pulseIn(ECHO_PIN, HIGH).

Controle Angular do Servomotor SG90

O micro servomotor SG90 é controlado por modulação de largura de pulso em frequência fixa de 50 Hz50\,\text{Hz} (período T=20 msT = 20\,\text{ms}):

  • Pulso de 0,5 ms0,5\,\text{ms} (500 μs500\,\mu\text{s}) posiciona o servo no batente de 0° (totalmente à direita).
  • Pulso de 1,45 ms1,45\,\text{ms} (1450 μs1450\,\mu\text{s} a 1500 μs1500\,\mu\text{s}) posiciona o servo na posição central de 90° (visão frontal).
  • Pulso de 2,4 ms2,4\,\text{ms} (2400 μs2400\,\mu\text{s}) posiciona o servo no batente de 180° (totalmente à esquerda).

Lição 4.1: Calibração e Centralização Angular do Servomotor (Servo_debug)

Antes de fixar os parafusos do suporte pan-tilt, é fundamental calibrar o ponto central de 90° via software para garantir alinhamento ortogonal perfeito com o chassi. O sketch original Servo_debug.ino (pasta Lesson 4) faz exatamente isso — 5 linhas: anexa o SG90 no D3 e trava em 90°.

📦 Bibliotecas desta lição: Servo — embutida na IDE 1.8.19, nada a baixar.

  • Instalação: nenhuma. Confira em Arquivo > Exemplos > Servo > Sweep que o exemplo abre e compila.
  • Conferência desta lição: o Servo_debug original usa myservo.attach(3) + myservo.write(90) com loop() vazio. A versão abaixo mantém o original e adiciona telemetria opcional + trava contínua (útil com o suporte já montado).

Código-fonte do fabricante (original + trava de bancada): Servo_debug.ino

/*
 * =====================================================================================
 * Projeto: Calibracao Angular do Servomotor SG90 (Robo 4WD AD118)
 * Autor: Engenharia RoboBuilders
 * Plataforma: Arduino Uno R3 + Servomotor SG90 no pino D3
 * Descricao: Posiciona o servo em 90 graus exatos para alinhamento mecanico
 * =====================================================================================
 */

#include <Servo.h>

#define SERVO_PIN 3

Servo servomotor;

void setup() {
  Serial.begin(9600);
  
  // Associa o objeto servo ao pino D3 com limites de pulso de 500us a 2400us
  servomotor.attach(SERVO_PIN, 500, 2400);
  
  // Posiciona no centro absoluto (90 graus)
  servomotor.write(90);
  
  Serial.println(F("Servomotor calibrado e travado na posicao central de 90 Graus."));
  Serial.println(F("Encaixe o suporte de acrilico alinhado perfeitamente com a frente do robo."));
}

void loop() {
  // Mantem a posicao travada para ajuste mecanico
  servomotor.write(90);
  delay(1000);
}

Lição 4.2: Algoritmo de Varredura Tridimensional e Desvio de Colisão

O algoritmo de navegação autônoma executa uma rotina contínua de varredura espacial:

  1. O robô avança com o servo apontado para frente (90∘90^\circ).
  2. Se a distância frontal for inferior a 40 cm, o robô freia instantaneamente.
  3. O servo gira para a direita (10∘10^\circ) e mede a distância lateral direita (dDd_D).
  4. O servo gira para a esquerda (170∘170^\circ) e mede a distância lateral esquerda (dEd_E).
  5. O microcontrolador compara as distâncias:
    • Se dD>dEd_D > d_E: recua brevemente e gira à direita.
    • Se dE>dDd_E > d_D: recua brevemente e gira à esquerda.
    • Se ambos os caminhos estiverem bloqueados (dD≤40 cmd_D \le 40\,\text{cm} e dE≤40 cmd_E \le 40\,\text{cm}): executa manobra de ré estendida.
Varredura angular do sensor ultrassônico voltado para a direita (10 graus) Varredura angular do sensor ultrassônico voltado para a esquerda (170 graus)

📦 Bibliotecas desta lição: Servo — embutida na IDE 1.8.19, nada a baixar (mesma da Lição 4.1, nada a baixar). O pulseIn() do HC-SR04 é nativo do núcleo AVR 1.8.6.

Código-fonte do fabricante (original, comentado linha a linha): Obstacle_Avoidance_Car.ino

// www.kuongshun.com — Lesson 4 Obstacle_Avoidance_Car (limiar 20 cm, servo 10°/90°/180°)
// Diferencas intencionais em relacao ao texto didatico: o fabricante usa limiar de
// 20 cm (nao 40 cm) e varredura 10°/90°/180°/90° com delays de 500–1000 ms.
// O texto da Lição 4.2 acima usa 40 cm como margem de seguranca para piso domestico;
// se quiser o comportamento exato do PDF, troque 40 por 20 e os delays pelos originais.
/*
 * Projeto original: Navegacao Autonoma Anti-Colisao com HC-SR04 + SG90 + L298N
 * Plataforma: Arduino Uno R3 (nucleo AVR 1.8.6, IDE 1.8.19)
 */

#include <Servo.h>

#define ECHO_PIN A4  // Pino Analogico A4 conectado ao Echo do HC-SR04
#define TRIG_PIN A5  // Pino Analogico A5 conectado ao Trigger do HC-SR04
#define SERVO_PIN 3  // Pino Digital D3 conectado ao sinal do Servomotor SG90

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11

#define carSpeed 200

Servo servoPanTilt;

int distanciaFrente = 0;
int distanciaDireita = 0;
int distanciaEsquerda = 0;

// Funcao telemetrica de medicao ultrassonica de distancia em centimetros
int getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  
  // Pulso de disparo de 10 microssegundos
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // Mede o tempo de nivel alto no pino Echo e converte para centimetros
  long duracaoPulso = pulseIn(ECHO_PIN, HIGH, 30000); // Timeout de 30ms (~5 metros)
  if (duracaoPulso == 0) return 400; // Caso nao haja eco, assume distancia livre
  
  return (int)(duracaoPulso / 58);
}

void forward() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void back() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void left() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void right() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
}

void setup() {
  Serial.begin(9600);
  
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  servoPanTilt.attach(SERVO_PIN, 500, 2400);
  servoPanTilt.write(90); // Posiciona apontando para frente
  delay(500);

  stop();
  Serial.println(F("Sistema de Desvio Autonomo de Obstaculos Ativo."));
}

void loop() {
  // Centraliza o sensor para frente
  servoPanTilt.write(90);
  delay(150);
  distanciaFrente = getDistance();

  // Se detectar obstaculo a menos de 40 cm
  if (distanciaFrente <= 40) {
    stop();
    delay(200);

    // Varredura para o lado direito (10 graus)
    servoPanTilt.write(10);
    delay(400);
    distanciaDireita = getDistance();

    // Varredura para o lado esquerdo (170 graus)
    servoPanTilt.write(170);
    delay(400);
    distanciaEsquerda = getDistance();

    // Retorna servo para a frente
    servoPanTilt.write(90);
    delay(200);

    // Tomada de decisao baseada na comparacao de rotas
    if (distanciaDireita > distanciaEsquerda) {
      // Caminho a direita esta mais desobstruido
      back();
      delay(200);
      right();
      delay(350);
      stop();
    } else if (distanciaEsquerda > distanciaDireita) {
      // Caminho a esquerda esta mais desobstruido
      back();
      delay(200);
      left();
      delay(350);
      stop();
    } else {
      // Ambos os lados estao comprometidos: manobra de recuo
      back();
      delay(400);
      left();
      delay(500);
      stop();
    }
  } else {
    // Caminho livre a frente
    forward();
  }
}

Módulo 5 — Robô Seguidor de Linha Autônomo com Sensores Ópticos Reflexivos

O rastreamento autônomo de trajetórias com sensores ópticos é a base tecnológica dos veículos guiados automaticamente (AGVs) aplicados na logística industrial moderna. Neste módulo, integraremos os 3 módulos reflexivos TCRT5000 instalados na dianteira do robô.

Construção de pista de testes com fita isolante preta de alta absorção Módulo óptico reflexivo TCRT5000 com comparador LM393 e trimpot de ajuste

Teoria da Reflexão Óptica Infravermelha e Condicionamento de Sinal

Cada módulo óptico é composto por um LED emissor infravermelho de arsenieto de gálio (GaAs) e um fototransistor receptor NPN de silício empacotados lado a lado:

  1. Pista Branca / Superfície Clara: Possui alta refletividade no infravermelho. A luz emitida é refletida de volta para o fototransistor, polarizando-o para a saturação (condução plena). A tensão de entrada do comparador cai abaixo da referência, e a saída digital comuta para Nível Lógico BAIXO (0).
  2. Pista Preta / Fita Isolante: Apresenta elevado coeficiente de absorção de luz. A radiação infravermelha é absorvida, mantendo o fototransistor em corte. A tensão sobe acima da referência do trimpot, e a saída comuta para Nível Lógico ALTO (1).
Diagrama esquemático do módulo TCRT5000 com comparador analógico LM393

Tabela Verdade dos 3 Sensores de Pista

Sensor Esquerdo (D2)Sensor Centro (D4)Sensor Direito (D10)Estado Espacial do RobôAção de Controle Corretivo
0 (Branco)1 (Linha)0 (Branco)Perfeitamente centralizado na fitaAvança reto em velocidade plena (forward())
0 (Branco)1 (Linha)1 (Linha)Início de desvio para a esquerdaCorreção suave para a direita (right())
0 (Branco)0 (Branco)1 (Linha)Desvio pronunciado para a esquerdaRotação rápida à direita até centralizar
1 (Linha)1 (Linha)0 (Branco)Início de desvio para a direitaCorreção suave para a esquerda (left())
1 (Linha)0 (Branco)0 (Branco)Desvio pronunciado para a direitaRotação rápida à esquerda até centralizar
0 (Branco)0 (Branco)0 (Branco)Perda total de linha / CruzamentoMantém última ação ou freia por timeout
1 (Linha)1 (Linha)1 (Linha)Interseção perpendicular em TMantém avanço ou executa parada programada

Lição 5.1: Seguidor de linha com 3× TCRT5000 (Line_tracking_car)

📦 Bibliotecas desta lição: nenhuma — o código usa digitalRead()/analogWrite() nativos do núcleo AVR 1.8.6, sem biblioteca externa. Se o robô ignorar a pista, o culpado é o trimpot/altura (5–10 mm), nunca biblioteca.

⚠️ Atenção: o setup() original do fabricante configura pinMode(LT_R,INPUT) com LT_R valendo !digitalRead(10) (ou seja, pinMode(0 ou 1,INPUT) por acidente). Funciona porque D2/D4/D10 já nascem como entrada, mas o correto é pinMode(10/4/2,INPUT). A versão abaixo mantém o original e marca o ponto com // NOTA: + correção ao lado.

Código-fonte do fabricante (original, comentado linha a linha): Line_tracking_car.ino

// www.kuongshun.com — Lesson 5 Line_tracking_car (3x TCRT5000, carSpeed 150)
// NOTA: o texto didatico usa carSpeed 180 para pista domestica lisa; o fabricante
// usa 150. Comece com 150 (original) e só suba para 180 após centralizar o trimpot.
/*
 * Projeto original: Seguidor de Linha Autonomo com 3 Sensores TCRT5000
 * Plataforma: Arduino Uno R3 + Driver L298N (nucleo AVR 1.8.6)
 */

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11

// Mapeamento dos pinos dos sensores de linha
#define LineTracking_Pin_Right  10 // Sensor Direito no pino D10
#define LineTracking_Pin_Middle 4  // Sensor Central no pino D4
#define LineTracking_Pin_Left   2  // Sensor Esquerdo no pino D2

// Macros de leitura logica (Inversao com ! para considerar 1 = Linha Preta Detectada)
#define LineTracking_Read_Right   !digitalRead(10)
#define LineTracking_Read_Middle  !digitalRead(4)
#define LineTracking_Read_Left    !digitalRead(2)

#define carSpeed 180 // Velocidade equilibrada para alta precisao de pista

unsigned long ultimoTempoNaLinha = 0;

void forward() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void left() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void right() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
}

void setup() {
  Serial.begin(9600);

  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  // Configura as portas dos sensores como entradas digitais
  pinMode(LineTracking_Pin_Right, INPUT);
  pinMode(LineTracking_Pin_Middle, INPUT);
  pinMode(LineTracking_Pin_Left, INPUT);

  stop();
  ultimoTempoNaLinha = millis();
}

void loop() {
  // Caso 1: Sensor central detecta a fita preta -> Mantem avanco reto
  if (LineTracking_Read_Middle) {
    forward();
    ultimoTempoNaLinha = millis();
  }
  // Caso 2: Sensor direito detecta a fita preta -> Corrige virando para a direita
  else if (LineTracking_Read_Right) {
    right();
    // Permanece corrigindo enquanto o sensor direito estiver sobre a linha
    while (LineTracking_Read_Right);
    ultimoTempoNaLinha = millis();
  }
  // Caso 3: Sensor esquerdo detecta a fita preta -> Corrige virando para a esquerda
  else if (LineTracking_Read_Left) {
    left();
    // Permanece corrigindo enquanto o sensor esquerdo estiver sobre a linha
    while (LineTracking_Read_Left);
    ultimoTempoNaLinha = millis();
  }
  // Caso 4: Todos os sensores fora da linha -> Timeout de protecao contra fuga
  else {
    if (millis() - ultimoTempoNaLinha > 150) {
      stop(); // Se perder a pista por mais de 150 ms, imobiliza o robo com seguranca
    }
  }
}

Apêndice A — Firmware Multifunção Integrado (SmartCar_Core, composição RoboBuilders)

O firmware SmartCar_Core NÃO faz parte do pacote do fabricante — é uma composição RoboBuilders que converge os 11 sketches das Lessons 1–5 em uma Máquina de Estados Finitos (FSM — Finite State Machine). Ele alterna entre pilotagem manual (Bluetooth/IR) e modos autônomos (linha/desvio) sem regravar. Use-o só após validar cada sketch original isoladamente; se algo falhar aqui, volte à lição do subsistema.

📦 Bibliotecas deste apêndice: IRremote 2.0.1 (ZIP da Lesson 3, tabela-mestre da Lição 0.3) + Servo embutida na IDE 1.8.19.

  • O código abaixo usa a API 2.0.1 (decode(&results), results.value, decimais 16736925…). Com 3.x/4.x instalada, dá erro de compilação — fixe a 2.0.1 e reinicie a IDE.
  • Ajuste obrigatório: troque os #define F/B/L/R/S pelos decimais do seu controle (Lição 3.1).
Estrutura arquitetural do firmware integrado unificado SmartCar_Core Controle simultâneo por aplicativo BLE e controle remoto infravermelho

Arquitetura de Software do Firmware Concorrente

O sistema é estruturado em duas enumerações de controle de alto nível:

  1. enum FUNCTIONMODE: Define o modo operacional corrente do robô (IDLE, LineTeacking, ObstaclesAvoidance, Bluetooth, IRremote).
  2. enum MOTIONMODE: Define o vetor de translação cinemática instantânea (STOP, FORWARD, BACK, LEFT, RIGHT).

A rotina delays(unsigned long t) substitui a função bloqueante tradicional delay(), realizando a leitura contínua e concorrente do buffer serial UART do Bluetooth (getBTData()) e das interrupções do receptor infravermelho (getIRData()) a cada milissegundo de espera.


Código-Fonte Completo Comentado: SmartCar_Core.ino

/*
 * =====================================================================================
 * Projeto: Firmware Multifuncao Integrado SmartCar_Core (Robo 4WD AD118)
 * Fabricante: KUONGSHUN / RoboBuilders
 * Plataforma: Arduino Uno R3 + Sensor Shield V5.0 + Driver L298N
 * Integracao: Bluetooth BLE + Controle IR + Desvio Ultrassonico + Seguidor de Linha
 * =====================================================================================
 */

#include <IRremote.h> // FIXAR 2.0.1 via ZIP da Lesson 3 (API decode(&results)/results.value)
#include <Servo.h> // embutida na IDE 1.8.19

// Definicoes de Pinagem do Sistema
#define ECHO_PIN  A4  // Sensor Ultrassonico Echo
#define TRIG_PIN  A5  // Sensor Ultrassonico Trigger
#define SERVO_PIN 3   // Micro Servomotor SG90

#define ENA 5         // PWM Motor Direito
#define ENB 6         // PWM Motor Esquerdo
#define IN1 7         // Sentido Motor Direito A
#define IN2 8         // Sentido Motor Direito B
#define IN3 9         // Sentido Motor Esquerdo A
#define IN4 11        // Sentido Motor Esquerdo B

#define Receiver 12   // Receptor Infravermelho AX-1838HS
#define LED_Pin  13   // LED Indicador de Status

// Sensores Seguidores de Linha
#define LineTeacking_Pin_Right  10
#define LineTeacking_Pin_Middle 4
#define LineTeacking_Pin_Left   2

#define LineTeacking_Read_Right   !digitalRead(10)
#define LineTeacking_Read_Middle  !digitalRead(4)
#define LineTeacking_Read_Left    !digitalRead(2)

#define carSpeed 200

// Instanciacao dos objetos perifericos (API IRremote 2.0.1 — ver tabela-mestre)
Servo servo;
IRrecv irrecv(Receiver); // receptor no D12
decode_results results; // estrutura 2.x com .value decimal
unsigned long last_val = 0; // ultimo codigo valido (para tecla segurada)

// Codigos IR decimais (IRremote 2.0.1) — AJUSTE aos do seu controle (Licao 3.1)
#define IR_F 16736925
#define IR_B 16754775
#define IR_L 16720605
#define IR_R 16761405
#define IR_S 16712445
#define IR_UF 5316027
#define IR_UB 2747854299UL
#define IR_UL 1386468383UL
#define IR_UR 553536955UL
#define IR_US 3622325019UL

unsigned long IR_PreMillis = 0;
unsigned long LT_PreMillis = 0;

int rightDistance = 0;
int leftDistance = 0;
int middleDistance = 0;

// Maquina de Estados Finitos para Modos Operacionais
enum FUNCTIONMODE {
  IDLE,
  LineTeacking,
  ObstaclesAvoidance,
  Bluetooth,
  IRremote
} func_mode = IDLE;

// Maquina de Estados Finitos para Movimentacao Cinematica
enum MOTIONMODE {
  STOP,
  FORWARD,
  BACK,
  LEFT,
  RIGHT
} mov_mode = STOP;

// Funcao de atraso nao-bloqueante com sondagem concorrente de comunicacao
void delays(unsigned long t) {
  for (unsigned long i = 0; i < t; i++) {
    getBTData();
    getIRData();
    delay(1);
  }
}

// Medicao telemétrica de distancia por eco ultrassonico
int getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  long duration = pulseIn(ECHO_PIN, HIGH, 30000);
  if (duration == 0) return 400;
  return (int)(duration / 58);
}

// Rotinas de acionamento cinemático dos motores
void forward(bool debug = false) {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  if (debug) Serial.println(F("Avanco: Frente"));
}

void back(bool debug = false) {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  if (debug) Serial.println(F("Avanco: Tras"));
}

void left(bool debug = false) {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  if (debug) Serial.println(F("Giro: Esquerda"));
}

void right(bool debug = false) {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  if (debug) Serial.println(F("Giro: Direita"));
}

void stop(bool debug = false) {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  if (debug) Serial.println(F("Parada Total"));
}

// Decodificacao de comandos via Bluetooth UART
void getBTData() {
  if (Serial.available()) {
    char c = Serial.read();
    switch (c) {
      case 'f': func_mode = Bluetooth; mov_mode = FORWARD;  break;
      case 'b': func_mode = Bluetooth; mov_mode = BACK;     break;
      case 'l': func_mode = Bluetooth; mov_mode = LEFT;     break;
      case 'r': func_mode = Bluetooth; mov_mode = RIGHT;    break;
      case 's': func_mode = Bluetooth; mov_mode = STOP;     break;
      case '1': func_mode = LineTeacking;                   break;
      case '2': func_mode = ObstaclesAvoidance;             break;
      default:  break;
    }
  }
}

// Decodificacao de comandos do Controle Remoto IR (API 2.0.1: decode(&results)/results.value)
void getIRData() {
  if (irrecv.decode(&results)) { // frame NEC valido? (2.x exige &results)
    unsigned long v = results.value; // decimal (ex.: 16736925)
    if (v == 0xFFFFFFFF) v = last_val; // repeticao (tecla segurada) = reusa ultimo
    switch (v) {
      case IR_F: case IR_UF: func_mode = IRremote; mov_mode = FORWARD; break; // frente
      case IR_B: case IR_UB: func_mode = IRremote; mov_mode = BACK;    break; // re
      case IR_L: case IR_UL: func_mode = IRremote; mov_mode = LEFT;    break; // esquerda
      case IR_R: case IR_UR: func_mode = IRremote; mov_mode = RIGHT;   break; // direita
      case IR_S: case IR_US: func_mode = IRremote; mov_mode = STOP;    break; // STOP
      default: break; // tecla fora do mapa: ignora (anote-a pela Licao 3.1)
    }
    last_val = v; // memoriza para repeticao
    delay(100); // debounce
    irrecv.resume(); // libera para o proximo frame
  }
}

// Execucao do Modo Teleoperado Bluetooth
void bluetooth_mode() {
  if (func_mode == Bluetooth) {
    switch (mov_mode) {
      case FORWARD: forward(); break;
      case BACK:    back();    break;
      case LEFT:    left();    break;
      case RIGHT:   right();   break;
      case STOP:    stop();    break;
      default: break;
    }
  }
}

// Execucao do Modo Teleoperado Infravermelho
void irremote_mode() {
  if (func_mode == IRremote) {
    switch (mov_mode) {
      case FORWARD: forward(); break;
      case BACK:    back();    break;
      case LEFT:    left();    break;
      case RIGHT:   right();   break;
      case STOP:    stop();    break;
      default: break;
    }
  }
}

// Execucao do Modo Autonomo Seguidor de Linha
void line_teacking_mode() {
  if (func_mode == LineTeacking) {
    if (LineTeacking_Read_Middle) {
      forward();
      LT_PreMillis = millis();
    } else if (LineTeacking_Read_Right) {
      right();
      while (LineTeacking_Read_Right) {
        getBTData();
        getIRData();
      }
      LT_PreMillis = millis();
    } else if (LineTeacking_Read_Left) {
      left();
      while (LineTeacking_Read_Left) {
        getBTData();
        getIRData();
      }
      LT_PreMillis = millis();
    } else {
      if (millis() - LT_PreMillis > 150) {
        stop();
      }
    }
  }
}

// Execucao do Modo Autonomo Desvio de Obstaculos
void obstacles_avoidance_mode() {
  if (func_mode == ObstaclesAvoidance) {
    servo.write(90);
    delays(400);
    middleDistance = getDistance();
    
    if (middleDistance <= 40) {
      stop();
      delays(400);
      
      // Varredura a direita
      servo.write(10);
      delays(400);
      rightDistance = getDistance();

      // Varredura a esquerda
      servo.write(90);
      delays(200);
      servo.write(170);
      delays(400);
      leftDistance = getDistance();

      // Retorno ao centro
      servo.write(90);
      delays(300);

      // Decisao Evasiva
      if (rightDistance > leftDistance) {
        stop();
        delay(100);
        back();
        delay(200);
        right();
        delay(300);
      } else if (rightDistance < leftDistance) {
        stop();
        delay(100);
        back();
        delay(200);
        left();
        delay(300);
      } else if ((rightDistance <= 40) || (leftDistance <= 40)) {
        back();
        delays(250);
      } else {
        forward();
      }
    } else {
      forward();
    }
  }
}

void setup() {
  // Inicializacao da UART para Bluetooth e Debug
  Serial.begin(9600);
  
  // Configuracao do Servo Pan-Tilt
  servo.attach(SERVO_PIN, 500, 2400);
  servo.write(90);
  
  // Inicializacao do Receptor Infravermelho
  irrecv.enableIRIn();
  
  // Configuracao das portas do Sensor Ultrassonico
  pinMode(ECHO_PIN, INPUT);
  pinMode(TRIG_PIN, OUTPUT);
  
  // Configuracao das portas da Ponte H L298N
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  
  // Configuracao dos sensores de linha
  pinMode(LineTeacking_Pin_Right, INPUT);
  pinMode(LineTeacking_Pin_Middle, INPUT);
  pinMode(LineTeacking_Pin_Left, INPUT);
  
  pinMode(LED_Pin, OUTPUT);

  stop();
  Serial.println(F("Firmware Integrado SmartCar_Core AD118 Pronto!"));
}

void loop() {
  // Sondagem de comandos sem fio
  getBTData();
  getIRData();
  
  // Execucao concorrente baseada na maquina de estados
  bluetooth_mode();
  irremote_mode();
  line_teacking_mode();
  obstacles_avoidance_mode();
}

Guia Diagnóstico de Resolução de Problemas (Troubleshooting)

A tabela diagnóstica abaixo sintetiza as principais falhas elétricas, mecânicas, de conectividade e de software encontradas durante o desenvolvimento e montagem do Kit Robô 4WD AD118, com seus respectivos procedimentos de correção de engenharia:

Sintoma ObservadoCausa Mais ProvávelProcedimento de Diagnóstico e Correção de Engenharia
Erro ao gravar código na IDE: “avrdude: stk500_recv(): programmer is not responding”Módulo Bluetooth conectado nos pinos D0/D1 causando conflito com o conversor USB CH340Desconectar temporariamente os cabos jumpers das portas RX/TX (D0 e D1) durante o Upload; reconectar somente após a conclusão da gravação.
O robô gira em círculos quando o comando é avançar em linha retaPolaridade invertida na fiação dos motores DC nos bornes OUT1/OUT2 ou OUT3/OUT4Inverter fisicamente a posição dos fios vermelho e preto do canal de motores correspondente no borne da Ponte H L298N ou ajustar as constantes HIGH/LOW nos pinos IN1 a IN4.
Os motores não giram e o LED do driver L298N fica fraco ou apagadoBaterias 18650 descarregadas ou chave geral de energia desligadaMedir a tensão no borne VCC do L298N com um multímetro (deve estar entre 7,4V e 8,4V); recarregar as células 18650 no carregador externo.
O Arduino reinicia (reset repentino) no instante em que os motores partemQueda abrupta de tensão (Brownout Reset) provocada pelo pico de corrente de partida (Inrush Current)Garantir que o jumper de alimentação 5V do L298N esteja inserido; certificar-se de que a terra comum (GND) está bem conectada; adicionar um capacitor eletrolítico de 100 μF100\,\mu\text{F} a 470 μF470\,\mu\text{F} em paralelo com a linha de 5V.
O sensor ultrassônico retorna distâncias fixas em 0 cm ou 400 cmMau contato nos pinos TRIG/ECHO ou alimentação abaixo de 4,75VVerificar se TRIG está em A5 e ECHO em A4; testar a continuidade dos cabos jumpers fêmea-fêmea; assegurar alimentação de 5V firme no barramento do Sensor Shield.
O robô não segue a linha preta e escapa nas curvasCalibração de sensibilidade dos trimpots nos módulos TCRT5000 ou altura inadequada em relação ao soloPosicionar o sensor sobre a superfície branca e ajustar o trimpot até o LED apagar; posicionar sobre a fita preta e confirmar que o LED acende; manter a altura entre 5 mm e 10 mm do chão.
O aplicativo mobile não encontra o dispositivo BluetoothMódulo HC-08 sem alimentação ou permissão de Localização/Bluetooth desativada no smartphoneVerificar se o LED vermelho do HC-08 está piscando (indicando busca); no Android, conceder permissões completas de Localização/Dispositivos Próximos para o KUONGSHUN BLE Tool.apk da Lesson 2. Validar primeiro com o bluetooth_blink (Lição 2.1): se o LED L não alternar com 'a', o problema é pareamento/APP — nunca a ponte H.
O controle remoto infravermelho não responde aos comandosPelícula plástica de proteção da bateria CR2025 não removida ou código de tecla divergente por loteRemover o plástico isolante da bateria do controle; carregar o sketch infrared_Blink.ino (Lição 3.1) e monitorar no Monitor Serial a 9600 baud para anotar os decimais do seu controle e ajustar os #define F/B/L/R/S da Lição 3.2.
Erro IRremote.h: No such file or directory / does not name a typeBiblioteca IRremote ausente ou na major erradaReinstalar pela tabela-mestre da Lição 0.3: desinstalar qualquer 3.x/4.x, instalar a 2.0.1 via ZIP da Lesson 3, conferir pasta libraries/IRremote/IRremote.h, reiniciar a IDE e recompilar. Erro has no member named 'decodedIRData' = você está com 2.0.1 e código novo; erro no matching function for call to 'IRrecv::decode(decode_results*)' = você está com 3.x/4.x e sketch do fabricante. Fixe a 2.0.1.
pinMode(LT_R,INPUT) parece estranho / linha instável após uploadsetup() original do Line_tracking_car passa a macro !digitalRead() ao pinModeFunciona porque D2/D4/D10 já nascem como entrada, mas corrija para pinMode(10,INPUT); pinMode(4,INPUT); pinMode(2,INPUT); (nota da Lição 5.1). Depois recalibre trimpots e altura 5–10 mm.
Servo treme / HC-SR04 congela em 0 cm com motores ligadosPico de corrente dos 4 motores derrubando o 5 V do ShieldAlimentar lógica pelo regulador do L298N (jumper 5 V fechado), terra comum bateria–L298N–Uno íntegra, baterias 18650 cheias (7,4–8,4 V no borne). Teste isolado: Servo_debug (Lição 4.1) com USB deve centralizar liso em 90°; se tremer só com motores, é energia.
AUTO_GO anda, mas bluetooth_car não respondeBluetooth ainda fora de D0/D1 ou APP pareado no dispositivo erradoRecoloque TXD→D0/RXD→D1 após o upload, chave ON, LED do HC-08 piscando, parear no KUONGSHUN BLE Tool e enviar f/b/l/r/s. Com USB plugado e Bluetooth em D0/D1, o Serial Monitor briga com o HC-08 — desplugue o USB para pilotar.

Solução de problemas

Olá! Sou o assistente técnico da RoboBuilders. Descreva seu problema com o Kit Robô Inteligente 4WD Completo AD118 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.