Go Down

Topic: Proyecto "Control Juego Mecánico" y Ayuda !!! [Solucionado] (Read 1 time) previous topic - next topic

Gatoloco65

Apr 16, 2013, 02:40 pm Last Edit: Apr 18, 2013, 02:39 pm by Gatoloco65 Reason: 1
Saludo !!!

Hace un tiempo estoy metido en el mundo de Arduino; he realizado varias cosas que me han dado mucha satisfacción pues para alguien como yo, que no tiene ningún tipo de preparación en ninguna de las áreas afines a este mundo... es un gran logro. Hace un tiempo me di a la tarea de hacer un control para un juego mecánicos de diversión infantil (aquellos que hay en los centros comerciales y  que funcionan con monedas o fichas). Ya tengo varios funcionando y con buenos resultados. La verdad se que para muchos debe ser algo muy sencillo pues solo es activar un motor por X cantidad de tiempo, prender y apagar algunas luces para darle vida a la maquina y sonar una melodía infantil; pero para mi fue algo verdaderamente complicado pero gracias a varias personas del foro y en especial al Sr. Curro92, logre lo que estaba buscando. Pues bien ahora decidí hacer otro control para una juego diferente (tren o locomotora)  pues a diferencia de los otros este se desplaza por unos rieles similares a los de un tren o locomotora real.

Lo primero que cambia es que ya no funciona por tiempo si no por numero de vueltas y segundo, al estar desplazándose por un espacio requiere tener seguridad por si un niño se atraviesa en la carrilera, para lo cual cuenta con un Interruptor final de carreras ubicado en el bomper o para choques delantero de la locomotora el cual al ser accionado detiene el motor por X cantidad de tiempo.

El siguiente es código y ahí es donde viene la pregunta para resolver un problema que tengo.
Code: [Select]
/*
 Contro Para Juego Mecanico (Tren Expreso)
 
 Creado por Andrs Botero (Gatoloco65) y la ayuda de muchas personas.
 la finalidad de este control es la de permitir el funcionamiento de
 un juego mecánico que se desplaza por unos riles el cual funciona con
 monedas, al depositar la(s) monedas necesarias este empieza a girar al
 rededor por X cantidad de vueltas según sea programado, a su vez suena
 una melodía infantil y las luces prenden y apagan secuencial mente.  
*/
int CV = 7;        // Control Vueltas
int MS = 12;       // Pulsador o Micro-Swiche Activa Motor (Monedero)
int CH = 13;       // Choque Motor Swiche (parada por colision)
int SM=6;          // Salida Para Activar Motor
int SC =   5;      // Salida Para Contador (cuenta la cantidad de monedas)
int S =   2;       // Salida Para Activar Sonido
int led1 = 3;      // Salida Para Luces Led Secuencia 1
int led2 = 4;      // Salida Para Luces Led Secuencia 2
int contadorM = 0; // Variable para almacenar el conteo de monedas (si la maquina
                        // funciona con una o dos o tres monedas etc.)
int contadorV =0;               // Variable para almacenar el conteo de vueltas
boolean anteriorMS = LOW;  // Estado anterior pulsador Activa Motor
boolean actualMS = LOW;    // Estado actual pulsador Activa Motor
boolean anteriorCV = LOW;  // Estado anterior Control Vueltas
boolean actualCV = LOW;    // Estado actual Control Vueltas

void setup() {
 pinMode(CV,INPUT);
 pinMode(MS,INPUT);
 pinMode(CH,INPUT);
 pinMode(SM,OUTPUT);
 pinMode(led1,OUTPUT);
 pinMode(led2,OUTPUT);
 pinMode(S,OUTPUT);
 pinMode(SC,OUTPUT);
 #define TIEMPO2_ON  500L
 #define TIEMPO2_OFF 500L
}

boolean antireboteMS (boolean anteriorMS) // Función antirebote

{
  boolean actualMS = digitalRead(MS);

  if (anteriorMS != actualMS)
  {
    delay(5);
    actualMS = digitalRead(MS);
  }
    return actualMS;
}

boolean antireboteCV (boolean anteriorCV) // Función antirebote

{
  boolean actualCV = digitalRead(CV);

  if (anteriorCV != actualCV)
  {
    delay(5);
    actualCV = digitalRead(CV);
  }
 return actualCV;
}
void loop() {
 
  if ( (millis() % (TIEMPO2_ON + TIEMPO2_OFF)) < TIEMPO2_ON) // asi funcionan las luces decorativas
    {
      digitalWrite(led2,HIGH);
      digitalWrite(led1,LOW);
    }
      if ( (millis() % (TIEMPO2_ON + TIEMPO2_OFF)) >= TIEMPO2_ON)
    {
      digitalWrite(led2,LOW);
      digitalWrite(led1,HIGH);
    }

 actualMS = antireboteMS (anteriorMS); // Eliminación de rebote
 
   if ( anteriorMS == LOW && actualMS == HIGH) // Si hay cambio de estado en el botón
   
    {
        contadorM++;               //Incrementa el contador
        delay (100);           // Retardo  
    }
 
 if (contadorM==2)   // En este caso se programo para que funcionara a 2 monedas
 
 {
    digitalWrite (S,HIGH); // Se activa primero el sonido
    delay(1000);
    digitalWrite(SM,HIGH); // Se activa luego el Motor
    contadorM=0;           // contador de monedas vuelve a 0 para el proximo evento
 }
 
 if (digitalRead(CH)==HIGH) // si alguin choca contra el bomper o para choques delantero
                            // del tren este desactiva el motor por x cantidad de tiempo
   
      {
       digitalWrite(SM,LOW); // se para el motor y el sonido
       digitalWrite(S,LOW);
       delay(5000);          // durante 5 segundos
       digitalWrite(S,HIGH); // se vuelve a activar sonido y motor
       digitalWrite(SM,HIGH);
      }
 
  actualCV = antireboteCV (anteriorCV); // Eliminación de rebote
 
  if ( anteriorCV == LOW && actualCV == HIGH) // Si hay cambio de estado en el cuenta vueltas
     
     {
        contadorV++;               //Incrementa el contador
        delay (100);                // Retardo  
    }
 
 if (contadorV==8)             // se programa para que de 8 dueltas en este caso
 
 {
       
      digitalWrite(SC,HIGH); // activa un contador electromecanico para registrar la cantidad de monedas
      delay (500);
      digitalWrite(SC,LOW);
      delay (200);
      digitalWrite(SM,LOW); // Se apaga el motor
      delay (300);
      digitalWrite(S,LOW);  // Se apaga el sonido
      delay (300);      
      contadorV=0;        // el contador de vueltas vuelve a 0 para un proximo evento
     
    }
 
 anteriorCV = actualCV; // Actualiza El Estado del Control Vueltas
 anteriorMS = actualMS; // Actualiza El Estado Del Pulsador Activa Motor
 
 }
 


El control funciona "correctamente" entre "" , el único problema es si alguien golpea el parachoques del tren este empieza a funcionar sin necesidad de echarle monedas, algo que no es lógico;  para detener el motor utilizo la estructura de control if

   if (digitalRead(CH),HIGH) // si alguin choca contra el bomper o para choques delantero
                                               // del tren este desactiva el motor por x cantidad de tiempo
     {
       digitalWrite(SM,LOW);  // Para el Motor
       delay(5000);                    // por 5 segundos
       digitalWrite(SM,HIGH); // vuelve a activar el motor
     }

Alguien dirá pero si se activa la parada de emergencia  fue por que ocurrió un accidente y el juego debería terminar; resulta que en ocasiones el parachoques es accionado involuntariamente por un adulto y no seria lógico que el niño perdiera las vueltas que aun le falta por dar.  

La pregunta concreta es que tipo de estructura, variable o función debo utiliza para poder ejecutar esta orden ? La idea es que mientra la maquina este parada y si alguien acciona el parachoques la maquina no se active.

De antemano les agradezco cualquier idea o sugerencia que me puedan dar. Y si alguien esta interesado en tener mas detalles de este proyecto con mucho gusto estoy para servirles.

American2020

Hola, bueno, más o menos leí el código, aunque no en súper detalle, pero se me ocurre que lo que debieras hacer, antes de encender el motor, después de esa pausa de 5 segundos, es ver si realmente aún hay vueltas por dar.

Seguramente tienes una variable que vas modificando para contar las vueltas, fijate después del "choque" si aún hay vueltas pendientes, de no ser así, entonces el código sabrá que se chocó con el frente del tren, mientras este estaba detenido. (Y ahora lo mismo, también lo puedes controlar de esa forma, alguien choca con el frente, se dispara ese código, puedes agregar un if que diga "¿Estaba el tren girando?" y lo mismo, si no, entonces el juego no estaba activado, no hacer nada)

Espero que se entienda la idea.
My 3x3x3 Led Cube

[url=http://arduino.cc/forum/index.php/topic,1642

Imagina

#2
Apr 17, 2013, 08:10 pm Last Edit: Apr 17, 2013, 08:14 pm by Imagina Reason: 1
Como bien dice Amercan 2020, cuando se activa el "choque" tienes que ver que queden vueltas por dar, tendrías que añadir al if de tu codigo de "choche" algo tal que  "&& (contadorV > 0)" sería como decir, "si choque y en marcha, entonces para, espera 5 segundos y reanuda la marcha" si no quedan vueltas quiere decir que ya está parado, por lo tanto no necesita parar y reanudar la marcha, que supongo que es lo que te pasa.

Gatoloco65

Saludo !!!

A Imagina y a American2020 gracias por su ayuda, modifique el código de la siguiente manera según me recomienda Imagina ("&& (contadorV > 0)") 
   
   if (digitalRead(CH)==HIGH && (contadorV > 0 )) // si alguien choca contra el bomper o para
                               //choques delantero del tren este desactiva el motor por x cantidad de                                 
                               //tiempo
     
       {
        digitalWrite(SM,LOW); // se para el motor y el sonido
        digitalWrite(S,LOW);
        delay(5000);          // durante 5 segundos
        digitalWrite(S,HIGH); // se vuelve a activar sonido y motor
        digitalWrite(SM,HIGH);
       }
 
Y efectivamente estando detenido ya no se activa el motor si alguien lo golpea. el problema ahora es que deberá dar una vuelta es decir girar hasta pasar por el sensor que cuentas las vuelta para que la condición " &&(contadorV > 0)"  se cumpla, en otras palabras si alguien deposita las monedas, y un niño o persona choca antes de que el tren de la primera vuelta este no parara.

Seguiré estudian y haciendo ensayos hasta dar con la solución; nuevamente gracias a ambos.

Imagina

#4
Apr 18, 2013, 11:59 am Last Edit: Apr 18, 2013, 12:01 pm by Imagina Reason: 1
segun tu codigo, cuando alguien echa dos monedas, se pone todo en marcha, cuenta el número de vueltas,  espera a dar un numero determinado de vueltas y despues da la orden de parar. Este codigo es muy sencillo, pero tiene la pega que la primera vuelta sigue siendo la vuelta 0, y por lo tanto la condición del "Bomper" no sabe que está en marcha.

Existen varias soluciones...

1 - Al echar la moneda añade "contadorV++;" y en la condición de numero de vueltas cambiala por "(contadorV > 8 )"

2 - Cambia el sistema de conteo de vueltas, y en vez de contar, descuenta vueltas, de tal forma que al echar las monedas la variable "contadorV" tome el valor del número de vueltas a dar, por ejemplo "contadorV=8", y la condición de parada tendría que ser "Si contadorV<=0"...  esto te permitiría, por ejemplo decidir si quieres que de un numero de vueltas distintas según la cantidad de monedas depositadas, (1 modeda contadorV=3; 2 monedas contadorV=6; 3 monedas contadorV=10).

Existen otros modos de solucionarlo como con una variable que actives al mismo tiempo que el motor, pero ya que tienes contadorV, aprovechala...

Un Saludo.

Gatoloco65

Saludo !!!

Imagina, con la opción # 1 que me diste se soluciono el problema; la segunda opción esta muy interesante y me podría servir mucho para otros proyectos y para este; hoy salgo de viaje a visitar a mi vieja; la próxima semana empezare a cacharriarle a esta segunda opción y te estaré contando los avances o pidiendo nuevamente ayuda si es necesario.

Gracias y hasta la próxima.

Go Up