bclose

CONTROLAR ARDUINO MEDIANTE LLAMADAS Y SMS

Encendiendo y apagando un LED con nuestro móvil

Objetivos

 

 

    • Encender y apagar un LED mediante llamadas y SMS.
    • Crear una agenda con números autorizados para las llamadas.
    • Reconocer y utilizar textos de los SMS para realizar diferentes acciones.
 

Material requerido.

Imagen de Arduino UNOArduino UNO o equivalente
modulo gprsUn Shield GPRS SIM900
conexionesAlgunos cables de protoboard.
Power supply

 Una fuente de alimentación para Arduino.

tienda online prometec

CONTROLAR ARDUINO CON NUESTRO MÓVIL

 

Con lo que hemos aprendido hasta ahora seguro que a muchos de vosotros (yo incluido) se os ha ocurrido que podríamos montar un sistema que, por ejemplo, encienda la calefacción de casa un ratillo antes de que lleguemos haciéndole una llamada con nuestro móvil, y así estemos bien a gustito en casa según lleguemos.

Pues en esta sesión vamos a ir acercándonos a eso. Primero utilizando una llamada para encender y apagar un LED, y después para hacer lo propio en función del SMS que le enviemos.

movil llama arduino

 

UTILIZAR UNA AGENDA PARA FILTRAR LAS LLAMADAS

 

Primero vamos a centrarnos en las llamadas. El concepto del programa será guardar en una variable el texto que recibamos del puerto serie del GPRS y si es una llamada, encender o apagar un LED alternativamente. Pero claro, no queremos que nadie que no seamos nosotros (u otra persona autorizada por nosotros) se equivoque al llamar de número y ande encendiendo cosas en nuestra casa, así que crearemos una agenda con los números que tienen nuestro beneplácito.

Además tendremos que crear una variable mensaje tipo String, donde iremos guardando los caracteres que nos vayan llegando del GPRS, con el fin de poder luego trabajar con ellos.

 #include <SoftwareSerial.h>
   SoftwareSerial SIM900(7, 8); // 10 y 11 para el Arduino Mega. Configura el puerto serial para el SIM900

   char incoming_char = 0; //Variable que guarda los caracteres que envia el SIM900
   String mensaje = "";
   int LED = 13 ;
   bool estado = false ;  //Variable para guardar el estado del LED
   String agenda[] = {"XXXXXXXXX" , "XXXXXXXXX"};  //Array con los numeros autorizados
   int numtotal = 2;  //Cantidad de numeros de telefono autorizados

Toda la parte de los programas que sirve para recibir las llamadas y los SMS correctamente va a ser el mismo que en la sesión anterior, sólo que esta vez hemos metido toda la parte que se encarga de poner en marcha el módulo GPRS en una función a la que llamaremos inicializaSIM900, y que lanzaremos en el setup.

 void inicializaSIM900()
   {
      //digitalWrite(9, HIGH); // Descomentar para activar la alimentación de la tarjeta por Software
      //delay(1000); 
      //digitalWrite(9, LOW);
      delay (5000);
      SIM900.begin(19200); //Configura velocidad del puerto serie para el SIM900
      Serial.begin(19200); //Configura velocidad del puerto serie del Arduino
      Serial.println("OK");
      delay (1000);
      SIM900.println("AT + CPIN = \"XXXX\""); //Comando AT para introducir el PIN de la tarjeta
      delay(25000); //Tiempo para que encuentre una RED
      Serial.println("PIN OK");
      SIM900.print("AT+CLIP=1\r"); // Activa la identificación de llamada
      delay(100);
      SIM900.print("AT+CMGF=1\r"); // Configura el modo texto para enviar o recibir SMS
      delay(1000);
      SIM900.print("AT+CNMI=2,2,0,0,0\r");   // Saca el contenido del SMS por el puerto serie del GPRS
      delay(1000);
    }

Y la recepción de caracteres va a ser también igual en el loop, sólo que esta vez iremos guardando los caracteres en una variable, como hemos indicado un poco más arriba.

 if (SIM900.available() > 0)
   {
       incoming_char = SIM900.read(); //Get the character from the cellular serial port.
       Serial.print(incoming_char); //Print the incoming character to the terminal.
       mensaje = mensaje + incoming_char ; // Añadimos el último caracter leído al mensaje
   }

Una vez tenemos el mensaje completo, vamos a ver si es una llamada, y a buscar el número de teléfono para encender un LED si está autorizado.

Para esto vamos a utilizar una función .indexof(). Esta función nos devuelve la posición, mediante un número entero, de una cadena o carácter dentro de una cadena de texto dada. En el caso de que no exista devuelve “-1”. La forma de usarlo es la siguiente:

 int pos = “texto”.indexOf(“caracteres a buscar”);
  if (pos >= 0)
      {
         Acciones que queremos realizar;
      }

Sabiendo esto crearemos una función identifica_llamada() para buscar primero el final de una llamada, y después el número de teléfono y si está autorizado.

Si recordáis la sesión anterior, una llamada finaliza con “NO CARRIER”, así que lo primero que haremos será buscarlo y si existe buscaremos los números de teléfono que hemos autorizado dentro del mensaje que hemos guardado. Si está autorizado cambiamos el estado del LED, y sino no hacemos nada.

Y una vez hecho todo esto, borramos el contenido de la variable mensaje para dejarla libre para la siguiente llamada.

 void identifica_llamada()
   {
      int finllamada = mensaje.indexOf("NO CARRIER");  //Buscamos el final de llamada
      if (finllamada >= 0)
         {
            for ( int i = 0; i < numtotal; i++) { int pos = mensaje.indexOf(agenda[i]); //Buscamos el número en la agenda if (pos >= 0)
                     {
                        estado = ! estado ;                       // cambiamos el estado
                        digitalWrite(LED, estado) ;
                        Serial.println("\nEl numero esta autorizado");
                     }
                }
            mensaje = "" ; //Bórralo para la próxima vez
       }
   }

Así el setup y el loop quedarían de la siguiente forma:

 void setup()
   {
      pinMode( LED, OUTPUT) ; // LED como salida
      inicializaSIM900();
   }

void loop()
   {
       if (SIM900.available() > 0)
         {
             incoming_char = SIM900.read(); //Guardamos el carácter del GPRS
            Serial.print(incoming_char); //Mostramos el carácter en el monitor serie
            mensaje = mensaje + incoming_char ; // Añadimos el carácter leído al mensaje
          }
      identifica_llamada ();
   }

Podéis descargar el programa completo aquí: Encender_LED_llamada.

Cuando hagáis pruebas os recomiendo dejar sonar más de un tono, por si acaso se perdiera algún carácter durante el envío y no recojamos bien el número de teléfono. Con cada tono se manda una vez el número que nos está llamando, y así nos aseguramos de que alguna de las veces llegue bien. No pasa muchas veces, pero todos conocemos las leyes de Murphy…

 

DIFERENCIAR Y RECONOCER TEXTOS EN LOS SMS

 

En el caso del SMS va a ser muy parecido, pero vamos a reconocer el texto del mensaje y en función de lo que le enviemos encenderá o apagará el LED. De esta manera sabremos en todo momento el estado del mismo, ya que con la llamada lo encendíamos o lo apagábamos, pero de momento no teníamos forma de saber si estaba encendido o apagado (aunque también podríamos solucionar esto).

Con el SMS ya no vamos a necesitar buscar el final de la llamada ni autorizar números, porque nadie se va a equivocar y mandar un SMS con el texto concreto a nuestro Arduino por equivocación (ya me parece bastante raro que alguien mande un SMS), aunque si buscáis máxima seguridad no os sería muy difícil incluir también esa comprobación. Así que podemos prescindir de las variables que creábamos para ello.

Por lo demás el programa es exactamente igual, salvo la función final, que quedaría así:

 void identifica_SMS()
   {
      int led_on = mensaje.indexOf("Encender LED");  //Buscamos el texto en el SMS
      int led_off = mensaje.indexOf("Apagar LED");  //Buscamos el texto en el SMS
      if (led_on >= 0)
         {
            digitalWrite( LED, HIGH) ;
            Serial.println("\nLED ENCENDIDO");
            mensaje = "" ; //Bórralo para la próxima vez
         }
      if (led_off >= 0)
         {
            digitalWrite( LED, LOW) ;
            Serial.println("\nLED APAGADO");
            mensaje = "" ; //Bórralo para la próxima vez
         }
   }

Y el programa completo lo tenéis aquí: Encender_LED_SMS.

Ahora podéis combinar ambos si queréis que reaccione ante las dos cosas. Y si, como a mí, os siguen cobrando los SMS y no estáis por la labor de pagar más, os propongo que contéis los tonos de la llamada y en función de cuántos sean, encendáis o apaguéis el LED. Recordad que con cada tono el GPRS nos envía una cadena de caracteres “RING”.

 

Resumen de la sesión

 

En esta sesión hemos aprendido varias cosas importantes:

 
    • A controlar un LED a distancia usando nuestro móvil.
    • Hemos presentado y explicado la función .indexof().
    • A hacer un filtro en las llamadas para autorizar sólo algunos números basándonos en una agenda.
    • A diferenciar textos en los SMS y actuar en consecuencia.
 
 
 

LikeUsOnFacebook_Icon

 

(49) Comments

  • Muy buenas! Necesito ayuda de algun alma caritativa xD Resulta que me encuentro en estos momentos en la etapa de “Proyecto Comunitario” de la carrera de Ing. Electrónica, y estoy haciendo un sistema de alarma para una grupo de casas, basado en arduino y por motivos varios se me hace imposible probar el sistema en fisica con el Sim900, el arduino y demas componentes, asi que no se a ciencia cierta si el codigo que he realizado esta bien o no, cabe destacar que soy novato aun en la programacion de arduino, y me ha tocado enfrascarme en este proyecto xD. El sistema se supone debe realizar lo siguiente:

    -Se tendrán varios numeros registrados y activada la identificacion de llamada del modulo GSM, esto para la agenda telefonica.
    -Si se recibe un llamada de uno de los numeros registrados se activara la alarma (altavoces y luces estroboscopicas).
    -También se podran recibir msjs e identificar su contenido a fin de poder activar “reinicios parciales o totales” del sistema:
    a) Si se envia un mensaje que diga “Matenimiento”, parpadeara 3 veces un LED verde.
    b) “Reset Programa”, reiniciara el programa.
    c) “Reset Sistema”, reiniciara el arduino mediante el pin de “RESET” que este posee.
    d) “Reset GSM”, reiniciara el SIM900

    -Una vez listo cualquier reinicio el sistema enviara un msjs de “Reinicio Completo”.
    -El codigo tambien posee comandos de “WatchDog” como mecanismo de seguridad.
    -Adicional, existen lineas de comando para mostrar la calidad de la señal o cobertura del GSM mediante el monitor serial en la PC, a la hora de instalar el sistema.
    -Asi mismo, poseera 3 leds indicadores de estados, un rojo para indicar que el arduino esta encendido, otro naranja para indicar que el GSM esta encendido, y el verde anteriomente mencionado que estara siempre activado e indicara que el codigo esta funcionando; este ultimo parpadera 3 veces al recibir un msjs que diga “Manteniento”, lo cual servira para probar el GSM. EL codigo es el siguiente; cabe mencionar que lo he hecho en base a lo visto en las varias paginas de este foro, pero necesito que alguien me diga si esta planteado, si asi como esta brinda todas las funciones que plantee, y en si, que me digan si el codigo funciona para lo que ya describi del sistema, y de no ser asi, que me ayuden a corregirlo por favor, de antemano muchas gracias!:

    #include
    #include
    #include
    SoftwareSerial SIM900(7, 8);
    char incoming_char = 0;
    String mensaje = “”;
    int LED = 10;
    int RELE = 11;
    int RESET = 12;
    char inSerial[256];
    bool estado = false ;
    String agenda[10] = {“+584267989946” , “+584249202682”};
    int numtotal = 10;

    void ShowSerialData()
    {
    wdt_reset();
    if (Serial.available() > 0)
    { int i = 0;
    while (Serial.available() > 0) {
    inSerial[i] = (Serial.read());
    i++;
    }
    inSerial[i] = ‘\0’;
    Serial.print(inSerial);
    }
    wdt_reset();
    }

    void setup()
    {
    wdt_disable();
    wdt_enable(WDTO_8S);
    digitalWrite( LED, HIGH) ;
    digitalWrite( RESET, HIGH) ;
    delay(200);
    pinMode( LED, OUTPUT) ;
    pinMode( RESET, OUTPUT) ;
    pinMode( RELE, OUTPUT) ;
    pinMode(9, OUTPUT);
    digitalWrite(9, HIGH);
    delay(1000);
    digitalWrite(9, LOW);
    delay (5000);
    SIM900.begin(19200);
    Serial.begin(19200);
    SIM900.print(“AT+CLIP=1\r”);
    wdt_reset();
    delay(1000);
    SIM900.print(“AT+CMGF=1\r”);
    delay(1000);
    SIM900.println(“AT+CPIN=\”1234\””);
    wdt_reset();
    delay(7000);
    wdt_reset();
    delay(7000);
    wdt_reset();
    delay(7000);
    wdt_reset();
    delay(7000);
    wdt_reset();
    Serial.println(“AT+CSQ”);
    delay(1000);
    ShowSerialData();
    }

    void identifica_llamada()
    {
    wdt_reset();
    int finllamada = mensaje.indexOf(“NO CARRIER”);
    if (finllamada >= 0)
    {
    for ( int i = 0; i = 0)
    {
    wdt_reset();
    for ( int j = 0; j > 3 ; j++) {
    digitalWrite( LED, HIGH) ;
    delay(200);
    digitalWrite( LED, LOW) ;
    delay(200);
    }
    wdt_reset();
    digitalWrite( LED, HIGH) ;
    mensaje = “” ;
    }

    if (reset1_on >= 0)
    {
    wdt_reset();
    reiniciarGSM();
    resetFunc();
    enviar_sms();
    delay(100);
    for ( int j = 0; j > 3 ; j++) {
    digitalWrite( LED, HIGH) ;
    delay(200);
    digitalWrite( LED, LOW) ;
    delay(200);
    }
    wdt_reset();
    digitalWrite( LED, HIGH) ;
    mensaje = “” ;
    }

    if (reset2_on >= 0)
    {
    wdt_reset();
    reiniciarGSM();
    digitalWrite( RESET, LOW); //Este pin debe conectarse al pin de reset del arduino mediante una resistencia de 1Kohm
    enviar_sms();
    delay(100);
    wdt_reset();
    }

    if (resetGSM >= 0)
    {
    wdt_reset();
    reiniciarGSM();
    }
    wdt_reset();
    }

    void loop()
    {
    wdt_reset();
    if (SIM900.available() > 0)
    {
    incoming_char = SIM900.read();
    mensaje = mensaje + incoming_char ;
    }
    wdt_reset();
    identifica_llamada ();
    wdt_reset();
    identifica_SMS();
    wdt_reset();
    }

    • Cristian

    Hola buenas, fijate que estoy medio loco que ya no se que hacer con esto, pues les cuento, tengo el arduino con la sim900, lo tengo conectado a la pc con el monitor y efectivamente cuando envio el mensaje me enciende/apaga el led segun sea el caso, ahora el inconveniente que tengo es que cuando lo desconecto de la pc y lo llevo al banco de pruebas ya no me funciona, ya hice varias pruebas y lo curioso es que si lo conecto al monitor serial de la pc, me trabaja muy bien pero cuando ya no lo tengo conectado ya no trabaja, alguien ha tenido este inconveniente?

    ya probe con fuentes de alimentacion independientes y tambien una de 5V*2A.

    Saludos.

    • Hola Cristian, pues he mirado un poco el código por encima y no se me ocurre por qué puede pasar. Ahora mismo no puedo probarlo pero en unos días cuando pueda te digo algo. Un saludo.

Give a Reply

WordPress Anti-Spam by WP-SpamShield