Control automático y manual de 2 bombas, no envía notificaciones de mensaje apropiadamente con SIM800L

Estoy realizando un pequeño proyecto en la cual requiero controlar dos bombas de agua de manera manual, enviando comandos de apagado y encendido y que el sensor de caudal encienda y apague de manera automática las bombas cuando haya presencia de agua o no.

Sensor De Flujo Yf-s201

Le he dado vuelta pero no he conseguido combinar lo automático con lo manual. pero el principal problema radica en que no he podido enviar de manera optima la notificación o mensaje por medio del modulo SIM800L siempre recibo en el celular las notificaciones repetidas ej;bomba1 encendido y bomba1 apagada infinitas veces que no es lo apropiado, aun no he agregado en el código la bomba2. Así es como lo intente.

#include <SoftwareSerial.h>

//CONFIGURACION DE UART GSM
#define CONFIG_GSM_RXPIN 9
#define CONFIG_GSM_TXPIN 10
#define CONFIG_GSM_BAUDRATE 9600

//PUERTO SERIE EMULADO: EL ARDUINO UNO TIENE SOLO 1 UART
//EN EL CONSTRUCTOR DE SOFTWARESERIAL SE ESPECIFICAN LOS PINES PARA RX Y TX
SoftwareSerial SerialComSim800 = SoftwareSerial(CONFIG_GSM_RXPIN, CONFIG_GSM_TXPIN);

//VARIABLES DE ENTRADA Y SALIDA DE MENSAJES
String mensaje;
String mensajeenviado;

//VARIABLES SENSOR
volatile int NumPulsos;             //variable para la cantidad de pulsos recibidos
int PinSensor = 2;                  //Sensor conectado en el pin 2 
float factor_conversion= 7.5;        //para convertir de frecuencia a caudal
int caudal = 0;
int contcaudal = 0;
int resicaudal = 0;

bool est_ant_sensor = LOW;

//VARIABLES CONTROL BOMBA
#define BOMBA1 11 
#define BOMBA2 12
volatile bool est_ant_bomba1 = HIGH;
bool est_ant_bomba2 = HIGH;
int cont_bombaError = 0;

//CODIGO SENSOR DE FLUJO
//FUNCION QUE SE EJECUTA EN INTERRUPCION
void ContarPulsos (){ 
 
  NumPulsos++;                       //incrementamos la variable de pulsos
  } 

//FUNCION PARA OBTENER FRECUENCIA DE LOS PULSOS
int ObtenerFrecuencia(){
  
  int frecuencia;
  NumPulsos = 0;                     //Ponemos a 0 el número de pulsos
  interrupts();                      //Habilitamos las interrupciones
  delay(1000);                       //muestra de 1 segundo
  noInterrupts();                    //Desabilitamos las interrupciones
  frecuencia=NumPulsos;              //Hz(pulsos por segundo)
  return frecuencia;
  }

 volatile float caudal_L_m;
//FUNCION PARA CONVERTIR FRECUENCA A CAUDAL Y CHEQUEO DE FLUJO
void chequeo_flujo(){

  float frecuencia=ObtenerFrecuencia();            //obtenemos la Frecuencia de los pulsos en Hz
  caudal_L_m = frecuencia/factor_conversion;   //calculamos el caudal en L/m
  float caudal_L_h=caudal_L_m*60;                  //calculamos el caudal en L/h

 /*/ //-----Enviamos por el puerto serie---------------
  Serial.print ("FrecuenciaPulsos: "); 
  Serial.print (frecuencia,0); 
  Serial.print ("Hz\tCaudal: "); 
  Serial.print (caudal_L_m,3); 
  Serial.print (" L/m\t"); 
  Serial.print (caudal_L_h,3); 
  Serial.println ("L/h"); 
  */
  }
       
void setup(){ 
  
  Serial.begin(CONFIG_GSM_BAUDRATE); 
  SerialComSim800.begin(CONFIG_GSM_BAUDRATE);
  
  Serial.println("Iniciando..."); 
  delay(9000);
  
  SerialComSim800.println("AT");
  delay(1000);
  SerialComSim800.println("AT+CMGF=1"); //Configuramos el módulo para trabajar con los SMS en modo texto
  delay(1000);
  
  SerialComSim800.print("AT+CNMI=2,2,0,0,0\r");    //El módulo enviará los mensaje directamente al puerto serial del dispositivo
  delay(500);
  
  pinMode(PinSensor, INPUT); 
  attachInterrupt(0,ContarPulsos,CHANGE);         //(Interrupcion 0(Pin2),funcion,Flanco de subida)
  
  pinMode(BOMBA1, OUTPUT);                        //salida bomba
  digitalWrite(BOMBA1, LOW);
  pinMode(BOMBA2, OUTPUT);                        //salida bomba
  digitalWrite(BOMBA2, LOW);
  
  } 

void loop (){
  
  //chequeo_flujo();
  Recibir_Mensaje();
  Envia_SMS_Automatico();
  }

//CODIGO MODULO GSM SIM800L
void Envia_SMS(){
              
  SerialComSim800.println("AT+CMGS=\"+573174507454\"");  // Definimos el numero del destinatario en formato internacional
  delay(1000);                                   // Pequeña pausa
  SerialComSim800.print( mensajeenviado);        // Ponemos las variable String para su envio
  delay(1000);                                   // Pequeña pausa
  SerialComSim800.print(char(26));               // Enviamos el equivalente a Control+Z
  delay(1000);                                   // Pequeña pausa
  SerialComSim800.println("");                        // Enviamos un fin de linea
  delay(1000);                                   // Pequeña pausa
  }

void Recibir_Mensaje(){

if(SerialComSim800.available()){            // 2. Si hay datos en el UART emulado
   mensaje=SerialComSim800.readString();    // Guarde los datos en la variable "mensaje"
   delay(1000);
   }
if (Serial.available()){                    // 1. Si hay datos en la interfaz serial por hardware
   SerialComSim800.write(Serial.read());    // Escribalos en el UART emulado
   }

//CONTROL MANUAL BOMBA 1
 if (mensaje.indexOf("encender")>=0){ 
     digitalWrite(BOMBA1,HIGH);
     caudal = 1;
     est_ant_bomba1 = HIGH;
     }

 if (mensaje.indexOf("apagar")>=0){       //Si la variable mensaje contiene la palabra Apagar 
     if(caudal == 1){                                 //Si bomba esta encendida apague la bomba
     digitalWrite(BOMBA1,LOW);                
     //est_ant_bomba1 = LOW;
     caudal = 0;
      }
      }
      }
      
void Envia_SMS_Automatico(){
  //CONTROL AUTOMATICO DE BOMBAS 
  
    if(caudal_L_m > 1.000){             //Si esta bombeando eficientemente                           
   if(est_ant_bomba1 == HIGH){   
      digitalWrite(BOMBA1, HIGH);
     // est_ant_bomba1 = HIGH;
      caudal = 1;
      }
     else{
      //cont_bombaError ++;
      //if (cont_bombaError > 5){                      //se espera 5 conteos para que la bomba se apague e informe el error
      digitalWrite(BOMBA1, LOW);
     // est_ant_bomba1 = LOW;
      cont_bombaError=0;
      caudal =0;
      }     
      }

if( caudal == 1){
    //Serial.println("BOMBA1 ENCENDIDO monitor");
    delay(1000);
    mensaje = "";
    mensajeenviado="BOMBA1 ENCENDIDO";
    Envia_SMS();
    }
   else{
     // Serial.println("BOMBA1 APAGADA monitor");
      delay(1000);
      mensaje = "";
      mensajeenviado="BOMBA1 APAGADO";
      Envia_SMS();
      contcaudal=0;
      caudal = "";
      }
      
      }

Bueno, siempre existe un modo de probar las cosas sin tener que usar todos los elementos en tu caso el SIM900.
Podrias reemplazar las llamadas al SIM900 con un simple Serial.print(mensaje) y ahi comprobarías que lo envia 1 y otra vez.
Acabo de ver que estaban y si estaban por que seguiste adelante enviando SMS? Bueno tal vez no te diste cuenta.

Por qué ocurre? Porque en ningún momento le dices que solo envíe cambios que es una forma simple de limitar los mensajes.
Si preguntas si hubo cambios y envias si solo si existe uno, entonces limitas los msgs.

if (caudal == 1) {
    // Serial.println("BOMBA1 ENCENDIDO monitor");
    delay(1000);
    mensaje = "";
    mensajeenviado = "BOMBA1 ENCENDIDO";
    Envia_SMS();
  } else {
    // Serial.println("BOMBA1 APAGADA monitor");
    delay(1000);
    mensaje = "";
    mensajeenviado = "BOMBA1 APAGADO";
    Envia_SMS();
    contcaudal = 0;
    caudal = "";
  }

Si caudal = 1 envia BOMBA1 ENCENDIDO y si es 0 APAGADO y al siguiente ciclo lo mismo una y otra vez solo interrumpido por algunos delay intermedios.

En cambio si tu dices ya envié caudal = 1 y ahora de nuevo tengo caudal = 1, entonces no lo envio porque es igual al anterior.
Como hago eso, simplemente uso una variable que guarde el estado anterior de caudal y solo envia cambios.

En tus variables globales agrego esto

int caudal = 0, caudalAnt = 1;

y en la rutina de envio la modifico asi

void Envia_SMS_Automatico() {
  // CONTROL AUTOMATICO DE BOMBAS

  if (caudal_L_m > 1.000) { // Si esta bombeando eficientemente
      if (est_ant_bomba1 == HIGH) {
          digitalWrite(BOMBA1, HIGH);
          // est_ant_bomba1 = HIGH;
          caudal = 1;
      } else {
          // cont_bombaError ++;
          // if (cont_bombaError > 5){                      //se espera 5 conteos
          // para que la bomba se apague e informe el error
          digitalWrite(BOMBA1, LOW);
          // est_ant_bomba1 = LOW;
          cont_bombaError = 0;
          caudal = 0;
      }
  }

  if (caudal != caudalant) {
      mensaje = "";
      delay(1000);
      if (caudal == 1) {
          // Serial.println("BOMBA1 ENCENDIDO monitor");
          mensajeenviado = "BOMBA1 ENCENDIDO";
          
      } else {
          // Serial.println("BOMBA1 APAGADA monitor");
          mensajeenviado = "BOMBA1 APAGADO";         
          contcaudal = 0;
      }
      Envia_SMS();
  }
  caudlaAnt = caudal;
}

¿Me puedes explicar este trozo?
¿Haces un ReadString y el delay lo haces después?
y ¿Después envías lo que escribes en el serial?
No tiene sentido.
Cambia la lectura completa por esto:


int repetir=0;
mensaje="";
if(SerialComSim800.available()>0)            // 2. Si hay datos en el UART emulado
do{
	delay(100);
	repetir++;
	if(SerialComSim800.available()>0)   
		mensaje+=SerialComSim800.readString();    // Guarde los datos en la variable "mensaje"
   }while(repetir<20); // unos 2 segundos

Con esto te esperas hasta 2 segundos a que al serial le lleguen todos los datos.

Saludos

Gracias Surbyte, funciono el código aunque estaba un poquito cerca, había puesto una variable que guarde el estado anterior pero me hizo falta los conceptos y no lo termine de implementar nuevamente gracias. Me di cuenta de que el modulo tiene problemas de alimentación por lo que me retrasa los mensajes incluso utilizando el monitor serial, decidí quitar la comunicación con el modulo para realizar pruebas cómodamente.

he estado moviendo el código para poder unir lo manual con lo automático, el programa se cuelga cuando envió los comandos encender o apagar, pero cuando desactivo en el loop la función chequeo flujo en donde se obtiene la frecuencia de los pulsos y se calcula el caudal; funciona el envió manual normalmente. No se si estoy tropezando con la interrupción del sensor, estuve leyendo acerca de las interrupciones la cual se pueden activar y desactivar. pero no sabría como empezar, aquí las modificaciones.

 void loop (){
  
  //chequeo_flujo();
  Recibir_Mensaje();
  Envia_SMS_Automatico();
  }

  void Recibir_Mensaje(){

if(Serial.available()){
mensaje=Serial.readString();
 delay(500);
}

//CONTROL MANUAL BOMBA 1
 if (mensaje.indexOf("a")>=0){ 
     digitalWrite(BOMBA1,HIGH);
     caudal = 1;
     //est_ant_bomba1 = HIGH;
     }

 if (mensaje.indexOf("b")>=0){       //Si la variable mensaje contiene la palabra Apagar 
     if(caudal == 1){                                 //Si bomba esta encendida apague la bomba
    digitalWrite(BOMBA1,LOW);                
     //est_ant_bomba1 = LOW;
     caudal = 0;
      }
      }
      }
      
void Envia_SMS_Automatico(){
  //CONTROL AUTOMATICO DE BOMBAS 
 
if(caudal != caudalAnt){
    mensaje = "";
    delay(1000);
  if (caudal == 1){
    Serial.println("BOMBA1 ENCENDIDO monitor");
    mensajeenviado = "BOMBA1 ENCENDIDO";
    digitalWrite(BOMBA1, HIGH);
    if(caudal_L_m > 1.000){
       Serial.println("BOMBA1 ENCENDIDO monitor");
       mensajeenviado = "BOMBA1 ENCENDIDO";
       digitalWrite(BOMBA1, HIGH);
       } 
    }
   else{
       Serial.println("BOMBA1 APAGADO monitor");
       mensajeenviado = "BOMBA1 APAGADO";
       //contcaudal=0;
      }
      Serial.print ("mensaje");
   }
   caudalAnt = caudal;
   //Serial.print (caudalAnt);
}

Muchas gracias por responder tratare de implementarlo nuevamente ya que hice pruebas con esta lectura y no hubo respuestas de parte del modulo tal vez sea la alimentación.

El módulo SIM900 requiere fuente de 2A mínimo asi que no te quedes corto.
Solo para el módulo.