Conteúdo detalhado
📝 Planejar o rover no papel
Antes de cortar o chassi, você responde três perguntas no papel: quais blocos o robô tem, em que pino cada fio entra e quanta corrente tudo puxa. As respostas viram o diagrama de blocos, a tabela de pinos e o orçamento de energia abaixo. O módulo 1.5 já usou estes mesmos pinos para os motores e o servo, então os sketches de lá servem de teste aqui.
🌱 Novo aqui?
Um diagrama de blocos mostra as partes do sistema como caixas e o que passa entre elas como setas, sem se preocupar com fios. O mapa de pinos diz qual GPIO do ESP32 vai em qual terminal de cada peça. O orçamento de energia soma o consumo de cada peça para escolher a bateria e o regulador com folga.
Como ler: as setas verdes são informação (a distância sobe do sensor, o ângulo desce ao servo, o PWM vai ao driver). As tracejadas âmbar são energia, que sai de um só lugar, embaixo. Os motores recebem a tensão da bateria pelo VM; todo o resto recebe 5 V do regulador. É o ciclo sentir, pensar, agir do módulo 1.1, agora com peças reais.
Mapa de pinos (vale para todo o módulo)
| Pino ESP32 | TB6612FNG | DRV8833 | Para quê |
|---|---|---|---|
| GPIO 25 | PWMA | livre | velocidade do motor esquerdo |
| GPIO 26 · 27 | AIN1 · AIN2 | AIN1 · AIN2 | sentido (e PWM no DRV8833) do esquerdo |
| GPIO 33 | PWMB | livre | velocidade do motor direito |
| GPIO 32 · 4 | BIN1 · BIN2 | BIN1 · BIN2 | sentido (e PWM no DRV8833) do direito |
| GPIO 13 | STBY | nSLEEP / EEP | liga o driver (nível alto) |
| GPIO 18 | HC-SR04 TRIG | dispara o pulso de som | |
| GPIO 19 | HC-SR04 ECHO, pelo divisor (1 kΩ do ECHO ao pino; 2 kΩ do pino ao GND) | eco de 5 V vira 3,3 V | |
| GPIO 23 | servo, fio laranja | gira o sensor | |
| GPIO 0 (BOOT) | botão que já vem na placa | pausa e continua | |
| 3V3 | VCC | não usa | lógica do driver |
| 5V / VIN | saída do buck 5 V, que também vai ao VCC do HC-SR04 e ao fio vermelho do servo | alimenta a eletrônica | |
| GND | GND comum: driver, buck, bateria (−), HC-SR04 e fio marrom do servo | referência única | |
| Orçamento de energia | Andando (cerca de) | Pico (cerca de) |
|---|---|---|
| ESP32 sem Wi-Fi | 50 a 100 mA | 250 mA com Wi-Fi |
| HC-SR04 | 15 mA | 15 mA |
| Servo SG90 | quase nada parado | algumas centenas de mA ao mover |
| 2 motores TT | 300 a 500 mA (juntos) | perto de 1 A cada, no arranque ou travado |
| Conclusão | buck de pelo menos 2 A para o 5 V; bateria que aguente 2 A ou mais de pico. Meça o seu com o multímetro: os números variam por modelo. | |
Por que aprender
Planejar evita refazer a fiação e trocar peça no meio do caminho. Engenheiros de robôs comerciais fazem exatamente estes três documentos antes do primeiro protótipo; com eles em mãos, você também consegue pedir ajuda num fórum de forma que alguém entenda o seu robô.
Conceitos-chave
🔧 Montar chassi e fiação
O chassi pode ser papelão grosso, MDF ou acrílico: o que importa é ser rígido e ter espaço para tudo ficar preso. Motores atrás, roda boba na frente (ou o contrário, se o seu kit vier assim), bateria baixa e perto do eixo das rodas, ESP32 e protoboard em cima, sensor na frente, livre de obstáculos no campo de visão.
Como ler: cada linha verde horizontal liga um GPIO à entrada do driver na mesma altura, então dá para conferir fio por fio com o dedo. Os círculos à direita são os motores. Embaixo, a linha âmbar vai ao servo e as do sensor passam pelo divisor: o eco sai do HC-SR04 com 5 V, atravessa o resistor de 1 kΩ e chega ao GPIO 19 com cerca de 3,3 V, porque o de 2 kΩ desvia o resto ao GND. As ligações de energia estão no mapa de pinos e na figura do módulo 1.5.
Passo a passo da montagem
Solde fios e capacitores nos motores
Dois fios por motor (vermelho e preto) e um capacitor cerâmico de 100 nF entre os terminais. Faça isso antes de prender: depois fica difícil alcançar.
Prenda motores, rodas e roda boba
Motores paralelos e alinhados, com parafusos M3 ou abraçadeiras. Gire as rodas com a mão: não podem raspar no chassi.
Bateria, chave e buck
Suporte com BMS embaixo, perto do eixo; chave no fio positivo. Com o multímetro, ajuste o buck para 5,0 V antes de ligar qualquer placa nele.
Protoboard, ESP32 e driver
Fita dupla-face na protoboard; ESP32 e driver nela. Faça primeiro a barra de GND comum e só depois os fios de sinal, seguindo a tabela.
Servo e sensor na frente
Servo colado na frente, HC-SR04 preso no braço dele, a cerca de 8 a 10 cm do chão e apontando reto. Os "olhos" do sensor não podem ver o próprio chassi.
✓ Fiação que dura
- ✓Cores com regra: vermelho = positivo, preto = GND, outras cores = sinal.
- ✓Alívio de tensão: uma abraçadeira segura o fio antes do terminal, para o puxão não chegar à solda.
- ✓Fios só do comprimento necessário, sem laço sobrando perto das rodas.
✗ Falha intermitente garantida
- ✗Jumper frouxo na protoboard em cima de um chassi que vibra.
- ✗Bateria solta: ela desloca o centro de massa e puxa os fios a cada curva.
- ✗ECHO do HC-SR04 de 5 V direto no GPIO, sem o divisor.
Por que aprender
Fiação solta é a maior fonte de falha intermitente em robô móvel: o defeito aparece só quando o robô vibra, some na bancada e consome uma tarde inteira de procura. Montar com ordem (GND primeiro, fio preso, peso embaixo) evita isso desde o começo.
Conceitos-chave
🧪 Testar cada parte isolada
Se você grava o código final e o robô não anda, o defeito pode estar em qualquer um de dez lugares. Testando uma parte por vez, na ordem certa, cada teste só depende dos que já passaram. É o equivalente, no hardware, do teste unitário da programação.
Como ler: comece embaixo, à esquerda. A energia (âmbar) vem primeiro porque, se ela estiver errada, todos os outros testes dão resultados falsos. Os motores são testados um de cada vez para você saber qual gira ao contrário. O degrau "tudo no chão" só acontece no tópico 4.
Checklist de bancada (degrau 1, com a chave ligada e sem USB)
- ✓Bateria: entre 7 e 8,4 V com as duas 18650 (ou perto de 5 V com 4 NiMH carregadas).
- ✓Saída do buck: 5,0 V. Pino 3V3 do ESP32: cerca de 3,3 V.
- ✓Continuidade (bipe) entre o GND do ESP32, do driver, do sensor e o negativo da bateria.
Objetivo (degrau 2): ver a distância no Serial Monitor e confirmar que o divisor do ECHO funciona. Também roda no Wokwi, que tem o HC-SR04.
// Teste isolado do HC-SR04 (ESP32, pacote esp32 3.x)
const int PINO_TRIG = 18, PINO_ECHO = 19; // ECHO pelo divisor 1k/2k
void setup() {
Serial.begin(115200);
pinMode(PINO_TRIG, OUTPUT); digitalWrite(PINO_TRIG, LOW);
pinMode(PINO_ECHO, INPUT);
}
void loop() {
digitalWrite(PINO_TRIG, HIGH); delayMicroseconds(10); digitalWrite(PINO_TRIG, LOW);
unsigned long us = pulseIn(PINO_ECHO, HIGH, 30000UL); // espera no maximo 30 ms
if (us == 0) Serial.println("sem eco (nada ate ~4 m, ou fio do ECHO solto)");
else Serial.printf("distancia: %.1f cm\n", us / 58.0); // 58 us por cm, ida e volta
delay(100);
}
Como verificar
- ✓Mão a 20 cm do sensor: o Serial mostra valores entre 18 e 22 cm, que mudam quando você aproxima ou afasta.
- ✓Degraus 3 e 4: grave o motores-teste.ino do módulo 1.5 (mesmos pinos) com o robô suspenso; com DRV8833, use o menu de testes do sketch do tópico 4. Degrau 5: o servo-olhar.ino.
- ✗Sempre "sem eco"? Confira o 5 V no VCC do sensor e os resistores do divisor (1 kΩ do lado do sensor).
Por que aprender
Quando tudo é testado junto, você não sabe qual parte falhou. Com a escada, cada problema aparece sozinho, no degrau dele, e o conserto leva minutos. Esse hábito vale para qualquer robô, do rover ao braço com IA.
Conceitos-chave
🧠 Lógica de desvio com máquina de estados
Um "se a parede está perto, vira" dentro do loop() funciona até o robô precisar fazer duas coisas em sequência (parar, dar ré, olhar, virar). Aí o código vira um novelo de if e delay. A saída é a máquina de estados: o robô está sempre em um estado com nome, faz só o que aquele estado manda e muda de estado quando uma condição acontece.
🌱 Novo aqui?
Um estado é um modo de comportamento (ANDAR, PARAR...). Uma transição é a regra que leva de um estado a outro ("distância menor que 25 cm"). Em C++, o enum cria a lista de nomes dos estados e o switch escolhe o bloco de código do estado atual. O millis() diz há quanto tempo a placa está ligada; com ele o robô mede quanto tempo está num estado sem travar com delay().
Como ler: cada cápsula é um estado e cada seta é uma transição, com a condição escrita ao lado. Repare que só uma condição depende do sensor (dist < 25 cm); as outras dependem do tempo. A seta ciano fecha o ciclo. No código abaixo, cada cápsula é um case do switch.
Objetivo: o rover completo. Ele liga pausado: o botão BOOT da placa alterna entre pausado e andando, e, pausado, aceita testes pelo Serial Monitor (s, e, d, c). Duas linhas no topo escolhem o driver (TB6612FNG ou DRV8833) e se há servo. Instale antes a biblioteca ESP32Servo (módulo 1.5).
// Rover que desvia de obstaculos - Robotica do Zero ao Expert, projeto 1.6
// ESP32 + HC-SR04 + 2 motores DC (TB6612FNG ou DRV8833) + servo opcional
// Pacote esp32 3.x (ledcAttach / ledcWrite) e biblioteca ESP32Servo
#include <ESP32Servo.h>
// ---------- escolha o hardware ----------
#define USAR_DRV8833 0 // 0 = TB6612FNG, 1 = DRV8833
#define USAR_SERVO 1 // 0 = sensor fixo, olhando para a frente
// ---------- pinos (mapa do topico 1) ----------
const int PINO_PWMA = 25, PINO_AIN1 = 26, PINO_AIN2 = 27; // motor esquerdo
const int PINO_PWMB = 33, PINO_BIN1 = 32, PINO_BIN2 = 4; // motor direito
const int PINO_STBY = 13; // STBY (TB6612) ou nSLEEP (DRV8833)
const int PINO_TRIG = 18, PINO_ECHO = 19; // ECHO pelo divisor 1k/2k
const int PINO_SERVO = 23;
const int PINO_BOTAO = 0; // botao BOOT da placa: pausa / continua
// ---------- ajustes (topico 5) ----------
const int PWM_FREQ = 20000, PWM_BITS = 8;
const int VEL_MAX = 180; // teto: cerca de 6 V medios com 2x 18650 (4x AA NiMH: 255)
const int VEL_MIN = 90; // zona morta do motor TT
const int VEL_FRENTE = 170, VEL_GIRO = 160;
const int AJUSTE_ESQ = 0, AJUSTE_DIR = 0; // some +10 no motor mais fraco
const float DIST_PARAR_CM = 25.0;
const unsigned long T_PARAR = 200, T_RE = 350, T_GIRO_90 = 380; // em ms
#if USAR_SERVO
Servo cabeca;
#endif
enum Estado { ANDAR, PARAR, RE, OLHAR, VIRAR };
const char* NOME[] = {"ANDAR", "PARAR", "RE", "OLHAR", "VIRAR"};
Estado estado = PARAR;
unsigned long inicioEstado = 0, ultimaLeitura = 0, tGiro = T_GIRO_90;
int ladoGiro = 1; // +1 = direita, -1 = esquerda
bool pausado = true; // liga parado: aperte BOOT para andar
float hist[3] = {400, 400, 400}; int iHist = 0; // ultimas 3 leituras
// ---------- motores ----------
void motor(int in1, int in2, int pinoPwm, int vel) {
vel = constrain(vel, -VEL_MAX, VEL_MAX);
int forca = abs(vel);
if (forca > 0 && forca < VEL_MIN) forca = VEL_MIN;
#if USAR_DRV8833
ledcWrite(in1, vel > 0 ? forca : 0); // DRV8833: PWM nos dois pinos de entrada
ledcWrite(in2, vel < 0 ? forca : 0);
#else
digitalWrite(in1, vel > 0 ? HIGH : LOW); // TB6612: sentido nos IN, forca no PWM
digitalWrite(in2, vel < 0 ? HIGH : LOW);
ledcWrite(pinoPwm, forca);
#endif
}
void andar(int esq, int dir) { // -255 a 255 em cada roda
if (esq != 0) esq += (esq > 0) ? AJUSTE_ESQ : -AJUSTE_ESQ;
if (dir != 0) dir += (dir > 0) ? AJUSTE_DIR : -AJUSTE_DIR;
motor(PINO_AIN1, PINO_AIN2, PINO_PWMA, esq);
motor(PINO_BIN1, PINO_BIN2, PINO_PWMB, dir);
}
// ---------- sensor ----------
float medirCm() {
digitalWrite(PINO_TRIG, HIGH); delayMicroseconds(10); digitalWrite(PINO_TRIG, LOW);
unsigned long us = pulseIn(PINO_ECHO, HIGH, 30000UL);
return (us == 0) ? 400.0 : us / 58.0; // sem eco = nada perto (cerca de 4 m)
}
float mediana3(float a, float b, float c) { return max(min(a, b), min(max(a, b), c)); }
float distanciaAndando() { // 1 leitura nova + as 2 anteriores
hist[iHist] = medirCm(); iHist = (iHist + 1) % 3;
return mediana3(hist[0], hist[1], hist[2]);
}
float distanciaParado() { // 3 leituras novas, 60 ms entre elas
float a = medirCm(); delay(60);
float b = medirCm(); delay(60);
return mediana3(a, b, medirCm());
}
// ---------- maquina de estados ----------
void mudar(Estado novo) {
estado = novo; inicioEstado = millis();
Serial.printf("-> %s\n", NOME[novo]);
}
void escolherLado() { // se o servo olhar ao contrario, troque 20 e 160
#if USAR_SERVO
cabeca.write(20); delay(400); float dDir = distanciaParado();
cabeca.write(160); delay(600); float dEsq = distanciaParado();
cabeca.write(90); delay(300);
Serial.printf("direita %.0f cm | esquerda %.0f cm\n", dDir, dEsq);
ladoGiro = (dDir >= dEsq) ? 1 : -1;
tGiro = (max(dDir, dEsq) < DIST_PARAR_CM) ? 2 * T_GIRO_90 : T_GIRO_90; // beco: meia-volta
#else
ladoGiro = -ladoGiro; // sem servo: alterna o lado
tGiro = T_GIRO_90;
#endif
}
void testar(char c) { // testes isolados pelo Serial Monitor
if (c == 's') Serial.printf("distancia: %.1f cm\n", distanciaParado());
if (c == 'e') { Serial.println("motor esquerdo, frente"); andar(VEL_FRENTE, 0); delay(1000); andar(0, 0); }
if (c == 'd') { Serial.println("motor direito, frente"); andar(0, VEL_FRENTE); delay(1000); andar(0, 0); }
#if USAR_SERVO
if (c == 'c') { Serial.println("servo: direita, esquerda, frente"); cabeca.write(20); delay(600); cabeca.write(160); delay(800); cabeca.write(90); }
#endif
}
void setup() {
Serial.begin(115200);
pinMode(PINO_BOTAO, INPUT_PULLUP);
pinMode(PINO_STBY, OUTPUT); digitalWrite(PINO_STBY, HIGH);
#if USAR_DRV8833
ledcAttach(PINO_AIN1, PWM_FREQ, PWM_BITS); ledcAttach(PINO_AIN2, PWM_FREQ, PWM_BITS);
ledcAttach(PINO_BIN1, PWM_FREQ, PWM_BITS); ledcAttach(PINO_BIN2, PWM_FREQ, PWM_BITS);
#else
pinMode(PINO_AIN1, OUTPUT); pinMode(PINO_AIN2, OUTPUT);
pinMode(PINO_BIN1, OUTPUT); pinMode(PINO_BIN2, OUTPUT);
ledcAttach(PINO_PWMA, PWM_FREQ, PWM_BITS); ledcAttach(PINO_PWMB, PWM_FREQ, PWM_BITS);
#endif
andar(0, 0);
pinMode(PINO_TRIG, OUTPUT); digitalWrite(PINO_TRIG, LOW); pinMode(PINO_ECHO, INPUT);
#if USAR_SERVO
ESP32PWM::allocateTimer(3); // servo num timer separado dos motores
cabeca.setPeriodHertz(50);
cabeca.attach(PINO_SERVO, 500, 2400);
cabeca.write(90);
#endif
Serial.println("Rover pronto e PAUSADO. Aperte BOOT para andar.");
Serial.println("Pausado, teste: s=sensor e=motor esq d=motor dir c=servo");
}
void loop() {
static bool botaoAntes = HIGH;
bool botao = digitalRead(PINO_BOTAO);
if (botaoAntes == HIGH && botao == LOW) { // acabou de apertar
pausado = !pausado; andar(0, 0); delay(250); // 250 ms filtram o repique
Serial.println(pausado ? "PAUSADO" : "ANDANDO");
if (!pausado) { hist[0] = hist[1] = hist[2] = 400; mudar(ANDAR); }
}
botaoAntes = botao;
if (pausado) { if (Serial.available()) testar(Serial.read()); return; }
unsigned long agora = millis(), noEstado = agora - inicioEstado;
switch (estado) {
case ANDAR:
andar(VEL_FRENTE, VEL_FRENTE);
if (agora - ultimaLeitura >= 60) { // HC-SR04: uma leitura a cada 60 ms
ultimaLeitura = agora;
if (distanciaAndando() < DIST_PARAR_CM) mudar(PARAR);
}
break;
case PARAR:
andar(0, 0);
if (noEstado >= T_PARAR) mudar(RE);
break;
case RE:
andar(-VEL_GIRO, -VEL_GIRO);
if (noEstado >= T_RE) { andar(0, 0); mudar(OLHAR); }
break;
case OLHAR:
escolherLado(); // robo parado, cerca de 1,5 s
mudar(VIRAR);
break;
case VIRAR:
andar(VEL_GIRO * ladoGiro, -VEL_GIRO * ladoGiro);
if (noEstado >= tGiro) {
andar(0, 0);
hist[0] = hist[1] = hist[2] = 400; // esquece as leituras antigas
mudar(ANDAR);
}
break;
}
}
Como verificar
- ✓Ao ligar, o Serial mostra "Rover pronto e PAUSADO". Digite s, e, d e c: cada parte responde sozinha (é o degrau 6 da escada, ainda na bancada).
- ✓Robô no chão, BOOT apertado: ele anda reto; diante de uma caixa, o Serial mostra "-> PARAR", "-> RE", "-> OLHAR", as duas distâncias e "-> VIRAR", e ele segue para o lado mais livre.
- ✗Servo tremendo ou motor apitando só depois de ligar o servo? É conflito de timer do PWM: confira a linha allocateTimer(3) e atualize a ESP32Servo.
- ✗Erro de compilação em ledcAttach? O pacote esp32 instalado é anterior ao 3.x: atualize no Gerenciador de Placas.
💡 Ensaio sem motor no Wokwi
O Wokwi simula o ESP32, o HC-SR04, o servo e o botão, mas não a ponte H. Para ensaiar a lógica sem o robô, ligue LEDs (com resistor) nos pinos 25 e 33 no lugar dos motores, arraste a distância do sensor virtual e acompanhe os estados no Serial.
Por que aprender
Máquina de estados é como robôs de verdade organizam o comportamento, do aspirador ao carro autônomo. Para acrescentar um comportamento novo (por exemplo, "buzinar quando der ré") você mexe em um estado só, sem quebrar os outros. Na Trilha 2 a mesma ideia ganha tarefas paralelas com FreeRTOS.
Conceitos-chave
🩺 Ajuste fino e problemas comuns
Todo primeiro rover precisa de ajuste: os motores nunca são idênticos, o piso muda o atrito e a bateria perde tensão ao longo do uso. Os números do bloco "ajustes" no topo do sketch existem para isso. Use o Serial Monitor como painel: ele diz em que estado o robô estava quando o problema aconteceu.
| Sintoma | Causa provável | Correção |
|---|---|---|
| Puxa para um lado | um motor mais fraco ou roda raspando | AJUSTE_ESQ ou AJUSTE_DIR de 10 em 10; confira as rodas |
| Reinicia ao dar ré ou virar | brownout: a inversão do motor puxa um pico | bateria carregada, capacitores, buck de 2 A, GND comum; confirme com o motivo-reset.ino do 1.5 |
| Não vê a parede | sensor torto, alto demais ou superfície macia/inclinada que espalha o eco | sensor reto a 8–10 cm do chão; aumente DIST_PARAR_CM |
| Para sozinho no meio da sala | leitura falsa curta (ruído no fio do sensor) | fios do sensor longe dos do motor; confira o divisor; a mediana já filtra picos isolados |
| Gira demais ou de menos | T_GIRO_90 depende do piso e da bateria | ajuste em passos de 50 ms e teste no piso onde ele vai andar |
| Nada se mexe | está pausado, ou STBY/nSLEEP em nível baixo | aperte BOOT; meça 3,3 V no STBY |
✓ Ajuste com método
- ✓Mude um número por vez e anote o antes e o depois.
- ✓Teste sempre no mesmo piso e com a bateria carregada.
- ✓Leia o Serial com o robô ligado ao computador por um cabo longo, ou suspenso.
✗ Ajuste no chute
- ✗Trocar três valores de uma vez e não saber qual resolveu.
- ✗Culpar o código antes de medir a bateria.
- ✗Tirar o teto VEL_MAX com 2× 18650 para "ganhar força".
Por que aprender
Saber diagnosticar é a habilidade que fica depois que o rover vai para a prateleira. A sequência "sintoma, estado no Serial, causa provável, uma mudança, novo teste" é a mesma que você vai usar para sintonizar o PID na Trilha 2 e a navegação na Trilha 4.
Conceitos-chave
🚀 Próximos passos: linha, buzina e Wi-Fi
O rover está pronto, mas o chassi aguenta muito mais. Três melhorias pequenas, cada uma um novo estado ou um novo sensor, mostram que o mesmo robô cresce com código e peças, sem recomeçar. Cada uma também abre um módulo da Trilha 2.
Como ler: o bloco verde é o que você já tem; os ciano são acréscimos independentes, que podem ser feitos em qualquer ordem. Nenhum deles exige trocar o chassi, os motores ou a máquina de estados: cada um entra como um sensor, um estado ou uma tarefa a mais.
Os dois módulos infravermelhos do kit (módulo 1.4) apontados para o chão, um de cada lado da linha preta. Crie o estado SEGUIR: se o sensor esquerdo vê preto, vire à esquerda. Na Trilha 2, a barra de 5 sensores e o PID deixam isso suave.
Um buzzer passivo num pino livre (o 25 e o 33 ficam livres com o DRV8833; com o TB6612, o 17 serve na DevKit WROOM-32). Na API 3.x, ledcAttach no pino e ledcWriteTone(pino, 2000) tocam um bipe; ligue no estado RÉ e desligue com tom 0.
O ESP32 cria uma página com botões frente, ré e parar, servida para o celular. O módulo 2.1 mostra como, com uma regra de segurança importante: se a conexão cair, o robô para sozinho.
💡 Registre o seu rover
Grave um vídeo curto do robô desviando, tire foto da fiação e guarde o sketch com os seus valores de ajuste. Use "Minha jornada" para marcar o que concluiu e exportar o progresso. Esse registro é o começo do seu portfólio de robótica, e é o que um professor pede na avaliação por projeto.
Por que aprender
Ver o robô crescer em pequenos passos ensina o modo de trabalho de toda a robótica: uma base que funciona, testada, e acréscimos que você consegue verificar um de cada vez. É exatamente assim que a Trilha 2 transforma este rover em um robô autônomo de verdade.
Conceitos-chave
✅ Resumo do módulo
Para ir além
- LEDC (PWM) no Arduino-ESP32 — ledcAttach, ledcWrite e ledcWriteTone na API 3.x
- Biblioteca ESP32Servo — exemplos e notas de compatibilidade
- HC-SR04 no Wokwi — ensaiar o sensor no navegador
- Arduino-ESP32 (Espressif) — referência completa do pacote 3.x
- TB6612FNG (Pololu) — limites de corrente e tensão do driver
Próxima trilha
Trilha 2 · Robô autônomo. Começa no módulo 2.1, controle pelo celular com Wi-Fi e BLE, e segue com IMU, encoders, PID e telemetria até um seguidor de linha.