Datos por serial entran entrecortados

¡Hola!
Estoy en un proyecto con un Arduino Mega2560 y un módulo SIM800L y tengo un problema.
Tengo el módulo conectado en el serial físico 2 (con el 1 pasa igual) del Mega.
Cuando envío un SMS desde mi teléfono hacia el módulo, a veces el texto del mensaje (donde figura la hora, la fecha, el número remitente y el cuerpo del mensaje) se muestra bien en el serial de la pc y otras no. Por ejemplo, si envío por SMS el texto "12345678901234567890", a veces llega todo y otras veces se muestran bien el número remitente, la fecha y la hora, pero en el cuerpo del mensaje puede mostrarse "1234567890123" solamente, es decir que corta la última parte. Y a veces quita algunos caracteres del medio del cuerpo del mensaje.
Cuando quito del loop la función "verificarRed", el problema ya no pasa todo el tiempo sino que pasa, por ejemplo, una de 15 o 20 veces.
En el loop probé recibiendo la información del serial del módulo GSM con "readStringUntil" y con "read()" (leyendo carácter por carácter) y el problema sigue igual.
¿Qué estaré haciendo mal o no teniendo en cuenta?
¡Muchas gracias!

Jerónimo

String respuestaLoop;

unsigned long inicioCorteRed;
unsigned long inicioCorteRed2;
byte pinRed = 5;
byte pinRed2 = 6;
byte numeroCorteRed;
byte numeroCorteRed2;

void setup() {

  Serial.begin(9600);
  Serial2.begin(19200);

  pinMode(pinRed, INPUT_PULLUP);
  pinMode(pinRed2, INPUT_PULLUP);

  numeroCorteRed = 0;
  numeroCorteRed2 = 0;

  encenderGsm();

  boolean shieldActivo = false;
  while (shieldActivo == false) {
    shieldActivo = verificarGsm();
  }

  prepararGsm();

}

void loop() {
  if (Serial2.available() > 0) {
    respuestaLoop = Serial2.readString();
    Serial.println(respuestaLoop);
    esperar(3000);
    procesarRspuesta(respuestaLoop);
  } else {
    if ((millis() - tIntervalo) /1000 / 60 >= inter) {
      //Tomar la temperatura.
      leerTemperatura();
      esperar(3000);
      leerTemperatura();
      verificarValores();
    } else {
        if (verificarRed() == true) {
          enviarAlarma('r');
        }

    }

  }
}

boolean enviarAlarma(char tipo) {
//Aquí se envía un SMS.      
}

void encenderGsm() {
  pinMode(9, OUTPUT);
  digitalWrite(9, HIGH);
  esperar(1000);
  digitalWrite(9, LOW);
  esperar(100);
  digitalWrite(9, HIGH);
  esperar(3000);
}

boolean verificarGsm() {
  char inchar;
  char prevchar;
  Serial2.println("AT");
  unsigned long T1;
  T1 = millis();
  while (millis() - T1 < 100);

  if (Serial2.available()) {
    while (Serial2.available()) {
      inchar = Serial2.read();
      if (inchar == 'K' && prevchar == 'O') {
        return true;
      } else {
        prevchar = inchar;
      }
    }
  }
  return false;
}

void esperar(unsigned long tiempoEspera) {
  unsigned long T1;
  T1 = millis();
  while (millis() - T1 < tiempoEspera);
}

void procesarRespuesta(String respuesta) {
//Aquí se procesa la respuesta que entró por el serie del GSM en el loop.
}

boolean verificarRed() {
  boolean mostrar = false;
  byte Valor = digitalRead(pinRed);
  if (Valor != hayRed) {
    if (numeroCorteRed == 0) {
      numeroCorteRed++;
      inicioCorteRed = millis();
    } else if (numeroCorteRed == 1) {
      //Si pasaron los 10 segundos...
      if (millis() - inicioCorteRed >= 10000) {
        hayRed = Valor;
        numeroCorteRed = 0;
        mostrar=true;
      }
    }
  } else {
    numeroCorteRed = 0;
  }

  esperar(100);
  
  byte ValorA = digitalRead(pinRed2);
  if (ValorA != hayRed2) {
    if (numeroCorteRed2 == 0) {
      numeroCorteRed2++;
      inicioCorteRed2 = millis();
    } else if (numeroCorteRed2 == 1) {
      //Si pasaron los 10 segundos...
      if (millis() - inicioCorteRed2 >= 10000) {
        hayRed2 = ValorA;
        numeroCorteRed2 = 0;
        mostrar=true;
      }
    }
  } else {
    numeroCorteRed2 = 0;
  }
  
  return mostrar;
}

void prepararGsm() {
//Aquí se prepara el dispositivo GSM enviando los comandos necesarios.
}

Y que es esto ?

void esperar(unsigned long tiempoEspera) {
   unsigned long T1;
   T1 = millis();
   while (millis() - T1 < tiempoEspera);
}

Lo que pasa es que tu variable respuestaLoop carga lo que tenga en ese momento en buffer y luego mandas al Arduino dormir 3 segundos. Dale oportunidad de capturar todo el buffer.

String respuestaLoop;
unsigned long tIntervalo;

void loop(){
   while (Serial2.available()){
      char caracter = Serial2.read();
      respuestaLoop.concat(caracter);
      delay(2);
   }
   if (respuestaLoop != ""){
      procesarRespuesta(respuestaLoop);
      Serial.println(respuestaLoop);
      respuestaLoop = "";
   }
   if (millis() - tIntervalo >= 3000) {
         tIntervalo = millis();
         leerTemperatura();
         verificarValores();
   }
}

Hola, Kike_GL.

Kike_GL:
Y que es esto ?

void esperar(unsigned long tiempoEspera) {

unsigned long T1;
  T1 = millis();
  while (millis() - T1 < tiempoEspera);
}

En lugar de usar delay creé esa función para que el Arduino espere el tiempo que le pida antes de continuar con otra sentencia. ¿Está mal también?
Había probado leer carácter por carácter pero había tenido el mismo resultado (no le ponía "delay(2)"). Lo voy a probar con el delay.
Y algo que también me gustó de tu recomendación es hacer todo secuencialmente, es decir, ver si hay información en el serial; si la hay, correr los procesos que necesito y luego hacer la verificación (de acuerdo al tiempo transcurrido) para ver si debo tomar la temperatura, etc. Yo esto último lo ponía dentro del "else" cuando verificaba si había información en el serial.
Voy a probar estas cosas y luego volveré con el resultado.
¡Muchas gracias!

Jerónimo

Hola.
Sigue pasando lo mismo. Le mandé tres mensajes iguales y obtuve respuestas diferentes.
El texto del mensaje enviado en ambos casos fue: 12345678901234567890
En el primer caso, la respuesta obtenida por el serial del SIM800L fue la siguiente(los guiones los agrego yo al mostrar la información por el serial de la computadora para ver dónde empieza y dónde termina lo recibido desde el módulo):

+CMT: 011xxxxxxxx,,19/05/09,19:10:44-12
12345678901234567890


Y en los otros dos casos, fue:

+CMT: 011xxxxxxxx,,19/05/09,19:11:16-12
12345678901234


¿Se te ocurre qué puede estar pasando?
Muchas gracias.

Jerónimo

¡Hola!
Estuve leyendo en el foro de inglés que si uno tiene en el loop alguna función que demore un poco, eso puede afectar la recepción de datos por el puerto serial. Siendo así, seguramente me esté pasando eso ya que si elimino todo el código del loop y dejo solo la parte inherente a la recepción de datos del serial del módulo GPRS, anda bien. Y cuando le dejo las funciones de verificar red y verificar temperatura, se corta el texto del SMS que proviene del módulo GPRS y al final viene indefinidamente el carácter "⸮". Si muestro en pantalla cada carácter que voy recibiendo por el serial, la respuesta que obtengo es:

+CMT: "011xxxxxxxx","","19/05/12,11:39:13-12"

12345678901234⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

El último carácter (⸮) sigue entrando por el puerto indefinidamente.
Entonces, dado principalmente que la lectura de temperatura toma 2 segundos y debo hacerla dos veces seguidas, la pregunta es: ¿cómo puedo hacer para poder poner otras funciones en el loop y que ellas no afecten la recepción de datos por el puerto serial?
Por otra parte, para verificar la red se me ocurrió poner el pin donde tengo conectado el relay en un pin del Arduino con interrupción, así no tengo que estar verificando todo el tiempo desde el loop. ¿Será positivo este cambio?
Muchas gracias.

Jerónimo