Falsos positivos con SIM900

Buenas a todos!! Hace un tiempo desarrollé una alarma hogareña usando una SIM900 en donde la misma la controlo por sms desde el celular.

Todo venía bien hasta que de pronto comencé a tener falsas alarmas, me costo encontrar el motivo de las mismas pero ya lo logré, ahora el tema es como evitarlo.

La falla o falsa alarma: si alguien (como alguna operadora ofreciendo promociones) llama al número de la SIM me genera un positivo o high en los pines digitales 6 y 7 dado que la que se alarma es la ZONA 2 (incluso ya probé dejando solo habilitados dichos pines quitando la ZONA 1 y al llamar al número me genera el falso positivo).

Como evitar entonces el ruido o falso positivo ante la recepción de una llamada?.

Este es básicamente el codigo (se puede mejorar? Si, pero de momento solo preciso centrarme en solucionar esas falsas alarmas):

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

/*** PARÁMETROS ***/
/******************************/
#define BUZZER 5
#define releR1 2
#define bluePin 4
#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;
int x = 0;
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(8, 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("+xxxxxxxxxxxxxx")>=0) or (incomingSMS.indexOf("+zzzzzzzzzzzzzzz")>=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");
      msessage = "ALARMA DESACTIVADA.";
      sendSMS(msessage);
    } 
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

void sendSMS(String mensajeSale){
  SIM900->println("AT");
  updateSerial();
  delay(500);
  SIM900->println("AT+CMGS=\"+xxxxxxxxxxxxxx\"");
  updateSerial();
  SIM900->print(mensajeSale);
  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;
  msessage = "SE HA ACTIVADO LA ALARMA EN ZONA " + zona + ". AutoReseteo en 25seg.";
  sendSMS(msessage);
  digitalWrite(releR1, LOW);
  x = 0;
  do
  {
    delay(200);
    userSMSCheck();
    if(state == OFF) break;
    x = x + 1;
  }while (x < 99);
  digitalWrite(releR1, HIGH);
}

void switch_ON(){
  digitalWrite(releR1, LOW);
  delay(100);
  digitalWrite(releR1, HIGH);
  x = 0;
  do
  {
    delay(100);
    x = x + 1;
  }while (x < 249);
  state = ON;
  monitoring = ON;
}

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

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

void alertTimeOnCheck(){
  RESET();
}

La forma de evitarlo es que tengas una lista blanca de números que pueden ingresar y todos los demas descartarlos.
Asi en simples palabras luce fácil, tu dirás si me entiendes o no.

Odio ser reiterativo pero ya en el mes de enero (porque desde el principio tenías problemas y justamente se alarmaba erróneamente la zona 2) te dijimos que estabas leyendo incorrectamente señales digitales con analogRead().

O sea que pasas por aquí a ver si te resolvemos un problema puntual pero no aceptas correcciones y sigues arrastrando tus viejos errores.

¿Cómo puede ser que 9 meses después, y luego de que tanto @Surbyte como yo mismo nos tomáramos el tiempo de explicarte las razones del error de hacerlo de esa forma y que dijeras entender, sigan existiendo esas dos sentencias analogRead() en tu código?

¿Supones que el tiempo que dedicamos a leer el código, tratar de comprenderlo e intentar encontrar una solución es menos valioso que el tuyo?

Por otro lado y para que no sean todas "pálidas", aunque no digo que sea la solución pero podría influir, ¿has verificado que la memoria de SMS no esté llena? Porque no veo alguna parte del código donde se borren los SMS ya leídos.

Saludos

@gatul , entonces les entendí mal. Y te explico porque:

1- En un principio yo usaba solo pines Analógicos y para ambas zonas, me dijeron que debía usar los digitales, entonces cambie la zona 2 que era la que fallaba a dos pines digitales y santo remedio, la zona 1 pregunté incluso el porque nunca fallaba y me dijeron que los pines A0 y A1 tienen otros mecanismos y controles especiales y que por ahi por eso no fallaban, entonces los dejé para evitar conectar y desconectar porque la caja donde esta todo no me quedó en un lugar de muy facil acceso.

2- Desde entonces no falló salvo ahora que detecté que cuando alguien llama al número de la sim me mete ruido en los pines digitales de la zona 2 y se alarma.

3- En cuanto al tiempo de cada uno de ustedes no se porque reaccionas de esa forma dado que en ningún momento lo pense de así, el tiempo es oro para todos y por eso mi pregunta fue muy puntual: la zona 2 se alarma cuando entra una llamada, solo eso es el tema. Para optimizar, mejorar, etc hay tiempo y justamente la zona 1 que usa los analógicos, y que por usar el 0 y 1, no es el problema y nunca me generaron problemas. Me fueron de mucha ayuda dado que con este tipo de plcadas (SIM) fue la primera vez que las use.

4- En cuanto a la memoria de SMS supongo que esta vacía porque fueron muy pocas veces que use la alarma con esto de la pandemia no salgo de casa casi, si fueron 4 veces ya te digo que fue mucho y solo envie mensaje de activar y desactivar una vez por cada vez que la use y solo un par de mensajes extras salientes cuando se generaron los falsos positivos. Había un comando que limpiaba los SMS al encender el arduino lo buscaré y lo agregaré al código.

@Surbyte : en cuanto a la lista blanca, como puedo hacer eso por código para indicarle que solo reciba llamadas y sms de dos números?. Esa sería la solución en este caso.

Saludos y gracias.

Si uso estos comandos AT para limpiar los SMS esta bien?

Sería para marcar todos como leidos:

Serial.println("AT+CMGL=</mark>“ALL</mark>”,0 ");

Sería para borrar todos:

mySerial.print("AT+CMGDA=\""); 
mySerial.println("DEL ALL\"");
delay(500);
Serial.println( "All Messages Deleted" );

Creo que aun no lo entiendes. Puedes usar los A0...A5 pero como digitales. Cuando los defines los usas como digitales de este modo.

// en el setup
pinMode(A0, INPUT);
//// en el loop
// al leer lees como entrada digital
int status = digitalRed(A0);

Espero que se comprenda este punto.

Si, claro que esta bien, no hay porque complicarse. De hecho cualquier librería termina usando los AT, asi que si los borra esta mas que bien.

La lista blanca es una lista de números permitidos. Cada vez que recibes un msg chequeas contra tu lista y autorizas o no si ese número puede hacer cambios.
Tenerlo abierto es una falla de seguridad a tu alarma. Algo que se te pasó por alto, pero ya estas en camino.
Entonces, varias maneras de implementarlo desde la menos flexible a la mas flexible.
La menos sería lista de números fijos como un array de String si quieres y luego cuando recibes un número haces un ciclo, chequeas y tendras un Si o No a ese chequeo.
El método mas flexibles sea con SD o EEPROM (te recomiendo EEPROM xq seran pocos números) es que escribas una rutina de tu número administrador que permita ingresar numeros de la lista blanca y asi hacerla varible, claro que tendras que poner un ABM o sea Altas Bajas y Modificaciones.
Alta es que das de alta un numero
Baja es que lo borras
Modificaciones cuando cometas errores de tipeo.

Tienes trabajo

Aaaaahhh esto no lo sabía, no pense que pidias declararlos de otro "tipo", entonces en ese caso no se hable mas lo cambio al toque.

En cuanto a la lista blanca asi como la mencionas fíjate que lo uso, o al menos supongo que es lo mismo a lo que me dices solo que estan "quemados" los números en el código en lugar de un file...

void userSMSCheck(){
  incomingSMS = "";
  if(SIM900->available()){
    incomingSMS = SIM900->readString();
  }
  if((incomingSMS.indexOf("+xxxxxxxxxxxxxx")>=0) or (incomingSMS.indexOf("+zzzzzzzzzzzzzzz")>=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");
      msessage = "ALARMA DESACTIVADA.";
      sendSMS(msessage);
    } 
    if(incomingSMS.indexOf("On")>=0){
      Serial.println("Procesando activación...");
      switch_ON();
      Serial.println("Activada");
    }
  }
}

El tema es que mi loop primero lee si llegaron mensajes y si no los hay entonces continua con la toma de datos de los sensores de las zonas. Cuando ingresa una llamada es el momento en que genera "el ruido" en los digitales (la zona 2 en este momento).

Suponiendo que ademas de mirar si llegan mensajes miro si alguien llama y quien llama, pero no me interesa saber quien porque la idea es justamente rechazar las llamadas para no permitir el ingreso del "ruido". Hay algun comando AT que bloquee la SIM para recepción de llamadas y solo la deje habilitada para SMS?.

Si aplico este seteo:

//Reject incoming calls
AT+GSMBUSY=1

Los SMS ingresarna igual? porque de nuevo, no quiero que la SIM acepte llamadas.

Pero eso es prohibitivo para todo el mundo incluido quien maneja el sistema.

Si, porque yo el sistema lo manejo solo por SMS. Si colocando el GSMBUSY=1 permite que los SMS ingresen igual entonces listo a mi me sirve.

Ahora te entiendo, te respondí erróneamente porque pensé que bloqueabas SMS y lo que haces es bloquear llamadas entrantes.