Robot de Sumo Zumo: Diseño, Tecnología y Funcionamiento
Robot Sumo EQMEE
Diseñado desde cero integrando modelado 3D, piezas impresas en 3D, electrónica digital con Arduino y programación en C/C++ enfocada en control y respuesta rápida para competencia minisumo.
Electrónica y Control
Sistema de control basado en microcontrolador con sensores de línea y proximidad para detección y estrategia autónoma.
Lista de Componentes
Programación y Lógica
Algoritmos de control autónomo con estrategias adaptativas y respuesta en tiempo real.
Estrategia de Ataque
El robot implementa un sistema de búsqueda en espiral y ataque directo cuando detecta al oponente.
void estrategia() {
// --- PRIORIDAD 1: ZONA DE ATAQUE ---
if (distanciaFrente < distanciaAtaque) {
Serial.println("Oponente en zona de ataque. ¡EMPUJAR!");
ultimaDireccionVista = FRENTE;
adelante(velocidadAtaque);
// Cuando atacamos de frente, no necesitamos actualizar la memoria de búsqueda.
}
// --- PRIORIDAD 2: ZONA DE DETECCIÓN ---
else if (distanciaFrente < distanciaDeteccion) {
Serial.println("Oponente al frente. Aproximando...");
ultimaDireccionVista = FRENTE;
adelante(velocidadBusqueda);
}
else if (distanciaIzquierda < distanciaDerecha && distanciaIzquierda < distanciaDeteccion) {
Serial.println("Oponente detectado a la IZQUIERDA. Girando...");
ultimaDireccionVista = IZQUIERDA; // ¡Guardamos que lo vimos a la izquierda!
girarIzquierda(velocidadBusqueda);
}
else if (distanciaDerecha < distanciaIzquierda && distanciaDerecha < distanciaDeteccion) {
Serial.println("Oponente detectado a la DERECHA. Girando...");
ultimaDireccionVista = DERECHA; // ¡Guardamos que lo vimos a la derecha!
girarDerecha(velocidadBusqueda);
}
// --- PRIORIDAD 3: ESTRATEGIA DE BÚSQUEDA CON MEMORIA ---
else {
// Si no vemos a nadie, usamos nuestra memoria.
Serial.print("Oponente perdido. Buscando en la última dirección vista: ");
if (ultimaDireccionVista == DERECHA) {
Serial.println("DERECHA");
girarDerecha(velocidadBusqueda); // Seguir girando a la derecha.
}
else if (ultimaDireccionVista == IZQUIERDA) {
Serial.println("IZQUIERDA");
girarIzquierda(velocidadBusqueda); // Seguir girando a la izquierda.
}
else {
// Esto solo ocurre al principio del combate (ultimaDireccionVista == NINGUNA)
Serial.println("INICIANDO BÚSQUEDA (por defecto a la derecha)");
if(direccionGiroBusqueda == DERECHA) {
girarDerecha(velocidadBusqueda);
} else {
girarIzquierda(velocidadBusqueda);
}
}
}
}
Control de Motores (PWM)
Sistema de control con modulación por ancho de pulso para velocidad variable y maniobras precisas.
void adelante(int velocidad) {
digitalWrite(MOTOR_IZQ_IN1_PIN, HIGH);
digitalWrite(MOTOR_IZQ_IN2_PIN, LOW);
analogWrite(MOTOR_IZQ_PWM_PIN, velocidad);
digitalWrite(MOTOR_DER_IN1_PIN, HIGH);
digitalWrite(MOTOR_DER_IN2_PIN, LOW);
analogWrite(MOTOR_DER_PWM_PIN, velocidad);
}
void atras(int velocidad) {
digitalWrite(MOTOR_IZQ_IN1_PIN, LOW);
digitalWrite(MOTOR_IZQ_IN2_PIN, HIGH);
analogWrite(MOTOR_IZQ_PWM_PIN, velocidad);
digitalWrite(MOTOR_DER_IN1_PIN, LOW);
digitalWrite(MOTOR_DER_IN2_PIN, HIGH);
analogWrite(MOTOR_DER_PWM_PIN, velocidad);
}
void girarDerecha(int velocidad) {
digitalWrite(MOTOR_IZQ_IN1_PIN, LOW); // Motor Izquierdo: Atrás
digitalWrite(MOTOR_IZQ_IN2_PIN, HIGH);
analogWrite(MOTOR_IZQ_PWM_PIN, velocidad);
digitalWrite(MOTOR_DER_IN1_PIN, HIGH); // Motor Derecho: Adelante
digitalWrite(MOTOR_DER_IN2_PIN, LOW);
analogWrite(MOTOR_DER_PWM_PIN, velocidad);
}
void girarIzquierda(int velocidad) {
digitalWrite(MOTOR_IZQ_IN1_PIN, HIGH); // Motor Izquierdo: Adelante
digitalWrite(MOTOR_IZQ_IN2_PIN, LOW);
analogWrite(MOTOR_IZQ_PWM_PIN, velocidad);
digitalWrite(MOTOR_DER_IN1_PIN, LOW); // Motor Derecho: Atrás
digitalWrite(MOTOR_DER_IN2_PIN, HIGH);
analogWrite(MOTOR_DER_PWM_PIN, velocidad);
}
void parar() {
analogWrite(MOTOR_IZQ_PWM_PIN, 0);
analogWrite(MOTOR_DER_PWM_PIN, 0);
} Detección de Línea
Los sensores infrarrojos detectan el borde del ring y activan maniobras evasivas para evitar salir del área de combate.
void estrategiaLinea() {
static unsigned long inicioManiobra = 0;
static bool enManiobra = false;
// Iniciar maniobra solo la primera vez que se detecta línea
if (!enManiobra) {
enManiobra = true;
inicioManiobra = millis();
}
unsigned long tiempo = millis() - inicioManiobra;
// --- Limitar duración total de maniobra (1.6 segundos) ---
if (tiempo > 1600) {
parar();
girando = false;
enManiobra = false;
ultimaLineaNegraVista = NINGUNA;
return;
}
// --- CASO 1: línea trasera detectada ---
if (ultimaLineaNegraVista == TRASERO) {
Serial.println("Adentro");
if (tiempo < 1500) {
// 600–1500 ms → avanza fuerte para volver al centro
adelante(255);
} else {
parar();
enManiobra = false;
girando = false;
ultimaLineaNegraVista = NINGUNA;
}
}
// --- CASO 2: línea al frente derecha ---
else if (ultimaLineaNegraVista == FRENTE_DERECHA) {
atras(255);
direccionGiroBusqueda = IZQUIERDA;
if (tiempo > 800) {
parar();
enManiobra = false;
girando = false;
ultimaLineaNegraVista = NINGUNA;
}
}
// --- CASO 3: línea al frente izquierda o ambos sensores frontales ---
else if (ultimaLineaNegraVista == FRENTE_IZQUIERDA || ultimaLineaNegraVista == FRENTE_COMPLETO) {
atras(255);
direccionGiroBusqueda = DERECHA;
if (tiempo > 800) {
parar();
enManiobra = false;
girando = false;
ultimaLineaNegraVista = NINGUNA;
}
}
// --- CASO 4: sin línea detectada ---
else {
enManiobra = false;
girando = false;
}
}