Proyecto: Mini Robot Móvil Controlado por ESP32
Este proyecto integra todos los conocimientos del módulo 6 para crear un robot móvil completo con múltiples actuadores y sensores, controlado remotamente vía WiFi y Bluetooth.
1. Arquitectura del Sistema
Chasis Móvil
Tracción diferencial con encoders
Brazo Manipulador
3 servomotores para pick & place
Sistema Sensorial
Cámara, ultrasónico, IMU
2. Implementación Completa
Robot Control System
#include
#include
#include
#include "BluetoothSerial.h"
// Configuración WiFi
const char* ssid = "TU_RED_WIFI";
const char* password = "TU_PASSWORD";
WebServer server(80);
BluetoothSerial SerialBT;
// Motores DC (L298N)
#define MOTOR_L_PWM 14
#define MOTOR_L_IN1 27
#define MOTOR_L_IN2 26
#define MOTOR_R_PWM 12
#define MOTOR_R_IN1 25
#define MOTOR_R_IN2 33
// Servomotores del brazo
Servo servoBase, servoHombro, servoCodo, servoGripper;
#define SERVO_BASE 18
#define SERVO_HOMBRO 19
#define SERVO_CODO 21
#define SERVO_GRIPPER 22
// Sensores
#define TRIGGER_PIN 5
#define ECHO_PIN 17
#define MPU_SDA 21
#define MPU_SCL 22
struct RobotState {
int velocidadL = 0, velocidadR = 0;
int anguloBase = 90, anguloHombro = 90;
int anguloCodo = 90, anguloGripper = 90;
float distancia = 0;
bool autonomous = false;
} robot;
void setup() {
Serial.begin(115200);
// Inicializar motores
setupMotors();
// Inicializar servos
setupServos();
// Inicializar sensores
setupSensors();
// Inicializar conectividad
setupWiFi();
setupBluetooth();
setupWebServer();
Serial.println("🤖 Robot inicializado correctamente");
}
void setupMotors() {
pinMode(MOTOR_L_PWM, OUTPUT);
pinMode(MOTOR_L_IN1, OUTPUT);
pinMode(MOTOR_L_IN2, OUTPUT);
pinMode(MOTOR_R_PWM, OUTPUT);
pinMode(MOTOR_R_IN1, OUTPUT);
pinMode(MOTOR_R_IN2, OUTPUT);
// Configurar PWM
ledcSetup(0, 1000, 8);
ledcSetup(1, 1000, 8);
ledcAttachPin(MOTOR_L_PWM, 0);
ledcAttachPin(MOTOR_R_PWM, 1);
}
void setupServos() {
servoBase.attach(SERVO_BASE);
servoHombro.attach(SERVO_HOMBRO);
servoCodo.attach(SERVO_CODO);
servoGripper.attach(SERVO_GRIPPER);
// Posición inicial
servoBase.write(robot.anguloBase);
servoHombro.write(robot.anguloHombro);
servoCodo.write(robot.anguloCodo);
servoGripper.write(robot.anguloGripper);
}
void setupSensors() {
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void setupWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Conectando a WiFi...");
}
Serial.printf("WiFi conectado. IP: %s\n", WiFi.localIP().toString().c_str());
}
void setupBluetooth() {
SerialBT.begin("ESP32_Robot");
Serial.println("Bluetooth iniciado como 'ESP32_Robot'");
}
void setupWebServer() {
server.on("/", handleRoot);
server.on("/move", handleMove);
server.on("/arm", handleArm);
server.on("/status", handleStatus);
server.begin();
}
void controlMotor(int motor, int velocidad, bool direccion) {
int pwmPin = (motor == 0) ? 0 : 1; // Canal PWM
int in1 = (motor == 0) ? MOTOR_L_IN1 : MOTOR_R_IN1;
int in2 = (motor == 0) ? MOTOR_L_IN2 : MOTOR_R_IN2;
digitalWrite(in1, direccion ? HIGH : LOW);
digitalWrite(in2, direccion ? LOW : HIGH);
ledcWrite(pwmPin, abs(velocidad));
}
void moverRobot(int velIzq, int velDer) {
robot.velocidadL = velIzq;
robot.velocidadR = velDer;
controlMotor(0, velIzq, velIzq >= 0);
controlMotor(1, velDer, velDer >= 0);
}
float leerDistancia() {
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
long duracion = pulseIn(ECHO_PIN, HIGH);
float distancia = (duracion * 0.034) / 2;
return distancia;
}
void moverBrazo(int base, int hombro, int codo, int gripper) {
if (base >= 0 && base <= 180) {
robot.anguloBase = base;
servoBase.write(base);
}
if (hombro >= 0 && hombro <= 180) {
robot.anguloHombro = hombro;
servoHombro.write(hombro);
}
if (codo >= 0 && codo <= 180) {
robot.anguloCodo = codo;
servoCodo.write(codo);
}
if (gripper >= 0 && gripper <= 180) {
robot.anguloGripper = gripper;
servoGripper.write(gripper);
}
}
void loop() {
server.handleClient();
// Leer sensores
robot.distancia = leerDistancia();
// Procesar comandos Bluetooth
if (SerialBT.available()) {
String comando = SerialBT.readString();
procesarComando(comando);
}
// Modo autónomo simple
if (robot.autonomous) {
navegacionAutonoma();
}
delay(50);
}
void procesarComando(String cmd) {
cmd.trim();
if (cmd.startsWith("MOVE")) {
// MOVE:velocidadIzq,velocidadDer
int idx = cmd.indexOf(':');
if (idx > 0) {
String params = cmd.substring(idx + 1);
int comma = params.indexOf(',');
if (comma > 0) {
int velL = params.substring(0, comma).toInt();
int velR = params.substring(comma + 1).toInt();
moverRobot(velL, velR);
}
}
}
else if (cmd.startsWith("ARM")) {
// ARM:base,hombro,codo,gripper
int idx = cmd.indexOf(':');
if (idx > 0) {
String params = cmd.substring(idx + 1);
// Parsear 4 ángulos separados por comas
// (implementación completa requiere parsing más robusto)
}
}
else if (cmd == "AUTO") {
robot.autonomous = !robot.autonomous;
SerialBT.printf("Modo autónomo: %s\n", robot.autonomous ? "ON" : "OFF");
}
}
void navegacionAutonoma() {
if (robot.distancia < 20) {
// Obstáculo detectado - girar
moverRobot(-150, 150); // Girar a la derecha
delay(500);
} else {
// Avanzar
moverRobot(150, 150);
}
}
// Handlers del servidor web
void handleRoot() {
String html = R"(
Control Robot ESP32
🤖 Control de Robot
)";
server.send(200, "text/html", html);
}
void handleMove() {
int velL = server.arg("l").toInt();
int velR = server.arg("r").toInt();
moverRobot(velL, velR);
server.send(200, "text/plain", "OK");
}
void handleArm() {
// Implementar control del brazo vía web
server.send(200, "text/plain", "Arm control");
}
void handleStatus() {
String json = "{\"distance\":" + String(robot.distancia) +
",\"motorL\":" + String(robot.velocidadL) +
",\"motorR\":" + String(robot.velocidadR) + "}";
server.send(200, "application/json", json);
}
3. Características Implementadas
🚗 Sistema de Locomoción
- Tracción diferencial con L298N
- Control de velocidad independiente
- Movimientos: adelante, atrás, giros, pivoteo
- Encoders para odometría (opcional)
🦾 Brazo Manipulador
- 4 grados de libertad
- Control preciso de posición
- Secuencias predefinidas
- Operación pick & place
📡 Conectividad
- Control vía WiFi (servidor web)
- Control vía Bluetooth
- API RESTful para integración
- Interfaz web responsive
🧠 Inteligencia
- Navegación autónoma básica
- Evitación de obstáculos
- Telemetría en tiempo real
- Logging de operaciones
4. Expansiones y Mejoras
🔮 Funcionalidades Avanzadas
Sensores Adicionales:
- Cámara ESP32-CAM para visión artificial
- Sensor de color para clasificación
- Encoder rotatorio para odometría precisa
- GPS para navegación outdoor
Algoritmos Inteligentes:
- SLAM (Simultaneous Localization and Mapping)
- Path planning con A*
- Reconocimiento de objetos
- Control PID para estabilización