Lectura completa de todos los datos enviados por Serial

Muy buenas, sucede que ando intentando hacer un código para poder obtener todos los datos que lleguen por Serial, ya que como sabemos al momento de enviar por ejemplo: AAAA, el código de ejemplo que da arduino para obtener los datos lee una letra a la vez y no las 4, porque en si así es el protocolo de comunicación. Entonces mi problema está en que yo deseo obtener las 4 letras guardarlas en una variable y luego preguntar si lo que me está llegando por el puerto es lo que deseo o no. He estado intentando con varios códigos que he visto en Internet pero no lo he podido lograr. El código que tengo actualmente es el siguiente:

String Puerto;
String Puerto2 = "";
unsigned int cant = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  serial();
  if (cant == 2) {
    Serial.println("Llego un dato");
    Puerto2 = "";
    cant = 0;
  }
  else {
    Puerto2 = "";
    //loop();
  }
  //Puerto2 = "";
}

void serial(){
  if (Serial.available() > 0) {
    Puerto = Serial.read();
    Puerto2 += Puerto;
    cant = Puerto2.length();
    Serial.println(Puerto2);
    Serial.println(cant);
    serial();
  }
  else{
    loop();
  }
}

Lo que hice fue crear una función para leer el serial y cada vez que entre al ciclo para leer lo que llegó vuelva a la misma función para volver a preguntar si aún hay algo en el puerto y si no ps simplemente vuelve al loop, pero este código no me ha funcionado, de hecho no logro ver nada por el puerto y aún no sé por qué. Si alguien tiene algún código que ya realice esto me lo podría pasar por favor? O me podrían ayudar hacerlo?

Muchas gracias.

Bueno pude resolverlo antes jeje, creo que estuve mucho tiempo buscando lo que no era. Lo pude hacer con la función Serial.readStringUntil('/n') como parámetro el salto de línea.

String Puerto;
unsigned int cant = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    Puerto = Serial.readStringUntil('\n');
    cant = Puerto.length();
    Serial.println(Puerto);
    Serial.println(cant);
  }
  if (cant == 1) {
    Serial.println("Llego un dato");
    Puerto = "";
    cant = 0;
  }
}

Por las pruebas que hice al parecer esta función regresa al Serial.available() si no encuentra el parámetro ingresado por lo que es perfecto para lo que necesito. Lo único negativo es que el tiempo de respuesta es un poco lento pero bueno.

Hola, se me pasó tu consulta. Es cierto lo que dices, he encontrado que Serial.readStringUntil('\n') es bastante lenta para responder luego de que uno realmente presiona el ENTER dandole ingreso a los datos.
Hace poco respondí a alguien por lo mismo y cuando iba a sugerirle esta opción no me convenció, y opte por un método digamos convencional.
Ahora lo busco y lo comporta para que lo evalués. Es lo mismo pero mucho mas rápido.

Este es el hilo Refrescar texto impreso en una Mtriz LED rgb 64x32

Esta es la rutina sugerida pero observa mejor todo el código

  while (Serial.available() > 0) {
        s = (char)Serial.read();
        if (s == '\n') {
            Serial.println(txtMsg); 
            presentar(txtMsg);   // solo envia txtMsg a un cartel RGB
            txtMsg = "";  
        } else {  
            txtMsg +=s; 
        }
    }

Hola surbyte he revisado el link y ps los veo sencillo, sin embargo, lo he probado y no me ha funcionado no sé por qué jajaja, esto es lo que he hecho:

char s;
String txtMsg = "";

void setup() {
  Serial.begin(9600);
}

void loop(){
while (Serial.available() > 0) {
    s = (char)Serial.read();
    Serial.println(s);
    if (s == '\n') {
      Serial.println(txtMsg);
      txtMsg = "";
    } else {
      txtMsg += s;
    }
  }
}

Prácticamente copié y pegué :confused:. El único cambio que puse fue un Serial.println(s), para ver si estaba llegando por el puerto y si está llegando pero al parecer no alcanza a detectar el salto de línea no sé por qué.

Muy bien ya supe cuál fue el error y es que en el monitor serial no había colocado que lo enviara con salto de línea. Creo que ese código me funciona perfecto y es mucho más rápido que la función del Serial.

Muchas gracias.

Te dije es exactamente lo que buscas, cuando presionas ENTER o sea el '\n' ni te enteras que la rutina ya tiene lo que enviaste.
Funciona perfecto, ahora entre nosotros, readStringUntil() debe funcionar pero habrá que ajustarle el TIMEOUT o sea.. debe estar esperando un tiempo antes de procesar. Lo investigo, pero tiene que funcionar bien o mucho mejor que cuando no se le pone nada mas que el caracter con el que termina.

Según esto:

readStringUntil() reads characters from the serial buffer into a string. The function terminates if the terminator character is detected or it times out (see setTimeout()).

Debería terminar cuando detecta el caracter COSA QUE NO HACE y achicar el timout.. pero no se que ocurre. Yo tmb experimenté su lentitud.

Como siempre hay una explicación.
Si usas

int myTimeout = 250;  // milliseconds for Serial.readString

y luego en el setup()

Serial.setTimeout(myTimeout);

verás que funciona mejor.

Lo he probado y uff la verdad es que si mejoró muchísimo, sin embargo, no sé si este cambio del Timeout traiga alguna repercusión o afecte en algo ¿hay algún punto negativo para esto?.

Por otro lado realicé dos códigos para verificar el tiempo que demora cada uno en ejecutar las lecturas, pero cuando ejecuto el código que tu me mostraste inicialmente supuestamente el tiempo es 0 lo cual creo que es un error, pero ya he revisado todo y la verdad es que no tengo idea por qué me dice eso. Aquí el código.

int i = 0;
char Puerto;
String str[9];
String SumaPuerto = "";

unsigned long tiempo;
unsigned long tiempoant = 0;
const long intervalo = 5000;

unsigned long tiempo2;
unsigned long tiempoant2 = 0;
unsigned long resta;

void setup() {
  Serial.begin(9600);
}

void loop() {
  tiempo = millis();
  if (tiempo - tiempoant >= intervalo) {
    tiempoant = tiempo;
    Serial.println("A");
    tiempo2 = millis();
    Serial.println(tiempo2);
    while (Serial.available() > 0) {
      Puerto = (char)Serial.read();
      if (Puerto == ';') {
        str[i] = SumaPuerto;
        i += 1;
        SumaPuerto = "";
        if (i == 9) {
          i = 0;
          tiempoant2 = millis();
          Serial.println(tiempoant2);
          resta = tiempoant2 - tiempo2;
          Serial.print("Tiempo: ");
          Serial.println(resta);
          for (int j = 0; j <= 9; j++) {
            Serial.print(str[j]);
          }
          Serial.println("");
        }
      } else {
        SumaPuerto += Puerto;
      }
    }
  }

}

Sin embargo, con el otro código ya modificado con el setTimeout me marca un tiempo de 251 milisegundos en enviar los datos. Aquí el código.

int i = 0;
String str[9];

unsigned long tiempo;
unsigned long tiempoant = 0;
const long intervalo = 5000;

unsigned long tiempo2;
unsigned long tiempoant2 = 0;
unsigned long resta;

int myTimeout = 250;

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(myTimeout);
}

void loop() {
  tiempo = millis();
  if (tiempo - tiempoant >= intervalo) {
    tiempoant = tiempo;
    Serial.println("A");
    tiempo2 = millis();
    if (Serial.available() > 0) {
      for (i = 0; i <= 9; i++) {
        str[i] = Serial.readStringUntil(';');
      }
      tiempoant2 = millis();
      resta = tiempoant2 - tiempo2;
      Serial.print("Tiempo: ");
      Serial.println(resta);
      for (i = 0; i <= 9; i++) {
        Serial.print(" ");
        Serial.print(str[i]);
      }
    }
  }
}