Portero Para Penaltis
Grupo 15: Ana Seseña Ferrero, Verónica Ramírez Marín y Javier Castellanos Serrano
1. Introducción
Tras una búsqueda intensiva en las diferentes entradas del blog, y varias lluvias de ideas sopesando originalidad, coste, dificultad, factibilidad, etcétera, decidimos apostar por lo que finalmente ha sido nuestro proyecto: el Portero Para Penaltis. Al no ver ningún proyecto similar y, teniendo en cuenta todo lo anterior, aceptamos el que ha sido uno de los retos más satisfactorios, gratificantes, y no menos complejos, de la carrera. Nuestra afición por el fútbol, en conjunto con la tecnología, ha sido una de las mayores motivaciones a la hora de alcanzar este objetivo.
Objetivos
- Diseño atractivo para el cliente: Para lograr un diseño atractivo para el cliente, hemos dado importancia a la estética del proyecto. Hemos utilizado materiales resistentes y hemos diseñado una estructura atractiva y llamativa.
- Precisión en el bloqueo de penaltis: Hemos dedicado una parte significativa de nuestro desarrollo a garantizar la precisión en el bloqueo de penaltis. Hemos implementado un sistema de detección y respuesta que permite al portero moverse de manera rápida y precisa para bloquear los tiros de penalti. Además, hemos utilizado sensores de ultrasonidos y algoritmos de cierta complejidad para asegurar que el portero se mueve hacia la dirección correcta.
- Lo más realista posible, replicar elementos de un estadio real: Para recrear la atmósfera de un estadio real, hemos incluido elementos como redes de portería, postes de la portería y un área de penalti bien definida. Además, hemos integrado efectos de sonido (el himno del Real Madrid), para mejorar la experiencia del usuario y hacer que se sienta como si estuviera en el Santiago Bernabéu.
- Baja probabilidad de meter gol: Hemos trabajado arduamente para garantizar que nuestro portero tenga una baja probabilidad de permitir que el balón entre en la portería durante los tiros de penalti. Hemos optimizado nuestros algoritmos de detección y respuesta para que el portero pueda reaccionar rápidamente a la dirección y velocidad del balón, minimizando así las oportunidades de anotación para el equipo contrario.
- Facilidad de configuración y uso: Por último, pero no menos importante, hemos diseñado nuestro proyecto para que sea fácil de configurar y usar.
Materiales Utilizados
Vamos a dividir los materiales en 3 secciones: los que nos ha proporcionado la URJC, los que hemos comprado nosotros, y los materiales no tecnológicos que hemos empleado en decoración o estructura.
Materiales URJC
Material | Descripción |
Batería de 9V | |
Placa de Arduino | |
Cables macho-macho | |
Servomotor con el que movemos el banderín | |
Buzzer para el himno |
Materiales Adquiridos
Materiales | Descripción | Precio |
Cables macho-hembra | 8,10€ | |
Motor CC | 0,85€ | |
Sensores ultrasonidos | 10€ | |
Pantalla OLED | 6,99€ | |
Módulo de controlador de motor CC | 1,45€ | |
Pilas | 4,60€ |
Materiales Estructura
Materiales | Descripción | Precio |
Balón de futbolín | 0,71€ | |
Barra metálica | 2,07€ | |
Césped y Sprays | 5€ | |
Malla (red portería) | 0,99€ | |
Kit engranajes | 9,45€ | |
Piezas impresas 3D | 30€ |
Circuito Montado
Nuestro proyecto implica un sistema complejo que integra múltiples componentes electrónicos, incluidos sensores ultrasónicos, motores, un servo, una pantalla OLED y un zumbador, todos controlados por un Arduino. A continuación, describimos cómo estos componentes están conectados y cómo interactúan entre sí para el funcionamiento del sistema:
Sensores Ultrasónicos
Se utilizan tres sensores ultrasónicos HC-SR04 para detectar la distancia a objetos. Cada sensor tiene un pin de trigger (trig) y un pin de eco (echo):
Sensor 1: Pin de trigger en el pin digital 12 y pin de echo en el pin digital 11.
Sensor 2: Pin de trigger en el pin digital 7 y pin de echo en el pin digital 6.
Sensor 3: Pin de trigger en el pin digital 8 y pin de echo en el pin digital 10 (modificado para evitar conflictos).
Cada pin de trigger se configura como salida y cada pin de echo como entrada. Estos sensores son responsables de emitir y recibir ultrasonidos para calcular la distancia a los objetos, utilizando el tiempo que tardan los ecos en regresar.
Pantalla OLED
Se utiliza una pantalla OLED de Adafruit (modelo SSD1306, de 128×64 píxeles) para mostrar información visual como mensajes de bienvenida y el conteo de goles. La pantalla se conecta a través de I2C utilizando:
SDA (Serial Data Line): Conectada al pin SDA del Arduino.
SCL (Serial Clock Line): Conectada al pin SCL del Arduino.
La pantalla no utiliza un pin de reset físico en este caso, configurado con -1 en el código.
Motor y Control de Motor
El proyecto incluye un control de motor con dos direcciones, usando un puente H integrado en un chip controlador:
IN3 y IN4: Conectados a los pines digitales 4 y 3 del Arduino, respectivamente, para controlar la dirección del motor.
EN_B: Pin de control PWM conectado al pin 9 del Arduino para ajustar la velocidad del motor.
Servo Motor
Se utiliza un servo motor controlado por el pin digital 5 del Arduino, que manipula un banderín para indicar cuando se anota un gol.
Zumbador (Buzzer)
El zumbador está conectado al pin digital 2. Se utiliza para generar tonos musicales que representan diferentes eventos (inicio del juego, un gol, etc.). Se utilizan frecuencias específicas para diferentes notas musicales.
Conexión General y Alimentación
Arduino: Es el cerebro del proyecto, ejecutando el código y controlando la comunicación entre todos los componentes.
Alimentación: Todos los componentes son alimentados a través de la placa Arduino, la cual puede ser alimentada por USB o por una fuente de alimentación externa. Ha sido esencial verificar que la alimentación es suficiente y estable para todos los componentes.
Software y Configuración
El código en Arduino configura cada pin, inicializa la comunicación (como I2C para la pantalla y Serial para depuración), y ejecuta la lógica principal que monitorea los sensores y activa las acciones correspondientes. Utiliza funciones para medir la distancia, actualizar la pantalla, manejar el servo y reproducir melodías.
Esta configuración interconectada y coordinada permite que el proyecto funcione de manera sincronizada para detectar objetos, mostrar información, mover elementos mecánicos y generar sonidos, creando una experiencia interactiva basada en la entrada sensorial y la respuesta dinámica del sistema.
Diagrama de Flujo
Problemas y Soluciones
Problema | Solución |
La cremallera que pedimos por Internet era demasiado corta y tenía los dientes muy pequeños, al igual que su piñón correspondiente | Diseñamos el sistema piñón-cremallera con las medidas que nos interesaban y lo imprimimos con una impresora 3D |
El motor stepper que venía en la caja iba demasiado lento, por lo que el portero no iba a lograr parar ningún penalti | Compramos otro motor CC que giraba más rápido |
La pantalla que venía en la caja de componentes ocupaba muchos pines de la placa Arduino, lo que no nos permitía enchufar el resto de los componentes necesarios | Compramos otra pantalla más pequeña que ocupaba menos pines, para dejar así el resto libres para los demás componentes |
Habíamos preparado el sensor para determinar si era gol con una superficie plana, y al probarlo sobre el césped, la porosidad de éste interfería de alguna forma con el sensor y daba medidas erróneas | Usamos una cartulina sobre el trozo de la portería para evitar que el sensor detecte la porosidad del césped e implementamos dos trozos de plástico trasparente rectangulares para el resto del campo de fútbol |
Diseñamos la portería con unas medidas, las cuales establecimos en la maqueta de cartón, pero la portería impresa con la impresora 3D resultó finalmente con otras medidas | Adaptamos el código, restableciendo los tramos en los que debía moverse el portero con las nuevas medidas |
Pasos seguidos
- Planificación del proyecto y reparto de tareas: organización de las tareas a realizar y división de estas entre los distintos miembros del grupo
- Revisión de materiales y compra de lo necesario: revisamos los materiales disponibles en la caja que se nos proporcionó y buscamos información sobre estos, para asegurarnos de cuáles de estos podíamos usar y cuáles había que comprar, además de la compra de materiales decorativos o de uso en la estructura
- Aprender a usar los elementos hardware por separado y software necesario: una vez que teníamos claro que los materiales usados iban a ser un motor, servomotor, pantalla, sensores y buzzer, junto con la placa Arduino, aprendimos a usarlos y programarlos con la tarea que debían hacer en el proyecto, y probamos cada uno por separado
- Croquis de la disposición de los elementos y medidas: realizamos planos croquis con las medidas de la estructura del producto y de cada elemento de esta, como las piezas que deben ser impresas por la impresora 3D, así como organizar la distribución de estos. Ideamos el sistema piñón-cremallera para trasladar el movimiento del motor al portero para que este se pueda mover horizontalmente
- Diseño de piezas e impresión 3D: portero, portería y sistema piñón-cremallera
- Prueba de algunos elementos en conjuntos en la maqueta de cartón: aunque el movimiento del portero aún no se podía probar porque no estaba listo el sistema piñón-cremallera, en una maqueta de cartón fuimos probando el uso de sensores para detectar el gol
- Construcción de la estructura: una vez disponible el sistema de transmisión de movimiento del motor al portero, construimos la estructura en torno a esto, integrando poco a poco todos los elementos necesarios
- Integración del hardware en la estructura
- Unión de todos los elementos para que funcionen en conjunto: formación del circuito necesario entre todos los elementos hardware para lograr su correcto funcionamiento
- Software final necesario para el correcto funcionamiento: ajuste de cada código que teníamos por separado, adaptándolo para unirlo en un solo código que proporcione el correcto funcionamiento del proyecto.
Casos de Uso
Este proyecto de portero automático para penaltis ofrece varias aplicaciones prácticas y casos de uso en la vida real, extendiéndose más allá de su función original en contextos recreativos, educativos y profesionales. A continuación, describimos algunos de estos casos de uso:
- Entrenamiento Deportivo
El uso más directo de este sistema es como herramienta de entrenamiento para jugadores de fútbol. Puede ser usado para mejorar la precisión y potencia de los tiros al practicar penaltis contra un portero automatizado que se mueve y reacciona de manera predecible, ayudando a los jugadores a mejorar su técnica en situaciones de juego controladas. - Análisis y Mejora del Rendimiento
Incorporando sensores adicionales y capacidades de análisis de datos, el sistema podría usarse para recolectar datos detallados sobre el rendimiento de los jugadores durante las sesiones de entrenamiento, como la velocidad del balón, la precisión de tiro y las tendencias en los patrones de tiro. Esto puede ayudar a los entrenadores a personalizar los regímenes de entrenamiento y proporcionar retroalimentación específica a los jugadores. - Educación y Aprendizaje STEM
Este proyecto puede ser una excelente herramienta educativa en el ámbito de la ciencia, tecnología, ingeniería y matemáticas (STEM). Los estudiantes pueden aprender sobre conceptos de física (como sensores ultrasónicos, principios de movimiento y dinámica), electrónica (uso de Arduino y circuitos), y programación al construir y modificar el sistema. - Eventos y Actividades de Entretenimiento
En eventos deportivos, ferias, o parques temáticos, este portero automático puede ser utilizado como una atracción interactiva donde los participantes intentan anotar goles contra el portero robotizado. Esto no solo añade diversión y competencia sino que también puede ser utilizado para promociones o sorteos basados en la cantidad de goles anotados. - Herramientas de Rehabilitación Física
Modificado para ofrecer resistencia variable y movimientos más controlados, este sistema puede ser utilizado en terapias de rehabilitación física, ayudando a los pacientes a mejorar su coordinación motora y fuerza de piernas de una manera motivadora y lúdica. - Investigación en Robótica y Automatización
Este proyecto puede servir como una plataforma de base para proyectos de investigación más complejos en áreas como robótica autónoma y sistemas de control adaptativo, donde algoritmos más avanzados podrían desarrollarse para mejorar la capacidad del portero robot de predecir y reaccionar a los tiros dirigidos. - Desarrollo de Productos Comerciales
Con adecuadas modificaciones y mejoras en la durabilidad y funcionalidad, el concepto podría ser adaptado en un producto comercial destinado a escuelas de fútbol, clubes deportivos, o incluso para uso residencial en hogares con suficiente espacio, ofreciendo una forma interactiva y divertida de practicar fútbol. - Marketing y Promoción
Empresas relacionadas con el deporte podrían utilizar versiones personalizadas de este portero automático en campañas publicitarias o eventos promocionales, donde los participantes interactúan con el producto en desafíos de habilidad, aumentando la visibilidad de la marca y el compromiso del cliente. - Desarrollo de Habilidades Motoras en Niños
Como herramienta educativa, este sistema también podría ser usado para ayudar a los niños a desarrollar habilidades motoras y de coordinación, proporcionando un entorno seguro y controlado para practicar deportes y aprender sobre tecnología de manera práctica.
Cada uno de estos casos de uso destaca la versatilidad del proyecto, mostrando cómo una idea inicial puede ser expandida o adaptada para servir a una amplia gama de aplicaciones prácticas y comerciales.
Código
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Servo.h>
// Definición de pines para los sensores ultrasónicos
int trigPin = 12; // marrón
int echoPin = 11; // blanco
int trigPin2 = 7; // marrón
int echoPin2 = 6; // blanco
int trigPin3 = 8; // Sensor de la portería
int echoPin3 = 10; // Cambiado de 9 a 10 para evitar conflicto
// Variables para medir el tiempo de viaje de los pings
long pingTravelTime;
long pingTravelTime2;
long pingTravelTime3;
// Contador para los goles
int contador = 0;
// Definición de pines para el control del motor
#define IN3 4
#define IN4 3
#define EN_B 9 // Control PWM para el motor
// Variables para controlar el tiempo y manejo de intervalos
unsigned long previousTime = 0;
const long interval = 200; // Intervalo de 0.2 segundos para acciones regulares
// Inicialización pantalla
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Cambiado a -1 si no se usa pin de reset físico
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Inicialización del Servo
Servo servomecatronicos;
int servoPin = 5; // Pin donde está conectado el servo
// Configuración del pin del zumbador (buzzer)
#define BUZZER_PIN 2
// Notas musicales (frecuencias en Hz)
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_G5 784
#define NOTE_A5 880
#define NOTE_B5 988
#define NOTE_SILENCE 0 // Frecuencia 0 representa silencio
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(trigPin3, OUTPUT);
pinMode(echoPin3, INPUT);
Serial.begin(9600);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(EN_B, OUTPUT);
// Inicializa la pantalla
Wire.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.display();
delay(2000); // Pause for 2 seconds
// Mostrar pantalla de bienvenida
pantallaBienvenida();
delay(2000);
// Inicializa el servo
servomecatronicos.attach(servoPin);
servomecatronicos.write(0); // Comienza con el banderín abajo
// Himno
pinMode(BUZZER_PIN, OUTPUT);
playMelodyInicio();
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - previousTime >= interval) {
previousTime = currentTime;
// Mediciones de los sensores
pingTravelTime = medirDistancia(trigPin, echoPin);
pingTravelTime2 = medirDistancia(trigPin2, echoPin2);
pingTravelTime3 = medirDistancia(trigPin3, echoPin3);
Serial.print("Sensor 1: ");
Serial.print(pingTravelTime);
Serial.print(" - Sensor 2: ");
Serial.println(pingTravelTime2);
Serial.print(" - Sensor 3: ");
Serial.println(pingTravelTime3);
// Evaluar distancias y actuar
evaluarDistancias();
}
}
long medirDistancia(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
return pulseIn(echoPin, HIGH, 10000); // 10 milisegundos de timeout
}
void evaluarDistancias() {
if (pingTravelTime >= 1 && pingTravelTime <= 1739) {
tramoIzq();
}
if (pingTravelTime2 >= 1 && pingTravelTime2 <= 1537) {
tramoDer();
}
if (pingTravelTime3 <= 949 && pingTravelTime3 > 0 && pingTravelTime3 != 936) {
contador++;
Serial.println("¡Gol!");
pantallaMensajeGol();
contadorPorPantalla();
levantarBanderin();
delay(3000); // Mantener el banderín levantado por 5 segundos
servomecatronicos.write(0); // Bajar el banderín
playMelodyGol();
if (contador == 4) {
playMelodyFinal();
asm volatile (" jmp 0"); // Reinicia el programa
}
}
}
void tramoIzq() {
// Controla el movimiento a la izquierda
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
delay(500);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(1000);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
delay(500);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(1000);
}
void tramoDer() {
// Controla el movimiento a la derecha
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
delay(500);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(1000);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
delay(500);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(1000);
}
// Subprograma pantalla
void pantallaBienvenida() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 30);
display.print("¡¡Bienvenido!!");
display.display();
}
void pantallaMensajeGol() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 30);
display.print("¡¡Goool!!");
display.display();
delay(1000);
}
void contadorPorPantalla() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Contador:");
display.setTextSize(2);
display.setCursor(10, 30);
display.print(contador);
display.display();
}
void levantarBanderin() {
servomecatronicos.write(90); // Levantar el banderín
}
// Subprograma himno RM
void playMelodyInicio() {
playNote(NOTE_E4, 500); // MI negra
playNote(NOTE_A4, 1000); // LA blanca
playNote(NOTE_A4, 375); // LA corchea con punto
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_B4, 375); // SI corchea con punto
playNote(NOTE_A4, 125); // LA semicorchea
playNote(NOTE_A4, 1000); // LA blanca
playNote(NOTE_G4, 500); // SOL sostenido negra
playNote(NOTE_E4, 500); // MI negra
playNote(NOTE_F4, 1000); // FA blanca
playNote(NOTE_F4, 375); // FA corchea con punto
playNote(NOTE_G4, 125); // SOL semicorchea
playNote(NOTE_G4, 375); // SOL corchea con puntillo
playNote(NOTE_A4, 125); // LA semicorchea
playNote(NOTE_E4, 1000); // MI blanca
playNote(NOTE_SILENCE, 500); // Silencio de negra
}
void playMelodyGol() {
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_C5, 1000); // DO agudo blanca con puntillo
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_D5, 1000); // RE agudo blanca con puntillo
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_E5, 1000); // MI agudo blanca
playNote(NOTE_E5, 375); // MI agudo corchea con puntillo
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_C5, 375); // DO agudo corchea con puntillo
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_F5, 1000); // FA agudo blanca
playNote(NOTE_F5, 375); // FA agudo corchea con puntillo
playNote(NOTE_F5, 125); // FA agudo semicorchea
playNote(NOTE_E5, 375); // MI agudo corchea puntillo
playNote(NOTE_D5, 125); // RE agudo semicorchea
playNote(NOTE_C5, 1000); // DO agudo blanca
}
void playMelodyFinal() {
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_C5, 1000); // DO agudo blanca con puntillo
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_D5, 1000); // RE agudo blanca con puntillo
playNote(NOTE_G4, 500); // SOL negra
playNote(NOTE_E5, 1000); // MI agudo blanca
playNote(NOTE_E5, 375); // MI agudo corchea con puntillo
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_C5, 375); // DO agudo corchea con puntillo
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_F5, 1000); // FA agudo blanca
playNote(NOTE_F5, 375); // FA agudo corchea con puntillo
playNote(NOTE_F5, 125); // FA agudo semicorchea
playNote(NOTE_E5, 375); // MI agudo corchea puntillo
playNote(NOTE_D5, 125); // RE agudo semicorchea
// Nuevas notas agregadas
playNote(NOTE_C5, 1000); // DO agudo blanca
playNote(NOTE_C5, 375); // DO agudo corchea puntillo
playNote(NOTE_E5, 125); // MI agudo semicorchea
playNote(NOTE_D5, 375); // RE agudo corchea puntillo
playNote(NOTE_C5, 125); // DO agudo semicorchea
playNote(NOTE_D5, 1000); // RE agudo blanca
playNote(NOTE_D5, 375); // RE agudo corchea puntillo
playNote(NOTE_F5, 125); // FA agudo semicorchea
playNote(NOTE_E5, 375); // MI agudo corchea punitllo
playNote(NOTE_D5, 125); // RE agudo semicorchea
playNote(NOTE_C5, 1000); // DO agudo blanca puntillo
playNote(NOTE_SILENCE, 500); // Silencio de negra
}
void playNote(int note, int duration) {
tone(BUZZER_PIN, note, duration);
delay(duration);
noTone(BUZZER_PIN);
delay(10); // Pequeño retraso entre notas para separarlas
}