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.

 

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

 

(22) Comments

  • Hola, estuve intentando como me dijiste pero la verdad es que no conozco mucho del tema y no logro poder registrar el numero mediante un mensaje, me podrías ayudar? de antemano gracias

    • Hola Manuel, una vez tienes guardado el contenido del sms en la variablwe mensaje como string puedes usar la función cadena.substring(posini,posfin); para sacar el número de teléfono que envíes en el sms. Una vez lo tengas no tienes más que guardarlo dentro del array en la posición que creas conveniente. Un saludo.

  • Hola, muy buenos tutoriales la verdad me están ayudando mucho para mi proyecto, pero lo que necesito es poder modificar la agenda de los números autorizados pero mediante un SMS, ¿Cómo le podría hacer?

    • Hola Manuel, podrías leer el número en el mensaje igual que hacemos en esta sesión y añadirlo al array en el que tengas guardados los números. Y para borrar podrías también leer el número y comprobar si está en array. Si está lo borras. Un saludo.

    • Lucas Gallay

    Hola. cuando cargo este programa:
    #include

    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

    Al verificar en el id de arduino, tengo este error:
    #include expects “FILENAME” or

    Solucion?
    Gracias.

    • Hola Lucas, había un error y se nos había pasado especificar la librería. Ya está corregido. Un saludo.

    • Héctor

    Hola, gracias por el tutorial, he conseguido encender y apagar un relé mediante sms pero al juntar este programa con mi programa principal donde cojo valores de temperatura, humedad y demas de unos sensores ocurre que al iniciar el sim900 con la funcion inicializasim900() en el monitor serie se empieza a inicializar pero de repente empiezan a salirme los valores de los sensores que estan en otras funciones mezclados con los comandos AT de la funcion de inicializasim900 y no se a que puede ser debido,
    por ejemplo:
    OK
    PIN OK
    ATTEMPERATURA:50%
    HUMEDAD

    +TEMPERATURA 50%
    HUMEDAD

    CTEMPERATURA 50%
    HUMEDAD

    PITEMPERATURA 50%
    HUMEDAD

    NTEMPERATURA 50%
    HUMEDAD

    y al final no llega a comunicar con el modulo SIM900. lo curioso es que si pongo vuestro programa funciona a la perfección.
    Alguna idea de como solucionarlo?

    gracias de antemano

  • Hola me ha servido de mucho para avanzar con mi proyecto, pero tengo un problema, necesito hacer que el shield active unos led ya sea por llamada o por sms, el problema es que cuando lo intento avtivar con sms, solo deja el al primer numero que tengo en el arreglo los demas no los compara ni los acepta, y en la llamada se queda almacenado el numero anterior que lo activo, me gustaria saber si hay manera de resolverlo o si hay manera de leer el numero del que esta llamando o mandando mensaje y almacenarlo en una variable, antes con otro shield si lo podia hacer pero aqui no sé como hacerle, saludos, les mando el codigo que contrui en base a sus ejemplos.

    #include
    SoftwareSerial SIM900(7, 8); // Configura el puerto serial para el SIM900
    char incoming_char = 0; //Variable que guarda los caracteres que envia el SIM900
    String agenda[] = {“5522060663″,”5527168263″,”5919172080″,”5551073729″,”5561666732″,”5577311328″,”5565346432″,”5577295864″,”5577295864”}; //Array con los numeros autorizados
    String nombres[] = {“Miguel Angel”,”Miguel 2″,”Numero local”,”Oscar”,”Alaejandra”,”Alejandra 2″,”Pepillo”,”ale 3″,”Miguel 3 prueba”};
    int numtotal = 9; //Cantidad de numeros de telefono autorizados
    String mensaje = “”;
    int iniciollamada;
    char receptora[]=”5577295864″;
    int LED = 13 ;
    int pos;
    bool estado = false; //Variable para guardar el estado del LED
    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
    }
    int llamadita = mensaje.indexOf(“RING”);
    int mensajito = mensaje.indexOf(“Activar”);
    if (llamadita >= 0)
    {
    identifica_llamada();
    mensaje=””;
    }
    if (mensajito >= 0){
    identifica_SMS();
    }

    }

    void inicializaSIM900()
    {
    delay (5000);
    SIM900.begin(19200); //Configura velocidad del puerto serie para el SIM900
    Serial.begin(9600); //Configura velocidad del puerto serie del Arduino
    Serial.println(“OK”);
    delay (1000);
    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 mensajes
    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);
    SIM900.println(“AT+CMGL=ALL”);
    delay(1000);

    }

    void identifica_llamada()
    {
    iniciollamada = mensaje.indexOf(“RING”);
    if (iniciollamada >= 0)
    {
    for ( int i = 0; i = 0)
    {

    delay(2000);
    SIM900.println(“ATH”); // Cuelga la llamada
    digitalWrite(LED, HIGH);
    delay(15000);
    digitalWrite(LED, LOW);
    Serial.println(“\nEl numero esta autorizado”);
    Serial.println(“Enviando SMS…”);
    String numerox=agenda[i];
    unsigned char* n=(unsigned char*)numerox.c_str();
    char sms[100];
    char comando[100];
    String nombre2=nombres[i];// nombre[pin];
    unsigned char* nom = (unsigned char*) nombre2.c_str();
    sprintf(sms,”Led activado por el numero: %s %s mediante llamada”,n,nom);
    sprintf(comando,”AT + CMGS = \”%s\””,receptora);
    SIM900.println(comando);
    delay(1000);
    SIM900.println(sms); // Texto del SMS
    delay(100);
    SIM900.println((char)26); //Comando de finalización ^Z
    delay(100);
    SIM900.println();
    delay(5000); // Esperamos un tiempo para que envíe el SMS
    Serial.println(“SMS enviado”);
    mensaje = “” ; //Bórralo para la próxima vez
    Serial.println(“Vaciando memoria 2”);
    Serial.flush();

    }
    else{
    Serial.println(“El numero no coincide”);
    }

    }mensaje = “” ;

    }

    }

    void identifica_SMS()
    { delay(2000);
    for ( int j = 0; j = 0){
    digitalWrite(LED, HIGH);
    delay(15000);
    digitalWrite(LED, LOW);
    Serial.println(“\nEl numero esta autorizado”);
    Serial.println(“Enviando SMS…”);
    String numerox=agenda[j];
    unsigned char* n=(unsigned char*)numerox.c_str();
    char sms[100];
    char comando[100];
    String nombre2=nombres[j];// nombre[pin];
    unsigned char* nom = (unsigned char*) nombre2.c_str();
    sprintf(sms,”Led activado por el numero: %s %s mediante APP”,n,nom);
    sprintf(comando,”AT + CMGS = \”%s\””,receptora);
    SIM900.println(comando);
    delay(1000);
    SIM900.println(sms); // Texto del SMS
    delay(100);
    SIM900.println((char)26); //Comando de finalización ^Z
    delay(100);
    SIM900.println();
    delay(5000); // Esperamos un tiempo para que envíe el SMS
    Serial.println(“SMS enviado”);
    delay(2000);
    Serial.println(“Vaciando memoria “);
    SIM900.println(“AT+CMGD=1,4”);//elimino mensajes en la SIM
    mensaje = “”;//eliminamos el contenido del mensaje
    Serial.flush();//libero memoria
    }
    else{

    Serial.println(“El numero no coincide”);

    }

    } mensaje = “” ;

    }

    • Hola Miguel Ángel, no sé si es problema del copia pega pero en el for que veo ahí no recorres el array de la agenda, únicamente miras la primera posición. Un saludo.

      • Hola si es problema del copia y pega, si tiene el i + +, pero no lo recorre todo el arreglo

        • Hola Miguel Ángel, pero en el for pone también desde i=0 hasta i=0; por lo que aunque incrementes i sólo recorre la primera posición del array. A no ser que sea otro error al copiar y pegar.

    • Fernando

    Hola buenas haber estoy haciendo una alarma con sim900 y arduino uno pero no consigo apagar la alarma y la tengo que apagar con un sms es decir enviar un sms al GSM diciéndole apagar alarma la cosa es que consigo recibir sms al celular pero no consigo enviar al GSM no lo detecta me puedes ayudar con eso

    • Hola Fernando, en principio debería servirte la función identifica_SMS que hay en la sesión, haciendo que busque la cadena que tu quieras que contenga el SMS. SI tienes alguna duda me dices. Si no puedes leer el SMS por el puerto serie fíjate que tengas bien la parte del programa en la que leemos los caracteres que nos llegan desde el SIM900. UN saludo!

  • Hola estoy tratando de unificar esto a un programa que en vez de encender el led mediante la llamada, me envíe las coordenadas gps a un server, esto ya esta echo pero con un pulsador como condición para el envió de los datos, el problema viene al momento unir los dos programas ya no funciona el el GPS, no estoy seguro si es porque los dos módulos trabajan con seriales al mismo tiempo y en este programa de identificar llamada en el loop esta llamando a cada momento solo al modulo GSM. Quisiera saber como podría hacer funcionar los dos programas unidos. Muchas Gracias

    • Hola Ivan! Es cierto que hay problemas cuando vamos complicando los programas con este shield, sobre todo si queremos tanto enviar como recibir. Echa un ojo a estos tutoriales que seguro que te van a servir:

      http://www.prometec.net/gprs-enviar-recibir-llamadas-sms/
      http://www.prometec.net/gprs-internet/

      No tienes más que meter en el switch al envío de las coordenadas cuando presiones el pulsador. De todas formas tenemos en mente también hacer un tutorial en el que precisamente unifiquemos un GPS con el shield GPRS. Un saludote!

  • Antes que nada desearles todo el éxito del mundo, este curso me ayudo bastante a comprender como funciona el modulo SIM900, estoy trabajando en una alarma y créame que gracias a sus enseñanzas pude lograr satisfactoriamente dicho proyecto. PROMETEC muchas gracias y sigan adelante. 😀

    • Hola Mauricio, nos alegramos mucho de que lo estés disfrutando y encontrando útil. Seguiremos subiendo sesiones relacionadas con el GPRS en cuanto podamos. Un saludote y muchas gracias!

  • Buenas tardes tengo el mismo problema que Luis y quiero ademas comunicarlos con xbee por medio de comandos At se podra, tengo que terminar un proyecto, espero pronta respuesta de ustedes, muchas gracias.

    • Hola Marcelo, donde tienes el problema exactamente? Consigues realizar llamadas pero no SMS? En cuanto a los Xbee no sé qué decirte, porque no lo he probado. Un saludo.

  • no pude hacer caminar mi sim900 con los mensaje de texto me pueden dar una ayudita?

    • Hola Luis, ¿nos puedes dar alguna pista más para poder ayudarte? ¿El problema es al enviarlos o al recibirlos? ¿Las llamadas consigues hacerlas funcionar correctamente? Un saludote!

Give a Reply

WordPress Anti-Spam by WP-SpamShield