Go Down

Topic: [SOLUCIONADO] PROBLEMA CON BUCLES (Read 336 times) previous topic - next topic

Ruben17

Jul 18, 2018, 11:03 pm Last Edit: Jul 19, 2018, 08:56 pm by Ruben17
Hola buenas, necesito ayuda con este código porque no soy capaz de, mediante el monitor serie, cambiar de un bucle a otro al enviar el valor 1 o 2. Llevo un par de días atascado mirando en Internet información sobre el uso de estos bucles while y he intentado todo lo que he podido pero no hay manera de que haga lo que yo quiero.

Code: [Select]

int LED = 13;
int Dato;

void setup()
{
  Serial.begin (9600);
  pinMode (LED, OUTPUT);
}

void loop()
{
  if (Serial.available())
  {
    Dato = Serial.read();

    while (Dato == '1')
    {
      digitalWrite (LED, HIGH);
      delay (1000);
      digitalWrite (LED, LOW);
      delay (1000);
    }

    while (Dato == '2')
    {
      digitalWrite (LED, HIGH);
      delay (250);
      digitalWrite (LED, LOW);
      delay (250);
    }
  }
}

Lo que quiero que haga es que el led de la placa conectado al PIN 13 parpadee cada 1 segundo cuando le mando por el puerto serie el número 1 y que cuando le mando el número 2 parpadee cada 1/4 de segundo. El problema que tengo es que cuando le mando el número 1 si hace el bucle que le corresponde pero cuando le mando el valor 2 no me hace caso y se queda pillado en el anterior bucle. No consigo solucionar eso.

Swift

#1
Jul 19, 2018, 12:24 am Last Edit: Jul 19, 2018, 12:35 am by Swift
Creo que no estas entendiendo muy bien cómo funcionan los bucles te dejo algo para que leas:
While
Do-While
For
Ahora en tu código como tu bien dices:
Quote
El problema que tengo es que cuando le mando el número 1 si hace el bucle que le corresponde pero cuando le mando el valor 2 no me hace caso y se queda pillado en el anterior bucle. No consigo solucionar eso.
La primera vez funciona por que no has entrado en ningún bucle entonces puede asignar la variable que pongamos el ejemplo tú mandas 1 por el puerto serial entonces a dato le asigna 1 por lo cual va a entrar al primer bucle pero nunca más sale  porque dato siempre va a ser 1 ya que no tiene otra forma de donde leer el puerto serie:

Code: [Select]
while (Dato == '1')
    {
      digitalWrite (LED, HIGH);
      delay (1000);
      digitalWrite (LED, LOW);
      delay (1000);
    }

Intenta plantearlo de otra manera además que no utilices delay ya que en esa parte se queda el arduino esperando y por lo tanto no realizará otra acción  hasta que pase el delay te recomiendo que leas cómo funciona millis y un ejemplo de millis y led.

surbyte

ve a documentación => Indice de temas tutoriales => millis() para entender esto que te pongo a continuación.

tambien estudia que es una máquina de estados.

Posible solución

Code: [Select]
int LED = 13;
int Dato;
unsigned long start1, start2;
byte estado1 = 0, estado2 = 0;

void setup()
{
  Serial.begin (9600);
  pinMode (LED, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    Dato = Serial.read();
   
  }

  switch(Dato) {
    case '1': secuencia1();
              break;

    case '2': secuencia2();
              break;
  }
}

void secuencia1() {
  switch(estado1) {
    case 0: digitalWrite (LED, HIGH);
            start1 = millis();
            estado1 = 1;
            break;
    case 1: if (millis() - start1 > 1000UL) {
                estado1 = 2;
                digitalWrite (LED, LOW);
                start1 = millis();
            }
            break;
    case 2: if (millis() - start1 > 1000UL) {
                estado1 = 0;
            }
            break;
  }
}

void secuencia2() {
  switch(estado2) {
    case 0: digitalWrite (LED, HIGH);
            start2 = millis();
            estado2 = 1;
            break;
    case 1: if (millis() - start2 > 250UL) {
                estado2 = 2;
                digitalWrite (LED, LOW);
                start2 = millis();
            }
            break;
    case 2: if (millis() - start2 > 250UL) {
                estado2 = 0;
            }
            break;
  }
}

Ruben17

Muchas gracias por vuestra ayuda, me voy a leer toda esa documentación que habéis indicado y estudiare a ver que es eso de la máquina de estados para aprender cosas nuevas. El código nuevo funciona justo como yo quería.
Saludos.

Ruben17

Siento haberme adelantado antes ha despedirme. Me ha surgido una duda aquí.
Code: [Select]

if (millis() - start1 > 1000UL)

No entiendo lo del interior del if.

torke100

¿Y por qué no dejarlo así y poner la variable DATO a 0 u otro valor distinto de 1 - 2 antes de salir de cada bucle. Debería funcionar, creo yo.

Ruben17

Voy a poner como SOLUCIONADO el post. Ya he trabajado con el programa y lo entiendo, funciona perfecto. Muchas gracias a todos.

surbyte

Quote
¿Y por qué no dejarlo así y poner la variable DATO a 0 u otro valor distinto de 1 - 2 antes de salir de cada bucle.
Porque esa no era la pregunta.
La pregunta esta relacionado con el problema que genera delay().
Ya lo expliqué. Delay detiene y tu esperas presionar algo y que responda y si tienes un delay de 1 seg tienes que esperar 1 seg pero si tienes varios delay hay que esperar que se cumplan todos para que responda a tu comando.

En cambio usando millis() y maquina de esatados eso no ocurre. El programa fluye, mira si hay cambios, ejecuta cosas y sigue y sigue..
De ese modo no hay detenciones.


Go Up