Cómo salir del estado de comandos if que está dentro del bucle for y volver al bucle vacío en Arduino

2

Mi código:

#define MAX 10
const int LED1 = 2;
const int LED2 = 8;
const int LED3 = 4;
const int LED4 = 5;
int val;
int array[MAX];
int counter = 0;
int i;
int old_b = 0;
int error;

void setup() { 
 Serial.begin(9600);
 pinMode(A5, INPUT_PULLUP); 
}

int readButtons(int pin) {
 int b,c;
 c=analogRead(pin);
 Serial.print("analogRead = ");
 Serial.println(c); 
 delay(100);
 if (c>1015) b = 0; 
 else if (c>70 && c<76) b = 1; 
 else if (c<128 && c>122) b = 2; 
 else if (c>169 && c<175) b = 3; 
 else if (c>209 && c<217) b = 4;
 else if (c>247 && c<256) b = 5;
 else if (c>280 && c<291) b = 6;
 else b = 0;
 if (b == old_b) {
  return 0;
  old_b = b;
 } else {
   return b;
   stari_b = b;
 }
}

void loop() {
 while ((val = readButtons(5)) != 5) {
  if (val == 1) {
   array[counter] = 1;
   counter++;
   Serial.print("In ");
   Serial.print(counter);
   Serial.print(" saving ");
   Serial.println("1");
   delay(500);
  } else if (val == 2) {
     array[counter] = 2;
     counter++;
     Serial.print("In ");
     Serial.print(counter);
     Serial.print(" saving ");
     Serial.println("2");
     delay(500);
  } else if (val == 3) {
     array[counter] = 3;
     counter++;
     Serial.print("In ");
     Serial.print(counter);
     Serial.print(" saving ");
     Serial.println("3");
     delay(500);
  } else if (val == 4) {
     array[counter] = 4;
     counter++;
     Serial.print("In ");
     Serial.print(counter);
     Serial.print(" saving ");
     Serial.println("4");
     delay(500);
  }
  if (counter == MAX) {
   counter = 0;
  }
 }

 for (i = 0; i < MAX; i++) {
  if (array[i] == 1) {
     digitalWrite(LED3, HIGH);
     digitalWrite(LED4, HIGH);
     delay(1000);
     digitalWrite(LED3, LOW);
     digitalWrite(LED4, LOW);
     delay(1000);
     Serial.print("Executing ");
     Serial.print(i);
     Serial.print(" ");
     Serial.println(array[i]);
     delay(500);
  }
  if (array[i] == 2) {
     digitalWrite(LED1, HIGH);
     digitalWrite (LED2, HIGH);
     delay(1000);
     digitalWrite(LED1, LOW);
     digitalWrite(LED2,LOW);
     delay(1000);
     Serial.print("Executing ");
     Serial.print(i);
     Serial.print(" ");
     Serial.println(array[i]);
     delay(500);
  }
  if (array[i] == 3) {
     digitalWrite(LED2, HIGH);
     digitalWrite(LED4, HIGH);
     delay(1000);
     digitalWrite(LED2, LOW);
     digitalWrite(LED4, LOW);
     delay(1000);
     Serial.print("Executing ");
     Serial.print(i);
     Serial.print(" ");
     Serial.println(array[i]);
     delay(500);
  }
  if (array[i] == 4) {
     digitalWrite(LED1, HIGH);
     digitalWrite(LED3, HIGH);
     delay(1000);
     digitalWrite(LED1, LOW);
     digitalWrite(LED3, LOW);
     Serial.print("Executing ");
     Serial.print(i);
     Serial.print(" ");
     Serial.println(array[i]);
     delay(500);
  }

 } 
}

Así que tengo botones conectados como esto , excepto que tengo ellos 5. Cuando se presiona uno de los primeros cuatro, el boceto almacena 1,2,3 o 4 para indicar qué botones se presionaron y los almacena en una matriz de enteros. Cuando se presiona el quinto botón (el botón "GO") mientras el bucle termina, se inicia el bucle for que, de acuerdo con los botones pulsados, parpadea los LED. Quiero hacer que mientras Arduino está parpadeando los LED, es decir, mientras se está ejecutando for loop, si en cualquier momento se presiona el quinto botón "GO", debería dejar de parpadear los LED y comenzar el programa desde el principio (void loop {... }) que es otra vez esperar las pulsaciones de los primeros cuatro botones.

Logré hacer esto:

#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;

void setup () {
  pinMode (A5, INPUT_PULLUP);
  Serial.begin(9600);
}

int readButtons (int pin) {
  int b, c;
  c = analogRead(pin);
  Serial.print("analogRead =  ");
  Serial.println(c);
  delay(100);
  if (c > 1015) b = 0;
  else if (c > 70 && c < 76) b = 1;
  else if (c > 122 && c < 128) b = 2;
  else if (c > 169 && c < 175) b = 3;
  else if (c > 209 && c < 217) b = 4;
  else if (c > 247 && c < 256) b = 5;
  else if (c > 280 && c < 291) b = 6;
  else b = 0;
  if (b == old_b) {
   return 0;
   old_b = b;
  } else {
    return b;
    old_b = b;              
    }                           
}

void loop () {
  while ((val = readButtons(5)) != 5) {
    if ((val == 1) || (val == 2) || (val == 3) || (val == 4)) {
      array[counter] = val;
      Serial.print("In  ");
      Serial.print(counter);                
      Serial.print(" saving ");            
      Serial.println(val);
      delay(200);
      counter++;
      if (counter == MAX) {
        counter = 0;
      } 
    }
  }

  temp = counter;
  counter = 0;

  for (i = 0; i < temp; i++) {
    if (array[i] % 2 == 0) {
      L1 = 2;
      L2 = array[i] / 3 + 3; 
    } else {
      L2 = 5;
      L1 = array[i] % 3 + 3;    
      }

    if (readButtons(5) != 5) {
     digitalWrite (L1, HIGH);
     if (readButtons(5) != 5) {
      digitalWrite (L2, HIGH);
      delay(1000);
      digitalWrite (L1, LOW);
      digitalWrite (L2, LOW);
      if (readButtons(5) == 5) {
        i = temp;
      }
     } else {
       digitalWrite (L1, LOW);
       i = temp; 
     }
    }

  }
}

Así que todavía tengo una función que detecta si se presionó un botón. Antes de eso, he determinado en qué rango están los valores para cierto botón. En el bucle while () {...} , mientras que no se presiona el quinto botón, Arduino está "mirando" si se presionó alguno de los primeros cuatro botones. Si se guardaba en una matriz y si no se seguía "buscando". Cuando se presiona el quinto botón, salimos y almacenamos el último lugar conocido en la matriz en el que se almacenó el valor y configuramos el contador de posición en cero, de modo que al comenzar de nuevo, Arduino almacena los valores en el primer lugar de la matriz. Luego, basándome en lo que está almacenado, determino qué pin / LED se encenderá. Si en algún momento durante el parpadeo de los LEDs se presiona nuevamente el quinto botón, Arduino detiene el parpadeo y espera de nuevo la presión de los primeros cuatro botones. Así es como se supone que funciona en teoría. En la práctica, todavía no puedo dejar de parpadear cada vez que se presiona el botón 5to. Tengo que presionarlo varias veces, a veces dos o incluso más veces. No creo que el uso de interrupciones ayude, ya que no sé cómo podría usarlas en mi problema.

    
pregunta Nick

3 respuestas

3

¿Está seguro de que necesita salir en CUALQUIER momento dondequiera que esté el puntero de ejecución? Normalmente, simplemente puede marcar el botón presionando al final de los bucles while y for y llamar a return cuando se presione.

Algunas veces pensamos que nuestro programa tiene que hacer algo y salir de la ejecución, pero tras un examen cuidadoso, llegamos a la conclusión de que puede terminar una interacción de bucle y luego cerrarse.

¿Podría decirnos qué se hace dentro de los bucles, para que podamos asegurarnos de lo que se necesita?

Editar: Como sospeché, el problema con tu programa es que tus intervalos de demora son demasiado largos, por ejemplo. delay(1000) y delay(500) , y no puede verificar si se presiona un botón mientras el programa está esperando.

Para solucionarlo, cree la siguiente función, que reemplazará sus llamadas para retrasar:

// waits for the specified miliseconds 
// or return (almost) immediately if button is pressed
// return value indicates whether button was pressed or not
boolean waitOrButtonPressed(int miliseconds) {
  for (int i = 0; i < miliseconds / 10; i++) {
    if (readButtons(5)) == 5)
      return true;
    delay(10);
  }
  return false;
}

Luego, dentro de tu bucle for , reemplaza tus llamadas a delay(1000) por el siguiente código:

if (waitOrButtonPressed(1000)) return;

La función que creé hará que su programa espere casi como delay() , pero devolverá true si se presiona un botón durante ese tiempo. Si eso sucede, la instrucción if anterior saldrá de loop() , que será llamada nuevamente por el código generado por Arduino.

Recuerde mantener los milisegundos para esperar cuando reemplace sus llamadas a delay() para mantener el comportamiento de espera de su programa sin cambios.

Edit 2: Ramblings

Casos como este me recuerdan a la película Tron , en la que el personaje principal se arrastra a una computadora, donde El tiempo pasa mucho más lento que en la vida real. Entonces, como en la película, 1000 milisegundos (1s) es MUCHO TIEMPO para la MCU. Puedes hacer mucho más que esperar en ese tiempo. Intenta romper las esperas largas y haz cosas útiles con tus ciclos de MCU.

También, aprenda cómo usar interrupciones, como otros mencionados en sus comentarios y respuestas. Es solo otra forma (un poco más complicada) de hacer cosas mientras esperas. En su caso, se pueden usar interrupciones para detectar la pulsación del botón sin la necesidad de verificarlo en todo momento. Aquí hay un lugar para comenzar a conocer las interrupciones con Arduino .

    
respondido por el Ricardo
2

Un método que puede usarse y tiene el efecto de restablecer el mcu (no estoy seguro de si este es el efecto que está buscando) es usar una interrupción externa para el botón y, dentro de la interrupción, habilitar el perro guardián con un pequeño tiempo de espera y deje que caduque y reinicie el mcu.

    
respondido por el alexan_e
0

Es por esto que C tiene la declaración goto ; para mover hacia adelante fuera de muchos bucles anidados.

La mayoría de las personas le dirán que no lo use, y es probable que pueda solucionarlo, pero ciertamente es una solución a su problema.

    
respondido por el Samuel

Lea otras preguntas en las etiquetas