funcionamiento de Hockey sobre el aire

les paso a explicar el funcionamiento.
primero veamos que contiene:
*dos servo motores uno en cada arco
*dos sensores DETECTOR DE OBSTÁCULOS CON SENSOR INFRARROJO
*pantalla lcd 16x2
*placa i2c para lcd 16x2
*RFID
*3 cooler ( trabajan al mismo tiempo alimentado por una fuente a través de un rele )
*2 display 7 segmentos
ahora paso a contar como trabaja el sistema:
para que todo empiece a funcionar el RFID tiene que detectar uno de los usuarios autorizados. lo cual habilita los cooler y mueve los servo para que el disco salga.
habiendo pasado esto empieza a correr un tiempo de milis para saber cuando tiene que cortar el juego o a los 9 goles entre los dos arcos.
durante el juego cada sensor infrarrojo ira contando los goles con cada display de 7 segmentos de cada arco.
finalizado el tiempo se mueven nuevamente los servo al punto inicial y cuando uno de los dos infrarrojo detecte nuevamente apaga los cooler y se termino el el juego hasta pasar nuevamente una usuario habilitado.

no se a donde se encuentra el error pero no me anda como yo quiero y no hay error de compilación.
por favor ayuda.

#include<Servo.h>
#include <LiquidCrystal.h>
#include <MFRC522.h>

#define RST_PIN  9   
#define SS_PIN  53   
MFRC522 mfrc522(SS_PIN, RST_PIN); 

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); 
Servo servo1 ;
Servo servo2 ;
int cont1 =0;
int cont2 =0;
int inflarrojo1 = 4;
int inflarrojo2 = 5;
long previousMillis = 0;
long interval =1000;
int cooler =1;

void setup() {
  


  Serial.begin(9600); 
  mfrc522.PCD_Init(); 
  
  for (int i=22; i<38; i++)
       {
        pinMode(i, OUTPUT);
       }
     
lcd.begin(16, 2); 
lcd.setCursor(2, 0);    
lcd.print("pase tarjeta"); 
lcd.setCursor(2,1);
lcd.print("tiempo 2 min");
servo1.attach(2,650,2400);
servo2.attach(3,650,2400);
pinMode(inflarrojo1,INPUT);
pinMode(inflarrojo2,INPUT);
}
byte ActualUID[4]; 
byte Usuario1[4]= {0x04, 0xAE, 0x73, 0xFD} ; 
byte Usuario2[4]= {0x3C, 0xA9, 0xB1, 0xD5} ; 

byte  Digit1 [10][8] =                
{  { 1,1,1,1,1,1,0,0 },       
   { 0,1,1,0,0,0,0,0 },    
   { 1,1,0,1,1,0,1,0 },   
   { 1,1,1,1,0,0,1,0 },    
   { 0,1,1,0,0,1,1,0 },   
   { 1,0,1,1,0,1,1,0 },   
   { 1,0,1,1,1,1,1,0 },   
   { 1,1,1,0,0,0,0,0 },   
   { 1,1,1,1,1,1,1,0 },   
   { 1,1,1,0,0,1,1,0 }                                

};
byte  Digit2 [10][8] =                
{                    
   { 1,1,1,1,1,1,0,0 },       
   { 0,1,1,0,0,0,0,0 },    
   { 1,1,0,1,1,0,1,0 },   
   { 1,1,1,1,0,0,1,0 },    
   { 0,1,1,0,0,1,1,0 },   
   { 1,0,1,1,0,1,1,0 },   
   { 1,0,1,1,1,1,1,0 },   
   { 1,1,1,0,0,0,0,0 },   
   { 1,1,1,1,1,1,1,0 },   
   { 1,1,1,0,0,1,1,0 }            

};


             
void loop () { 
servo1.write(0);
servo2.write(0);
  if ( mfrc522.PICC_IsNewCardPresent()) 
        {  
            if ( mfrc522.PICC_ReadCardSerial()) 
            {
           
                  for (byte i = 0; i < mfrc522.uid.size; i++) {
                      
                          ActualUID[i]=mfrc522.uid.uidByte[i];          
                  } 
  if((compareArray(ActualUID,Usuario1))or(compareArray(ActualUID,Usuario2)))
   {   lcd.setCursor(0, 0);    
       lcd.print("juego iniciado"); 
      lcd.setCursor(3, 1);
      lcd.print("A JUGAR!!!");
 
digitalWrite(cooler,HIGH);
servo1.write(60);
servo2.write(60);
 

if(inflarrojo1==LOW)
{
cont1++;
Display1(cont1);
}

if(inflarrojo2==LOW)
  {
cont2++;
Display2(cont2);
}
  
           
 unsigned long currentMillis = millis();
  if(( currentMillis- previousMillis ==interval) or (cont1+cont2==14)) 
           {
            servo1.write(0);
            servo2.write(0);
          
          if((inflarrojo1==LOW) or (inflarrojo2==LOW))
         { digitalWrite(cooler,LOW);
         lcd.setCursor(2, 0);
         lcd.print("pase tarjeta"); 
         lcd.setCursor(2,1);
         lcd.print("tiempo 2 min"); 
         }
           }
}
else
 {     lcd.setCursor(1, 0);   
      lcd.print("pase tarjeta");
      lcd.setCursor(1, 1);
      lcd.print("juego DENEGADO");}
} 
}
}
 boolean compareArray(byte array1[],byte array2[])
{
  if(array1[0] != array2[0])return(false);
  if(array1[1] != array2[1])return(false);
  if(array1[2] != array2[2])return(false);
  if(array1[3] != array2[3])return(false);
  return(true);
}
void Display1(int N)
   {      for (int i= 0 ; i<7 ; i++)
               digitalWrite(i+22 , Digit1[N][i] ) ;
   }
            
   
void Display2(int L)

  { for (int u=0; u<7 ; u++)
             digitalWrite(u+29 , Digit1[L][u] ) ;
   }

tejo_final_pagina.ino (3.29 KB)

Aveces ayuda escribir en estos foros auque no te den una solucion . Ayuda a aclarar las ideas. Los pasos. Los procedimientos . Secuencia pasos finitos y sin ambiguedades. Programacion.

Es decir. Que quieres. Y veras la solucion.

La matrix.

Hola,
Bien has puesto el código y nos has contado de que va el juego. ¿ pero cual es el problema? No cuenta los goles, No cuenta el tiempo, no finaliza, no reconoce a los usuarios autorizados.

rodipelto ya te digo yo cual es el problema. Si ves el programa, a parte de dolerte los ojos porque apenas lo ha indentado correctamente (parece como si hubiera medio probado las cosas por separado y después las ha "pegado" una detrás de otra con algún if de por medio), verás que el único bucle que tiene es el loop() y "se lo ha cargado" porque ha puesto en él lo que ha dicho en la descripción de "lo que quiere que haga" el Arduino, tal cual, pero "traducido al Arduino".

locoman194, la idea es buena. Pero no la ejecución. Has de tener en cuenta que en Arduino la filosofía habitual es que el loop() se ejecute rápidamente una y otra vez haciendo "pequeñas cosas" cada vez, sin detenerse en nada en concreto. Pero aún así, en tu caso podrías adaptar lo que tienes y meter un while para que sólo una parte del programa esté en bucle mientras se esté jugando. Ya que ese es tu problema, que tienes un único bucle (el loop()) que trata de hacerlo todo de una sola pasada, y no. No se puede hacer todo todo de una sola pasada. Sino que, una vez ha comenzado el juego, has de "entretenerte" una y otra vez en un bucle que compruebe cómo transcurre el juego y si ha terminado.

Tal cual lo tienes ahora, lo único que compruebas "una y otra vez" en bucle es si da comienzo la partida.

Un consejo. Trata de hacer la traza al programa y verás que una vez "empieza la partida" compruebas sólo una vez cada uno de los infrarrojos, verificas otro par de cosas más y acto seguido se termina la partida. ¿No crees que deberías de hacer algunas de esas cosas una y otra vez, hasta que debiera de terminarse el juego? Pues para hacer algo "una y otra vez" se suelen utilizar los bucles.

locoman194, no sé si te he aclarado algo y si te ha servido de ayuda. Pero espero haberte dado pistas de cómo solucionar tu problema. Y por lo que más quieras... ¡usa la herramienta de autoindentación! :smiley:

Bueno te han dado algunas pistas de como encarar la tarea.
Olvida lo que hiciste y siguiendo la idea de IgnoranteAbsoluto, te recomiendo que hagas esto:

Crea un código tal que en un principio no haga nada pero si contanga las tareas que quieres que haga

Supongamos en el loop tendría una forma asi por ejemplo, que puede mejorarse.

void loop() {
    while(compruebo_jugadores());   // si no tienes dos jugadores el resto no tiene sentido
    if (barrera1 && barrera1Ant)  {     // verifico cambio 1 a 0
       cont1++;
              Display1(cont1);
    }
    if (barrera2 && barrera2Ant)  {     // verifico cambio 1 a 0
       cont2++;
              Display2(cont2);
    }
    barrera1Ant = barrera1;
    barrera2Ant = barrera2;   
}

// los procedimientos anteriores aca abajo

Bueno, he mirado con un poco más de detenimiento el programa y parece que sólo te han faltado por controlar un par de detalles. He hecho algunas correcciones y modificaciones según mi criterio, que puede estar acertado o no. Y, como no tengo el hardware, no lo he podido probar.

Un detalle: comentas que es a los 9 goles cuando se ha de acabar, pero en el código tienes un 14 que apunta a que sean 15 goles. Lo he cambiado por un 8 para que se termine la partida a los 9 goles.

Primeramente me he tomado la libertad de sangrar el código para que no me sangren los ojos :cry: y para que sea más fácil de leer por un humano.

Se te ha colado una 'l' en lugar de una 'r' en las variables inflarrojo1 e inflarrojo2, pero no importa, todo irá bien siempre y cuando las llames siempre mal. Esas dos variables y cooler las he convertido en constantes ya que lo que almacenan son los pines al que está conectado los dispositivos y esos pines, durante la ejecución del programa, siempre son los mismos.

Las variables previousMillis e interval las tenías declaradas como long, mientras que currentMillis la tenías declarada como unsigned long. Bueno, pues por "cuestiones técnicas" y para "evitar posibles problemas" he convertido las dos primeras en unsigned long.

Como he visto que tienes un mensaje por ahí que pone "tiempo 2 min", he supuesto que ese es el tiempo que se tiene de juego, y que una vez pasado ese tiempo (o se han marcado un total de 8 goles) se han de bloquear las salidas. Y, después, en cuanto detectas que ha habido otro gol se termina la partida. Así que he supuesto que el límite de tiempo lo estás controlando con la variable interval (que yo convertiría en constante, pero eso te lo dejo a ti) que inicializabas con 1000 milisegundos (un segundo). Pues he cambiado el valor de inicialización a 120000 milisegundos (120 segundos, dos minutos).

Una vez que se da por comenzado el juego, antes de meternos en el bucle infinito que controla el desarrollo de la partida, inicializamos los marcadores a cero y la variable que controla en qué momento dio comienzo la partida (previousMillis).

Acto seguido no metemos en el "bucle infinito" while(true), infinito porque siempre se cumple, que no lo será tanto ya que en algún momento se hará un break que nos sacará de él, dando por terminada la partida.

Dentro del "bucle infinito" controlaremos los sensores, marcadores y tiempo.

En el control de los sensores te has despistado y comparas el valor del número del pin al que está conectado, en lugar de comparar el valor de la lectura del pin (vamos, que te faltó el digitalRead).

No es lo más recomendable, pero tal cual lo tienes es la solución más sencilla: al detectar un gol he puesto un par de delay(500) para que durante ese tiempo "se detenga el bucle", para que el sensor no detecte varias veces consecutivas el paso del disco y, en lugar de contar de uno en uno, cuente varios goles cada vez que se interrumpe el sensor (si quieres puedes probar sin los delay para ver qué pasa y, si eso, nos cuentas).

Creo entender que lo que quieres es que una vez que se acabe el tiempo, o que se llegue a 8 goles en conjunto, se bloquean las salidas y al siguiente gol se paran los ventiladores y se da el juego por terminado. Para ello nos ayudaremos de una variable (esperandoUltimoGol) que nos va a indicar si se está esperando a que se marque el último gol porque se ha finalizado el tiempo o ya se han marcado un total de 8 goles. Al empezar, lógicamente, estará a false. Mientras esté a false comprobará si se ha finalizado el tiempo, o si ya se han marcado los 8 goles, para pasar a true y bloquear las salidas. Si cuando se marca un gol esperandoUltimoGol está a true, entonces se termina la partida con un break para salirse del bucle. Para todo esto he hecho cambios más "profundos" en el código, pero no mucho.

En la comparación, entre el tiempo transcurrido y el que se espera que ha de transcurrir, he cambiado el == por >= por si el delay(500) se está ejecutando justo cuando se cumple el tiempo.

Finalmente, al salirse del bucle, con un break, detiene los ventiladores y muestra el mensaje de final de partida. El resto del programa lo he dejado tal cual lo tenías (salvo la sangría).

Recuerda que no lo he podido probar. Espero que te funcione o que tengas que hacer muy pocos ajustes para ello. Tengo la impresión de que los mensajes del LCD se te van a solapar unos con otros, ya que no borras lo que estabas mostrando el LCD justo antes de mostrar un nuevo mensaje.

Adjunto programa con las modificaciones y comentarios. Suerte.

foro_tejo.ino (6.42 KB)

rodripelto:
Hola,
Bien has puesto el código y nos has contado de que va el juego. ¿ pero cual es el problema? No cuenta los goles, No cuenta el tiempo, no finaliza, no reconoce a los usuarios autorizados.

el problema que el bien alimento todo. andan los cooler sin necesidad de pasar la tarjeta. no anota los goles al detectar los sensores y los servo nunca se vuelven a mover al momento de terminar el juego. tampoco corta el cooler

IgnoranteAbsoluto:
rodipelto ya te digo yo cual es el problema. Si ves el programa, a parte de dolerte los ojos porque apenas lo ha indentado correctamente (parece como si hubiera medio probado las cosas por separado y después las ha "pegado" una detrás de otra con algún if de por medio), verás que el único bucle que tiene es el loop() y "se lo ha cargado" porque ha puesto en él lo que ha dicho en la descripción de "lo que quiere que haga" el Arduino, tal cual, pero "traducido al Arduino".

locoman194, la idea es buena. Pero no la ejecución. Has de tener en cuenta que en Arduino la filosofía habitual es que el loop() se ejecute rápidamente una y otra vez haciendo "pequeñas cosas" cada vez, sin detenerse en nada en concreto. Pero aún así, en tu caso podrías adaptar lo que tienes y meter un while para que sólo una parte del programa esté en bucle mientras se esté jugando. Ya que ese es tu problema, que tienes un único bucle (el loop()) que trata de hacerlo todo de una sola pasada, y no. No se puede hacer todo todo de una sola pasada. Sino que, una vez ha comenzado el juego, has de "entretenerte" una y otra vez en un bucle que compruebe cómo transcurre el juego y si ha terminado.

Tal cual lo tienes ahora, lo único que compruebas "una y otra vez" en bucle es si da comienzo la partida.

realmente soy muy nuevo en esto y no me di cuenta de los nombrados bucles ni sabia de la funsion

Un consejo. Trata de hacer la traza al programa y verás que una vez "empieza la partida" compruebas sólo una vez cada uno de los infrarrojos, verificas otro par de cosas más y acto seguido se termina la partida. ¿No crees que deberías de hacer algunas de esas cosas una y otra vez, hasta que debiera de terminarse el juego? Pues para hacer algo "una y otra vez" se suelen utilizar los bucles.

locoman194, no sé si te he aclarado algo y si te ha servido de ayuda. Pero espero haberte dado pistas de cómo solucionar tu problema. Y por lo que más quieras... ¡usa la herramienta de autoindentación! :smiley:

realmente soy muy nuevo en todo esto. no me di cuenta de loa bucles y no sabia de la funcion while. muchisimas gracias ahora seguire intentando aver como me sale

IgnoranteAbsoluto:
Bueno, he mirado con un poco más de detenimiento el programa y parece que sólo te han faltado por controlar un par de detalles. He hecho algunas correcciones y modificaciones según mi criterio, que puede estar acertado o no. Y, como no tengo el hardware, no lo he podido probar.

Un detalle: comentas que es a los 9 goles cuando se ha de acabar, pero en el código tienes un 14 que apunta a que sean 15 goles. Lo he cambiado por un 8 para que se termine la partida a los 9 goles.

Primeramente me he tomado la libertad de sangrar el código para que no me sangren los ojos :cry: y para que sea más fácil de leer por un humano.

Se te ha colado una 'l' en lugar de una 'r' en las variables inflarrojo1 e inflarrojo2, pero no importa, todo irá bien siempre y cuando las llames siempre mal. Esas dos variables y cooler las he convertido en constantes ya que lo que almacenan son los pines al que está conectado los dispositivos y esos pines, durante la ejecución del programa, siempre son los mismos.

Las variables previousMillis e interval las tenías declaradas como long, mientras que currentMillis la tenías declarada como unsigned long. Bueno, pues por "cuestiones técnicas" y para "evitar posibles problemas" he convertido las dos primeras en unsigned long.

Como he visto que tienes un mensaje por ahí que pone "tiempo 2 min", he supuesto que ese es el tiempo que se tiene de juego, y que una vez pasado ese tiempo (o se han marcado un total de 8 goles) se han de bloquear las salidas. Y, después, en cuanto detectas que ha habido otro gol se termina la partida. Así que he supuesto que el límite de tiempo lo estás controlando con la variable interval (que yo convertiría en constante, pero eso te lo dejo a ti) que inicializabas con 1000 milisegundos (un segundo). Pues he cambiado el valor de inicialización a 120000 milisegundos (120 segundos, dos minutos).

Una vez que se da por comenzado el juego, antes de meternos en el bucle infinito que controla el desarrollo de la partida, inicializamos los marcadores a cero y la variable que controla en qué momento dio comienzo la partida (previousMillis).

Acto seguido no metemos en el "bucle infinito" while(true), infinito porque siempre se cumple, que no lo será tanto ya que en algún momento se hará un break que nos sacará de él, dando por terminada la partida.

Dentro del "bucle infinito" controlaremos los sensores, marcadores y tiempo.

En el control de los sensores te has despistado y comparas el valor del número del pin al que está conectado, en lugar de comparar el valor de la lectura del pin (vamos, que te faltó el digitalRead).

No es lo más recomendable, pero tal cual lo tienes es la solución más sencilla: al detectar un gol he puesto un par de delay(500) para que durante ese tiempo "se detenga el bucle", para que el sensor no detecte varias veces consecutivas el paso del disco y, en lugar de contar de uno en uno, cuente varios goles cada vez que se interrumpe el sensor (si quieres puedes probar sin los delay para ver qué pasa y, si eso, nos cuentas).

Creo entender que lo que quieres es que una vez que se acabe el tiempo, o que se llegue a 8 goles en conjunto, se bloquean las salidas y al siguiente gol se paran los ventiladores y se da el juego por terminado. Para ello nos ayudaremos de una variable (esperandoUltimoGol) que nos va a indicar si se está esperando a que se marque el último gol porque se ha finalizado el tiempo o ya se han marcado un total de 8 goles. Al empezar, lógicamente, estará a false. Mientras esté a false comprobará si se ha finalizado el tiempo, o si ya se han marcado los 8 goles, para pasar a true y bloquear las salidas. Si cuando se marca un gol esperandoUltimoGol está a true, entonces se termina la partida con un break para salirse del bucle. Para todo esto he hecho cambios más "profundos" en el código, pero no mucho.

En la comparación, entre el tiempo transcurrido y el que se espera que ha de transcurrir, he cambiado el == por >= por si el delay(500) se está ejecutando justo cuando se cumple el tiempo.

Finalmente, al salirse del bucle, con un break, detiene los ventiladores y muestra el mensaje de final de partida. El resto del programa lo he dejado tal cual lo tenías (salvo la sangría).

Recuerda que no lo he podido probar. Espero que te funcione o que tengas que hacer muy pocos ajustes para ello. Tengo la impresión de que los mensajes del LCD se te van a solapar unos con otros, ya que no borras lo que estabas mostrando el LCD justo antes de mostrar un nuevo mensaje.

Adjunto programa con las modificaciones y comentarios. Suerte.

realmente estoy analizando todos los errores marcados y son muchos. se nota que me falta largo trecho pero de alguna forma se empieza.
agradezco muchísimo lo que hiciste y analizaste, como también espero que le sirva a otra persona que este aprendiendo las librerías las tengo por si alguno las requiere.
y ahora probare conectando todo espero que funcione como se desea.
y lo de el mensaje lcd tendré que poner que borre antes de mandar un mensaje nuevo así no tenga problema.