Objetivos
- Optimizar la programación del GPRS.
- Dotarlo de mayor autonomía.
- Crear una función para enviar los comandos AT
- Agrupar el envío y la recepción de llamadas y SMS en un sólo programa.
Material requerido.
OPTIMIZAR EL PROGRAMA
En las sesiones anteriores dedicadas al GRPS hemos visto cómo conectarlo correctamente y los comandos AT necesarios para enviar y recibir llamadas y SMS de una forma bastante sencilla. Sin embargo, para el que se haya fijado, aunque los comandos AT se envían correctamente y el módulo cumple la función que buscamos, hay algunas cosillas que se pueden mejorar.
Y es que al parecer la librería SoftwareSerial no se lleva del todo bien con el módulo GPRS y los comandos AT; y al enviar simplemente estos comandos con función SIM900.println(); algunas respuestas se quedan en el limbo.
A esto podríamos añadir que, siendo el GPRS un módulo orientado hacia proyectos autónomos y sin supervisión, no tendremos acceso al monitor serie (hasta ahora lo hemos supervisado desde ahí), no estaremos seguros de que las cosas estén yendo bien y estemos realmente conectados a la red móvil.
Y por último, podría ser que durante el periodo que tengamos funcionando nuestro proyecto perdiera la alimentación del Arduino o del GPRS, o se desconectase de la red móvil por alguna razón. Así que también vamos a implementar una serie de funciones para que sea capaz de reiniciarse y configurarse de forma autónoma, y de que se asegure que estemos conectados a la red antes de enviar llamadas o SMS.
Para poder reiniciarlo de esta forma y dotarle de autonomía es imprescindible haber realizado la soldadura que habilita el encendido por software del módulo GPRS mediante un pulso en el pin 9, y conectarlo al pin 9 de Arduino que usaremos para ello (ya hablamos de esto en las sesiones anteriores).

FUNCIÓN PARA ENVIAR LOS COMANDOS AT
Al parecer el error al recibir algunas respuestas de los comandos AT por el monitor serie se debe a que enviamos el comando siguiente antes de recibir la respuesta, y los “delays” no parecen solucionarlo, sino todo lo contrario (como casi siempre).
Por lo tanto crearemos una función sendATcommand2 con los siguientes objetivos:
- Enviar el comando AT.
- Esperar una respuesta del SIM900.
- Comprobar que la respuesta es correcta.
- Mostrar por el monitor serie la respuesta recibida.
La programación de la función queda de la siguiente forma:
int enviarAT(String ATcommand, char* resp_correcta, unsigned int tiempo) { int x = 0; bool correcto = 0; char respuesta[100]; unsigned long anterior; memset(respuesta, '\0', 100); // Inicializa el string delay(100); while ( SIM900.available() > 0) SIM900.read(); // Limpia el buffer de entrada SIM900.println(ATcommand); // Envia el comando AT x = 0; anterior = millis(); // Espera una respuesta do { // si hay datos el buffer de entrada del UART lee y comprueba la respuesta if (SIM900.available() != 0) { respuesta[x] = SIM900.read(); x++; // Comprueba si la respuesta es correcta if (strstr(respuesta, resp_correcta) != NULL) { correcto = 1; } } } // Espera hasta tener una respuesta while ((correcto == 0) && ((millis() - anterior) < tiempo)); Serial.println(respuesta); return correcto; }
Está función la usaremos siempre que enviemos un comando AT, y si queremos verificar la respuesta, simplemente la incluiremos dentro de un if que verifique que nos el módulo nos haya devuelto la respuesta que buscamos.
Esta estructura condicional la usaremos para verificar que realmente estemos conectados a la red móvil, aunque podríamos usarlo en todos los comandos AT para que, en caso de que algo falle, nos saque un mensaje por pantalla indicándonos dónde está el error. Realmente no totalmente necesario ya que leyendo el monitor serie se puede ver dónde falla con sólo mirar las respuestas a los comandos AT.
ENCENDER EL MÓDULO POR SOFTWARE
Ya hemos hablado anteriormente acerca de cómo encender y apagar el módulo sin tener que presionar el pulsador del GPRS, enviando un pulso de un segundo desde Arduino al pin 9 de la tarjeta. Sin embargo, imaginad que enviamos las instrucciones para encenderlo y resulta que ya estaba encendido. Lo que haríamos sería apagarlo.
Así que vamos a crear también una función para encender el módulo pero comprobando antes que no está encendido ya. Es muy sencillo, si enviamos el comando “AT” y nos devuelve OK es que estaba encendido. Si no devuelve nada tendremos que enviar el pulso para encenderlo.
void power_on() { int respuesta = 0; // Comprueba que el modulo SIM900 esta arrancado if (enviarAT("AT", "OK", 2000) == 0) { Serial.println("Encendiendo el GPRS..."); pinMode(9, OUTPUT); digitalWrite(9, HIGH); delay(1000); digitalWrite(9, LOW); delay(1000); // Espera la respuesta del modulo SIM900 while (respuesta == 0) { // Envia un comando AT cada 2 segundos y espera la respuesta respuesta = enviarAT("AT", "OK", 2000); SIM900.println(respuesta); } } }
Complementariamente a esta función vamos a crear otras dos muy sencillitas, una que apague el módulo y otra que incluya estás dos que para reiniciar el módulo, y que usaremos si perdemos la conexión a la red.
void power_off() { digitalWrite(9, HIGH); delay(1000); digitalWrite(9, LOW); delay(1000); } void reiniciar() { Serial.println("Conexion a la red perdida. Reiniciando el modulo..."); power_off(); delay (5000); power_on(); }
FUNCIONES PARA CONFIGURAR EL MÓDULO Y ENVIAR LLAMADAS Y SMS
También tenemos funciones que ya hemos usado anteriormente, pero que tenemos que adaptar a la filosofía de esta sesión. Es decir, enviaremos los comandos AT utilizando la función que hemos creado y comprobaremos que estemos conectados correctamente a la red móvil.
Estas funciones son las que usamos para configurar el módulo correctamente y las que propiamente realizan el envío de las llamadas y los SMS.
void iniciar() { enviarAT("AT+CPIN=\"1867\"", "OK", 1000); Serial.println("Conectando a la red..."); delay (5000); //espera hasta estar conectado a la red movil while ( enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 0 ) { } Serial.println("Conectado a la red."); enviarAT("AT+CLIP=1\r", "OK", 1000); // Activamos la identificacion de llamadas enviarAT("AT+CMGF=1\r", "OK", 1000); //Configura el modo texto para enviar o recibir mensajes enviarAT("AT+CNMI=2,2,0,0,0\r", "OK", 1000); //Configuramos el modulo para que nos muestre los SMS recibidos por comunicacion serie Serial.println("Preparado."); } void mensaje_sms() { if (enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 1) //comprueba la conexion a la red { Serial.println("Enviando SMS..."); enviarAT("AT+CMGF=1\r", "OK", 1000); //Comando AT para mandar un SMS sprintf(aux_str, "AT+CMGS=\"XXXXXXXXX\"", strlen(sms)); //Numero al que vamos a enviar el mensaje //Texto del mensaje if (enviarAT(aux_str, ">", 10000) == 1) { enviarAT(sms, "OK", 10000); } Serial.println("SMS enviado"); } else { reiniciar(); iniciar(); } } void llamar() { if (enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 1) //Comprueba la conexion a la red { Serial.println("Realizando llamada..."); enviarAT("ATDXXXXXXXXX;", "OK", 1000); delay(20000); // Espera 20 segundos mientras realiza la llamada enviarAT("ATH", "OK", 1000); // Cuelga la llamada Serial.println("Llamada finalizada"); } else { reiniciar(); iniciar(); } }
ESTRUCTURA DEL PROGRAMA
Una vez hemos creado las funciones que vamos a necesitar, la estructura del programa no tiene nada demasiado complicado. Con este programa realizaremos una llamada al teclear una “l” en el monitor serie y enviaremos un SMS con la letra “s”. Evidentemente también recibiremos llamadas y SMS y mostraremos la información de ambas en pantalla, del número de teléfono y del contenido del mensaje en el caso de que sea un SMS.
#include <SoftwareSerial.h> SoftwareSerial SIM900(7, 8); // Configura el puerto serial para el SIM900. Para el Arduino MEGA utilizar pines 10 y 11 int respuesta; char aux_str[50]; //Contenido del sms que enviamos. \x1A corresponde al caracter de finalizacion char sms[] = "Mensaje enviado desde el Arduino de Prometec! \x1A \r\n"; void setup() { SIM900.begin(19200); //Configura velocidad del puerto serie para el SIM900 Serial.begin(19200); //Configura velocidad del puerto serie del Arduino delay(1000); Serial.println("Iniciando..."); power_on(); iniciar(); } void loop() { if (Serial.available()) switch (Serial.read()) { case 'l': llamar(); break; case 's': mensaje_sms(); break; } if (SIM900.available()) { Serial.write(SIM900.read()); } }

Podéis descargar aquí el programa completo: Envio_y_recepcion_de_llamadas_y_SMS.
Con este programa creemos que ya podréis afrontar vuestros proyectos con mayores garantías de éxito, otorgándoles un cierto nivel de autonomía y confianza. La estructura de tipo switch() que hemos creado nos da la posibilidad de incluir de forma muy sencilla otros casos en los que sean las lecturas de ciertos sensores las que activen las llamadas o los SMS, e incluso podrías incluir en estos últimos el valor de las lecturas dentro del texto del SMS en el caso que sea necesario.
Resumen de la sesión
En esta sesión hemos aprendido varias cosas importantes:
- A enviar correctamente los comandos AT y asegurarnos de recibir la respuesta del módulo GPRS.
- A verificar la respuesta cuando lo creamos necesario.
- Asegurarnos de que estamos correctamente conectado a la red móvil.
- A encender y reiniciar el módulo por software.
- Hemos creado un programa para recibir y enviar llamadas y SMS, al que hemos dotado de capacidad de trabajar de forma autónoma con ciertas garantías de éxito.

Hola buenas noches
podrían ayudarme por favor para que al recibir una llamada se conteste automaticamente
como podría hacer tal cosa?? he dado vueltas y no encuentro la solución
https://www.prometec.net/gprs-controlar-led/ Echa un ojo aquí. Tendrías que buscar de alguna forma el teléfono después de encontrar el NO CARRIER. Teniendo el teléfono sólo tienes que realizar la llamada en vez de encender el LED. Un saludo.
Estoy trabajando en un sistema con Arduino UNO y SIM900, el inconveniente que tengo es que no envía todos los SMS, encontré este artículo que me parece muy bueno para poder investigar la falla, pero al intentar compilar me me da varios errores como los que detallo a continuación, me podrías ayudar.
Muchas Gracias
H:\Arduino\Envio_y_recepcion_de_llamadas_y_SMS-1\Envio_y_recepcion_de_llamadas_y_SMS\Envio_y_recepcion_de_llamadas_y_SMS.ino:161:31: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
enviarAT(“ATH”, “OK”, 1000); // Cuelga la llamada
^
H:\Arduino\Envio_y_recepcion_de_llamadas_y_SMS-1\Envio_y_recepcion_de_llamadas_y_SMS\Envio_y_recepcion_de_llamadas_y_SMS.ino:161:31: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
Hola Julian, he descargado el programa y funciona bien. Si estás haciendo copia y pega te recomiendo que lo descargues con el enlace que hay al final de la página, para asegurarnos que no tengas ningún error.
Hola a todos, tengo una pregunta estoy usando un modulo SIM808 y me gustaria saber si en esta placa es necesario algun tipo de intervencion para poder activar el encendido por software del modulo GPRS como ocurre en la SIM900 que hay que soldar el pin R13. He echado un vistazo a otros post que se emplea la SIM808 y no se habla de ello (o yo no lo he visto).
Gracias, un saludo.
Hola Oscar, yo no he encontrado información sobre cómo hacerlo. Pero se me ocurre que puedes puentear el pulsador con un cable y un pulsador.
hola como puedo hacer que se prenda un led con algun mensaje
https://www.prometec.net/gprs-controlar-led/
hola como se cual es mi pin?
Es el pin de tu tarjeta, te lo tiene que haber dado la operadora de telefonía.
Hola
¿Se puede modificar la función mensaje_sms() para que reciba como parametros el numero telefónico de destino y el mensaje?
Para que quede así: mensaje_sms(String Telefono, String Mensaje)
Saludos.
La función está diseñada para trabajar con array de char no con String.
Hola.
Eso lo sé.
¿Pero alguien sabe como modificarla para que pueda recibir un número de teléfono y un mensaje, para que así se pueda enviar diferentes mensajes a diferentes personas?
Yo escribi esta función para realizar la función que menciono, y funcionaba, pero al tratar de mejorarla, algo dañe y ya no sirve. ¿Que dañe?
void mensaje_sms2(String Telefono, String Mensaje)
{
String Cabecera = “AT+CMGS=\”+57”;
String Destinatario;
Destinatario = Cabecera + Telefono + “\””;
Mensaje = Mensaje + “\x1A \r\n”;
if (enviarAT(“AT+CREG?”, “+CREG: 0,1”, 1000) == 1) //comprueba la conexion a la red
{
Serial.println(“Enviando SMS…”);
enviarAT(“AT+CMGF=1\r”, “OK”, 1000); //Comando AT para mandar un SMS
//Texto del mensaje
if (enviarAT(string2char(Destinatario), “>”, 10000) == 1)
{
enviarAT(string2char(Mensaje), “OK”, 10000);
}
Serial.println(“SMS enviado?”);
}
else
{
reiniciar();
iniciar();
}
}
Saludos.
Te da error al compilar o no hace lo que esperas?
Hola a todo!
Podria usarse el modulo gps/gprs con el Esp8266?
No lo he probado, pero con el NodeMCU debería funcionar.
Hola a todos.
En alguna página, que lamentablemente perdí, había visto que se podía obtener la hora de la red celular.
Puede que sea con este comando ?
SIM900.print(“AT+CCLK?\r”);
Gracias.
Parece que esta es la forma, pero no me funcionó.
A alguien le funciona ?
Perdón, me faltó el link https://elementztechblog.wordpress.com/2016/12/28/getting-time-and-date-from-gsm-modem/
Otro https://importgeek.wordpress.com/2016/01/13/obtain-time-from-gsm-netwok-using-sim900/
Hola Gustavo, no lo he probado nunca, pero si saco un rato lo pruebo. A ver si alguien lo ha usado ya.
Hola buenas, he seguido el tutorial entero y no consigo que reciba el mensaje y encienda el led, le mando el mensaje y no hace nada, he probado que me envie el sim900 el mesaje y lo hace correctamente, pero no hace nada cuando se lo mando yo, saben porque podria ser??
Hola Pedro, lo primero que deberías comprobar es si cuando llamas a la SIM del módulo te da tono, para saber que funcione correctamente.
Hola buenas, he estado jugando con un modulo gsm SIM800L y me va muy bien, consigo controlar cosas via sms y via llamada, ahora estoy intentando entender mas o menos las instrucciones.
¿Podrías explicar un poco esta parte del programa por favor?
AT(“AT+CLIP=1\r”, “OK”, 1000); // Activamos la identificacion de llamadas
AT(“AT+CMGF=1\r”, “OK”, 1000); //Configura el modo texto para enviar o recibir mensajes
AT(“AT+CNMI=2,2,0,0,0\r”, “OK”, 1000); //Configuramos el modulo para que nos muestre los SMS recibidos por comunicacion serie
Me gustaría saber la utilidad del mandar “OK” y 1000 después del comando AT y también que significan los números 2,2,0,0,0 y que se consigue con diferentes combinaciones.
Muchas gracias
Hola Daniel,
El OK no lo mandamos si no que esperamos a que lo reciba de vuelta, y le damos un segundo para hacerlo. Es una función que hemos creado para que además de enviar el comando AT espere hasta recibir una respuesta. Los números 2,2,0,0,0 sirvern para que el módulo nos envíe los sms por el monitor serie al Arduino. La verdad es que no he investigado más sobre estos códigos. Un saludo.
buenas disculpe ya le eh probado con este y otros codigos en este codigo m sale solamente encendiend gprs y de ahi no pasa que podria ser ?
Hola, pues tiene pinta de que no se están comunicando. Puede ser que esté mal comunicado, que no tenga alimentación suficiente, o que la velocidad de comunicación del Arduino y del shield sea diferente.
Hola Ivan, Excelente iniciativa al exponer tus conocimientos.
Tengo una duda, al usar el comando AT+CGATT=1, me da error, y de ahi en adelante los comandos AT+CGATT=1 y el AT+CIICR me dan error, de casualidad tienes alguna sugerencia,
Saludos Cordiales
Asegúrate que la SIM que estás usando te permite conectarte a Internet
Buenas gente, necesito su ayuda, estoy trabajando en una alarma gsm que funciona con un arduino uno, un par de sensores y un modulo sim800l, hasta ahora lo que logre es que al detectar movimiento me llegue una llamada a mi celular, pero lo que se me complica es para activarla y desactivarla desde mi celular, que funcion podria utilizar?, con activar y desactivar me refiero a mandar un sms con la palabra “Desactivar” para que no suene la alarma en caso de que detecte movimiento.
Hola Manuel, echa un ojo a esta sesión donde hacemos algo parecido con un LED https://www.prometec.net/gprs-controlar-led/
Hola Ivan
Muchas gracias por responder, si, efectivamente me aparece RING en el monitor serie cuando llamo al número de SIMCARD que está en el módulo.