DURACION DEL JUEGO

Hola,
Soy nuevo en el mundo Arduino, investigo por mi cuenta para aprender en mis ratos de ocio.
El código que adjunto es de un juego de tiro al blanco con servomotores y LDRs que ordenan el movimiento de los servomotores con el aumento de luz proveído con un puntero láser.
No pude encontrar la forma correcta de ponerle un tiempo de duración al juego. Quiero que solo dure un minuto y que luego del minuto culmine el juego regresando los servomotores (los que se quedaron en 90 grados) a 0 grados.
Agradecido de antemano por la ayuda a recibir.

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;

Servo myservo2;
Servo myservo3; 
Servo myservo4;
Servo myservo5; 

void setup()
{ 
  myservo2.attach(2);
  myservo3.attach(3);
  myservo4.attach(4);
  myservo5.attach(5);
}

void loop()
{

  sensor0Value = analogRead(sensorPin0);
  if (sensor0Value < 450)
  {
  myservo2.write(90);
  delay(15);
  }
  else
  {
  myservo2.write(0);      
  delay(1500);
  }

{
  sensor1Value = analogRead(sensorPin1);
  if (sensor1Value < 450)
  {
  myservo3.write(90);
  delay(15);
  }
  else
  {
  myservo3.write(0);      
  delay(1500);
  }

{
  sensor2Value = analogRead(sensorPin2);
  if (sensor2Value < 450)
  {
  myservo4.write(90);
  delay(15);
  }
  else
  {
  myservo4.write(0);      
  delay(1500);
  }

{
  sensor3Value = analogRead(sensorPin3);
  if (sensor3Value < 450)
  {
  myservo5.write(90);
  delay(15);
  }
  else
  {
  myservo5.write(0);      
  delay(1500);
  }
}}}}

Muy buenas.

También soy nuevo, peeeero podrías usar la funcion millis(), la cual te devuelve el tiempo que ha transcurrido desde que empezó el programa (en milisegundos), busca millis() en la página de arduino.cc para tener información más detallada, podrías hacer que si millis() llega a 1 minuto (ó 60.000 milisegundos) finalice el programa con un ciclo "while(true);" que simplemente parará el programa hasta que se reinicie.

Saludos.

En la sección de documentación tienes millis explicado, también puedes usar el ejemplo del propio IDE, Ejemplos, Digital, BlinkWithoutDelay

No se te ocurra usar

while(true)

si no sabes como detenerlo, de hecho loop() ya es un while(true) entonces para que usar otro?

En la sección Documentación hay muchos tutoriales sobre millis(). Explicado para todos los niveles, desde inicial hasta mas avanzados.

@surbyte
Gracias, buscaré por allí.

Buenas tardes a todos,

Encontré de un post antiguo la indicación de como dar la duración de segundos al juego, lo inserté y no funciona la duración, dejó de funcionar todo.

Qué estoy haciendo mal?

Ayuda por favor.

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;

//int timer = 30;
//unsigned long interval = 30; // the time we need to wait
//unsigned long previousMillis = 0; // millis() returns an unsigned long.


Servo myservo2; //Create and instance of the Servo object
Servo myservo3; //Create and instance of the Servo object
Servo myservo4; //Create and instance of the Servo object
Servo myservo5; //Create and instance of the Servo object

void setup()
{ 
  myservo2.attach(2); //Use pin 2 for servo control
  myservo3.attach(3); //Use pin 3 for servo control
  myservo4.attach(4); //Use pin 4 for servo control
  myservo5.attach(5); //Use pin 5 for servo control
}

void loop()
{

unsigned long start = millis()+60000UL; // cargo a start con el valor +60mil milisegundos
while (millis() > start) {
   // lo que este aqui dentro tiene 60 segundos para ejecutarse
   // o puedes salir con break


  sensor0Value = analogRead(sensorPin0);
  if (sensor0Value < 450)
  {
  myservo2.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo2.write(0);      
  delay(1500);
  }

{
  sensor1Value = analogRead(sensorPin1);
  if (sensor1Value < 450)
  {
  myservo3.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo3.write(0);      
  delay(1500);
  }

{
  sensor2Value = analogRead(sensorPin2);
  if (sensor2Value < 450)
  {
  myservo4.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo4.write(0);      
  delay(1500);
  }

{
  sensor3Value = analogRead(sensorPin3);
  if (sensor3Value < 450)
  {
  myservo5.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo5.write(0);      
  delay(1500);
  }
}}}}}

En cada ciclo del loop estas cambiado la variable start al millis actual + 60000, esa variable solo debería cambiarse al iniciar el juego.

El comparador del while lo tienes al revés, pon <

Gracias krnlpanic. Muy amable por tu rápida respuesta, muy gentil.
Ahora si funciona el juego pero no se culmina al minuto. Adjunto el código con el cambio a ''<''.
Qué me está faltando para que se detenga? Algo estoy haciendo mal.
Necesito que se detenga al minuto de iniciarse y que para iniciarse nuevamente pulse el botón RESET.

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;

Servo myservo2; //Create and instance of the Servo object
Servo myservo3; //Create and instance of the Servo object
Servo myservo4; //Create and instance of the Servo object
Servo myservo5; //Create and instance of the Servo object

void setup()
{ 
  myservo2.attach(2); //Use pin 2 for servo control
  myservo3.attach(3); //Use pin 3 for servo control
  myservo4.attach(4); //Use pin 4 for servo control
  myservo5.attach(5); //Use pin 5 for servo control
}

void loop()
{

unsigned long start = millis()+60000UL; // cargo a start con el valor +60mil milisegundos
while (millis() < start) {
   // lo que este aqui dentro tiene 60 segundos para ejecutarse
   // o puedes salir con break

  sensor0Value = analogRead(sensorPin0);
  if (sensor0Value < 450)
  {
  myservo2.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo2.write(0);      
  delay(1500);
  }

{
  sensor1Value = analogRead(sensorPin1);
  if (sensor1Value < 450)
  {
  myservo3.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo3.write(0);      
  delay(1500);
  }

{
  sensor2Value = analogRead(sensorPin2);
  if (sensor2Value < 450)
  {
  myservo4.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo4.write(0);      
  delay(1500);
  }

{
  sensor3Value = analogRead(sensorPin3);
  if (sensor3Value < 450)
  {
  myservo5.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo5.write(0);      
  delay(1500);
  }
}}}}}

ohhh.... una omisión grande.... unsigned long start = millis()+60000UL; DEBÍA ESTAR FUERA DEL LOOP.

Ahora todo OK. Muchas gracias caballeros.

Lo que deseo ahora es que luego de cumplirse el tiempo (60 segundos), los servomotores que se han quedado en 90 grados vuelvan a 0 grados. Ellos volverán a 90 grados una vez que se inicie un nuevo juego presionando el botón reset.

Qué debo hacer para lograr ello?

gracias anticipadas por la ayuda que reciba.

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;

Servo myservo2; //Create and instance of the Servo object
Servo myservo3; //Create and instance of the Servo object
Servo myservo4; //Create and instance of the Servo object
Servo myservo5; //Create and instance of the Servo object

void setup()
{
  myservo2.attach(2); //Use pin 2 for servo control
  myservo3.attach(3); //Use pin 3 for servo control
  myservo4.attach(4); //Use pin 4 for servo control
  myservo5.attach(5); //Use pin 5 for servo control
}

void loop()
{

unsigned long start = millis()+60000UL; // cargo a start con el valor +60mil milisegundos
while (millis() < start) {
   // lo que este aqui dentro tiene 60 segundos para ejecutarse
   // o puedes salir con break

  sensor0Value = analogRead(sensorPin0);
  if (sensor0Value < 450)
  {
  myservo2.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo2.write(0);     
  delay(1500);
  }

{
  sensor1Value = analogRead(sensorPin1);
  if (sensor1Value < 450)
  {
  myservo3.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo3.write(0);     
  delay(1500);
  }

{
  sensor2Value = analogRead(sensorPin2);
  if (sensor2Value < 450)
  {
  myservo4.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo4.write(0);     
  delay(1500);
  }

{
  sensor3Value = analogRead(sensorPin3);
  if (sensor3Value < 450)
  {
  myservo5.write(90); //instruct servo to turn 90 degrees
  delay(15);
  }
  else
  {
  myservo5.write(0);     
  delay(1500);
  }
}}}}}

Al querer que el juego se active despues de reset y este quede con los servos a 90 pasado ese tiempo tal y como comentabas en privado, he eliminado la variable start y lo que comparo es que millis no supere 60000, una vez acabado ese tiempo los servos pasan a 90º, he creado una nueva variable que se llama fin para que solo ejecute el movimiento de servos 1 vez. Espero entiendas la explicación, en caso contrario sientete libre de preguntar.

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;
byte fin = 0;

Servo myservo2; //Create and instance of the Servo object
Servo myservo3; //Create and instance of the Servo object
Servo myservo4; //Create and instance of the Servo object
Servo myservo5; //Create and instance of the Servo object

void setup() {
  myservo2.attach(2); //Use pin 2 for servo control
  myservo3.attach(3); //Use pin 3 for servo control
  myservo4.attach(4); //Use pin 4 for servo control
  myservo5.attach(5); //Use pin 5 for servo control

}

void loop() {

  while (millis() < 60000) {
    // lo que este aqui dentro tiene 60 segundos para ejecutarse
    // o puedes salir con break

    sensor0Value = analogRead(sensorPin0);
    if (sensor0Value < 450)
    {
      myservo2.write(90); //instruct servo to turn 90 degrees
      delay(15);
    }
    else
    {
      myservo2.write(0);
      delay(1500);
    }

    {
      sensor1Value = analogRead(sensorPin1);
      if (sensor1Value < 450)
      {
        myservo3.write(90); //instruct servo to turn 90 degrees
        delay(15);
      }
      else
      {
        myservo3.write(0);
        delay(1500);
      }

      {
        sensor2Value = analogRead(sensorPin2);
        if (sensor2Value < 450)
        {
          myservo4.write(90); //instruct servo to turn 90 degrees
          delay(15);
        }
        else
        {
          myservo4.write(0);
          delay(1500);
        }

        {
          sensor3Value = analogRead(sensorPin3);
          if (sensor3Value < 450)
          {
            myservo5.write(90); //instruct servo to turn 90 degrees
            delay(15);
          }
          else
          {
            myservo5.write(0);
            delay(1500);
          }
        }
      }
    }
  }
  if (!fin) {
    myservo2.write(90)
    myservo3.write(90)
    myservo4.write(90)
    myservo5.write(90)
    fin = 1;
  }
}

Muchas gracias krnpanic. Muy amable e instructivo.
El código quedó tal lo adjunto.
Saludos

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;
byte fin = 0;

Servo myservo2; //Create and instance of the Servo object
Servo myservo3; //Create and instance of the Servo object
Servo myservo4; //Create and instance of the Servo object
Servo myservo5; //Create and instance of the Servo object

void setup() {
  myservo2.attach(2); //Use pin 2 for servo control
  myservo3.attach(3); //Use pin 3 for servo control
  myservo4.attach(4); //Use pin 4 for servo control
  myservo5.attach(5); //Use pin 5 for servo control

}

void loop() {

  while (millis() < 15000) {
    // lo que este aqui dentro tiene 60 segundos para ejecutarse
    // o puedes salir con break

    sensor0Value = analogRead(sensorPin0);
    if (sensor0Value < 450)
    {
      myservo2.write(90); //instruct servo to turn 90 degrees
      delay(15);
    }
    else
    {
      myservo2.write(0);
      delay(1500);
    }

    {
      sensor1Value = analogRead(sensorPin1);
      if (sensor1Value < 450)
      {
        myservo3.write(90); //instruct servo to turn 90 degrees
        delay(15);
      }
      else
      {
        myservo3.write(0);
        delay(1500);
      }

      {
        sensor2Value = analogRead(sensorPin2);
        if (sensor2Value < 450)
        {
          myservo4.write(90); //instruct servo to turn 90 degrees
          delay(15);
        }
        else
        {
          myservo4.write(0);
          delay(1500);
        }

        {
          sensor3Value = analogRead(sensorPin3);
          if (sensor3Value < 450)
          {
            myservo5.write(90); //instruct servo to turn 90 degrees
            delay(15);
          }
          else
          {
            myservo5.write(0);
            delay(1500);
          }
        }
      }
    }
  }
  if (!fin) {
    myservo2.write(0);
    myservo3.write(0);
    myservo4.write(0);
    myservo5.write(0);
    fin = 1;
  }
}

Buenas noches estimados,

Tengo el juego avanzado. Le agregué un buzzer (BEEP) para emitir sonidos al culminar el juego. Asimismo, le agregué un módulo de voz para emitir un sonido de disparo cada vez que se da en el blanco y "cae'' el servomotor a posición CERO grados. También he agregado leds verde y rojo para indicar ''juego en proceso'' y ''juego terminado''. Todo funciona bien, pero como siempre se desea aumentar efectos para mejorar el juego, en mi caso no es la excepción. Ahora deseo ponerle un grado de dificultad. Así como está ahora, el juego se inicia levantándose todos los servos a 90 grados, ninguno regresa a CERO grados salvo que se le de en el blanco o termine el tiempo del juego.

Deseo que los servos que no han recibido el tiro al blanco pasado 3 segundos (por ejemplo) regresen automáticamente a CERO grados emitiendo un ''tone(BEEP, 1500)''; delay(200); noTone(BEEP); para luego de un ''delay (1500)'' vuelva a ponerse en 90 grados y continuar disponibles a dispararle con el láser.

Espero vuestra gentil ayuda.

Adjunto el código. GRACIAS!!!

#include <Servo.h>
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;

int sensor0Value;
int sensor1Value;
int sensor2Value;
int sensor3Value;
byte fin = 0;

int const PLAY=6;
const int BEEP = 11;

const int LEDVERDE = 13;
const int LEDROJO = 12;

Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;

void setup() {
myservo2.attach(2);
myservo3.attach(3);
myservo4.attach(4);
myservo5.attach(5);

pinMode(LEDVERDE, OUTPUT);
pinMode(LEDROJO, OUTPUT);

pinMode(PLAY, OUTPUT);

}

void loop() {




while (millis() < 60000) {

digitalWrite(LEDVERDE, HIGH);

sensor0Value = analogRead(sensorPin0);
if (sensor0Value < 450)
{myservo2.write(90);
delay(15);}
else {
digitalWrite(PLAY,HIGH);
delay(15);
digitalWrite(PLAY,LOW);

myservo2.write(0);
delay(1500);}

{
sensor1Value = analogRead(sensorPin1);
if (sensor1Value < 450)
{myservo3.write(90);
delay(15);}
else {
digitalWrite(PLAY,HIGH);
delay(15);
digitalWrite(PLAY,LOW);
  
myservo3.write(0);
delay(1500);}

{
sensor2Value = analogRead(sensorPin2);
if (sensor2Value < 450)
{myservo4.write(90);
delay(15);}
else {

digitalWrite(PLAY,HIGH);
delay(15);
digitalWrite(PLAY,LOW);

myservo4.write(0);
delay(1500);}

{sensor3Value = analogRead(sensorPin3);
if (sensor3Value < 450)
{myservo5.write(90);
delay(15);}
else {

digitalWrite(PLAY,HIGH);
delay(15);
digitalWrite(PLAY,LOW);

myservo5.write(0);
delay(1500);}
        }
      }
    }
  }
  if (!fin) {
    tone(BEEP, 400);
    delay(200);
    noTone(BEEP);
    tone(BEEP, 800);
    delay(200);
    noTone(BEEP);
    tone(BEEP, 3000);
    delay(200);
    noTone(BEEP);
    tone(BEEP, 1500);
    delay(200);
    noTone(BEEP);
    myservo2.write(0);
    myservo3.write(0);
    myservo4.write(0);
    myservo5.write(0);
    digitalWrite(LEDVERDE, LOW);
    digitalWrite(LEDROJO, HIGH);
    delay(15000);
    digitalWrite(LEDROJO, LOW);
    fin = 1;
  }
}

Deberías pasar por la sección de documentación y leer acerca de millis ya que cada delay que pones detiene el código completamente por lo que si tienes una señal de entrada que debe actuar no lo hará, revisa también la de maquina de estados.

Si quieres que a los 3 segundos cambie el servo a 0 tan sencillo como usar un if para ver si millis supera 3000, si quieres que vuelva a 90 tras un tiempo pues otro if, pero se te añade un nuevo problema, necesitas saber los estados, debes comparar también si ese servo no habia sido disparado anteriormente para que no vuelva a subir así que tendrás que usar un if con varias condiciones.

Si, efectivamente. Estaba revisando justamente eso, hacerlo con if y millis.
creo que debería hacerlo con un ''if dentro de otro if''

Puedes poner varias condiciones dentro de un if separando con && si se deben cumplir todas las condiciones o con || si se ha de cumplir cualquiera de ellas

if (millis() > 3000 && millis() < 10000)

Hola krnlpanic,

Estuve buscando las opciones para aplicarlas, la tuya la encuentro más sencilla y lógica pero tengo el inconveniente que los tiempos no siempre serán cada 3000. Me explico:
Si desde el inicio un ldr/servo no recibió el tiro laser, sí deberá volverse a CERO luego de 3000. Sin embargo, ese u otro puede haber recibido el tiro en el segundo 1000, se irá a CERO y después de 1500 volverá a 90 grados en el segundo 2500. Es decir, si no se le da un tiro, a los 5500 deberá volverse a CERO, y así sucesivamente.

Adjunto la porción de código de uno de los ldr/servo

gracias nuevamente. Espero tu gentil solución a mi problema.

sensor0Value = analogRead(sensorPin0);
if (sensor0Value < 450){myservo2.write(90); delay(5);

[b]
//AQUI ES DONDE CREO ME FALTAN MAS DE LAS INSTRUCIONES if, millis, ETC[/b]


}else {digitalWrite(PLAY,HIGH); delay(5); digitalWrite(PLAY,LOW);
myservo2.write(0); delay(1500);}

Entonces tendrás que crear una variable unsigned long con valor 0 al inicio y guardar en esa variable el millis cada vez que se acierte un tiro y hacer la siguiente comparación

if ((tuvariable + 3000) > millis())

Por eso es necesario entender millis, espero entiendas como aplicarlo.

Gracias, investigaré más.
....y si no lo logro, te molestaré nuevamente.
Saludos