MOLUXO PINBALL
AUTORES: Vik Mlaurz Bernardo Bautista, Sergio Sen Recamal y David Rubio Rollano
Grupo 5
INTRODUCCIÓN
El objetivo de este proyecto de Arduino es construir un juego de pinball interactivo y controlado por microcontrolador. En lugar de utilizar un dispositivo tradicional, nuestro juego de pinball contará con una serie de sensores y actuadores que permitirán a los jugadores controlar la bola y marcar puntos.
El juego constará de un tablero de juego, que será diseñado y construido para que se asemeje a un tablero de pinball real, y estará equipado con sensores y actuadores para detectar y controlar el movimiento de la bola.
Para controlar el juego, utilizaremos un microcontrolador Arduino, que se encargará de recopilar datos de los sensores, controlar los actuadores y procesar la información del juego en tiempo real. Además, utilizaremos una pantalla LCD para mostrar información relevante del juego, como la puntuación y los objetivos.
REPARTO DE TAREAS
Comenzamos con un brainstorm o lluvia de ideas buscando un proyecto que nos gustase a todos y decidimos hacer el juego clásico conocido como “PINBALL”, y trabajamos en buscar las mejoras ideas y soluciones juntos, además creímos que era una opción muy completa ya que usamos varios componentes de Arduino.
El código nos lo repartimos equitativamente y lo realizamos por separado para luego posteriormente unirlo.
La parte física, nos hemos ido rotando en los puestos, ya sea de montaje de circuitería, de la estructura y de la realización de pruebas de cada componente previo a la unión.
MATERIALES
Estos son los materiales y los componentes que hemos usado para la realización de nuestro proyecto. Aquí podéis ver una tabla en la que se muestra el nombre y su precio. Comentar, que aquellos huecos en los que no se ha puesto el precio son materiales proporcionados por la Universidad URJC, o porque disponíamos de ellos en nuestras casas:
NOMBRE | PRECIO |
Arduino UNO | – |
Cables (Incluyendo cables adicionales) | 1,50 € |
Desplazador 74HC595 | – |
Servomotor 90 grados | 3 € |
Pantalla LCD | – |
Potenciómetro | – |
2 x Pulsadores | – |
Zumbador | – |
Motor de corriente continua 3-6V | 1,95 € |
4 x Sensores PIR | 10 € |
Extensores de cables | – |
Tablas de madera | 15 € |
Cartón | – |
Palos de madera | 1 € |
Pelotas pequeñas de poliespán | 1.20 € |
Recargas para pistola de silicona | 1.20 € |
Gomas elásticas | 1.90 € |
Bote de grafiti y pinturas | 5.10 € |
TOTAL | 41.75 € |
DISEÑO
En cuanto al diseño inicial tenemos una imagen que lo ilustra:
Como se puede ver en la imagen el diseño inicial consistía en la implementación de sensores, motor, botón, servomotor, además de un Display para el tiempo y otra para el marcador. Este fue el primer diseño que se nos ocurrió.
Y luego en base al diseño fuimos optimizando los distintos elementos, en vez de 2 Display optamos por usar una pantalla LCD, además de un botón de inicio de partida y otro para activar el motor.
IMPLEMENTACIÓN DEL HARDWARE
El hardware lo dividimos en la parte de la estructura y en la parte de la circuitería:
-En la parte de la estructura:
La estructura física del proyecto ha sido realizada en madera para una mayor dureza, formando una estructura rectangular y un panel de madera encima de la caja para poner los botones y el LCD, y otra tabla que colocaremos en una orientación diagonal que será donde realizaremos el juego. El resto de los elementos físicos han sido creados con cartón, siendo estos los obstáculos y elementos que conforman el juego. La estructura de las palancas ha sido realizada para el uso manual.
-En la parte de circuitería:
Para el montaje de la circuitería hemos usado varios componentes, incluyendo una Arduino Uno, dos placas protoboard, cables, resistencias, sensores PIR (son sensores de temperatura), un motor de 3-6 V, servomotor, altavoz, una LCD y dos botones.
-Estructura vista desde TinkerCad:
CÓDIGO REALIZADO EN ARDUINO
#include <LiquidCrystal.h>
#include <Servo.h>
//servo
Servo myservo;
int pos;
//desplazador
const int clock = 11; // Conectar el pin SRCLK del desplazador al pin digital 3 de Arduino
const int latch = 12; // Conectar el pin RCLK del desplazador al pin digital 4 de Arduino
const int data = 13; // Conectar el pin SER del desplazador al pin digital 5 de Arduino
//numero inicial para el desplazador
byte desp = 12;
//timer
unsigned long previousMillis = 0; // Almacenará el tiempo transcurrido en milisegundos
const long interval = 1000; // La cantidad de tiempo (en milisegundos) que tarda el temporizador en actualizarse
int timerValue = 180; // El tiempo inicial del temporizador (en segundos)
bool timerRunning = false; // Almacena si el temporizador está en marcha o no
//partida
bool jugando = false;
//Pines de los sensores infrarojos
int s1 = 14;
int s2 = 15;
int s3 = 16;
int s6 = 18;
//Sonido
int sp = 3;
int f1 = 220;
//Botones
const int buttonPin =19;
const int buttonPin1 = 17;
//Crear el objeto LCD con los números correspondientes (rs, en, d4, d5, d6, d7)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int puntos=0;
void setup() {
Serial.begin(9600);
//Inicializamos le servo
myservo.attach(10);
//inicializar el desplazador
pinMode(clock, OUTPUT);
pinMode(latch, OUTPUT);
pinMode(data, OUTPUT);
//inicializar los sensores
pinMode(s1,INPUT);
pinMode(s2,INPUT);
pinMode(s3,INPUT);
pinMode(s6,INPUT);
//Inicializar los botones
pinMode(buttonPin, INPUT);
pinMode(buttonPin1, INPUT);
// Inicializar el LCD con el número de columnas y filas del LCD
lcd.begin(16, 2);
lcd.command(0x0D);
// Escribimos el Mensaje en el LCD.
lcd.print("PULSA EL BOTON ");
lcd.setCursor(0,1);
lcd.print("PARA EMPEZAR");
}
void loop() {
if (digitalRead(buttonPin) == HIGH && not jugando) {
tone(sp,f1); // inicia el zumbido
delay(1000);
noTone(sp); //detiene el sonido
myservo.write(90); //se gira el servo para iniciar partida
puntos=0; //se inicializan / resetean los puntos
jugando = true; // booleano que nos indica que la partida ha iniciado
//escribimos en la lcd
lcd.setCursor(0,0);
lcd.print("POINTS: ");
lcd.setCursor(0,1);
lcd.print("TIEMPO: ");
lcd.setCursor(8,0);
lcd.print(puntos);
lcd.setCursor(8,0);
timerValue = 20; // valor del temporizador en segundos
timerRunning = true; // Inicia el temporizador
}
if (timerRunning) { // Si el temporizador está en marcha
// Obtiene el tiempo actual en segundos
timerValue--; // Resta 1 segundo al temporizador
lcd.setCursor(8, 1);
lcd.print(" "); // Borra el tiempo anterior
lcd.setCursor(8, 1);
lcd.print(timerValue/60); // Imprime los minutos restantes
lcd.print(":");
if ((timerValue%60) < 10) {
lcd.print("0"); // Agrega un cero delante si los segundos restantes son menores que 10
}
lcd.print(timerValue%60); // Imprime los segundos restantes
if (timerValue <= 0) { // Si el temporizador ha llegado a cero
lcd.clear(); // Limpia la pantalla
lcd.setCursor(0, 0);
lcd.print("Tiempo agotado!");
lcd.setCursor(0, 1);
lcd.print("PULSA PARA JUGAR");
timerRunning = false; // Detiene el temporizador
jugando = false;
//movimiento del servo para bloquear el paso
myservo.write(0);
//melodía
tone(sp, 392, 100); // Tono 1 (G)
delay(200);
tone(sp, 440, 200); // Tono 2 (A)
delay(200);
tone(sp, 494, 300); // Tono 3 (B)
delay(300);
tone(sp, 523, 400); // Tono 4 (C)
delay(400);
tone(sp, 494, 300); // Tono 3 (B)
delay(300);
tone(sp, 440, 200); // Tono 2 (A)
delay(200);
tone(sp, 392, 100); // Tono 1 (G)
delay(200);
noTone(sp); // Detiene la reproducción de tonos
}
delay(1000); //delay de 1 segundo
}
if (digitalRead(buttonPin1) == HIGH && jugando){
//acción del motor
bitSet(desp, 0);
actualizar();
delay(2000);
bitClear(desp, 0);
actualizar();
}
//Suma de puntos de los sensores PIR
if (digitalRead(s1) == HIGH && jugando) {
tone(sp, 659, 200); // Frecuencia de 659 Hz durante 200 milisegundos
delay(100); // Espera de 100 milisegundos entre tonos
noTone(sp);
// Segundo tono
tone(sp, 523, 200); // Frecuencia de 523 Hz durante 200 milisegundos
delay(100);
puntos = puntos+100;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(puntos);
delay(2000);
}
if (digitalRead(s2) == HIGH && jugando) {
tone(sp, 659, 200); // Frecuencia de 659 Hz durante 200 milisegundos
delay(100); // Espera de 100 milisegundos entre tonos
noTone(sp);
// Segundo tono
tone(sp, 523, 200); // Frecuencia de 523 Hz durante 200 milisegundos
delay(100);
puntos = puntos+100;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(puntos);
delay(2000);
}
if (digitalRead(s3) == HIGH && jugando) {
tone(sp, 659, 200); // Frecuencia de 659 Hz durante 200 milisegundos
delay(100); // Espera de 100 milisegundos entre tonos
noTone(sp);
// Segundo tono
tone(sp, 523, 200); // Frecuencia de 523 Hz durante 200 milisegundos
delay(100);
puntos = puntos+100;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(puntos);
delay(2000);
}
if (digitalRead(s6) == HIGH && jugando) {
tone(sp, 659, 200); // Frecuencia de 659 Hz durante 200 milisegundos
delay(100); // Espera de 100 milisegundos entre tonos
noTone(sp);
// Segundo tono
tone(sp, 523, 200); // Frecuencia de 523 Hz durante 200 milisegundos
delay(100);
puntos = puntos+100;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(puntos);
delay(2000);
}
}
//método para que se transmita la señal por el desplazador
void actualizar()
{
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, desp);
digitalWrite(latch, HIGH);
}
FUNCIONAMIENTO
En cuanto al funcionamiento vamos a ver que todo el programa empieza a funcionar en base a la activación de un boolean, que será activado por un pulsador. Este pulsador hará que el boolean se active y que todos los demás casos de uso puedan funcionar.
Tras activar la partida, se inicia un TIMER, Arduino no permite la implementación de muchos hilos, por lo que los segundos del contador se pueden alargar dependiendo de las funciones del bucle.
En cuanto el pulsador inicial sea pulsado, el servomotor que bloquea el movimiento de la pelota se moverá habilitando el movimiento de la pelota hacia la zona de propulsión donde estará el motor. En cuanto el TIMER llegue a 0, el servomotor se cerrará volviendo a su posición inicial.
La siguiente función que ocurre tras la activación es la propulsión de la pelota que se activará con un segundo pulsador. Este pulsador, activará el motor de 3-6v por 2 segundos y empezará a girar con una rueda, que impulsará la bola de poliespán.
El sistema de puntuación se basa en la suma de puntos cuando los sensores detectan el movimiento de la bola. Al detectar el movimiento se sumarán puntos al contador dentro del LCD.
También hemos implementado 3 sonidos al proyecto, el primero sonará en cuanto empiece la partida, el segundo, cuando acabe y el tercero irá sonando cuando se sumen puntos.
En cuanto el contador llegue a 0, se nos avisará mediante la pantalla LCD que se ha acabado la partida y que si queremos empezar otra partida pulsemos de nuevo el primer pulsador.
Además, cuando el contador acabe, todos los casos de uso mencionados anteriormente se bloquearán hasta que se inicie una nueva partida.
PROBLEMAS Y SOLUCIONES
1. Impulso de la pelota:
Dado que nosotros queríamos usar bastantes componentes de Arduino, nos pareció buena idea hacer que la pelota fuera impulsada por un motor. Así que investigando decidimos comprar un motor de corriente continua el cual disponía de suficiente fuerza para lanzar una pelota.
Para impulsar la bola con el motor pusimos una rueda, pero no llegaba a funcionar bien del todo. Así que tomamos una pequeña hélice de un juguete que teníamos y la pusimos.
Pero al hacer pruebas nos dimos cuenta de que no nos servían pelotas ligeras de plástico, ya que no se impulsaban los suficiente. Por lo que decidimos comprar unas pequeñas pelotas de poliespán.
2. Unión de los códigos y componentes:
Al inicio pensábamos implementar un sensor de ultrasonidos para que cuando detecte algo se active el motor y un display de 4 dígitos para colocar el tiempo restante de la partida. Sin embargo, al combinar estos componentes y los demás, nos dimos cuenta de que nos haría falta bastantes pines, por lo que debíamos sustituir las funcionalidades de dichos componentes. El contador de tiempo ahora se mostraría en la pantalla LCD en la segunda fila y el sensor de infrarrojos se sustituiría por un botón manual para impulsar el motor.
3. Añadir Pila para que funcionase todo el circuito:
Cuando hicimos el circuito final, el voltaje de la placa Arduino fue insuficiente para dar energía a todos los componentes. Principalmente a la placa LCD y e Motor a la vez, ya que cada vez que ambos funcionaban al mismo tiempo, o el motor no arrancaba o la pantalla se oscurecía. Por tanto, se nos ocurrió añadir una pile de 4.5V para que alimente el desplazador y el motor. Al poner la pila, el circuito funcionó correctamente.
4. Diseño de la LCD:
La pantalla LCD tiene agujeros los cuales teníamos que colocar sus respectivos cables, al inicio se colocaron los cables al LCD y funcionó correctamente. El problema surgió cuando intentamos manipular la LCD para colocarla encima del pinball, debido a que ciertos cables hacían contacto entre ellos que causaban que la pantalla no funcionase adecuadamente la pantalla e incluso Arduino. Para solucionarlo volvimos a colocar los cables de una nueva forma y tuvimos cuidado para que no se produjese contacto entre ellos.
5. Creación del circuito físico:
A la hora de realizar el circuito físico nos surgieron diferentes problemas. Principalmente lo que mas quebraderos de cabeza nos dio fue hacer bien las uniones de los distintos componentes. Además, varias veces se nos solían soltar los cables, por lo que decidimos de utilizar alargadores ya que estos también nos permitían mejorar las conexiones entre cables dado que de vez en cuando no uníamos del todo bien unos cables con otros.
Otro problema fue el siguiente. Al principio nos confundimos al crear el circuito que iba dedicado al motor, por eso no nos funcionaba. Así que vimos otra manera de implementarlo y conseguimos que funcionase correctamente.
Pero no solo eso nos ocurrió en cuanto al motor, sino que, al realizar pruebas con él se nos desoldó un cable e intentamos pegarlo con silicona. Esto resultó no dar muy buen efecto puesto que la conexión a veces fallaba. Por lo que al no tener una soldadora, a última hora decidimos comprar un nuevo motor.
6. Sensores PIR
Este problema fue detectado casi al final del desarrollo de la práctica. Dado que nosotros para hacer pruebas para ver si funcionaban o no, pasábamos una pelota por delante del sensor con la ayuda de nuestra mano y veíamos que el sensor la detectaba.
Pero al realizar sucesivas pruebas, varias veces los sensores no detectaban la pelota de poliespán, lo cual nos intrigaba bastante.
Al final conseguimos ver cual era el error. Se trataba de que el problema era el funcionamiento que nos ofrecía este tipo de sensor. Resulta que solo detectaba presencia humana y cambios de temperatura en el entorno. Pero en un principio, nosotros vimos que estos sensores, además, podían medir la luz infrarroja de los objetos en su campo de visión.
Así que para que funcionase perfectamente y si ningún error vimos que la mejor solución podría ser usar sensores IR, los cuales sirven detectar y medir la distancia cuando un objeto pasa a través de él.
CONCLUSIONES Y MEJORAS A FUTURO
En conclusión, tras hacer esta práctica hemos llegado a la conclusión que para realizar un proyecto de este estilo hace falta mucha paciencia, tanto en la parte de software, pero principalmente en la de hardware que es donde realmente surgen problemas de conexiones o problemas físicos.
Cabe destacar que este proyecto se ha realizado de forma exitosa en base al trabajo en equipo coordinado que hemos tenido. Si alguno de nosotros no se hubiese implicado al mismo nivel que el otro hubiese sido un camino más difícil.
Además, hemos acabado pensado que cualquiera que sepa un mínimo de programación, y tenga ganas y creatividad. Puede completar un proyecto Arduino de este estilo.
La importancia del montaje es esencial. Aunque en simuladores como Tinkercad el código te ejecute correctamente, el montaje en la vida real es la prueba de fuego para ver que todos los componentes funcionen y que todos los contactos sean los correctos y que en resumen, te funciones todo bien.
Unas posibles mejoras al proyecto podrían ser:
Añadir un sistema que te compare dos partidas para que jueguen dos jugadores. Que en una partida jugué un jugador y en otra que juegue otro y que al final de ambas partidas, decida un vencedor.
Otra mejora al proyecto podría ser añadir leds para que sea más visual y que vayan cambiando de color en cuanto se sumen puntos o que cuando inicie o termine partida.