Cómo hacer un robot móvil con ESP32 desde cero
Cuando alguien piensa en robótica, normalmente imagina proyectos muy avanzados, robots humanoides o máquinas que parecen imposibles de construir.
Pero la realidad es diferente. Uno de los mejores caminos para aprender robótica es comenzar con un proyecto sencillo que te permita entender cómo funcionan los robots.
En este tutorial aprenderás cómo hacer un robot móvil desde cero, aunque no tengas experiencia previa.
Construiremos un robot móvil de tracción diferencial capaz de navegar de manera autónoma evitando obstáculos, utilizando una ESP32 y componentes fáciles de conseguir.
Durante el proceso aprenderás conceptos fundamentales como el control de motores, el uso de sensores, la programación de microcontroladores y la lógica utilizada en los robots autónomos.
Lo mejor es que iremos paso a paso: desde el armado de la estructura, las conexiones eléctricas, hasta la programación final del robot.
Al terminar este proyecto tendrás tu primer robot funcional construido por ti mismo y una base sólida para continuar aprendiendo robótica.
Materiales necesarios para hacer un robot móvil con ESP32
Antes de comenzar con la construcción de nuestro robot móvil, es importante conocer todos los componentes que vamos a utilizar.
Este proyecto está pensado para principiantes, por lo que utilizaremos materiales fáciles de conseguir y elementos básicos de electrónica que nos permitirán construir un robot capaz de navegar de manera autónoma evitando obstáculos.
Los materiales necesarios son los siguientes:
Electrónica y control
- ESP32 Devkit V1 30 pines: será el cerebro del robot, encargado de procesar la información del sensor y controlar los motores.
- Shield para ESP32 o protoboard (una de las dos opciones): puedes utilizar una shield diseñada para ESP32 para facilitar las conexiones del proyecto o realizar el montaje utilizando un protoboard. Cualquiera de las dos opciones es válida.
- Sensor ultrasónico: permite detectar obstáculos mediante la medición de distancia.
- 2 motores reductores DC de 3 a 6V: son los encargados de generar el movimiento del robot.
- 2 ruedas compatibles con los motores reductores: permiten el desplazamiento del robot móvil diferencial.
- 2 baterías 18650: proporcionan la alimentación necesaria para el funcionamiento del robot.
- Porta baterías para 2 celdas 18650: permite conectar y sujetar las baterías de forma segura.
- Switch de palanca: utilizado para encender y apagar el robot.
Conexiones y montaje electrónico
- Cables jumper hembra-hembra y hembra-macho: necesarios para realizar las conexiones entre la ESP32, sensor y demás componentes.
- Cable de timbre: utilizado para realizar conexiones adicionales dentro del montaje.
Estructura mecánica
- Chasis del robot: para montar todos los componentes necesitamos una estructura donde colocar la electrónica y los elementos mecánicos. Para esto tienes dos opciones: puedes adquirir un chasis comercial, una simple plancha de madera o utilizar nuestro kit de robótica.
Para este proyecto, si vas a utilizar nuestro chasis, necesitarás los siguientes elementos de fijación:
- 4 tornillos M3 x 30 mm: para la fijación principal del chasis.
- 4 tornillos M3 x 15 mm: para el montaje de componentes.
- 2 tornillos M3 x 10 mm: para fijaciones adicionales.
- Rueda loca: proporciona estabilidad al robot y permite un movimiento más fluido.
Con estos componentes tendremos todo lo necesario para construir nuestro primer robot móvil con ESP32 y comenzar en el mundo de la robótica.
Diseño y opciones del chasis para el robot móvil
El chasis del robot es la estructura encargada de sostener todos los componentes del proyecto, como la ESP32, motores, baterías y sensor ultrasónico.
Para construir nuestro robot móvil tienes tres opciones:
Opción 1: Utilizar un chasis comercial
La primera alternativa es adquirir un chasis comercial para robot móvil diferencial.
Te recomiendo utilizar este tipo de chasis si deseas comenzar rápidamente, ya que normalmente vienen preparados para colocar motores, ruedas y componentes electrónicos sin necesidad de fabricar la estructura desde cero.
Opción 2: Fabricar tu propio chasis
Si no consigues un chasis comercial, también puedes fabricar tu propia estructura utilizando una plancha de MDF o triplex de 3 mm.
Para este proyecto puedes utilizar una base con las siguientes dimensiones aproximadas:
- 22 cm de largo
- 15 cm de ancho
Con estas medidas podrás colocar los componentes principales del robot y realizar el montaje siguiendo la distribución del proyecto.
Opción 3: Utilizar nuestro diseño de chasis
La tercera opción es utilizar nuestro diseño de chasis, creado específicamente para este proyecto.
Este diseño está adaptado para nuestro robot móvil diferencial y cuenta con las perforaciones necesarias para montar fácilmente todos los componentes del robot.
Además, incluye:
- Perforaciones listas para colocar motores y componentes.
- Ranuras adaptadas para la instalación del sensor ultrasónico.
- Diseño preparado específicamente para este proyecto.
- Una estructura elegante y organizada para obtener un mejor acabado final.
Nuestro diseño puede ser fabricado mediante corte láser en MDF de 3 mm o mediante impresión 3D, dependiendo del proceso de fabricación que tengas disponible.
Sus dimensiones son:
- 22 cm de largo
- 15 cm de ancho
Este chasis fue diseñado pensando en este proyecto y en futuros desarrollos utilizando la misma plataforma.
Montaje de los componentes en el chasis del robot móvil
Una vez seleccionado el chasis que utilizarás para tu proyecto, es momento de realizar el montaje de los componentes principales del robot.
En el siguiente video podrás observar el proceso de armado utilizando nuestro diseño de chasis, donde colocaremos los motores, ruedas, soporte para baterías y demás elementos necesarios para construir la estructura del robot móvil.
Los siguientes videos te servirán como guía de referencia para realizar el montaje, independientemente de la opción de chasis que hayas elegido.
Sigue cada paso del proceso para lograr una distribución correcta de los componentes y obtener una estructura firme antes de continuar con las conexiones eléctricas.
Conexiones eléctricas del robot móvil con ESP32
Una vez realizado el montaje de la estructura, el siguiente paso es conectar todos los componentes electrónicos del robot.
En este proyecto utilizaremos una ESP32 como controlador principal, la cual se encargará de procesar la información del sensor ultrasónico y controlar el movimiento de los motores.
Dependiendo de la opción que hayas elegido para realizar las conexiones, puedes utilizar una shield para ESP32 o un protoboard.
A continuación encontrarás los diagramas de conexión para cada alternativa:
Conexiones utilizando Shield para ESP32
Si estás utilizando una shield para ESP32, sigue el siguiente diagrama de conexión para conectar el sensor ultrasónico, motores, alimentación y demás componentes.
Conexiones utilizando Protoboard
Si prefieres realizar el montaje utilizando un protoboard, utiliza el siguiente diagrama como guía para conectar cada componente correctamente.
🧠 Aprende IA con Arduino
Explora nuestro eBook con proyectos guiados paso a paso para aprender inteligencia artificial con Arduino desde cero, en casa o en el aula.
Antes de continuar con la programación, verifica que todas las conexiones estén correctamente realizadas para evitar problemas durante las primeras pruebas del robot.
Programación del robot móvil con ESP32
Antes de programar la ESP32, asegúrate de tener instalado Arduino IDE en tu computadora. Puedes utilizar la versión clásica o Arduino IDE 2, ya que este proyecto es compatible con ambas.
También es indispensable instalar la placa ESP32 dentro de Arduino IDE. Para evitar problemas de compilación o incompatibilidades con el código, te recomiendo instalar exactamente la versión de la placa ESP32 que se muestra en mi tutorial, ya que es la versión utilizada durante el desarrollo de este proyecto.
Si todavía no has realizado estas instalaciones, te recomiendo revisar los siguientes tutoriales antes de continuar:
Una vez que tengas todo configurado, podrás copiar el siguiente programa y cargarlo en tu ESP32.
El siguiente código permite que el robot avance de forma autónoma mientras mide continuamente la distancia con el sensor ultrasónico. Cuando detecta un obstáculo a una distancia determinada, retrocede, gira y continúa su recorrido evitando la colisión.
El programa está completamente comentado para facilitar su comprensión y servir como base para futuros proyectos de robótica.
// ===================== CONEXIONES DE MOTORES =====================
// Motor A -> lado DERECHO del robot
int ENA = 14; // Pin de velocidad (PWM) del Motor A (derecho)
int IN1 = 27; // Pin de dirección 1 del Motor A (derecho)
int IN2 = 26; // Pin de dirección 2 del Motor A (derecho)
// Motor B -> lado IZQUIERDO del robot
int ENB = 32; // Pin de velocidad (PWM) del Motor B (izquierdo)
int IN3 = 25; // Pin de dirección 1 del Motor B (izquierdo)
int IN4 = 33; // Pin de dirección 2 del Motor B (izquierdo)
// ===================== SENSOR ULTRASÓNICO (HC-SR04) =====================
int PIN_TRIG = 19; // Pin que envía el pulso ultrasónico
int PIN_ECHO = 18; // Pin que recibe el eco
// ===================== CONFIGURACIÓN PWM (VELOCIDAD) =====================
const int freq = 10000; // Frecuencia PWM
const int pwmChannelA = 0; // Canal PWM para el motor A (derecho)
const int pwmChannelB = 1; // Canal PWM para el motor B (izquierdo)
const int resolution = 8; // Resolución de 8 bits (valores de 0 a 255)
// ===================== PARÁMETROS AJUSTABLES =====================
// Modifica estos valores para cambiar el comportamiento del robot
// sin tener que tocar el resto del código.
int velocidadAvance = 200; // Velocidad normal al avanzar (0-255)
int velocidadGiro = 180; // Velocidad al girar (0-255)
int distanciaMinimaCm = 20; // Distancia (cm) a la que se considera "obstáculo"
int tiempoRetroceso = 400; // Tiempo (ms) que retrocede al detectar obstáculo
int tiempoGiro = 500; // Tiempo (ms) que gira para esquivar el obstáculo
void setup() {
Serial.begin(115200); // Para ver la distancia medida en el Monitor Serial
// Pines de dirección de los motores como salida
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
// Pines del sensor ultrasónico
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
// Configurar PWM para el control de velocidad
ledcSetup(pwmChannelA, freq, resolution);
ledcAttachPin(ENA, pwmChannelA);
ledcSetup(pwmChannelB, freq, resolution);
ledcAttachPin(ENB, pwmChannelB);
detenerMotores(); // Estado inicial: motores apagados
}
void loop() {
long distancia = medirDistanciaCm();
Serial.print("Distancia: ");
Serial.print(distancia);
Serial.println(" cm");
if (distancia > 0 && distancia < distanciaMinimaCm) {
// Hay un obstáculo cerca: esquivarlo
detenerMotores();
delay(200);
moverAtras(velocidadAvance);
delay(tiempoRetroceso);
girarDerecha(velocidadGiro); // Puedes cambiar a girarIzquierda() si prefieres
delay(tiempoGiro);
detenerMotores();
} else {
// Camino libre: avanzar
moverAdelante(velocidadAvance);
}
}
// ===================== FUNCIONES DE MOVIMIENTO =====================
// Mueve el robot hacia adelante a la velocidad indicada (0-255)
void moverAdelante(int velocidad) {
// Motor A (derecho) hacia adelante
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
// Motor B (izquierdo) hacia adelante
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
establecerVelocidad(velocidad, velocidad);
}
// Mueve el robot hacia atrás a la velocidad indicada (0-255)
void moverAtras(int velocidad) {
// Motor A (derecho) hacia atrás
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
// Motor B (izquierdo) hacia atrás
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
establecerVelocidad(velocidad, velocidad);
}
// Gira el robot hacia la izquierda:
// el motor derecho (A) avanza y el izquierdo (B) retrocede
void girarIzquierda(int velocidad) {
digitalWrite(IN1, HIGH); // Motor A (derecho) adelante
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW); // Motor B (izquierdo) atrás
digitalWrite(IN4, HIGH);
establecerVelocidad(velocidad, velocidad);
}
// Gira el robot hacia la derecha:
// el motor izquierdo (B) avanza y el derecho (A) retrocede
void girarDerecha(int velocidad) {
digitalWrite(IN1, LOW); // Motor A (derecho) atrás
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH); // Motor B (izquierdo) adelante
digitalWrite(IN4, LOW);
establecerVelocidad(velocidad, velocidad);
}
// Detiene ambos motores por completo
void detenerMotores() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
establecerVelocidad(0, 0);
}
// Aplica la velocidad (PWM) a cada motor de forma independiente.
// Útil si en el futuro quieres que un motor vaya más rápido que el otro.
void establecerVelocidad(int velocidadA, int velocidadB) {
ledcWrite(pwmChannelA, velocidadA);
ledcWrite(pwmChannelB, velocidadB);
}
// ===================== FUNCIÓN DEL SENSOR =====================
// Mide la distancia al objeto más cercano en centímetros.
// Devuelve -1 si no se detecta ningún eco (fuera de rango).
long medirDistanciaCm() {
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
long duracion = pulseIn(PIN_ECHO, HIGH, 30000); // timeout de 30ms
if (duracion == 0) {
return -1; // No se detectó ningún objeto en rango
}
long distancia = duracion * 0.0343 / 2; // velocidad del sonido ≈ 0.0343 cm/us
return distancia;
}
Explicación del código
Aunque el programa está comentado, es importante comprender las partes principales de su funcionamiento. A continuación se describen las secciones más importantes del código.
Configuración de los pines
En la primera parte del programa se definen los pines utilizados por la ESP32 para controlar los motores y comunicarse con el sensor ultrasónico. También se configuran los canales PWM que permiten regular la velocidad de cada motor.
// Motor A -> lado DERECHO del robot
int ENA = 14; // Pin de velocidad (PWM) del Motor A (derecho)
int IN1 = 27; // Pin de dirección 1 del Motor A (derecho)
int IN2 = 26; // Pin de dirección 2 del Motor A (derecho)
// Motor B -> lado IZQUIERDO del robot
int ENB = 32; // Pin de velocidad (PWM) del Motor B (izquierdo)
int IN3 = 25; // Pin de dirección 1 del Motor B (izquierdo)
int IN4 = 33; // Pin de dirección 2 del Motor B (izquierdo)
// ===================== SENSOR ULTRASÓNICO (HC-SR04) =====================
int PIN_TRIG = 19; // Pin que envía el pulso ultrasónico
int PIN_ECHO = 18; // Pin que recibe el eco
// ===================== CONFIGURACIÓN PWM (VELOCIDAD) =====================
const int freq = 10000; // Frecuencia PWM
const int pwmChannelA = 0; // Canal PWM para el motor A (derecho)
const int pwmChannelB = 1; // Canal PWM para el motor B (izquierdo)
const int resolution = 8; // Resolución de 8 bits (valores de 0 a 255)
Parámetros ajustables
Una de las ventajas de este programa es que los parámetros principales se encuentran agrupados en una sola sección.
int velocidadAvance = 200; // Velocidad normal al avanzar (0-255)
int velocidadGiro = 180; // Velocidad al girar (0-255)
int distanciaMinimaCm = 20; // Distancia (cm) a la que se considera "obstáculo"
int tiempoRetroceso = 400; // Tiempo (ms) que retrocede al detectar obstáculo
int tiempoGiro = 500; // Tiempo (ms) que gira para esquivar el obstáculo
Desde aquí puedes modificar fácilmente:
- Velocidad de avance: controla la velocidad normal del robot.
- Velocidad de giro: ajusta la velocidad utilizada durante los giros.
- Distancia mínima: define a qué distancia el robot considera que existe un obstáculo.
- Tiempo de retroceso: determina cuánto tiempo retrocede antes de cambiar de dirección.
- Tiempo de giro: establece la duración del giro para evitar el obstáculo.
Gracias a esta organización, podrás modificar el comportamiento del robot sin necesidad de cambiar el resto del programa.
Función setup()
La función setup() se ejecuta una sola vez cuando la ESP32 se enciende.
Aquí se inicializa la comunicación serial, se configuran los pines de entrada y salida y se prepara el sistema PWM para controlar la velocidad de los motores.
void setup() {
Serial.begin(115200); // Para ver la distancia medida en el Monitor Serial
// Pines de dirección de los motores como salida
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
// Pines del sensor ultrasónico
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
// Configurar PWM para el control de velocidad
ledcSetup(pwmChannelA, freq, resolution);
ledcAttachPin(ENA, pwmChannelA);
ledcSetup(pwmChannelB, freq, resolution);
ledcAttachPin(ENB, pwmChannelB);
detenerMotores(); // Estado inicial: motores apagados
}
Función loop()
La función loop() es el corazón del programa.
Durante su ejecución, el robot mide constantemente la distancia utilizando el sensor ultrasónico.
long distancia = medirDistanciaCm();
Si detecta un obstáculo por debajo de la distancia configurada, ejecuta la siguiente secuencia:
- Detiene los motores.
- Retrocede durante unos milisegundos.
- Gira hacia la derecha.
- Continúa avanzando.
Si no detecta obstáculos, el robot simplemente sigue avanzando.
if (distancia > 0 && distancia < distanciaMinimaCm) {
// Hay un obstáculo cerca: esquivarlo
detenerMotores();
delay(200);
moverAtras(velocidadAvance);
delay(tiempoRetroceso);
girarDerecha(velocidadGiro); // Puedes cambiar a girarIzquierda() si prefieres
delay(tiempoGiro);
detenerMotores();
} else {
// Camino libre: avanzar
moverAdelante(velocidadAvance);
}
Funciones de movimiento
Para mantener el programa organizado, cada movimiento del robot se implementó mediante funciones independientes.
Entre ellas se encuentran:
- moverAdelante()
- moverAtras()
- girarIzquierda()
- girarDerecha()
- detenerMotores()
Esta estructura facilita futuras mejoras, como agregar nuevos comportamientos o modificar únicamente una función sin afectar el resto del código.
Función de medición de distancia
La función medirDistanciaCm() utiliza el sensor ultrasónico HC-SR04 para calcular la distancia hasta el objeto más cercano.
long medirDistanciaCm() {
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
long duracion = pulseIn(PIN_ECHO, HIGH, 30000); // timeout de 30ms
if (duracion == 0) {
return -1; // No se detectó ningún objeto en rango
}
long distancia = duracion * 0.0343 / 2; // velocidad del sonido ≈ 0.0343 cm/us
return distancia;
}
El sensor envía un pulso ultrasónico y mide el tiempo que tarda en regresar el eco. Con esta información, el programa calcula la distancia en centímetros y toma las decisiones necesarias para que el robot pueda navegar de manera autónoma evitando obstáculos.
Pruebas experimentales del robot móvil
Una vez realizadas las conexiones y cargado el programa en la ESP32, es momento de comprobar el funcionamiento del robot.
Si es la primera vez que programas una ESP32 y todavía no sabes cómo cargar un programa desde Arduino IDE, te recomiendo revisar el tutorial Cómo instalar ESP32 en Arduino IDE 2, donde aprenderás paso a paso cómo cargar tu primer programa en la tarjeta.
Una vez cargado el código, enciende el robot y colócalo sobre una superficie plana o una pista de pruebas.
En el siguiente video podrás observar el funcionamiento esperado del robot y utilizarlo como referencia para comprobar que tu proyecto se comporte de la misma manera.
En condiciones normales, el robot comenzará a avanzar mientras mide continuamente la distancia utilizando el sensor ultrasónico.
Cuando detecte un obstáculo a la distancia configurada en el programa, realizará automáticamente la siguiente secuencia:
- Se detendrá.
- Retrocederá durante unos instantes.
- Girará para evitar el obstáculo.
- Continuará avanzando hasta encontrar un nuevo obstáculo.
Es importante tener en cuenta que el robot puede no desplazarse completamente en línea recta. Esto es normal, ya que los motores reductores DC presentan pequeñas diferencias de fabricación y velocidad, incluso cuando ambos reciben el mismo voltaje y la misma señal PWM.
Solución de problemas
Si al encender el robot una de las ruedas gira en sentido contrario y el robot no avanza correctamente, simplemente intercambia los dos cables de ese motor en el driver de motores. Con este cambio, el sentido de giro quedará corregido.
Si el robot no detecta correctamente los obstáculos, verifica que el sensor ultrasónico esté conectado según el diagrama y que los pines definidos en el programa coincidan con las conexiones realizadas.
También es recomendable comprobar que las baterías tengan suficiente carga, ya que un nivel bajo de alimentación puede afectar el funcionamiento de los motores y del sensor.
¡Felicidades! Si tu robot ya navega de manera autónoma evitando obstáculos, significa que has construido con éxito tu primer robot móvil con ESP32. A partir de esta base podrás desarrollar proyectos más avanzados e incorporar nuevos sensores, actuadores y algoritmos para seguir aprendiendo robótica.
🧠 Aprende IA con Arduino
Explora nuestro eBook con proyectos guiados paso a paso para aprender inteligencia artificial con Arduino desde cero, en casa o en el aula.