Proyecto Diseño de Sistemas Empotrados: Repartidor de cartas

Introducción

Nuestro proyecto consiste en la elaboración de un dispensador de cartas, el cual se trata de un mecanismo que va a repartir un número concreto de cartas ha distintas posiciones de la mesa, dicha disposición de las cartas repartidas dependerá del número de jugadores elegido previamente. Dicho dispositivo va a permitir que mediante un display se elija un número de jugadores concretos y se inicie la repartición de cartas, de tal manera que la base donde se sitúan las cartas comenzará a rotar y expulsar cartas mediante la activación de diferentes motores.

Este proyecto ha sido realizado por el grupo 3 durante el desarrollo de la asignatura Diseño de Sistemas Empotrados del grado en Ingeniería de Computadores, realizado por los alumnos:

Eric Mellado Acevedo e.mellado2019@alumnos.urjc.es

Javier de la Torre Morales j.delatorre.2019@alumnos.urjc.es

Alex Palomo Barrado a.palomo.2019@alumnos.urjc.es

Andrés Tena De Tena a.tena.2016@alumnos.urjc.es

En el presente blog se pasará a explicar las diferentes fases del desarrollo del proyecto, hablando del diseño e implementación del mismo, el presupuesto invertido en él, problemas enfrentados durante su desarrollo, diferentes materiales utilizados, es decir el hardware del dispositivo, el código desarrollado para su funcionamiento, así como una serie de vídeos e imágenes en los cuales se muestra el resultado final del proyecto y sus diferentes casos de uso.

Diseño e implementación

Durante los primeros días de clase, se comenzó a pensar en una idea sobre el proyecto que se iba a realizar. Nos pareció que un dispensador de cartas podría ser algo muy útil e interesante de desarrollar, además de que se adecua bastante bien a los materiales que la universidad nos proporciona. La mayoría del proyecto se ha ido desarrollando durante las horas de clase, aunque se han debido emplear horas extra fuera de ella para realizar tareas como el corte de materiales.

Lo primero que se realizó fueron una serie de planos que mostraban como iba a estar organizado el dispositivo, así como la cantidad de materiales, motores que íbamos a necesitar y su disposición, para ello todos los participantes del grupo planteamos distintos prototipos de baja fidelidad e ideas de diseño, de esta manera se fue mejorando el diseño poco a poco, eligiendo las mejores opciones de diseño aportadas mediante una puesta en común del grupo obteniendo así el prototipo de baja fidelidad definitivo (ver Figura 1).

Figura 1: Prototipo de baja fidelidad.

Como se puede observar en 1, se obtuvieron las decisiones de diseño relativas al hardware del sistema, dado que se muestran los materiales empleados, así como las dimensiones de las superficies empleadas en el proyecto.

Después de las primeras sesiones de organización y enfoque para obtener la solución del problema, se pasó a realizar una búsqueda de los diferentes materiales que se iban a necesitar comprar, ya que el kit proporcionado no disponía de dichos elementos. Además de estimar un presupuesto base que todos los integrantes del grupo estaban dispuestos a pagar.

Una vez obtenidos todos los materiales necesarios para el desarrollo del proyecto, se decidió repartir las tareas entre los diferentes integrantes del grupo dividiendo el proyecto en hardware y software. De tal manera que Alex y Javier se enfocaron en la parte hardware, mientras que Eric y Andrés en la parte software.

Posteriormente se dedicaron una serie de días para realizar el corte de materiales y la construcción de la base que iba a sostener nuestro dispositivo. Una vez organizada la base que iba a sostener todo, así como el diseño de engranajes y su disposición, se pasó a diseñar e implementar el cableado necesario para el funcionamiento del repartidor como se puede observar en la figura 2, tenemos el montaje de la caja según el planteamiento inicial.

Figura 2: Soporte de madera.

Mientras que en 3 se muestra en tinkercad el esquema del circuito implementado en el repartidor, donde se puede observar todas las conexiones de los diferentes motores a los pines del Arduino, así como las resistencias, diodos, cables y transistores utilizados, además del lcd.

Figura 3: Circuito diseñado en tinkercad.

Presupuesto

Se ha decidido dividir el presupuesto en dos, componentes electrónicos y componentes no electrónicos. A continuación se muestran varias tablas con los materiales que se han empleado para la consecución del proyecto, en ella se especifica: el nombre del producto, la cantidad de productos que se han comprado, el precio de cada uno de ellos si es que lo tiene, ya que se han empleado múltiples componentes que ha proporcionado la universidad. Así como la suma total de dinero que se ha tenido que invertir para realizar dicho proyecto.

En la Tabla 1, se muestra los componentes electrónicos empleados, la mayoría de ellos han sido obtenidos a partir del kit de arduino que nos ha proporcionado la universidad, por tanto no ha supuesto una gran suma de dinero.

Por otra parte, todos los componentes no electrónicos necesarios para la consecución del proyecto han tenido que ser comprados, es por ello que aquí se ha invertido la mayor parte del presupuesto (ver Tabla 2).

CantidadProductoProcedenciaImporte
3Resistencias 1000KitGratis
1Motor de corriente continuaKitGratis
1LCD1602 Module 1PCKitGratis
1Joystick Module 1PCKitGratis
1Fan Blade and 3-6V Motor 1PCKitGratis
1Diodo KitGratis
1UNO R3 Controller Board 1PCKitGratis
1Transistor NPNKitGratis
1BateríaEn propiedadGratis
1L298N Motor DriverCompra3,99
1Motor Twotrees paso a paso Nema 17(17HS4401)Compra10,41
Tabla 1: Componentes electrónicos empleados en el proyecto.

CantidadProductoImporte
1Varilla lisa haya 10/1000MM1,89
1Contrachapado 800X400X5MM6,79
1Madera MDF 600X300X10MM4,39
1Kit de Engranajes de Plástico7,93
2Engranajes6,00
1Fidget Spinner1,50
Tabla 2: Componentes no electrónicos comprados para la realización del proyecto.

Precio
Total:42,9
Tabla 3: Precio total invertido.

Problemas enfrentados

En general, los principales problemas que han surgido durante el desarrollo del proyecto han sido problemas físicos, durante el montaje y ensamblaje del proyecto:

  • Dado que el proyecto se planteó en un inicio para que rotase utilizando engranajes, tratamos de diseñarlo en función a estos. Por tanto, el mayor problema al que nos enfrentamos durante su desarrollo es que debido a que los engranajes no realizaban su función a la hora de rotar por un pequeño error de diseño. Esto provocó que los dientes no hicieran un contacto perfecto entre ellos, lo cual a su vez implicó que el soporte no pudiera realizar el giro esperado y se quedase estático. Dado este problema y que no se disponía del tiempo suficiente para obtener otros engranajes nuevos, con el diseño óptimo, se tuvo que diseñar el soporte de otra forma para que así no se dependiese de dichos engranajes. Se decidió que el motor por pasos iba a estar en contacto directo con la plataforma que repartiría las cartas e iba a producir el giro directamente sobre dicha plataforma. Esto nos generó una serie de nuevos problemas:
    • En primer lugar, es que ahora se debía tener en cuenta que el motor por pasos no podía realizar un giro superior a 360 grados, dado que los cables se enrollarían. Es por ello que vía software se contempla dicha opción y cada vez que se realiza un lanzamiento de cartas a cada jugador el motor por pasos vuelve a su posición inicial.
    • El segundo problema, se trató de un problema de diseño ya que se tuvo que invertir el display, para que este se pudiera visualizar correctamente.
  • Otro problema interesante es que una vez montado el repartidor y a la hora de realizar una prueba con él. Comprobamos que, si se utilizaba cada uno de los dos motores por separado, estos se activaban correctamente, pero en el momento que se trataba de utilizar ambos a la vez el motor pequeño se quedaba sin fuerza, dicho problema se pudo solucionar aumentando el voltaje suministrado al Arduino.
  • Por último, otro aspecto que no se tuvo en cuenta en un principio es que utilizar el motor por pasos y realizar giros con él se trataba de una tarea complicada sino se dispone del controlador óptimo para dicho motor. Es por ello que, indagando por internet, se descubrió el controlador de puente H de tipo L298N, el cual por un precio asequible facilitó la tarea del giro.
Figura 4: Controlador L298N.

Código desarrollado

A continuación, se presenta el código desarrollado para producir el funcionamiento esperado por nuestro dispositivo:

#include <LiquidCrystal.h>
#include <Stepper.h>

//LCD
int rs = 13, en = 12, d4 = 5, d5 = 4, d6 = 3, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int jugadores = 4;
int cartas = 108;

//JoyStick
int VRx = A0;int VRy = A1;int SW = 2;

int xPosition = 0;int yPosition = 0;
int SW_state = 1;
int mapX = 0;int mapY = 0;

//Motor
int motorPin = 7;

//Stepper
int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

//Menu
int estado = 1;
int sig_estado = 1;
int estadoMotor = 1;
int paso = 0;

void setup() {
  
  lcd.begin(16, 2); //Reinicia el display sin importar su estado
    lcd.setCursor(0, 0);
    lcd.print("Bienvenido al");
    lcd.setCursor(0, 1);
    lcd.print("Crupier");
  
  pinMode(VRx, INPUT);
  pinMode(VRy, INPUT);
  pinMode(SW, INPUT_PULLUP);

  pinMode(motorPin, OUTPUT);

  myStepper.setSpeed(60);
}

void loop() {     
   if(estadoMotor == 0){
    lcd.clear();
    menu();
   }

   if(analogRead(VRx) > 800){
    estadoMotor = 0;
   }
}

//Función que resetea automáticamente el arduino
//Pensada para solucionar carga de voltaje del stepper, pero no parece funcionar de la manera esperada
void(* resetFunc) (void) = 0;

//Menu
void menu(){
  estado = sig_estado;

  if(estado == 1) {
    int menu;
    String opciones[] = {"2 Jugadores", "3 Jugadores", "4 Jugadores", "5 Jugadores", "Reiniciar"};
    menu = funcMenu(opciones, 5);

      if(menu == -1){
        sig_estado = 1;
      }else if(menu == 1){
        sig_estado = 2;
      }else if(menu == 2){
        sig_estado = 3;
      }else if(menu == 3){
        sig_estado = 4;
      }else if(menu == 4){
        sig_estado = 5;
      }else if(menu == 5){
        sig_estado = 6;
      }
      
  }else if(estado == 2){
    lcd.clear();
    lcd.print("Iniciando Juego para 1...");
    delay(500);
    lcd.clear();

    //Inicia el juego
    juego(2);

    estadoMotor = 0;
    sig_estado = 1;
  }else if(estado == 3){
    lcd.clear();
    lcd.print("Iniciando Juego para 2...");
    delay(500);
    lcd.clear();
    
    //Inicia el juego
    juego(3);
     estadoMotor = 0;
    sig_estado = 1;
  }else if(estado == 4){
    lcd.clear();
    lcd.print("Iniciando Juego para 3...");
    delay(500);
    
    //Inicia el juego
    juego(4);
     estadoMotor = 0;
    sig_estado = 1;
  }else if(estado == 5){
    lcd.clear();
    lcd.print("Iniciando Juego para 4...");
    delay(500);
    
    //Inicia el juego
    juego(5);
     estadoMotor = 0;
    sig_estado = 1;
  }else if(estado == 6){
    lcd.clear();
    lcd.print("Reiniciando...");
    delay(500);
     estadoMotor = 0;
    sig_estado = 1;
  }
}

//Funcion que hace que el menu funcione, pintando el cursor y las opciones
int funcMenu(String *opciones, int size){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("> ");
  float opcion  = 1;
  int extraOpcion = 0;

  //Imprime las primeras 2 opciones del menu
  for(int i = 0; i<size && i <=1;i++){
    lcd.setCursor(2, i);
    lcd.print(opciones[i]);
  }
  delay(500);

  //Bucle para controlar el menu, si se pulsa el joystick salimos del menu.
  while(digitalRead(SW)==HIGH){
    xPosition = analogRead(VRx);
    delay(100);
    if(xPosition > 800 || xPosition < 200){
      //Hacia abajo
      if(xPosition > 800){
        if(opcion < size){     
          opcion += 1;
        }
      }
      //Hacia arriba
      if(xPosition<200){
        if(opcion >1){ 
          opcion -= 1;
        }  
      }
      //Aqui controlamos que no se salga del array opcione y si baja de la opcion salir, vuelva a la opcion 1 jugador
      if(opcion < 1 + extraOpcion){
        extraOpcion--;
      }
      //Aqui controlamos que no se salga del array opcione y si suve de la opcion 1 jugador, vuelva a la opcion salir
      if(opcion > 2 + extraOpcion){
        extraOpcion++;
      }
      //Pintamos de nuevo el menu
      lcd.clear();
      for(int x = extraOpcion; x < size && x <= (1+ extraOpcion); x++){
        lcd.setCursor(1, x - extraOpcion);
        lcd.print(opciones[x]);
      }
      //Pintamos el cursor
      lcd.setCursor(0, opcion - 1 - extraOpcion);
      lcd.print(">");
    }
  }

  return opcion;
}

//Se le pasa un numero de jugadores para iniciar el juego
void juego(int jugadores){
  
    int grados = (200*(180/jugadores))/360;
    for(int i = 0; i < jugadores; i++){

        myStepper.step(-grados);
  
        delay(1000);
        digitalWrite(motorPin, HIGH);
        delay(400);
        digitalWrite(motorPin, LOW);
            
        delay(500);      
    }
    myStepper.step((grados * jugadores) - 10);

    resetFunc();
}

Casos de uso

Caso de 2 Jugadores

Caso 4 Jugadores

Vídeo final

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *