Datos incompletos recibidos del puerto serial

Hola espero que estén bien, llevo muy poco tiempo con usando lo que es Arduino y por lo que veo es una gran comunidad que la verdad es fabuloso, actualmente estoy trabajando en un proyecto que es un pastillero electrónico, en el cual trabaja de la siguiente manera:

  • Recibe por el puerto serial y guarda en una variable String los datos de las pastillas que tiene el siguiente formato:
  • NombrePast1,Cantidad1,nroHoras1,hora1|hora2|hora3...._NombrePast2,Cantidad2,nroHoras2,hora1|hora2|hora3....._NombrePast3,Cantidad3,nroHoras3,hora3|hora3|hora3....._NombrePast4,Cantidad4,nroHoras4,hora1|hora2|hora3....*
  • Luego estos datos se separan y guardan mediante un método que implemente en un arreglo multidimensional de String llamado datPast[4][4].
[code]
void loop() {
     if(digitalRead(pulsadorRecirDat) == HIGH){
       datReci = recibirDatos(); //LLAMO A LA FUNCION PARA RECIBIR LOS DATOS datReci
       separadoGuardado(datReci); //FUNCION QUE Separa los datos y Los guarda en el Array datPast[4][4]
     }
}
String recibirDatos(){
     String datos = "";
     while(1){
          if(Serial.available()>0){
             delay(1000);
             while(Serial.available()>0){
                 recibDatPC += (char)Serial.read();
             }
                 recibDatPC.trim();
                 Serial.println(recibDatPC); //AGREGE ESTO PARA MOSTRARLO EN EL MONITOR
                 break;
     }
     return recibDatPC;
}

[/code]

Y es en el punto numero 1 donde tengo problemas muchas veces ya que en la mayoría de casos no me recibe todos los datos ejemplo yo inserto en el monitor serial lo siguiente
**PastillaA,1,2,15:30|15:40_PastillaB,1,2,15:50|16:0PastillaC,1,2,16:30|16:40**PastillaD,1,2,17:0|17:40

En la mayoría de casos el resultado que se muestra el monitor es el siguiente:
**PastillaA,1,2,15:30|15:40_PastillaB,1,2,15:50|16:0PastillaC,1,2,16:30|16:40**PastillaD,1,2,17
O en algunos casos
**PastillaA,1,2,15:30|15:40_PastillaB,1,2,15:50|16:0PastillaC,1,2,16:30|16:40**PastillaD,1,2,17:0
Y en extraños casos se obtienen los datos completos
**PastillaA,1,2,15:30|15:40_PastillaB,1,2,15:50|16:0PastillaC,1,2,16:30|16:40**PastillaD,1,2,17:0|17:40

Y como resultado de este problema los datos se guardan incompletos en datPast [4] [4]
Ya intente muchas cosas como subiendo los baudios en Serial.begin (115200); o otro valor intente tambien aumentando Serial.setTimeout() y también intente leer los datos usando Serial.readString (); pero no obtengo resultados favorables.
Espero que puedan ayudarme con este problema desde ya muchas gracias de antemano por su tiempo y ayuda.

Creo que tu problema es que si no pulsas el botón al mismo tiempo que llegan los datos se llena el buffer de recepción (solo tiene 64 bytes, o sea, 64 caracteres) y pierdes el resto.
¡Y para peor pones un delay de 1 segundo en medio!

Una solución es usar serialEvent() que, como su nombre lo indica, se dispara cada vez que llegan datos.
Algo así

String datReci;
bool hayDatos;

void loop(){
  if(digitalRead(pulsadorRecirDat) == HIGH){
    if(hayDatos){
       datReci.trim();
       Serial.println(datReci);
       separadoGuardado(datReci); 
       datReci = "";
       hayDatos = false;
     }
  }
}

void serialEvent() {  // esta función va siempre despues de loop()
  while(Serial.available()) {
    char inChar = Serial.read();
    datReci += inChar;
  }
  hayDatos = true;
}

Lo he simulado y en principio funciona pero me sigue truncando en 64 caracteres (creo que la consola del simulador no envía más de 64 caracteres por vez).
Prueba si en el arduino "de verdad" funciona como debería.

gatul:
Creo que tu problema es que si no pulsas el botón al mismo tiempo que llegan los datos se llena el buffer de recepción (solo tiene 64 bytes, o sea, 64 caracteres) y pierdes el resto.
¡Y para peor pones un delay de 1 segundo en medio!

Una solución es usar serialEvent() que, como su nombre lo indica, se dispara cada vez que llegan datos.
Algo así

String datReci;

bool hayDatos;

void loop(){
 if(digitalRead(pulsadorRecirDat) == HIGH){
   if(hayDatos){
      datReci.trim();
      Serial.println(datReci);
      separadoGuardado(datReci);
      datReci = "";
      hayDatos = false;
    }
 }
}

void serialEvent() {  // esta función va siempre despues de loop()
 while(Serial.available()) {
   char inChar = Serial.read();
   datReci += inChar;
 }
 hayDatos = true;
}



Lo he simulado y en principio funciona pero me sigue truncando en 64 caracteres (creo que la consola del simulador no envía más de 64 caracteres por vez). 
Prueba si en el arduino "de verdad" funciona como debería.

Hola muchas gracias por responder hice lo que me recomendaste y sigue igual se corta en 64 caracteres

Eliminé un par de post porque ya no tenían sentido.

Después de renegar con la consola que uso en el celular (perdía datos al recibir del arduino) fui al PC y todo resultó como esperaba.
El código que funciona sin perder ni un solo caracter es éste

const byte PIN_BTN = 12;

String datReci ="";
bool hayDatos=false;

bool get_button() {
  static bool stat = false;
  static bool oldstat = false;
  static bool debouncer = false;
  static unsigned long oldtime = 0;
  
  if(debouncer) {
    if(millis() - oldtime >= 20UL) {
      debouncer = false;
    }
  }
  else {
    stat = !digitalRead(PIN_BTN);  // pulsador a masa
//  stat = digitalRead(PIN_BTN);   // pulsador a +V
    if(stat != oldstat) { 
        oldstat = stat;
        debouncer = true;
        oldtime = millis();
    }
  }
  return stat;
}
      
void setup(){
  Serial.begin(115200);
  pinMode(PIN_BTN, INPUT_PULLUP);  // solo para pulsador a masa
}

void loop(){
  if(get_button()){
    if(hayDatos){
//      datReci.trim();
      Serial.println(datReci);  // supongo que después lo eliminas
      Serial.flush();           // esta línea también elimínala despues de las pruebas
      separadoGuardado(datReci);
      datReci = "";
      hayDatos = false;
    }
  }
}

void serialEvent() {  // esta función va siempre despues de loop()
  while(Serial.available()) {
    char inChar = Serial.read();
    datReci += inChar;
  }
  if(datReci.length()>0) hayDatos = true;
}

Agregué una rutina de lectura del pulsador con antirrebote porque también podrían provocar fallos los rebotes

Lo máximo fue 1667 caracteres a 115200 bps de una sola pasada, nada mal para un procesador con solo 2kB de memoria.

Obviamente es la base (este código es mínimo), cuando tu código crezca va a usar seguramente más variables por ende más memoria y va a disminuir la cantidad de caracteres que podrás recibir por vez. Igual no creo que necesites tantos caracteres.

Te dejo captura de pantalla de la consola del IDE donde se ve el máximo de 1667 caracteres procesados y la memoria libre de 160 bytes (supongo que es lo mínimo que el micro necesita para funcionar por eso no toma más datos)

Saludos