Arduino Uno + Sim900+ time Alarms

Estimados, buenos días!, les consulto por el siguiente problema:

Estoy desarrollando un proyecto que mediante un sms prende o apaga un relé. Como estoy usando sms, tengo un mensaje donde habilita o no las notificaciones, esto es: el sistema me contesta con el un sms por ejemplo el estado del mismo.
El flujo correcto debería ser:
Se envía sms para setear alarma que prende relé
El sistema prende relé
Se envía sms para saber estado, el sistema devuelve estado
La habilitación de las notificaciones se debería poder hacer en cualquier momento.

Si el flujo es:

  1. Envio de sms para setear alarma que prende rele
  2. Alarma se ejecuta correctamente

Si ejecuto el siguiente flujo, la alarma no se dispara.

  1. Envio de sms para habilitar notificaciones, el sistema me devuelve NOTI ONN, esto es correcto
  2. Envío de sms para setear alarma que prende relé, la alarma no se dispara nunca

Si ejecuto el siguiente flujo

  1. Envio de sms para setear alarma que prende rele, alarma se está ejecutando por X tiempo
  2. Envio de sms para habilitar notificaciones, el sistema me devuelve NOTI ONN, esto es correcto
  3. Envío de sms para consultar estado, el sistema contesta correctamente

Desde ya muchas gracias!!

Adjunto código en Mensaje Siguiente:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 8);
#include <Time.h>
#include <TimeLib.h>
#include <TimeAlarms.h>

#include "RTClib.h"


//------------ gsm
char incoming_char=0;
String smsRecibo;
int largo;
String mensaje;
String buffer;
String mensajeRecibido;
int automatico;
int notificaciones;
String nroDetectado;

int myReleeA = 13; //releA
int myReleeB = 6; //releB
int myReleeC;
int myReleeD;
int rele2;

//-programar Alarmas
RTC_DS1307 rtc;
AlarmID_t alarmaA1Onn;
AlarmID_t alarmaA1Off;
AlarmID_t alarmaA1Onn8;
AlarmID_t alarmaA1Off8;

int hora;
int minuto;
String horaDetectada;
String salida;
String dia;

String HoraEnviada;
String diaSemana;
String accionSalida;
int tiempoEnv;
int diaEnviado; 
String tiempoEnviado;
String programRecibido;

int horaApagado;
int minutoApagado;
int resto;
int resta;
int divide;

String estadoAlarmaA1;
String estadoAlarmaA2;

void setup()
{
   Serial.begin(9600);
   Alarm.delay(3000);   
   alarmaA1Onn = Alarm.alarmRepeat(hora,minuto,0, enciendeReleA1);
   alarmaA1Off = Alarm.alarmRepeat(horaApagado,minutoApagado,0, apagaReleA1);  
  
   powerUpOrDown(); //enciende sim900  
 
  mySerial.begin(19200); // for GSMshield
  Alarm.delay(1000);
  mySerial.print("AT+CMGF=1\r");  // set SMS mode to text
  Alarm.delay(1000);
  mySerial.print("AT+CNMI=2,2,0,0,0\r");    
  
  Alarm.delay(100);  
  pinMode(13, OUTPUT);
 
  pinMode(myReleeA, OUTPUT);
  pinMode(myReleeB, OUTPUT); 
  digitalWrite(myReleeA, LOW);
  digitalWrite(myReleeB, HIGH);
    
  buffer = "";
  automatico=0;
  notificaciones = 0;

 if (! rtc.begin()) {
 Serial.println("No hay un módulo RTC");
 while (1);
 } 
  DateTime now = rtc.now();
  setTime(now.hour(), now.minute(), now.second(), now.month(), now.day(), now.year());  
 Serial.println(now.day(), DEC);
 Serial.println(now.month(), DEC);
 Serial.println(now.year(),DEC);
}
void loop()
{     
  char SerialInByte;  
  if(mySerial.available() >0)
  {
   Serial.println("disponible");
   buffer = ""; 
   readSIM900A();
   
    //Habilita las notificaciones por SMS
    int elenotion = buffer.indexOf("NOTI-ON"); //para encender notificaciones
   
      if (elenotion>=0)
      {      
      notificaciones = 1; //habilita notificaciones 
      mensaje = "NOTIF ON";
      mensaje_sms(mensaje);
      }

      int elementoNotiOf = buffer.indexOf("NOTI-OFF"); //para encender notificaciones
    
      if (elementoNotiOf>=0)
      {
      mensaje = F("NOTIF OFF");   
      mensaje_sms(mensaje);
      notificaciones = 0; //deshabilita notificaciones       
      }    
    
    int elementoTiempo = buffer.indexOf("IA1");                                        
    if (elementoTiempo>=0)
      {
        capturaEvento(); 
        mensaje= programRecibido;        
        mensaje_sms(mensaje);                
        armoHoras();        
        setAlarmaIA1();        
      }

    int elementoTiempoA2 = buffer.indexOf("IA2");                                       
    if (elementoTiempoA2>=0)
      {        
        estadoAlarmaA2="";
        capturaEvento(); 
        mensaje= programRecibido;        
        mensaje_sms(mensaje);                
        armoHoras();        
        setAlarmaIA2();        
      }
   //consultas estado
  int elementoConsultaA1 = buffer.indexOf("CA1");                                        
    if (elementoConsultaA1>=0)
      {
        Serial.println(buffer); 
        mensaje= estadoAlarmaA1; mensaje_sms(mensaje);         
      }      
  }   
}

//lee los characteres del mensaje y los mete en un buffer
String readSIM900A()
{
  buffer = "";
   while (mySerial.available())
    {      
        char c = mySerial.read();
        buffer.concat(c);       
        Alarm.delay(10);        
    }    
    mensajeRecibido = buffer;
    return buffer;    
}

void enciendeReleA1()
{
  Serial.println("Enciende rele A1-------------------------------");
  digitalWrite(myReleeA, HIGH);  
  setEstadoAlarmaA1();  
}

void enciendeReleA2()
{
  Serial.println("Enciende rele A1--------------por alarma 2-----------------");
  digitalWrite(myReleeA, HIGH);
  setEstadoAlarmaA2();  
}

// Apaga Reles ----

void apagaReleA1()
{
  Serial.println("Apaga rele A1 ++++++++++++++++++++++++++++++");
  digitalWrite(myReleeA, LOW);    
  duermeEstadoAlarmaA1();
  
}

void apagaReleA2()
{
  Serial.println("apaga rele A1--------------por alarma 2-----------------");
  digitalWrite(myReleeA, LOW);     
  //duermeEstadoAlarmaA2();
  //duermeEstadoAlarmaB2();
}



void mensaje_sms(String mensaje)
   {
    
      capturaNroEnviado();      
      String nroEnvio2 = "AT+CMGS=\"+" + String(nroDetectado);
      nroEnvio2.concat("\"");           
      if (notificaciones == 1)
      {    
      Serial.println("Enviando SMS...");     
      mySerial.print("AT+CMGF=1\r");  //Configura el modo texto para enviar o recibir mensajes
      Alarm.delay(1000);
      //mySerial.println("AT+CMGS=\"+11111111111\"");  //Numero al que vamos a enviar el mensaje
      mySerial.println(nroEnvio2);  //Numero al que vamos a enviar el mensaje
      Alarm.delay(1000);
      mySerial.println(mensaje);  // Texto del SMS
      Alarm.delay(100);
      mySerial.println((char)26); //Comando de finalización ^Z
      Alarm.delay(100);
      mySerial.println();
      Alarm.delay(5000);  // Esperamos un tiempo para que envíe el SMS     
      }
    
   }

void capturaNroEnviado()
{
  int elementoComilla = mensajeRecibido.indexOf('5');  
  int elementoSegundaComilla =  mensajeRecibido.indexOf('"',elementoComilla); 
  
  nroDetectado = mensajeRecibido.substring(elementoComilla,21);   
  Alarm.delay(100);
  }

void powerUpOrDown()
{
    pinMode(9, OUTPUT);
    digitalWrite(9,LOW);
    Alarm.delay(1000);
    digitalWrite(9,HIGH);
    Alarm.delay(5000); //era 5000
    digitalWrite(9,LOW);
    Alarm.delay(3000);
}

void capturaEvento()
{
  //int elementoAsterisco = mensajeRecibido.indexOf('#');  
  accionSalida = mensajeRecibido.substring(49,53);
  diaSemana = mensajeRecibido.substring(54,55);
  HoraEnviada = mensajeRecibido.substring(56,60);
  tiempoEnviado = mensajeRecibido.substring(61,63);

  programRecibido = "#S"+accionSalida+"#D"+diaSemana+"#H"+HoraEnviada+"#T"+tiempoEnviado;
    
}


void armoHoras(){ 
  hora  = HoraEnviada.substring(0,2).toInt();
  minuto  = HoraEnviada.substring(2,4).toInt();
  tiempoEnv = tiempoEnviado.toInt();
  diaEnviado = diaSemana.toInt();
    
  
  if (diaEnviado >=0 and diaEnviado <=9){
  //  Serial.println("dia entre 1 y 7");
  resta = 60 - tiempoEnv;
  if (resta < 60){
    Serial.println("resta menor de 60");
    horaApagado = HoraEnviada.substring(0,2).toInt();
    minutoApagado = HoraEnviada.substring(2,4).toInt()+tiempoEnv;
  }
  if (tiempoEnv >= 60 and tiempoEnv <=900){
    Serial.println("tiempo enviado mayor de 60");
      resto = tiempoEnv % 60;
      divide = tiempoEnv / 60;
      horaApagado = HoraEnviada.substring(0,2).toInt() + divide;
      minutoApagado = HoraEnviada.substring(2,4).toInt()+ resto;
      
      if (horaApagado = 23 and minutoApagado >59){
        minutoApagado = 59;
      }
      if (horaApagado > 24){
        horaApagado = 24;
        minutoApagado = 0;
      }
  }
  
}
}


 void setAlarmaIA1(){  //Salida 1 : Alarma1
   //guardo valores: hora,minuto y hora minuto apagado
   //guard dia
    
    Serial.println("-----------");
    Serial.println(horaApagado);
    Serial.println(minutoApagado); 
    Serial.println("-----------");
    
    if (diaEnviado == 0){
    Serial.println("Cerooooo");  
    Alarm.disable(alarmaA1Onn);
    Alarm.free(alarmaA1Onn);
    Alarm.disable(alarmaA1Off);
    Alarm.free(alarmaA1Off);            
    alarmaA1Onn = Alarm.alarmRepeat(hora,minuto,0, enciendeReleA1);
    alarmaA1Off = Alarm.alarmRepeat(horaApagado,minutoApagado,0, apagaReleA1);
    }
} 


void setEstadoAlarmaA1(){ 
  estadoAlarmaA1 = "#S"+accionSalida+"#D"+diaSemana+"#H"+HoraEnviada+"#T"+tiempoEnviado;
 
}

void duermeEstadoAlarmaA1(){  
  estadoAlarmaA1 = "Espera "+accionSalida+ "/" + diaSemana +"/"+ HoraEnviada +"/"+ tiempoEnviado;
}

void liberarAlarmas(){

}

Puede ser que está influyendo los momentos que modifco la velocidad del serial??, ya que para el sim900 es 115200 ....

Tengo errores con los procedimientos

setEstadoAlarmaA2();

dice que no esta definido

setAlarmaIA2() tampoco

Comentalos, serían para la segunda alarma,
Gracias,
Saludos
Juan

Es curioso, vienes con un problema y colocas un código que no compila. Entonces no entiendo qué has comprobado o hasta donde poder creer lo que dices en el primer post?

La compilación arrojó que no ocupa mas del 50% de la RAM de modo que si hay problemas se debe ha algun error de creación de objetos.
Hasta que valor has permitido que TimeAlarms genere alarmas, o mejor dicho que valor has puesto en le .h de TimeAlarms?

Estimado, el código que tengo tiene mas de 1068 líneas, donde el sitio no me deja subir por la cantidad de caracteres que tengo, por este motivo hice un recorte. Esa es la parte curiosa.

Pruebas he realizado muchas y por este motivo como última opción salí a pedir ayuda a gente que evidentemente sabe mucho mas que uno.

Ahora bien, como comentaba en los post anteriores, si utilizo el flujo 1 y 3 funciona correctamente, pero lo ideal sería que en cualquier momento, el usuario habilite o no las notificaciones. Para esta realidad, si el usuario lo primero que hace es habilitar las notificaciones.
Luego setear alarmas, la alarma no funciona.

En la h de time alarms, hoy en la mañana probé dejando solamente 6, la que tenia hasta ayer era 20.

Gracias por tu tiempo

Ahh ok o sea que lo que hice no sirvió para nada!!

Sube el código completo como adjunto, vamos que cuando un código no puede subirse se sube como adjunto y claro que esta bien asi hacerlo.

Sin el código no se puede evaluar nada.

ok, adjunto el código, lo pasé como un txt.
gracias

CodigoTXT.txt (25.2 KB)

Bueno, he logrado compilar el código agregando al comienzo las funciones que me daban error que te señalé antes.

El reporte de mi compilador dice

Program:   14218 bytes (43.4% Full)
(.text + .data + .bootloader)

Data:       1106 bytes (54.0% Full)
(.data + .bss + .noinit)
 [SUCCESS] Took 5.17 seconds

Lo que indica que estas al 54% de RAM en uso.

Necesito saber que Arduino usas, por lo visto es un UNO o un NANO no?

Estoy viendo el código.

Arduino UNO

Lo primero que no me gusta es la cantidad de Strings que usas y no veo que en ningún sitio los inicialices.

String horaDetectada;
String salida;
String dia;

String HoraEnviada;
String diaSemana;
String accionSalida;

String tiempoEnviado;
String programRecibido;

String estadoAlarmaA1;
String estadoAlarmaA2;

String estadoAlarmaB1;
String estadoAlarmaB2;

String estadoAlarmaC1;
String estadoAlarmaC2;

String estadoAlarmaD1;
String estadoAlarmaD2;

Posibildad de problemas conforme el código funciona.

Tienes comentados lugares donde los Strings eran puestos a 0 como este

if (elementoTiempo>=0)  {
      //Serial.println("llego mensaje");     
      //estadoAlarmaA1="";                   // <=== NO se porque lo comentaste
      capturaEvento(); 
      mensaje= programRecibido;        
      mensaje_sms(mensaje); 
             
      armoHoras();        
      setAlarmaIA1();        
    }

ese caso de la variable comentada, era para una vez que lee el sms, el estado vuelva a vacío.

Bueno, yo encararía varias cosas de otro modo pero no se si eso resuelve el problema y no se como probarlo sin tener que armar todo lo que tu tienes.
Ejemplo no usaría Strings al menos no tantos como tu usas.
Y si usaría vectores fijos de dimensión establecida y luego los armo con sprintf similar a tu composición de concatenación de datos usando + como por ejemplo acá

programRecibido = "#S"+accionSalida+"#D"+diaSemana+"#H"+HoraEnviada+"#T"+tiempoEnviado;

Se me dificulta probar el código y ver en que falla.

Veré si me hago un tiempo y monto la placa SIM para comprobarlo.

Entiendo lo que decis, pero como tu dices no creo que esto solucione el problema, gracias de todos modos

Olvidaré lo que dije antes y me concentro en tu consulta.
Las notificaciones.
Primero dices que con la secuencia NOTI ON se activa la notificacion = 1 y entonces devuelve un SMS. Okay y que eso lo recibe bien pero luego se detienen las Alarmas prefijadas.

Esto va para comprender tu código
Supongomos que enviaste NOTI ON y se activan las notificaciones.
Luego envias IA1 que supongo será para activar setAlarmaIA1
Si miras el código de setAlarmaIA1 te encuentras con que diaEnviado debe ser 0, porque? No veo que lo cambies en ningún momento y cuando lo envias puede valor desde 0 a 9? Tampoco entiendo porque 9

 void setAlarmaIA1(){  //Salida 1 : Alarma1
   //guardo valores: hora,minuto y hora minuto apagado
   //guard dia
    
    Serial.println("-----------");
    Serial.println(horaApagado);
    Serial.println(minutoApagado); 
    Serial.println("-----------");
    
    if (diaEnviado == 0){
        Serial.println("Cerooooo");  
        Alarm.disable(alarmaA1Onn);
        Alarm.free(alarmaA1Onn);
        Alarm.disable(alarmaA1Off);
        Alarm.free(alarmaA1Off);            
        alarmaA1Onn = Alarm.alarmRepeat(hora,minuto,0, enciendeReleA1);
        alarmaA1Off = Alarm.alarmRepeat(horaApagado,minutoApagado,0, apagaReleA1);
    }
}

Una pista, una cosa rara que pasa es que cuando envías el mensaje : con el texto "IA1"

ejecuta 2 veces el envio de sms, pero a mi me llega solamente uno.

Esto no pasa cuando envías el mensaje "NOTI-ONN"

No estará pasando que esto está bloqueando algo?????

Segunda vez que dices que el mensaje es "NOTI-ONN" pero no tienen ningún mensaje con esa etiqueta pero si
"NOTI-ON"

Estimados, estoy intentando usar otra librería para el manejo del sim900, hasta ahora lo hacía con comandos AT.

La duda que tengo, es que si el código es correcto, para obtener el sms y extraer los datos.
Desde ya muchas gracias,

#include "SIM900.h"
#include <SoftwareSerial.h>
//If not used, is better to exclude the HTTP library,
//for RAM saving.
//If your sketch reboots itself proprably you have finished,
//your memory available.
//#include "inetGSM.h"

//If you want to use the Arduino functions to manage SMS, uncomment the lines below.
#include "sms.h"
SMSGSM sms;

//To change pins for Software Serial, use the two lines in GSM.cpp.

//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.

//Simple sketch to send and receive SMS.

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];

int notificaciones;
char mensaje;
String nroDetectado;
String str;
char *p;

void setup() 
{
  notificaciones = 0;
  //Serial connection.
  Serial.begin(9600);
  Serial.println("GSM Shield testing.");
  //Start configuration of shield with baudrate.
  //For http uses is raccomanded to use 4800 or slower.
  if (gsm.begin(2400)){
    Serial.println("\nstatus=READY");
    started=true;  
  }
  else Serial.println("\nstatus=IDLE");
  
  if(started){
    //Enable this two lines if you want to send an SMS.
    //if (sms.SendSMS("1111111111", "Arduino SMS"))
    //Serial.println("\nSMS sent OK");
  }

};

void loop() 
{
  
  if(started)
  {
    if(gsm.readSMS(smsbuffer, 160, n, 20))
    {
      Serial.println(n);
      Serial.println(smsbuffer);
      
      String str2(smsbuffer);
      str = str2;
      Serial.println("---------------");
      Serial.println(str);
      Serial.println("---------------");
      int elenotion = str.indexOf("NOTI-ON"); //para encender notificaciones
   
      if (elenotion>=0)
      {
      Serial.println("notificacinoes");  
      notificaciones = 1; //habilita notificaciones 
      mensaje = "NOTIF ON";
      mensaje_sms(mensaje);
      }
    }
    
  }
  
}

void capturaNroEnviado()
{
  int elementoComilla = str.indexOf('5');  
  int elementoSegundaComilla =  str.indexOf('"',elementoComilla); 
  
  nroDetectado = str.substring(elementoComilla,21);   
  delay(100);
  }


void mensaje_sms(char mensaje){
  if(started){
     capturaNroEnviado();
     string2char(nroDetectado);     

    //Enable this two lines if you want to send an SMS.
    if (sms.SendSMS(p, mensaje))
    Serial.println("\nSMS sent OK");
  }
}

  
char* string2char(String command){
    if(command.length()!=0){
        p = const_cast<char*>(command.c_str());
        return p;
    }
}

El código esta bien. Podría manejarse sin el uso de Strings pero con ellos te sientes cómodo asi que adelante.