PTENES
MÓDULO 1.6 · PROYECTO

🛞 Proyecto: rover que esquiva obstáculos

El proyecto que cierra la Ruta 1 lo reúne todo: el HC-SR04 detecta la pared, el ESP32 decide con una máquina de estados y dos motores DC esquivan los obstáculos. Vas a planificar en papel, montar, probar cada parte por separado y solo entonces poner el robot en el suelo.

6
Temas
Principiante
Nivel
Proyecto
Tipo
Kit completo
Hardware necesario
0%
0 de 0 temas leídos · Sección 1 de 6

Contenido detallado

1

📝 Planifica el rover en papel

Antes de cortar el chasis, responde tres preguntas en papel: qué componentes tiene el robot, a qué pin va cada cable e cuánta corriente consume todo. Las respuestas se convierten en el diagrama de bloques, la tabla de pines y el presupuesto de energía que aparecen abajo. En el módulo 1.5 ya usaste estos mismos pines para los motores y el servo, así que los sketches de allí sirven para probarlos aquí.

🌱 ¿Eres nuevo aquí?

Un diagrama de bloques muestra las partes del sistema como cajas y lo que pasa entre ellas como flechas, sin preocuparte por los cables. El mapa de pines indica qué GPIO del ESP32 va a qué terminal de cada componente. El presupuesto de energía suma el consumo de cada componente para elegir la batería y el regulador con margen.

SENTIRHC-SR04+ servo (cuello) PENSARESP32máquina de estados ACTUARdriver TB6612+ 2 motores TT cmánguloPWM ENERGÍA: 2× 18650 + interruptorbuck 5 V · VM del driver 5 V5 VVM

Cómo leer: las flechas verdes son información (la distancia sube desde el sensor, el ángulo baja hacia el servo y el PWM llega al driver). Las líneas discontinuas color ámbar son energía, que sale de un solo lugar, abajo. Los motores reciben la tensión de la batería por VM; todo lo demás recibe 5 V del regulador. Es el ciclo sentir, pensar y actuar del módulo 1.1, ahora con componentes reales.

Mapa de pines (válido para todo el módulo)

Pin ESP32TB6612FNGDRV8833Para qué
GPIO 25PWMAlibrevelocidad del motor izquierdo
GPIO 26 · 27AIN1 · AIN2AIN1 · AIN2sentido (y PWM en el DRV8833) del motor izquierdo
GPIO 33PWMBlibrevelocidad del motor derecho
GPIO 32 · 4BIN1 · BIN2BIN1 · BIN2sentido (y PWM en el DRV8833) del motor derecho
GPIO 13STBYnSLEEP / EEPenciende el driver (nivel alto)
GPIO 18HC-SR04 TRIGdispara el pulso de sonido
GPIO 19HC-SR04 ECHO, a través del divisor (1 kΩ de ECHO al pin; 2 kΩ del pin a GND)el eco de 5 V se convierte en 3,3 V
GPIO 23servo, cable naranjagira el sensor
GPIO 0 (BOOT)botón integrado en la placapausa y continúa
3V3VCCno se usalógica del driver
5V / VINsalida del buck 5 V, que también va a VCC del HC-SR04 y al cable rojo del servoalimenta la electrónica
GNDGND común: driver, buck, batería (−), HC-SR04 y cable marrón del servoreferencia única
Presupuesto de energíaEn movimiento (aprox.)Pico (aprox.)
ESP32 sin Wi-Fi50 a 100 mA250 mA con Wi-Fi
HC-SR0415 mA15 mA
Servo SG90casi nada cuando está quietoalgunos cientos de mA al moverse
2 motores TT300 a 500 mA (juntos)cerca de 1 A cada uno, al arrancar o estar bloqueado
Conclusiónbuck de al menos 2 A para los 5 V; batería que soporte 2 A o más de pico. Mide el tuyo con el multímetro: los valores varían según el modelo.

Por qué aprender

Planificar evita rehacer el cableado y cambiar componentes a mitad del camino. Los ingenieros de robots comerciales preparan exactamente estos tres documentos antes del primer prototipo; con ellos a mano, tú también puedes pedir ayuda en un foro de forma que alguien entienda tu robot.

Conceptos clave

Diagrama de bloques
qué pasa entre las partes
Mapa de pines
un cable, un destino
Consumo
promedio y de pico
Margen
regulador por encima del pico
2

🔧 Montar el chasis y el cableado

El chasis puede ser de cartón grueso, MDF o acrílico: lo importante es que sea rígido y tenga espacio para sujetar todo. Motores atrás, rueda loca adelante (o al revés, si tu kit viene así), batería abajo y cerca del eje de las ruedas, ESP32 y protoboard arriba, sensor al frente, sin obstáculos en su campo de visión.

ESP32 GPIO 25GPIO 26GPIO 27GPIO 33GPIO 32GPIO 4GPIO 13GPIO 23GPIO 18GPIO 19 5V/VIN ← buck TB6612FNG PWMAAIN1AIN2PWMBBIN1BIN2STBY AO1/AO2BO1/BO2 VM: batería · VCC: 3V3 · GNDizq. der. servo (naranja) TRIGECHOHC-SR04 1 kΩ 2 kΩGND

Cómo leer: cada línea verde horizontal conecta un GPIO con la entrada del driver a la misma altura, así puedes revisar cada cable con el dedo. Los círculos de la derecha son los motores. Abajo, la línea color ámbar va al servo y las del sensor pasan por el divisor: el eco sale del HC-SR04 con 5 V, atraviesa la resistencia de 1 kΩ y llega al GPIO 19 con cerca de 3,3 V, porque la de 2 kΩ desvía el resto a GND. Las conexiones de energía están en el mapa de pines y en la figura del módulo 1.5.

Paso a paso del montaje

1

Suelda los cables y capacitores a los motores

Dos cables por motor (rojo y negro) y un capacitor cerámico de 100 nF entre los terminales. Hazlo antes de sujetarlos: después será difícil acceder.

2

Sujeta los motores, las ruedas y la rueda loca

Motores paralelos y alineados, con tornillos M3 o bridas. Gira las ruedas con la mano: no deben rozar el chasis.

3

Batería, interruptor y buck

Soporte con BMS abajo, cerca del eje; interruptor en el cable positivo. Con el multímetro, ajusta el buck a 5,0 V antes de conectar cualquier placa.

4

Protoboard, ESP32 y driver

Cinta doble faz en la protoboard; coloca allí el ESP32 y el driver. Primero arma la barra de GND común y después conecta los cables de señal, siguiendo la tabla.

5

Servo y sensor al frente

Pega el servo al frente y sujeta el HC-SR04 a su brazo, a unos 8 a 10 cm del suelo y apuntando hacia adelante. Los «ojos» del sensor no deben ver el propio chasis.

✓ Cableado duradero

  • ✓Colores según una regla: rojo = positivo, negro = GND, otros colores = señal.
  • ✓Alivio de tensión: una brida sujeta el cable antes del terminal para que el tirón no llegue a la soldadura.
  • ✓Cables del largo necesario, sin bucles sobrantes cerca de las ruedas.

✗ Falla intermitente garantizada

  • ✗Jumper flojo en la protoboard sobre un chasis que vibra.
  • ✗Batería suelta: desplaza el centro de masa y tira de los cables en cada curva.
  • ✗ECHO del HC-SR04 de 5 V conectado directamente al GPIO, sin el divisor.

Por qué aprender

El cableado suelto es la principal causa de fallas intermitentes en un robot móvil: el problema aparece solo cuando el robot vibra, desaparece en la mesa de trabajo y consume una tarde entera de búsqueda. Montarlo con orden (primero GND, cables sujetos, peso abajo) lo evita desde el principio.

Conceptos clave

Centro de masa
peso abajo, entre las ruedas
Alivio de tensión
el tirón no llega a la soldadura
Interruptor general
apaga todo de una vez
Divisor en ECHO
5 V se convierten en 3,3 V
3

🧪 Probar cada parte por separado

Si cargas el código final y el robot no se mueve, la falla puede estar en cualquiera de diez lugares. Al probar una parte a la vez, en el orden correcto, cada prueba depende solo de las que ya pasaron. Es el equivalente, en el hardware, de prueba unitaria de la programación.

1 energíamultímetro 2 sensorcm en el Serial 3 motor izq.ruedas en el aire 4 motor der.mismo sentido 5 servosin temblar 6 todoen el suelo solo sube cuando se supera el nivel anterior

Cómo leer: empieza abajo, a la izquierda. La energía (ámbar) va primero porque, si está mal, todas las demás pruebas dan resultados falsos. Los motores se prueban uno a la vez para que sepas cuál gira al revés. El nivel «todo en el suelo» solo se alcanza en el tema 4.

Lista de verificación en la mesa de trabajo (nivel 1, con el interruptor encendido y sin USB)

  • ✓Batería: entre 7 y 8,4 V con las dos 18650 (o cerca de 5 V con 4 NiMH cargadas).
  • ✓Salida del buck: 5,0 V. Pin 3V3 del ESP32: cerca de 3,3 V.
  • ✓Continuidad (pitido) entre el GND del ESP32, del driver, del sensor y el negativo de la batería.

Objetivo (nivel 2): ver la distancia en el Serial Monitor y confirmar que el divisor de ECHO funciona. También funciona en Wokwi, que incluye el HC-SR04.

teste-sensor.ino
// Prueba aislada del HC-SR04 (ESP32, paquete esp32 3.x)
const int PINO_TRIG = 18, PINO_ECHO = 19;   // ECHO mediante el 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 maximo 30 ms
  if (us == 0) Serial.println("sin eco (nada hasta ~4 m, o cable de ECHO suelto)");
  else Serial.printf("distancia: %.1f cm\n", us / 58.0);  // 58 us por cm, ida y vuelta
  delay(100);
}

Cómo verificar

  • ✓Mano a 20 cm del sensor: el Serial muestra valores entre 18 y 22 cm, que cambian cuando acercas o alejas la mano.
  • ✓Niveles 3 y 4: carga el motores-prueba.ino del módulo 1.5 (los mismos pines) con el robot suspendido; con DRV8833, usa el menú de pruebas del sketch del tema 4. Nivel 5: el servo-olhar.ino.
  • ✗¿Siempre aparece «sin eco»? Revisa los 5 V en VCC del sensor y las resistencias del divisor (1 kΩ del lado del sensor).

Por qué aprender

Cuando pruebas todo junto, no sabes qué parte falló. Con la escalera, cada problema aparece por separado, en su propio nivel, y la reparación lleva minutos. Este hábito sirve para cualquier robot, desde el rover hasta el brazo con IA.

Conceptos clave

Prueba unitaria
una pieza a la vez
Orden
la energía antes que todo
Ruedas en el aire
prueba sin riesgos
Lista de verificación
la misma en cada montaje
4

🧠 Lógica para evitar obstáculos con una máquina de estados

Un «si la pared está cerca, gira» dentro del loop() funciona hasta que el robot necesita hacer dos cosas en secuencia (parar, retroceder, mirar, girar). Entonces el código se vuelve un enredo de if e delay. La solución es la máquina de estados: el robot siempre está en un estado con nombre, hace solo lo que ese estado indica y cambia de estado cuando ocurre una condición.

🌱 ¿Eres nuevo aquí?

Un estado es un modo de comportamiento (ANDAR, PARAR...). Una transición es la regla que lleva de un estado a otro («distancia menor que 25 cm»). En C++, el enum crea la lista de nombres de los estados y el switch elige el bloque de código del estado actual. El millis() indica cuánto tiempo lleva encendida la placa; con él, el robot mide cuánto tiempo permanece en un estado sin bloquearse con delay().

ANDAR PARAR RETROCEDER MIRAR GIRAR dist < 25 cm200 ms350 msmidiólos ladosterminó el giro: vuelve a avanzar

Cómo leer: cada cápsula es un estado y cada flecha es una transición, con la condición escrita al lado. Observa que solo una condición depende del sensor (dist < 25 cm); las demás dependen del tiempo. La flecha cian cierra el ciclo. En el código de abajo, cada cápsula es un case del switch.

Objetivo: el rover completo. Se enciende en pausa: el botón BOOT de la placa alterna entre pausa y movimiento, y, cuando está en pausa, acepta pruebas desde el Serial Monitor (s, e, d, c). Dos líneas al principio permiten elegir el driver (TB6612FNG o DRV8833) y si hay servo. Instala primero la biblioteca ESP32Servo (módulo 1.5).

rover-desvia.ino
// Rover que evita obstaculos - Robotica desde cero hasta experto, proyecto 1.6
// ESP32 + HC-SR04 + 2 motores DC (TB6612FNG o DRV8833) + servo opcional
// Paquete esp32 3.x (ledcAttach / ledcWrite) y biblioteca ESP32Servo
#include <ESP32Servo.h>
// ---------- elige el hardware ----------
#define USAR_DRV8833 0   // 0 = TB6612FNG, 1 = DRV8833
#define USAR_SERVO   1   // 0 = sensor fijo, mirando hacia el frente
// ---------- pines (mapa del tema 1) ----------
const int PINO_PWMA = 25, PINO_AIN1 = 26, PINO_AIN2 = 27;  // motor izquierdo
const int PINO_PWMB = 33, PINO_BIN1 = 32, PINO_BIN2 = 4;   // motor derecho
const int PINO_STBY = 13;          // STBY (TB6612) o nSLEEP (DRV8833)
const int PINO_TRIG = 18, PINO_ECHO = 19;  // ECHO mediante el divisor 1k/2k
const int PINO_SERVO = 23;
const int PINO_BOTAO = 0;          // boton BOOT de la placa: pausa / continua
// ---------- ajustes (tema 5) ----------
const int PWM_FREQ = 20000, PWM_BITS = 8;
const int VEL_MAX = 180;   // limite: cerca de 6 V medios con 2x 18650 (4x AA NiMH: 255)
const int VEL_MIN = 90;    // zona muerta del motor TT
const int VEL_FRENTE = 170, VEL_GIRO = 160;
const int AJUSTE_ESQ = 0, AJUSTE_DIR = 0;  // suma +10 al motor mas debil
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 = derecha, -1 = izquierda
bool pausado = true;         // arranca detenido: presiona BOOT para avanzar
float hist[3] = {400, 400, 400}; int iHist = 0;  // ultimas 3 lecturas
// ---------- 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 en los dos pines de entrada
  ledcWrite(in2, vel < 0 ? forca : 0);
#else
  digitalWrite(in1, vel > 0 ? HIGH : LOW);   // TB6612: sentido en IN, fuerza en PWM
  digitalWrite(in2, vel < 0 ? HIGH : LOW);
  ledcWrite(pinoPwm, forca);
#endif
}
void andar(int esq, int dir) {   // -255 a 255 en cada rueda
  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;    // sin eco = nada cerca (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 lectura nueva + las 2 anteriores
  hist[iHist] = medirCm(); iHist = (iHist + 1) % 3;
  return mediana3(hist[0], hist[1], hist[2]);
}
float distanciaParado() {                // 3 lecturas nuevas, 60 ms entre ellas
  float a = medirCm(); delay(60);
  float b = medirCm(); delay(60);
  return mediana3(a, b, medirCm());
}
// ---------- máquina de estados ----------
void mudar(Estado novo) {
  estado = novo; inicioEstado = millis();
  Serial.printf("-> %s\n", NOME[novo]);
}
void escolherLado() {                    // si el servo mira al reves, intercambia 20 y 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("derecha %.0f cm | izquierda %.0f cm\n", dDir, dEsq);
  ladoGiro = (dDir >= dEsq) ? 1 : -1;
  tGiro = (max(dDir, dEsq) < DIST_PARAR_CM) ? 2 * T_GIRO_90 : T_GIRO_90;  // callejon sin salida: media vuelta
#else
  ladoGiro = -ladoGiro;                  // sin servo: alterna el lado
  tGiro = T_GIRO_90;
#endif
}
void testar(char c) {                   // pruebas aisladas desde el Serial Monitor
  if (c == 's') Serial.printf("distancia: %.1f cm\n", distanciaParado());
  if (c == 'e') { Serial.println("motor izquierdo, adelante"); andar(VEL_FRENTE, 0); delay(1000); andar(0, 0); }
  if (c == 'd') { Serial.println("motor derecho, adelante"); andar(0, VEL_FRENTE); delay(1000); andar(0, 0); }
#if USAR_SERVO
  if (c == 'c') { Serial.println("servo: derecha, izquierda, 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 en un timer separado de los motores
  cabeca.setPeriodHertz(50);
  cabeca.attach(PINO_SERVO, 500, 2400);
  cabeca.write(90);
#endif
  Serial.println("Rover listo y EN PAUSA. Presiona BOOT para avanzar.");
  Serial.println("En pausa, prueba: s=sensor e=motor izq d=motor der c=servo");
}
void loop() {
  static bool botaoAntes = HIGH;
  bool botao = digitalRead(PINO_BOTAO);
  if (botaoAntes == HIGH && botao == LOW) {      // acaba de presionar
    pausado = !pausado; andar(0, 0); delay(250);   // 250 ms filtran el rebote
    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: una lectura 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();                              // robot detenido, 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;         // descarta las lecturas antiguas
        mudar(ANDAR);
      }
      break;
  }
}

Cómo verificar

  • ✓Al encender, el Serial muestra «Rover listo y EN PAUSA». Escribe s, e, d y c: cada parte responde por separado (es el nivel 6 de la escalera, todavía en la mesa de trabajo).
  • ✓Robot en el piso, con BOOT presionado: avanza en línea recta; frente a una caja, el Serial muestra "-> PARAR", "-> RE", "-> MIRAR", las dos distancias y "-> GIRAR", y continúa hacia el lado más despejado.
  • ✗¿El servo tiembla o el motor emite un pitido solo después de encender el servo? Es un conflicto del temporizador PWM: revisa la línea allocateTimer(3) y actualiza ESP32Servo.
  • ✗Error de compilación en ledcAttach? El paquete esp32 instalado es anterior a la versión 3.x: actualízalo en el Administrador de placas.

💡 Prueba sin motor en Wokwi

Wokwi simula el ESP32, el HC-SR04, el servo y el botón, pero no el puente H. Para probar la lógica sin el robot, conecta LED (con resistencia) a los pines 25 y 33 en lugar de los motores, cambia la distancia del sensor virtual y observa los estados en el Serial.

Por qué aprender

Las máquinas de estados son la forma en que los robots reales organizan su comportamiento, desde una aspiradora hasta un automóvil autónomo. Para agregar un comportamiento nuevo (por ejemplo, "tocar la bocina al ir en reversa"), modificas un solo estado sin afectar los demás. En la Ruta 2, la misma idea incorpora tareas paralelas con FreeRTOS.

Conceptos clave

Estado
modo con nombre
Transición
condición que cambia el modo
enum
lista de nombres
switch + millis
un bloque por estado, sin bloquear
5

🩺 Ajustes y problemas frecuentes

Todo primer rover necesita ajustes: los motores nunca son idénticos, el piso cambia la fricción y la batería pierde voltaje con el uso. Los números del bloque "ajustes" al inicio del sketch sirven para eso. Usa el Serial Monitor como panel: te indica en qué estado estaba el robot cuando ocurrió el problema.

SíntomaCausa probableCorrección
Se desvía hacia un ladoun motor más débil o una rueda que rozaAJUSTE_ESQ o AJUSTE_DER de 10 en 10; revisa las ruedas
Se reinicia al ir en reversa o girarbrownout: la inversión del motor genera un pico de consumobatería cargada, capacitores, buck de 2 A, GND común; confirma con el motivo-reset.ino del 1.5
No detecta la paredsensor torcido, demasiado alto o una superficie blanda/inclinada que dispersa el ecosensor recto a 8–10 cm del piso; aumenta DIST_PARAR_CM
Se detiene solo en medio de la habitaciónlectura falsa de poca distancia (ruido en el cable del sensor)separa los cables del sensor de los del motor; revisa el divisor; la mediana ya filtra los picos aislados
Gira demasiado o muy pocoT_GIRO_90 depende del piso y de la bateríaajusta en pasos de 50 ms y prueba en el piso donde va a avanzar
No se mueve nadaestá pausado o STBY/nSLEEP está en nivel bajopresiona BOOT; mide 3,3 V en STBY

✓ Ajusta con método

  • ✓Cambia un número a la vez y anota el antes y el después.
  • ✓Prueba siempre en el mismo piso y con la batería cargada.
  • ✓Lee el Serial con el robot conectado a la computadora con un cable largo o suspendido.

✗ Ajusta al tanteo

  • ✗Cambiar tres valores a la vez y no saber cuál lo resolvió.
  • ✗Culpar al código antes de medir la batería.
  • ✗Quitar el límite VEL_MAX con 2× 18650 para "ganar fuerza".

Por qué aprender

Saber diagnosticar es la habilidad que permanece cuando guardas el rover. La secuencia "síntoma, estado en el Serial, causa probable, un cambio, nueva prueba" es la misma que usarás para ajustar el PID en la Ruta 2 y la navegación en la Ruta 4.

Conceptos clave

Compensación
iguala los motores
Umbral
distancia que activa la parada
Mediana
ignora una lectura disparatada
Serial como panel
estado + números
6

🚀 Próximos pasos: línea, bocina y Wi-Fi

El rover está listo, pero el chasis puede hacer mucho más. Tres mejoras pequeñas, cada una con un nuevo estado o sensor, muestran cómo el mismo robot puede crecer con código y piezas, sin empezar de nuevo. Cada una también abre un módulo de la Ruta 2.

TU ROVERRuta 1 completa 2 sensores IR: líneaPID en el módulo 2.6 buzzer: avisospitido en el estado RE Wi-Fi: celularcontrol en el módulo 2.1

Cómo leer: el bloque verde es lo que ya tienes; los cian son agregados independientes que puedes hacer en cualquier orden. Ninguno requiere cambiar el chasis, los motores ni la máquina de estados: cada uno se incorpora como un sensor, un estado o una tarea más.

〰️ Seguir la línea

Los dos módulos infrarrojos del kit (módulo 1.4), apuntando al piso, uno a cada lado de la línea negra. Crea el estado SEGUIR: si el sensor izquierdo detecta negro, gira a la izquierda. En la Ruta 2, la barra de 5 sensores y el PID hacen que el movimiento sea fluido.

🔊 Bocina

Un buzzer pasivo en un pin libre (el 25 y el 33 quedan libres con el DRV8833; con el TB6612, el 17 sirve en la DevKit WROOM-32). En la API 3.x, ledcAttach en el pin y ledcWriteTone(pino, 2000) reproducen un pitido; actívalo en el estado RE y desactívalo con el tono 0.

📶 Wi-Fi

El ESP32 crea una página con botones de adelante, reversa y detener, disponible para el celular. El módulo 2.1 muestra cómo hacerlo, con una regla de seguridad importante: si se pierde la conexión, el robot se detiene solo.

💡 Registra tu rover

Graba un video corto del robot esquivando obstáculos, toma una foto del cableado y guarda el sketch con tus valores de ajuste. Usa "Mi recorrido" para marcar lo que completaste y exportar tu progreso. Este registro es el comienzo de tu portafolio de robótica y lo que te pide un profesor para evaluar un proyecto.

Por qué aprender

Ver cómo el robot crece paso a paso enseña la forma de trabajar en robótica: una base que funciona y está probada, más agregados que puedes verificar uno por uno. Así es exactamente como la Ruta 2 transforma este rover en un robot autónomo de verdad.

Conceptos clave

Expansión
un sensor o estado más
Reutilización
mismo chasis, nuevo código
Pines libres
planifica dónde cabe el próximo
Siguiente nivel
Ruta 2: robot autónomo

✅ Resumen del módulo

✓
Planifica primero: diagrama de bloques, mapa de pines y presupuesto de energía.
✓
Monta con orden: peso abajo, primero GND común, cable bien sujeto, divisor en ECHO.
✓
Prueba paso a paso: alimentación, sensor, cada motor, servo y solo después todo junto.
✓
Máquina de estados: AVANZAR, DETENERSE, RETROCEDER, MIRAR, GIRAR, con enum, switch e millis().
✓
Ajusta con método: un número a la vez, Serial como panel, alimentación antes que el código.

Para profundizar

Siguiente ruta

Ruta 2 · Robot autónomo. Comienza en el módulo 2.1, control desde el celular con Wi-Fi y BLE, y continúa con IMU, encoders, PID y telemetría hasta llegar a un seguidor de línea.