Parar un bucle(while, do while, for) con la consola

Hola, soy un estudiante en ingeniería informática de primer año y es la primera vez en mi vida que hago arduino y tengo un problema con un ejercicio práctico que trata de controlar con la consola 3 leds haciendo que cuando escribo:

  • ‘A’ los tres leds se encienden
  • ‘B’ los tres leds se encienden de forma rotativa. (En blucle hasta que entre en la consola otra letra)
  • ‘C’ se apagan los leds.

El problema me viene cuando intento escribir la ‘B’ pues o solo me hace una secuencia o se convierte en un bucle haciendo que después no pueda cambiar a otra de las dos opciones.

He probado hacer los 3 casos con if, else if, else if y con switch (este es el que tengo en el código) haciendo que dentro del caso ‘B’ haga un bucle y me deje enviar otro valor al mismo tiempo pero como ya he explicado antes no me ha funcionado.

int option;
int entC=13;
int entB=12;
int entA=11;
void setup() {
  Serial.begin(9600);
  pinMode(entC,OUTPUT);
  pinMode(entB,OUTPUT);
  pinMode(entA,OUTPUT);
}

void loop() {
  if(Serial.available()>0){
    option=Serial.read();
    switch (option) {
    case 'A':
      option=Serial.read();
      digitalWrite(entA,HIGH);
      digitalWrite(entB,HIGH);
      digitalWrite(entC,HIGH);
      Serial.println("ON");
      break;
    case 'C':
      option=Serial.read();
      digitalWrite(entA,LOW);
      digitalWrite(entB,LOW);
      digitalWrite(entC,LOW);
      Serial.println("OFF");
      break;
      case 'B':
     while (option == 'B'){
       if (Serial.read()=='B'){
      break; 
       }else{
    digitalWrite(entA, HIGH);
    digitalWrite(entB, LOW);
    digitalWrite(entC, LOW);
    delay(1000);
    digitalWrite(entA, LOW);
    digitalWrite(entB, HIGH);
    digitalWrite(entC, LOW);
    delay(1000);
    digitalWrite(entA, LOW);
    digitalWrite(entB, LOW);
    digitalWrite(entC, HIGH);
    delay(1000);
    
    }break;}
    }}}

Uso arduino UNO.

Muchas gracias :grinning:

Y cual es el problema de hacerlo asi?

void loop() {
  if (Serial.available() > 0) {
      
      option = Serial.read();

      switch (option) {
          case 'A': option=Serial.read();
                    digitalWrite(entA, HIGH);
                    digitalWrite(entB, HIGH);
                    digitalWrite(entC, HIGH);
                    Serial.println("ON");
                    break;

          case 'C': option=Serial.read();
                    digitalWrite(entA, LOW);
                    digitalWrite(entB, LOW);
                    digitalWrite(entC, LOW);
                    Serial.println("OFF");
                    break;

          case 'B': digitalWrite(entA, HIGH);
                    digitalWrite(entB, LOW);
                    digitalWrite(entC, LOW);
                    delay(1000);
                    digitalWrite(entA, LOW);
                    digitalWrite(entB, HIGH);
                    digitalWrite(entC, LOW);
                    delay(1000);
                    digitalWrite(entA, LOW);
                    digitalWrite(entB, LOW);
                    digitalWrite(entC, HIGH);
                    delay(1000);
                    break;
          default: break;
        }
    }
}

Cuando leas datos del monitor serie no vuelvas a hacerlo dentro del mismo loop. Se hace en un sitio y de ahi se controla el flujo del programa.

cuando presiones algo diferente a A,B,C simplemente no hace nada

No sé si me he explicado bien pero lo que intento conseguir es que al entrar 'B' en la consola se quede haciendo un bucle y poderlo parar entrando 'A' (que en este caso encendería todos los leds) o 'C' (que los apagaría todos).
Con este código lo que me pasa es que no se queda haciendo un bucle sino que acaba con el led que esta en entC=13 encendido después de haber hecho lo que está escrito en

case 'B': digitalWrite(entA, HIGH);
                    digitalWrite(entB, LOW);
                    digitalWrite(entC, LOW);
                    delay(1000);
                    digitalWrite(entA, LOW);
                    digitalWrite(entB, HIGH);
                    digitalWrite(entC, LOW);
                    delay(1000);
                    digitalWrite(entA, LOW);
                    digitalWrite(entB, LOW);
                    digitalWrite(entC, HIGH);
                    delay(1000);
                    break;
          default: break;
        }

Adjunto la imagen de como se queda cuando entro 'B'. (Es un enlace a google drive)

https://drive.google.com/open?id=1s043JtyNS3vu9aPKO_3ywIDsFBrlQw7A

Debe haber muchas formas de hacerlo pero acá lo tienes.

con un poco de esfuerzo de tu parte lo hubieras resuelto igualmente.

i

nt option, comando;
const byte entC = 13;
const byte entB = 12;
const byte entA = 11;
unsigned int contador;

void setup() {
  Serial.begin(9600);
  pinMode(entC,OUTPUT);
  pinMode(entB,OUTPUT);
  pinMode(entA,OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
      
      option = Serial.read();
      if (option != '\r' && option != '\n')
          comando = option;
  }

  switch (comando) {
      case 'A': digitalWrite(entA, HIGH);
                digitalWrite(entB, HIGH);
                digitalWrite(entC, HIGH);
                Serial.println("ON");
                comando = 0;
                break;

      case 'C': digitalWrite(entA, LOW);
                digitalWrite(entB, LOW);
                digitalWrite(entC, LOW);
                Serial.println("OFF");
                comando = 0;
                break;

      case 'B': Serial.print("Ciclo: " +String(contador++));
                digitalWrite(entA, HIGH);
                digitalWrite(entB, LOW);
                digitalWrite(entC, LOW);
                delay(1000);
                digitalWrite(entA, LOW);
                digitalWrite(entB, HIGH);
                digitalWrite(entC, LOW);
                delay(1000);
                digitalWrite(entA, LOW);
                digitalWrite(entB, LOW);
                digitalWrite(entC, HIGH);
                delay(1000);
                break;
      default: break;
    }
}

Cada comando = 0 termina la secuencia pero no ocurre lo mismo con B que debe esperar algun comando del Monitor Serie.
El sistema es lento en reaccionar debido a los 3 delays o sea tiene 3 segundos de demora.

Aprende a trabajar sin delay(), usa millis()

Muchas gracias, la verdad es que para hacer ese programa (aunque no lo creas) he estado más de dos horas y veía que no me llevaba a ninguna parte a demás de que no sabía en lo que estaba fallando.

Aunque tengo una duda sobre el código que me has pasado.
En la parte de

 if (option != '\r' && option != '\n')
          comando = option;

No entiendo que tratas de hacer aquí.

hay un compañero tuyo que probablemente esta haciendo el mismo ejercicio y ha preguntado algo muy similar

el caso es que aquí esta la explicación

Cuando digitas algo en el monitor Serie y le das ENTER para ingresarlo, se envían dos caracteres más, un \r y un \n

Lo que hace ese código es descartarlos para que no afecten el control de tu programa.

\r es Retorno de carro o Carriage-return
\n es Nueva linea o Line-feed.

Si digitas A en realidad llegan 3 cosas : 'A' + '\r' + '\n'

quieres verlo coloca esto

 if (Serial.available() > 0) {
      Serial.println(option, HEX); // lo veras como Hexadecimal y entonces '\r'sera 0x0a y '\n' sera 0x0d
      option = Serial.read();

Entonces tu crees que solo llega 'A' pero los otros dos caracteres complican el código porque para A y C detienen el proceso pero para B que queremos que siga no sirven.