Aquí hay una implementación más robusta que maneja condiciones anormales de entrada y carrera.
- Detecta valores de entrada inusualmente largos y los descarta con seguridad. Por ejemplo, si la fuente tenía un error y una entrada generada sin el terminador esperado; o fue malicioso.
- Asegura que el valor de la cadena siempre es nulo terminado (incluso cuando el tamaño de la memoria intermedia está completamente lleno).
- Espera hasta que se capture el valor completo. Por ejemplo, los retrasos en la transmisión pueden hacer que Serial.available() vuelva a cero antes de que el resto del valor termine de llegar.
- No omite valores cuando varios valores llegan más rápido de lo que pueden procesarse (sujeto a las limitaciones del buffer de entrada en serie).
- Puede manejar valores que son un prefijo de otro valor (por ejemplo, "abc" y "abcd" pueden leerse).
Utiliza deliberadamente matrices de caracteres en lugar del tipo String
, para ser más eficaz y evitar problemas de memoria. También evita usar la función readStringUntil()
para no tener que esperar hasta que llegue la entrada.
La pregunta original no decía cómo se definen las cadenas de longitud variable, pero supongo que terminan con un solo carácter de nueva línea, lo que lo convierte en un problema de lectura de línea.
int read_line(char* buffer, int bufsize)
{
for (int index = 0; index < bufsize; index++) {
// Wait until characters are available
while (Serial.available() == 0) {
}
char ch = Serial.read(); // read next character
Serial.print(ch); // echo it back: useful with the serial monitor (optional)
if (ch == '\n') {
buffer[index] = 0; // end of line reached: null terminate string
return index; // success: return length of string (zero if string is empty)
}
buffer[index] = ch; // Append character to buffer
}
// Reached end of buffer, but have not seen the end-of-line yet.
// Discard the rest of the line (safer than returning a partial line).
char ch;
do {
// Wait until characters are available
while (Serial.available() == 0) {
}
ch = Serial.read(); // read next character (and discard it)
Serial.print(ch); // echo it back
} while (ch != '\n');
buffer[0] = 0; // set buffer to empty string even though it should not be used
return -1; // error: return negative one to indicate the input was too long
}
Aquí es un ejemplo de lo que se utiliza para leer comandos desde el monitor serie:
const int LED_PIN = 13;
const int LINE_BUFFER_SIZE = 80; // max line length is one less than this
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
Serial.print("> ");
// Read command
char line[LINE_BUFFER_SIZE];
if (read_line(line, sizeof(line)) < 0) {
Serial.println("Error: line too long");
return; // skip command processing and try again on next iteration of loop
}
// Process command
if (strcmp(line, "off") == 0) {
digitalWrite(LED_PIN, LOW);
} else if (strcmp(line, "on") == 0) {
digitalWrite(LED_PIN, HIGH);
} else if (strcmp(line, "") == 0) {
// Empty line: no command
} else {
Serial.print("Error: unknown command: \"");
Serial.print(line);
Serial.println("\" (available commands: \"off\", \"on\")");
}
}
Por favor, compruebe mi respuesta a continuación, es mucho más fácil/simple de lo que la respuesta que eligió –