Hice una aplicación móvil simple para enviar LED_ON o LED_OFF cuando se hace clic en un botón. En el siguiente código, el ciclo while no se completa completamente durante la ejecución, pero el controlador va al ciclo vacío () 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 my_final=""
cuando tengo que hacer esto para aceptar una nueva entrada del bluetooth. Parece que no puedo encontrar una manera de evitar este problema.
EDITAR
Esto es lo que obtengo en el monitor serial. test L test E test D test _ test O test N
.
La comunicación en serie es la transmisión de datos de 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 bueno.
Puede enviar un carácter de marcador al final de cada comando, por ejemplo, LED_ON!
. Entonces sabrá que debe seguir agregando caracteres a su matriz hasta que vea 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 podrías simplemente esperar hasta que recibas 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 comandos correctamente hasta que vuelva a sincronizar. Para volver a sincronizar, podría, por ejemplo, desechar el contenido de Serial
después de un tiempo de espera, si un comando incompleto permanece allí durante demasiado tiempo.
@9600 Baudrate, está recibiendo datos a 10 bits por milisegundo. Un carácter es de 8 bits + bits de inicio y parada en un marco. 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 más o menos después de la lectura en serie (), dentro del ciclo.
delay(1)
ing después de read()
cuandoSerial.available() == 0
El almacenamiento en búfer hasta que un salto de línea se vea así (mi código arduino está un poco oxidado, así que perdone 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 ciclo seguirá leyendo caracteres y agregando estos caracteres al comando variable.
Esto supone que el enlace de comunicaciones es perfecto, en el sentido de que no perderá ni alterará los caracteres. Para hacer esto más sólido, puede poner un control 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 ack o un huh? (nack) respuesta, dejando que el servidor sepa lo que está pasando.
¡Feliz fabricación!
Qué sucede cuando el flujo de datos entrante se ve así:
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, habrá reiniciado my_final = "";
con solo LE
en él. Es decir, a continuación recibes D_O
, y luego lo reinicias de nuevo.
\n
, pero aún tendrá que sondear Serial.available()
, por lo que tendrá que resolver algo.
Dmitri Grigoriev
while
ciclo con la condiciónSerial.available()
aún siendo verdadera?ganesh vicky
test L test E test D test _ test O test N
Dmitri Grigoriev
while
bucle, lo cual es imposible de ver con un monitor en serie.aarond
my_final == "LED_ON";
supone que debe hacer? (al final delif(my_final == "LED_ON"){}
bloque, y del mismo modo paraOFF
)usuario253751
ganesh vicky