Problemas, sin lógica, entre Arduino Nano y SIM900

Buenas tardes,

Mi nombre es Leandro, estoy desarrollando una alarma domiciliaria con control de estado de la misma usando una placa SIM900 enviando y/o recibiendo mensajes SMS.

Ya tengo todo montado en la casa, pero surge un problema:

1- Envio el sms de activación, y se activa sin problema.
2- Si detecta movimiento me envía el SMS de alerta y suena por x tiempo y se rearma sola.

Pero:

3- Estando activada, y cuando le envio el mensaje de desactivación o Reset aparece el problema: se alarma la zona 2 y luego hace caso a la órden recibida por mensaje.

Probé incluso de cambiar de pines los sensores de zona 2 pero aún así siempre se alarma la misma zona.

El hardware que utilizo es:

1- Arduino Nano
2- Sensores PIR x 2 + Sensores de presencia x 2 (combinado uno y uno, en 2 zonas).
3- Rele para sirenas
4- Reguladores de voltaje, uno para Arduino y otro para la SIM900.
5- Placa SIM900.

Este es todo mi código (las lineas comentadas es para no generar ruido durante las pruebas o bien gastar el saldo recibiendo mensajes que ya se que eso funciona):

#include <SoftwareSerial.h>
#include <Arduino.h>

/*** PARÁMETROS ***/
/******************************/
#define BUZZER 5
#define releR1 2
#define SERIAL_BAUDRATE 9600
#define GSM_BAUDRATE 9600
#define RX_pin 10
#define TX_pin 11
#define ON 1
#define OFF 0
#define ACTIVATION_DELAY 3
/******************************/

bool state, monitoring;
double lecturaPirP1, lecturaEcoP1, lecturaPirP2, lecturaEcoP2;
double sensorPirP1, sensorEcoP1, sensorPirP2, sensorEcoP2;
int bluePin, redPin, vueltas;
SoftwareSerial *SIM900;
String incomingSMS;
  
void setup(){
  state = OFF;
  monitoring = OFF;
  sensorPirP1 = A0;
  sensorEcoP1 = A1;
  lecturaPirP1 = 0;
  lecturaEcoP1 = 0;
  sensorPirP2 = A4;
  sensorEcoP2 = A5;
  lecturaPirP2 = 0;
  lecturaEcoP2 = 0;
  bluePin = 4;
  vueltas = 0;
  SIM900 = new SoftwareSerial(RX_pin, TX_pin);
  pinMode(BUZZER, OUTPUT);  
  pinMode(bluePin, OUTPUT);
  pinMode(releR1, OUTPUT);
  pinMode(sensorPirP1, INPUT);
  pinMode(sensorEcoP1, INPUT);
  pinMode(sensorPirP2, INPUT);
  pinMode(sensorEcoP2, INPUT);
  digitalWrite(releR1, HIGH);
  
  delay(5000);
  mySerialPower();
  delay(10000);
  GSM_init();
  delay(15000);
  countdown();
  digitalWrite(bluePin, HIGH);
  delay(2000);
  digitalWrite(bluePin, LOW);
  delay(1000);
  Serial.println("AT+CMGD=1,4");
  Serial.println("Alarma lista");
}

void loop(){
  userSMSCheck();
  delay(3000);
  if(state == ON){
    if(monitoring == ON){
      lecturaPirP1 = analogRead(sensorPirP1);
      lecturaEcoP1 = analogRead(sensorEcoP1);
      delay(200);
      if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
        Serial.println("ALARMA ZONA Uno!!...");
        activate_ALERT();
      }
      lecturaPirP2 = analogRead(sensorPirP2);
      lecturaEcoP2 = analogRead(sensorEcoP2);
      delay(200);
      if((lecturaPirP2 > 450) and (lecturaEcoP2 > 450)){
        Serial.println("ALARMA ZONA Dos!!...");
        activate_ALERT();
      }
    } 
    else{
      alertTimeOnCheck();
      Serial.println("Resetada, alarma activa nuevamente.");
      userSMSCheck();
    }
  }
}

void mySerialPower(){
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(8, HIGH);
  delay(2000);
  digitalWrite(8, LOW);
  delay(3000);
}

void GSM_init(){
  Serial.begin(SERIAL_BAUDRATE);
  SIM900->begin(GSM_BAUDRATE);
  SIM900->println("AT");
  updateSerial();
  SIM900->println("AT+CREG=1");
  updateSerial();
  delay(10000);
  SIM900->println("AT+CMGF=1");
  updateSerial();
  delay(100);
  SIM900->println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  SIM900->println("AT+CSQ");
  updateSerial();
  SIM900->println("AT+CREG?");
  updateSerial();
}

void countdown(){
  for(int i=ACTIVATION_DELAY;i>1;i--){
    if(i>10){
      beep(50,50,1);
      delay(100);
    }else{
      beep(50,50,2);
    }
    delay(900);
  }
  beep(50, 50, 10);
}

void beep(int msON, int msOFF, int rep) {
  for (int i = 0; i < rep; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(msON);//wait for X ms
    digitalWrite(BUZZER, LOW);
    delay(msOFF);
  }
}

void userSMSCheck(){
  incomingSMS = "";
  if(SIM900->available()){
    incomingSMS = SIM900->readString();
  }
  if((incomingSMS.indexOf("+XXXXXXXXXXXXXX")>=0) or (incomingSMS.indexOf("+ZZZZZZZZZZZZZ")>=0)){
    if(incomingSMS.indexOf("Reset")>=0){
      Serial.println("Procesando Reseteo...");
      RESET();
      Serial.println("Alarma reactivada...");
    }  
    if(incomingSMS.indexOf("Off")>=0){
      Serial.println("Procesando desactivación...");
      switch_OFF();
      Serial.println("Desactivada");
    }  
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

void sendSMS(){
  SIM900->println("AT");
  updateSerial();
  delay(500);
  SIM900->println("AT+CMGS=\"+XXXXXXXXXXXX\"");
  updateSerial();
  SIM900->print("SE HA ACTIVADO LA ALARMA\n\"Resetear\"-> Reinio auto en 25seg.");
  SIM900->write(26);
  updateSerial();
}

void updateSerial(){
  delay(500);
  while (Serial.available()) 
  {
    SIM900->write(Serial.read());
  }
  if (SIM900->available()){
    while(SIM900->available())
    {
      Serial.write(SIM900->read());
    } 
  }
}

void activate_ALERT() {
  monitoring = OFF;
  //sendSMS();
  //digitalWrite(releR1, LOW);
  delay(25000);
  //digitalWrite(releR1, HIGH);
}

void switch_ON(){
  delay(200);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(25000);
  state = ON;
  monitoring = ON;
}

void switch_OFF(){
  delay(200);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(500);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(200);
  state = OFF;
  monitoring = OFF;
}

void RESET(){
  switch_OFF();
  delay(2000);
  switch_ON();
}

void alertTimeOnCheck(){
  RESET();
  delay(3000);
}

Espero que alguien me pueda ayudar, la falla a mi entender no tiene lógica alguna dado que primero controlo la llegada de mensajes y luego controlo estado de los sensores, no se porque ante la llegada de un nuevo SMS y estando activa se dispara la alarma en Zona 2 y luego procesa el mensaje entrante.

Saludos y gracias de antemano!.

Buen día,

Adjunto esquema de conexiones por si alguien quiere reutilizar el código/sistema o bien por si desean tratar de replicar el problema para poder dar algun idea o solución.

Gracias!!!.

Esquema_Alarma.pdf (280 KB)

Hola.
Llámame tiquismiquis pero... ¿para que usar un regulador externo de 12 a 9 si la placa lo lleva incorporado?
Si lo alimentas a través del jack para 12V del SIM900 te ahorras dolores de cabeza y componentes. Por cierto, ¿donde se unen los GND?

Saludos

Hola bosoft,

Los GND van todos juntos y eso al negativo de alimentación general de los 12v como negativo común a todo.
Lo del regulador extra para la SIM900 es para mantener estabilizada (en cuanto a voltaje) la entrada a la misma dado que, del lado de la bateria, uso una fuente que mantiene cargada la misma y tiene el cambio atumático cuando se corta la luz (o sea, mientras se tenga luz o energia en la red alimenta de forma directa pero ante un corte la misma switchea a bateria sin generar microcortes en la salida y eso mantiene la alarma funcionando) y dicha fuente entrega 13,6v y por eso y por las dudas use el regulador para bajar a 9v y asegurarme que no tenga una sobrealimentación.

Saludos.

El regulador del SIM900 aguanta hasta 16V, Yo tengo unos cuantos montados y la mejor solución que he encontrado ha sido conectarlos a las baterías directamente y hacer el gasto "gordo" en los cargadores que están conectados directos también a las baterías. Llevo varios años y ningún problema. Todo lo que probé antes de eso acabó dándome problemas o por tensión o por amperios.
Y algunos SIM900 se alimentan desde la batería a través de placa solar. A una de esas baterías también le he conectado un cargador conectado a red para cuando el nivel de batería baja de 11,9V. Y directamente, desde los 12V, se alimentan uno mega 2560 y el SIM900 además de un ESP01s con su regulador 1117 3.3

Y te cuento esto porque, usando los reguladores que llevan incluidos tanto los SIM como los arduinos, te curas en salud

Saludos

En el esquema, los sensores están en A0 A1 A2 A3, en el código A0 A1 A4 A5

Que es vueltas ?

No termino de ver el porque de state y monitoring

En el loop llamas 2 veces a userSMSCheck();

Los delay() son terribles

Esto no procede, los quieres analogicos

pinMode(sensorPirP1, INPUT);
 pinMode(sensorEcoP1, INPUT);
 pinMode(sensorPirP2, INPUT);
 pinMode(sensorEcoP2, INPUT);

Las entradas analógicas que no utilizas, yo las pondría a nivel alto,

pinMode(Ax, INPUT_PULLUP);

Moderador
Aunque sea una sola línea de código se deben usar etiquetas.

Hola jordsi3sk97,

Vamos por partes:

  1. El tema de la diferencia de pines entre esquema y código es porque estuve probando cambio de pines de los sensores a ver si el problema dejaba de existir tal como comente en el post.

  2. Vueltas es una simple variable que use para controlar las veces que se ejecutaba el loop y ver como es que al llegar un mensaje hacía otra vuelta o loop.

  3. Lo del state y monitoring quedó así por pruebas, podría dejar solo uno de esos estados dado que no tiene sentido tenerlos anidados.

  4. Si, en el loop esta dos veces la llamada a la función userSMSCheck() dado que una es por cada loop y no importa si la alarma esta activa o no, y el otro es luego del rearme automático ante una alerta controla la recepción de comandos (si suena por algún motivo al rearmarse quiero que al instante reciba mensajes). Esto puede quitarse y dejar solo uno.

  5. Los delay los uso como comodin para generar interrupciones o esperas en los comandos a ejecutarse.

  6. Con respecto a los pinMode, dices que no es necesario los declare como IMPUT porque son analógicos?.

  7. En que beneficia poner a nivel alto las analógicas no utilizadas?.

Alguna idea del porqué al llegar un SMS estando "activa" se alarma la zona2???

Gracias.

Aca dejo nuevo código un poco más limpio en cuanto a delays y variables no necesarias, pero el problema sigue estando:

#include <SoftwareSerial.h>
#include <Arduino.h>

/*** PARÁMETROS DEL SISTEMA ***/
/******************************/
#define BUZZER 5
#define releR1 2
#define SERIAL_BAUDRATE 9600
#define GSM_BAUDRATE 9600
#define RX_pin 10
#define TX_pin 11
#define ON 1
#define OFF 0
#define ACTIVATION_DELAY 3
/******************************/

bool state;
double lecturaPirP1, lecturaEcoP1, lecturaPirP2, lecturaEcoP2;
double sensorPirP1, sensorEcoP1, sensorPirP2, sensorEcoP2;
int bluePin, redPin;
SoftwareSerial *SIM900;
String incomingSMS;
  
void setup(){
  state = OFF;
  sensorPirP1 = A0;
  sensorEcoP1 = A1;
  lecturaPirP1 = 0;
  lecturaEcoP1 = 0;
  sensorPirP2 = A4;
  sensorEcoP2 = A5;
  lecturaPirP2 = 0;
  lecturaEcoP2 = 0;
  bluePin = 4;
  SIM900 = new SoftwareSerial(RX_pin, TX_pin);
  pinMode(BUZZER, OUTPUT);  
  pinMode(bluePin, OUTPUT);
  pinMode(releR1, OUTPUT);
  pinMode(sensorPirP1, INPUT);
  pinMode(sensorEcoP1, INPUT);
  pinMode(sensorPirP2, INPUT);
  pinMode(sensorEcoP2, INPUT);
  digitalWrite(releR1, HIGH);
  
  mySerialPower();
  delay(10000);
  GSM_init();
  delay(15000);
  countdown();
  digitalWrite(bluePin, HIGH);
  delay(2000);
  digitalWrite(bluePin, LOW);
  delay(1000);
  Serial.println("AT+CMGD=1,4");
  Serial.println("Alarma lista");
}

void loop(){
  userSMSCheck();
  delay(3000);
  if(state == ON){
    lecturaPirP1 = analogRead(sensorPirP1);
    lecturaEcoP1 = analogRead(sensorEcoP1);
    if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
      Serial.println("ALARMA ZONA Uno!!...");
      activate_ALERT();
    }
    lecturaPirP2 = analogRead(sensorPirP2);
    lecturaEcoP2 = analogRead(sensorEcoP2);
    if((lecturaPirP2 > 450) and (lecturaEcoP2 > 450)){
      Serial.println("ALARMA ZONA Dos!!...");
      activate_ALERT();
    }
  }
  else{
    alertTimeOnCheck();
    Serial.println("Resetada, alarma activa nuevamente.");
  }
}

void mySerialPower(){
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(8, HIGH);
  delay(2000);
  digitalWrite(8, LOW);
}

void GSM_init(){
  Serial.begin(SERIAL_BAUDRATE);
  SIM900->begin(GSM_BAUDRATE);
  SIM900->println("AT");
  updateSerial();
  SIM900->println("AT+CREG=1");
  updateSerial();
  delay(10000);
  SIM900->println("AT+CMGF=1");
  updateSerial();
  SIM900->println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  SIM900->println("AT+CSQ");
  updateSerial();
  SIM900->println("AT+CREG?");
  updateSerial();
}

void countdown(){
  for(int i=ACTIVATION_DELAY;i>1;i--){
    if(i>10){
      beep(50,50,1);
      delay(100);
    }else{
      beep(50,50,2);
    }
    delay(900);
  }
  beep(50, 50, 10);
}

void beep(int msON, int msOFF, int rep) {
  for (int i = 0; i < rep; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(msON);//wait for X ms
    digitalWrite(BUZZER, LOW);
    delay(msOFF);
  }
}

void userSMSCheck(){
  incomingSMS = "";
  if(SIM900->available()){
    incomingSMS = SIM900->readString();
  }
  if((incomingSMS.indexOf("+xxxxxxxx")>=0) or (incomingSMS.indexOf("+zzzzzzzzzz")>=0)){
    if(incomingSMS.indexOf("Reset")>=0){
      Serial.println("Procesando Reseteo...");
      RESET();
      Serial.println("Alarma reactivada...");
    }  
    if(incomingSMS.indexOf("Off")>=0){
      Serial.println("Procesando desactivación...");
      switch_OFF();
      Serial.println("Desactivada");
    }  
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

void sendSMS(){
  SIM900->println("AT");
  updateSerial();
  delay(500);
  SIM900->println("AT+CMGS=\"+xxxxxxxxxxxx\"");
  updateSerial();
  SIM900->print("SE HA ACTIVADO LA ALARMA\n\"Resetear\"-> Reinio auto en 25seg.");
  SIM900->write(26);
  updateSerial();
}

void updateSerial(){
  delay(500);
  while (Serial.available()) 
  {
    SIM900->write(Serial.read());
  }
  if (SIM900->available()){
    while(SIM900->available())
    {
      Serial.write(SIM900->read());
    } 
  }
}

void activate_ALERT() {
  state = OFF;
  //sendSMS();
  //digitalWrite(releR1, LOW);
  delay(25000);
  //digitalWrite(releR1, HIGH);
}

void switch_ON(){
  delay(200);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(25000);
  state = ON;
}

void switch_OFF(){
  delay(200);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(500);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(2000);
  state = OFF;
}

void RESET(){
  switch_OFF();
  switch_ON();
}

void alertTimeOnCheck(){
  RESET();
}
  1. En que beneficia poner a nivel alto las analógicas no utilizadas?.

Algunos usan esto para evitar ruidos en el Sample & Hold del ADC.

Los delay() son terribles

Comparto lo de los delay que menciona @jordi3sk97.
El problema con los SIM900 es que pocos se toman el trabajo de esperar la respuesta del SIM900.
Cuando le envias un comando como

SIM900->println("AT");

Cuesta tanto esperar con Serial.Read() y leer un simple OK?
Eso evitaria tus delay() tan largos y además ganas en posibles mensajes de error y en tiempo de respuesta.

Considéralo.

Es algo para mejorar, tu código va bien tal como esta.
Tengo por ahi una o dos respuestas en las que sugiero como hacerlo. Simplemente debes buscarlo.

lap2021:
6. Con respecto a los pinMode, dices que no es necesario los declare como I N PUT porque son analógicos?.

Si

Esto no es double, con int ya vale, o mejor hazlo con define
double sensorPirP1, sensorEcoP1, sensorPirP2, sensorEcoP2;

redpin lo defines pero no lo utilizas

Que es mySerialPower() , en el esquema no hay nada en D8

void mySerialPower(){
 pinMode(8, OUTPUT);      esto estaría más bonito en el setup

alertTimeOnCheck(); No veo porque es necesaria una función que solo llama a otra función, y tampoco para que hacer un reset

En el esquema conectas la sirena que esta dibujada como un altavoz conectando el (-), es mejor practica que los (-) estén siempre conectados y el relé conmute el (+)

Bueno, la verdad es que no entiendo casi nada, culpa mía.

En un futuro que han de hacer 2 relés ?

Para que sirve el reset ?

Para que hay un conteo en la activación, si se hace por sms ?

Porque la puedes desactivar con un sms si al siguiente loop haces un reset y se vuelve a activar ?

Porque en ALERT() pones state en OFF , si en el siguiente loop harás un RESET() donde lo vuelves a poner en ON sin que haya pasado nada más que 1 loop ?

Las variables que condicionan el error, o las pones a 0 despuès de detectar el error o las actualizas en cada iteración, no es buena idea dejarlas con valores de error.

El loop, con lo que has mandado y aún sin entenderlo, yo quizás lo haría así,

]void loop(){
  userSMSCheck();

  lecturaPirP1 = analogRead(sensorPirP1);
   lecturaEcoP1 = analogRead(sensorEcoP1);
   lecturaPirP2 = analogRead(sensorPirP2);
   lecturaEcoP2 = analogRead(sensorEcoP2);


  if(state == ON){
  
    if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
      Serial.println("ALARMA ZONA Uno!!...");
      activate_ALERT();
    }

    if((lecturaPirP2 > 450) and (lecturaEcoP2 > 450)){
      Serial.println("ALARMA ZONA Dos!!...");
      activate_ALERT();
    }
  }
  else{
    RESET();
    Serial.println("Resetada, alarma activa nuevamente.");
  }
}

En el foro parece que nadie habla de los diagramas de flujo, y no se el porque, puede que no estén de moda, pero quizá te convenga dibujar el de tu aplicación y empezar el código desde cero.

Me ha llamado la atención tu problema, y le he dedicado un poco de tiempo, pero no soy capaz de entender tu código, lo siento.

Si te apetece prueba con lo que ya te he dicho anteriormente más lo que te digo ahora

@lap2021 hay algo que no entiendo...

¿Por qué lees el estado de los sensores con las entradas analógicas si sus salidas son digitales?

Sería entendible si no tuvieras pines digitales disponibles y quisieras aprovechar los dos pines exclusivamente analógicos del Nano, pero no es tu caso.

Además una lectura ADC de valor 450 (que fijaste como umbral) es equivalente a 2.2V, eso se considera un estado indeterminado y el menor ruido (como el generado por el módulo RF de la placa SIM) te puede generar una lectura alta que no es tal.

Si es porque los niveles altos de los sensores son 3.3V, no te preocupes que son suficientes para que el Nano los lea correctamente.

Wow! a ver, ire por partes y de a uno:

Hola surbyte!!

  • Tendré en cuenta lo de "Algunos usan esto para evitar ruidos en el Sample & Hold del ADC."

  • Justamente es la idea (no cometer ese error): "El problema con los SIM900 es que pocos se toman el trabajo de esperar la respuesta del SIM900", aplicare el control de respuestas sacando algunos de esos delay.

  • Tomaré las recomendaciones!!

gracias!.

Hola jordi3sk97!!

  • "Esto no es double, con int ya vale, o mejor hazlo con define" si no se porque o para que puse double.

  • "Que es mySerialPower() , en el esquema no hay nada en D8" cuando arme y conecte todo por un tema de comodidad puse en D8 en lugar de D5, es un led verde, es un juego de luces para cuando la enciendo nada más.

  • "alertTimeOnCheck(); No veo porque es necesaria una función que solo llama a otra función, y tampoco para que hacer un reset" es correcto, pasa que la tenía con librerias y codigo en cpp en tres capas pero como me salto ese problema planteado desde el principio en mi post decidí dejarlo todo plano y quedó así.

  • "En un futuro que han de hacer 2 relés ? " puse el que tenía y usé, pero no es necesario uno doble.

  • "Para que sirve el reset ?" una vez que se alarma y luego del tiempo de sonido alarmante el sistema se rearma o reactiva solo por si siguen intrusos dentro".

  • "Para que hay un conteo en la activación, si se hace por sms ?" es para el juego de luces al encender la alarma, es solo un agregado de indicador visual al enchufarla.

  • "Porque la puedes desactivar con un sms si al siguiente loop haces un reset y se vuelve a activar ?" si miras mi código original esto no pasaba, fué error mio en una de las respuestas durante el hilo. Ahora colocaré nuevo código.

  • "Porque en ALERT() pones state en OFF , si en el siguiente loop harás un RESET() donde lo vuelves a poner en ON sin que haya pasado nada más que 1 loop ?" idem anterior.

  • "Las variables que condicionan el error, o las pones a 0 despuès de detectar el error o las actualizas en cada iteración, no es buena idea dejarlas con valores de error." te refieres a las que toman la lectura de los sensores? con cada lectura se pisa el valor anterior no tiene sentido ponerles 0.

  • "En el foro parece que nadie habla de los diagramas de flujo, y no se el porque, puede que no estén de moda, pero quizá te convenga dibujar el de tu aplicación y empezar el código desde cero." esto es muy usado en quines arrancan en la programación en sí, y hay que decirlo no todos saben hacerlo, o como guía para quien lee el código de otro y no logra entender la lógica, en mi caso no veo necesario hacer el diagrama dado que es un flujo y lógica funcional muy simple (poco código, pocas funciones, un loop sencillo) pero ojo no tomes a mal mi comentario porque no es la idea por ahí para mi es simple pero para otros no lo es.

  • "Me ha llamado la atención tu problema, y le he dedicado un poco de tiempo, pero no soy capaz de entender tu código, lo siento." a mi también me llama mucho la atención, como ya dije no tiene lógica la falla lo único que se me ocurre es que sea una falla del Nano, creo que comprare un Uno para probar y descartar que sea eso.

Gracias!!!!

Hola gatul!!

  • "¿Por qué lees el estado de los sensores con las entradas analógicas si sus salidas son digitales?" si los lees como digitales obtienes solo LOW o HIGH, en cambio al leerlos como analógicos obtienes el valor en número y puedes discriminar en falsos positivos por eso pongo que sea mayor a 450 en los if.

  • "Además una lectura ADC de valor 450 (que fijaste como umbral) es equivalente a 2.2V, eso se considera un estado indeterminado y el menor ruido (como el generado por el módulo RF de la placa SIM) te puede generar una lectura alta que no es tal." sabes que esto lo pense? pero porque entonces no me mete ruido en los D0 y D1?? porque lo hace en todos los demas pines digitales y no en esos dos?. Puse print de los valores de los 4 pines digitales que uso y siempre salta en los que están en la zona 2 sin embargo los sensores más cercanos (si fuese un tema de cercanía los mismos) son los de la zona 1. Además, debería primero leer el mensaje entrante y desactivar, pero en lugar de eso al llegar un mensaje primer se alarma la zona y luego en el siguieten loop toma el mensaje y lo procesa aunque esto puede ser no exacto dada la velocidad de procesamiento.

Gracias!.

Pondré debajo el código con la lógica original, con algunos toques mínimos (quite variables que no se usan, un par de delays, etc).

Gracias!!!

#include <SoftwareSerial.h>
#include <Arduino.h>

/*** PARÁMETROS ***/
/******************************/
#define BUZZER 5
#define releR1 2
#define SERIAL_BAUDRATE 9600
#define GSM_BAUDRATE 9600
#define RX_pin 10
#define TX_pin 11
#define ON 1
#define OFF 0
#define ACTIVATION_DELAY 3
/******************************/

bool state, monitoring;
int lecturaPirP1, lecturaEcoP1, lecturaPirP2, lecturaEcoP2;
int sensorPirP1, sensorEcoP1, sensorPirP2, sensorEcoP2;
int bluePin;
SoftwareSerial *SIM900;
String incomingSMS;
  
void setup(){
  state = OFF;
  monitoring = OFF;
  sensorPirP1 = A0;
  sensorEcoP1 = A1;
  lecturaPirP1 = 0;
  lecturaEcoP1 = 0;
  sensorPirP2 = A4;
  sensorEcoP2 = A5;
  lecturaPirP2 = 0;
  lecturaEcoP2 = 0;
  bluePin = 4;
  SIM900 = new SoftwareSerial(RX_pin, TX_pin);
  pinMode(BUZZER, OUTPUT);  
  pinMode(bluePin, OUTPUT);
  pinMode(releR1, OUTPUT);
  pinMode(sensorPirP1, INPUT);
  pinMode(sensorEcoP1, INPUT);
  pinMode(sensorPirP2, INPUT);
  pinMode(sensorEcoP2, INPUT);
  digitalWrite(releR1, HIGH);
  
  mySerialPower();
  delay(10000);
  GSM_init();
  delay(15000);
  countdown();
  digitalWrite(bluePin, HIGH);
  delay(2000);
  digitalWrite(bluePin, LOW);
  delay(1000);
  Serial.println("AT+CMGD=1,4");
  Serial.println("Alarma lista");
}

void loop(){
  userSMSCheck();
  delay(3000);
  if(state == ON){
    if(monitoring == ON){
      lecturaPirP1 = analogRead(sensorPirP1);
      lecturaEcoP1 = analogRead(sensorEcoP1);
      delay(200);
      if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
        Serial.println("ALARMA ZONA Uno!!...");
        activate_ALERT();
      }
      lecturaPirP2 = analogRead(sensorPirP2);
      lecturaEcoP2 = analogRead(sensorEcoP2);
      delay(200);
      if((lecturaPirP2 > 450) and (lecturaEcoP2 > 450)){
        Serial.println("ALARMA ZONA Dos!!...");
        activate_ALERT();
      }
    }
    else{
      RESET();
      Serial.println("Resetada, alarma activa nuevamente.");
      userSMSCheck();
    }
  }
}

void mySerialPower(){
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(8, HIGH);
  delay(2000);
  digitalWrite(8, LOW);
  delay(3000);
}

void GSM_init(){
  Serial.begin(SERIAL_BAUDRATE);
  SIM900->begin(GSM_BAUDRATE);
  SIM900->println("AT");
  updateSerial();
  SIM900->println("AT+CREG=1");
  updateSerial();
  delay(10000);
  SIM900->println("AT+CMGF=1");
  updateSerial();
  delay(100);
  SIM900->println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  SIM900->println("AT+CSQ");
  updateSerial();
  SIM900->println("AT+CREG?");
  updateSerial();
}

void countdown(){
  for(int i=ACTIVATION_DELAY;i>1;i--){
    if(i>10){
      beep(50,50,1);
      delay(100);
    }else{
      beep(50,50,2);
    }
    delay(900);
  }
  beep(50, 50, 10);
}

void beep(int msON, int msOFF, int rep) {
  for (int i = 0; i < rep; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(msON);//wait for X ms
    digitalWrite(BUZZER, LOW);
    delay(msOFF);
  }
}

void userSMSCheck(){
  incomingSMS = "";
  if(SIM900->available()){
    incomingSMS = SIM900->readString();
  }
  if((incomingSMS.indexOf("+XXXXXXXXXXXXXX")>=0) or (incomingSMS.indexOf("+ZZZZZZZZZZZZZ")>=0)){
    if(incomingSMS.indexOf("Reset")>=0){
      Serial.println("Procesando Reseteo...");
      RESET();
      Serial.println("Alarma reactivada...");
    }  
    if(incomingSMS.indexOf("Off")>=0){
      Serial.println("Procesando desactivación...");
      switch_OFF();
      Serial.println("Desactivada");
    }  
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

void sendSMS(){
  SIM900->println("AT");
  updateSerial();
  delay(500);
  SIM900->println("AT+CMGS=\"+XXXXXXXXXXXX\"");
  updateSerial();
  SIM900->print("SE HA ACTIVADO LA ALARMA\n\"Resetear\"-> Reinio auto en 25seg.");
  SIM900->write(26);
  updateSerial();
}

void updateSerial(){
  delay(500);
  while (Serial.available())
  {
    SIM900->write(Serial.read());
  }
  if (SIM900->available()){
    while(SIM900->available())
    {
      Serial.write(SIM900->read());
    }
  }
}

void activate_ALERT() {
  monitoring = OFF;
  //sendSMS();
  //digitalWrite(releR1, LOW);
  delay(25000);
  //digitalWrite(releR1, HIGH);
}

void switch_ON(){
  delay(200);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(25000);
  state = ON;
  monitoring = ON;
}

void switch_OFF(){
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(500);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(200);
  state = OFF;
  monitoring = OFF;
}

void RESET(){
  switch_OFF();
  switch_ON();
}

Hola gatul!!

Algo que olvide mencionar sobre este tema:

"Además una lectura ADC de valor 450 (que fijaste como umbral) es equivalente a 2.2V, eso se considera un estado indeterminado y el menor ruido (como el generado por el módulo RF de la placa SIM) te puede generar una lectura alta que no es tal."

El valor que retornan los pines digitales (menos el D0 y el D1) son los máximos, ni siquiera son intermedios a modo de ruido.

Saludos,

En la imágen adjunta la evidencia funcional con el problema...

Mas evidencia:

Entiendo todo lo que dices pero no lo comparto.

Si bien puedes leer una salida digital con un conversor ADC, nada lo impide, es un gasto de recursos innecesarios (además de una perdida de tiempo al esperar que se realice la conversión), e insisto, más propenso a "falsos positivos" al contrario de lo que planteas.

Te dije, tomas un valor umbral que está entre los 0.7V típicos para un LOW y los 3.2V declarados por las hojas de datos de ambos dispositivos para un HIGH, cualquier "ruido" superior a 2.2V lo lees como HIGH, eso no lo hace inmune a "falsos positivos", me parece.

Y mas allá de eso, si un dispositivo digital, sea TTL, CMOS o la tecnología que sea da valores intermedios a los definidos para alto y bajo para esa tecnología, definitivamente funciona mal.

De todos modos la idea fue ayudarte pero, obviamente, tu tomas tus decisiones. :wink:

Saludos

Hola gatul,

Pues tenías razón en cuanto a utilizarlos comos digitales y no como analógicos dado que cambié la zona con problemas a ese tipo de pines y ya no se alarmó más al recibir un mensaje!!!.

Ahora, dos preguntas:

  1. Que tienen los pines A0 y A1 que no chupan ruido del mismo mosmo que lo hacen los demás pines Analógicos? porque en esos dos deje la zona 1 y sin problemas con ellos. Esto mucho no me importa porque ya no es problema.

2- Esto si me importa porque es otro problema:

Tengo el siguiente código en el loop (el maquillaje, o sea quitar basura como los Serial.println, lo haré luego):

void loop(){
  userSMSCheck();
  if(state == ON){
    if(monitoring == ON){
      lecturaPirP1 = analogRead(sensorPirP1);
      lecturaEcoP1 = analogRead(sensorEcoP1);
      if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
        Serial.println("ALARMA ZONA Uno!!...");
        activate_ALERT("1");
      }
      lecturaPirP2 = digitalRead(sensorPirP2);
      lecturaEcoP2 = digitalRead(sensorEcoP2);
      if((lecturaPirP2 == HIGH) and (lecturaEcoP2 == HIGH)){
        Serial.println("ALARMA ZONA Dos!!...");
        activate_ALERT("2");
      }
    }
    else{
        alertTimeOnCheck();
        Serial.println("Alarma auto-reactivada.");
    }
  }
}

Por cada vuelta controlo mensajes entrantes llamando a la función userSMSCheck() y luego miro sensores si es que la alarma está en estado Activo y en Monitoring. Hasta acá ok...
Cuando se alarma alguna de las zonas, lo que hago es llamar la funcion activate_ALERT pasando el parametro de la zona alarmada, esa función hace esto:

void activate_ALERT(String zona){
  monitoring = OFF;
  sendSMS(zona);
  digitalWrite(releR1, LOW);
  delay(25000);
  digitalWrite(releR1, HIGH);
}

Lo que haces es: pone el monitoreo en OFF; invoca a la función que manda el SMS de alerta; enciende relay para que suene sirena; espera 25 segundos (tiempo de sirena sonando); apaga relay; vuelve al loop...
Ahora, si mientras esta sonando yo envío mensaje de que se apague debería: esperar a que termine el delay, se apague la sirena y lea mensajes por ser la primera acción o linea de código del loop... pero no lo hace!!; una vez que termina y vuelve al loop es como que pasa por alto la lectura de mensajes y entra al "else" donde invoca a la función alertTimeOnCheck() y se rearma la alarma de forma automática (esto es porque si no recibe mensaje alguno se rearma sola para volver a monitorear sensores). Con lo cual, una vez rearmada si le vuelvo a enviar otro SMS ahí si lo toma y lo procesa.
Denajo colocaré todo el nuevo código....
Gracias de nuevo!!.

De nuevo, el "maquillaje" lo dejo para luego...

#include <SoftwareSerial.h>
#include <Arduino.h>

/*** PARÁMETROS ***/
/******************************/
#define BUZZER 5
#define releR1 2
#define bluePin 4
#define greenPin 8
#define SERIAL_BAUDRATE 9600
#define GSM_BAUDRATE 9600
#define RX_pin 10
#define TX_pin 11
#define ON 1
#define OFF 0
#define sensorPirP1 A0
#define sensorEcoP1 A1
#define sensorPirP2 6
#define sensorEcoP2 7
/******************************/

bool state, monitoring;
int lecturaPirP1, lecturaEcoP1, lecturaPirP2, lecturaEcoP2;
SoftwareSerial *SIM900;
String incomingSMS, msessage;
  
void setup(){
  state = OFF;
  monitoring = OFF;
  SIM900 = new SoftwareSerial(RX_pin, TX_pin);
  pinMode(BUZZER, OUTPUT);  
  pinMode(bluePin, OUTPUT);
  pinMode(releR1, OUTPUT);
  pinMode(sensorPirP1, INPUT);
  pinMode(sensorEcoP1, INPUT);
  pinMode(sensorPirP2, INPUT);
  pinMode(sensorEcoP2, INPUT);
  digitalWrite(releR1, HIGH);
  pinMode(greenPin, OUTPUT);
  
  mySerialPower();
  GSM_init();
  delay(15000);
  countdown();
  digitalWrite(bluePin, HIGH);
  delay(2000);
  digitalWrite(bluePin, LOW);
  delay(1000);
  Serial.println("Alarma lista para ser activada...");
}

void loop(){
  userSMSCheck();
  if(state == ON){
    if(monitoring == ON){
      lecturaPirP1 = analogRead(sensorPirP1);
      lecturaEcoP1 = analogRead(sensorEcoP1);
      if((lecturaPirP1 > 450) and (lecturaEcoP1 > 450)){
        Serial.println("ALARMA ZONA Uno!!...");
        activate_ALERT("1");
      }
      lecturaPirP2 = digitalRead(sensorPirP2);
      lecturaEcoP2 = digitalRead(sensorEcoP2);
      if((lecturaPirP2 == HIGH) and (lecturaEcoP2 == HIGH)){
        Serial.println("ALARMA ZONA Dos!!...");
        activate_ALERT("2");
      }
    }
    else{
        alertTimeOnCheck();
        Serial.println("Alarma auto-reactivada.");
    }
  }
}

void mySerialPower(){
  digitalWrite(8, LOW);
  delay(1000);
  digitalWrite(8, HIGH);
  delay(2000);
  digitalWrite(8, LOW);
  delay(3000);
}

void GSM_init(){
  Serial.begin(SERIAL_BAUDRATE);
  SIM900->begin(GSM_BAUDRATE);
  SIM900->println("AT");
  updateSerial();
  SIM900->println("AT+CREG=1");
  updateSerial();
  delay(10000);
  SIM900->println("AT+CMGF=1");
  updateSerial();
  delay(100);
  SIM900->println("AT+CNMI=1,2,0,0,0");
  updateSerial();
  SIM900->println("AT+CSQ");
  updateSerial();
  SIM900->println("AT+CREG?");
  updateSerial();
}

void countdown(){
  for(int i=3;i>1;i--){
    if(i>10){
      beep(50,50,1);
      delay(100);
    }else{
      beep(50,50,2);
    }
    delay(900);
  }
  beep(50, 50, 10);
}

void beep(int msON, int msOFF, int rep) {
  for (int i = 0; i < rep; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(msON);//wait for X ms
    digitalWrite(BUZZER, LOW);
    delay(msOFF);
  }
}

void userSMSCheck(){
  incomingSMS = "";
  if(SIM900->available()){
    incomingSMS = SIM900->readString();
  }
  if((incomingSMS.indexOf("+xxxxxxxxxxxxx")>=0) or (incomingSMS.indexOf("+zzzzzzzzzzzzzz")>=0)){
    if(incomingSMS.indexOf("Reset")>=0){
      Serial.println("Procesando Reseteo...");
      RESET();
      Serial.println("Alarma reactivada...");
    }  
    if(incomingSMS.indexOf("Off")>=0){
      Serial.println("Procesando desactivación...");
      switch_OFF();
      Serial.println("Desactivada");
    }  
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

void sendSMS(String donde){
  msessage = "SE HA ACTIVADO LA ALARMA EN ZONA " + donde + ". AutoReseteo en 25seg.";
  SIM900->println("AT");
  updateSerial();
  delay(500);
  SIM900->println("AT+CMGS=\"+xxxxxxxxxxxxx\"");
  updateSerial();
  SIM900->print(msessage);
  SIM900->write(26);
  updateSerial();
}

void updateSerial(){
  delay(500);
  while (Serial.available())
  {
    SIM900->write(Serial.read());
  }
  if (SIM900->available()){
    while(SIM900->available())
    {
      Serial.write(SIM900->read());
    }
  }
}

void activate_ALERT(String zona){
  monitoring = OFF;
  sendSMS(zona);
  //digitalWrite(releR1, LOW);
  delay(25000);
  //digitalWrite(releR1, HIGH);
}

void switch_ON(){
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(25000);
  state = ON;
  monitoring = ON;
}

void switch_OFF(){
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(500);
  //digitalWrite(releR1, LOW);
  delay(100);
  //digitalWrite(releR1, HIGH);
  delay(200);
  state = OFF;
  monitoring = OFF;
}

void RESET(){
  switch_OFF();
  delay(2000);
  switch_ON();
}

void alertTimeOnCheck(){
  RESET();
}

Revisa el manejo de la variable monitoring porque solo switch_On() la pone ON pero switch_Off() no lo hace y monitoring está OFF desde activate_Alert() por eso despues de leer el msj salta al else.

Saludos

PD: lo de A0 y A1 podría ser porque tienen una configuración levemente diferente porque se usan para un comparador interno.