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.

01. Ingeniería de Precisión

Diseño Mecánico

Nuestra victoria se basó en una estrategia de diseño mecánico enfocada en tres pilares clave, resolviendo las limitaciones de espacio de la categoría de 10x10 cm.

Transmisión

Engranajes Cónicos

Sistema a medida con ángulo de ejes de 65 grados para máxima eficiencia espacial.

Relación

1.385:1 (18T/13T)

Optimizado para un aumento de torque del +38.5% en combate.

Dimensiones y Peso

10x10 cm | 495g

Límite reglamentario aprovechado al milímetro con chasis de PETG FDM.

Centro de Masa

Ultra Bajo

Motores inclinados para bajar el centro de gravedad y evitar vuelcos.

Pilares de Victoria

1. Potencia Optimizada

En lugar de una transmisión directa, diseñamos un sistema de engranajes a medida con una relación de 1.385:1. ¿El objetivo? Aumentar el torque en un 38.5%, dándonos una fuerza de empuje decisiva en cada enfrentamiento.

2. Disposición Inteligente de Motores

Desarrollamos una solución única: engranajes cónicos que operan en un ángulo de 65 grados. Esto nos permitió inclinar los motores, resolver una colisión de espacio imposible y optimizar el diseño interno del chasis de 10x10 cm.

3. Estabilidad Máxima

Esta disposición nos permitió colocar los componentes más pesados en el punto más bajo del chasis. El resultado es un centro de masa ultra bajo que hizo a nuestro robot increíblemente estable y resistente a ser volcado.

"Todo el chasis y la compleja transmisión fueron fabricados con precisión mediante impresión 3D, demostrando cómo la manufactura aditiva puede llevar a la victoria."

02. Documentación

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

Arduino Nano
Microcontrolador principal
x1
Motor DC jga25-310 6V
200 RPM
x2
Puente H tb6612fng
Control de motores
x2
Sensor Ultrasónico HC-SR04
Detección de oponente
x3
Sensor Infrarrojo QTR1A
Detección de línea
x3
Batería LiPo 3.7V
2200mAh
x2
Ver documentación completa
03. Documentación

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.

main.cpp

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.

motor_control.cpp
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.

sensors.cpp
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;
}
}

Características del Código