void loop se ejecuta incluso cuando el bucle while dentro es verdadero en arduino

5

Hice una aplicación móvil simple para enviar LED_ON o LED_OFF cuando se hace clic en un botón. En el código a continuación, el bucle while no se completa completamente durante la ejecución, pero el controlador va al void loop () y continúa desde allí.

char command;
String my_final="LED_OFF";
#define led 9

void setup(){
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  Serial.println("ready");
}

void loop(){
  if(Serial.available() > 0){
    my_final = "";
    while(Serial.available() > 0){
      command = (byte)Serial.read();
      my_final += command;
      Serial.println("test");
    }
    Serial.println(my_final);
    }

  if(my_final == "LED_ON"){
    Serial.println(my_final);
    analogWrite(led, 255);
    my_final == "LED_ON";
  }

  if(my_final == "LED_OFF"){
    Serial.println(my_final);
    analogWrite(led, 0);
    my_final == "LED_OFF";
  }
}

El problema principal ocurre en my_final="" , ya que tengo que hacer esto para aceptar nuevas entradas desde el bluetooth. Parece que no puedo encontrar una solución a este problema.

EDIT

Esto es lo que estoy recibiendo en el monitor de serie. test L test E test D test _ test O test N .

    
pregunta ganesh vicky

4 respuestas

9

La comunicación serie está transmitiendo datos un byte a la vez. Su código es lo suficientemente rápido para leer y procesar un byte antes de que se reciba el siguiente.

Hay muchas soluciones posibles para esto, y usar retrasos no es una buena.

Puede enviar un carácter de marcador al final de cada comando, por ejemplo. %código%. Entonces sabes que tienes que seguir agregando caracteres a tu matriz hasta que veas un signo de exclamación. Un candidato común para un marcador es el carácter de nueva línea.

Otra solución es asegurarse de que todos los comandos tengan la misma longitud (por ejemplo, 6 bytes). Entonces, simplemente puede esperar hasta que reciba tantos caracteres, es decir,

if(Serial.available() >= 6) ...

Tenga en cuenta que en la segunda solución, si pierde un solo byte no podrá recibir los comandos correctamente hasta que vuelva a sincronizar. Para volver a sincronizar, podría, por ejemplo, eliminar el contenido de LED_ON! después de un tiempo de espera, si un comando incompleto permanece allí por mucho tiempo.

    
respondido por el Dmitry Grigoryev
5

@ 9600 Baudrate, está recibiendo datos a 10 bits por milisegundo. Un carácter es 8 bits + bits de inicio y parada en un cuadro. Estás leyendo el búfer más rápido que él. Entonces, una solución simple sería poner un retraso de > 1 ms o menos después de leer en serie (), dentro del bucle.

    
respondido por el MITU RAJ
1

El almacenamiento en búfer hasta que el salto de línea se vea así (mi código arduino está un poco oxidado, así que perdona los errores simples, el algoritmo debería ser correcto):

finished = false;
command = "";
while (!finished) {
   if (Serial.available() > 0) {
      c = (byte)Serial.read();
      if (c == '\n') {
         finished = true;
      }
      else {
         command += c;
      }
   }
}

Este bucle solo continuará leyendo los caracteres y agregando estos caracteres al comando variable.

Esto supone que el enlace de comunicaciones es perfecto, ya que no soltará ni dañará los caracteres. Para hacer que esto sea más sólido, puede hacer un chequeo para asegurarse de que el tiempo para recibir el comando no sea demasiado largo.

También es posible que desee responder a cada comando con una respuesta de acuse de recibo o con un eh? Respuesta (nack), informando al servidor qué está pasando.

Hacer feliz!

    
respondido por el NomadMaker
0

¿Qué sucede cuando el flujo de datos entrante tiene este aspecto?

LE .. Td .. D_O .. Td .. N ?

Td es un pequeño retraso aleatorio.

Si su while(Serial.available() > 0){ es más rápido que Td, tendrá que reiniciar my_final = ""; con solo LE . Es decir, a continuación recibe D_O y luego lo restablece nuevamente.

    
respondido por el Jeroen3

Lea otras preguntas en las etiquetas