Tarea_GSM Equipo Rojo 2019_1 Universidad Nacional de Colombia, Materia:Procesadores. Este código envía la ubicación del módem a un smartphone al mandarle "Coordenadas" o "coordenadas"

Dependencies:   mbed GPS_G

main.cpp

Committer:
tony63
Date:
2019-04-12
Revision:
3:8aef67673965
Parent:
2:ea6275d1222f
Child:
4:215ec13079de

File content as of revision 3:8aef67673965:

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Programa para establecer la comunicación con un módem Siemens A56 y un modulo FRDMKL25Z
// opera como rastreador satelital para Geolocalizacion.
// Por la UART (1) se conecta el MODEM y por la uart (2) el GPS (se lee en modo NEMEA)
// Este sistema genera una cadena de geolocalizacion para GoogleMaps con las coordenadas locales
// Si previamente se envia el mensaje (Coordenadas   o coordenadas) 
// El sistema ademas recibe ordenes de tipo mensaje GSM PDU para accionar cargas
// 1----Una supuesta valvula de combustible (On y Off.....on  y off......)
// 2----Una cantonera para cerradura electrica (Pulso  o  pulso) (pulso de 7 segundos)
// Este sistema responde con un mensaje si el mensaje fue recibido (Mensaje Recibido)
//
// Adicionalmente este sistema mide un valor analogico en respuesta al mensaje..(Voltaje o voltaje)
// El sistema dispone de un jumper que permite operar el sistema con o sin GPS (jumper a tierra)
// El sistema detecta si el modem GSM esta bien conectado configurado y respondiendo correctamente
// El sistema detecta si el GPS emite cadenas NEMEA y señaliza con un led si es exitosa la conexion
// Presenta borrado automatico de  SMS entrantes para evitar perdida de sincronismo en la deteccion
// de cadenas y prefijos.
// Este codigo compila sin problemas para un modulo chino bluepill STM32F103
// con las modificaciones adecuadas de puertos y leds

//+++++++++++++++++++++++++++++++ARCHIVOS INCLUIDOS*************************************************************************
#include "mbed.h"
#include "DebouncedIn.h"
#include "stdio.h"
#include "string.h"
#include "GPS.h"

Timer t;
//++++++++++++++++++++++++++++++++++++salidas y entradas digitales+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DigitalOut LedVerde(LED2);
DigitalOut LedRojo(LED1);
DigitalOut LedAzul(LED3);
DigitalOut valvula(PTC5);//salida de la valvula
DigitalOut puerta(PTC6);//salida de cerradura magnetica (en caso de usarlo en casa o desbloquear puertas de carro)
DigitalIn sin_gps(PTA13);

// Entrada análoga
AnalogIn v(PTB0);
float medi;

// Declaración de los puertos de la FRDM, Módem GSM y GPS.
Serial GSM(PTE0,PTE1);  // Puertos del FRDM para el Módem.
Serial pc(USBTX,USBRX);
GPS gps(PTE22, PTE23);   // Puerto del FDRM para el GPS.

// Declaración de variables
// Cadenas de caracteres con las que se va a trabajar.
char DE1[255];
char DS1[255];
char DE2[255];
char DS2[255];
char buffer[512];
char resp[6];
char tam[2];
char mensaje[100];
char gprsBuffer[30];

//Variables enteras y caracteres
int g=0;
int count;
int i, K, LENOUT1, LENIN1, LENOUT2, LENIN2, C;
int c=0;
char r[]=""; 
char msg[256];
char char1;
int ind;
float med;
char outmed[16], outmedn[16];
int ret = 1;

// Adquisición de números de teléfono, emisor - receptor
char tel[15];

// El GPS entregará al celular coordenadas expresadas en latitud y longitud 
// según la ubicación que encuentre, por lo tanto se declaran estas variables.
float lo,la;
char clo[255], cla[255]; // Cadenas a capturar para latitud y longitud.
char la_lo[255], volt[255];

// Cadena de google maps
char http2[255];
char http[] = "http://maps.google.com/maps?q=";
char buf[100];

// Relleno de datos propio del protocolo de SMS.
char relle1[] = "0011000A91";
char relle2[] = "0000AA";

// Reverses a string 'str' of length 'len'
// driver program to test above funtion.
void reverse(char *str, int len)
{
    int i=0, j=len-1, temp;
    while (i<j)
    {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
        i++; j--;
    }
}
 
 // Converts a given integer x to string str[].  d is the number
 // of digits required in output. If d is more than the number
 // of digits in x, then 0s are added at the beginning.
int intToStr(int x, char str[], int d)
{
    int i = 0;
    while (x)
    {
        str[i++] = (x%10) + '0';
        x = x/10;
    }
 
    // If number of digits required is more, then
    // add 0s at the beginning
    while (i < d)
        str[i++] = '0';
 
    reverse(str, i);
    str[i] = '\0';
    return i;
}

// Converts a floating point number to string.
void ftoa(float n, char *res, int afterpoint)
{
    // Extract integer part
    int ipart = (int)n;
 
    // Extract floating part
    float fpart = n - (float)ipart;
 
    // convert integer part to string
    int i = intToStr(ipart, res, 0);
 
    // check for display option after point
    if (afterpoint != 0)
    {
        res[i] = '.';  // add dot
 
        // Get the value of fraction part upto given no.
        // of points after dot. The third parameter is needed
        // to handle cases like 233.007
        float fp=10;
        fpart =fpart * pow(fp,afterpoint);
        
        intToStr((int)fpart, res + i + 1, afterpoint);
    }
}
//++++++++++++++++++++++++++++++++++++libreria para vaciar el modem+++++++++++++++++++++++++++++++++++++++++++++++++++++++
void FlushGSM(void) { 
    char1 = 0;
    while (GSM.readable()){
        char1 = GSM.getc();
    }
        return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void callback(){
    // Note: you need to actually read from the serial to clear the RX interrupt
    pc.printf("%c\n", GSM.getc()); 
}
//-----------------------------------------------------------------------------------------------------------------------------
// Esta funcion de abajo lee todo un bufer hasta encontrar CR o LF y el resto lo rellena de
// $, count es lo que va a leer. Lo leido lo mete en buffer que es una cadena previamente definida
// incorpora medida de tiempo si se demora mas de tres segundos retorna fracaso con -1
int readBuffer(char *buffer,int count){
    int i=0; 
    t.start();  // start timer
    while(1) {
        while (GSM.readable()) {
            char c = GSM.getc();
            if (c == '\r' || c == '\n') c = '$';
            buffer[i++] = c;
            if(i > count)break;
        }
        if(i > count)break;
        if(t.read() > 3) {
            t.stop();
            t.reset();
            break;
        }
    }
    wait(0.5);
    while(GSM.readable()){  // display the other thing..
        char c = GSM.getc();
    }
    return 0;
}
//--------------------------------------------------------------------------------------------------------------
// Esta función de abajo limpia o borra todo un "buffer" de tamaño "count",
// lo revisa elemento por elemento y le mete el caracter null que indica fin de cadena.
// No retorna nada.
void cleanBuffer(char *buffer, int count){
    for(int i=0; i < count; i++) {
        buffer[i] = '\0';
    }
}
//--------------------------------------------------------------------------------------------------------------
// Esta función de abajo envia un comando parametrizado como cadena
// puede ser un comando tipo AT.
void sendCmd(char *cmd){
    GSM.puts(cmd);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo espera la respuesta de un comando que debe ser idéntica a la cadena "resp" y un tiempo "timeout",
// si todo sale bien retorna un cero que en la programacion hay que validar,
// si algo sale mal (no se parece o se demora mucho) retorna -1 que debera validarse con alguna expresion logica.
int waitForResp(char *resp, int timeout){
    int len = strlen(resp);
    int sum=0;
    t.start();
 
    while(1) {
        if(GSM.readable()) {
            char c = GSM.getc();
            sum = (c==resp[sum]) ? sum+1 : 0;// esta linea de C# sum se incrementa o se hace cero segun c
            if(sum == len)break;  //ya acabo se sale
        }
        if(t.read() > timeout) {  // time out chequea el tiempo minimo antes de salir perdiendo
            t.stop();
            t.reset();
            return -1;
        }
    }
    t.stop();                 // stop timer  antes de retornar
    t.reset();                    // clear timer
    while(GSM.readable()) {      // display the other thing..
        char c = GSM.getc();
    }
    return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo es muy completa y útil, se encarga de enviar el comando y esperar la respuesta.
// Si todo sale bien retorna un cero (herencia de las funciones contenedoras) que en la programacion hay que validar
// con alguna expresion lógica.
int sendCmdAndWaitForResp(char *cmd, char *resp, int timeout){
    sendCmd(cmd);
    return waitForResp(resp,timeout);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo chequea que el módem este vivo, envia AT, le contesta con OK y espera 2 segundos.
int powerCheck(void){ // Este comando se manda para verificar si el módem esta vivo o conectado.
    return sendCmdAndWaitForResp("AT\r\n", "OK", 2);    
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo chequea el estado de la sim card
// y si todo sale bien retorna un cero que en la programacion hay que validar
// con alguna expresión lógica.
int checkSIMStatus(void){
    char gprsBuffer[30];
    int count = 0;
    cleanBuffer(gprsBuffer, 30);
    while(count < 3){
        sendCmd("AT+CPIN?\r\n");
        readBuffer(gprsBuffer,30);
        if((NULL != strstr(gprsBuffer,"+CPIN: READY"))){
            break;
        }
        count++;
        wait(1);
    }
 
    if(count == 3){
        return -1;
    }
    return 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo chequea la calidad de la señal
// y si todo sale bien retorna con el valor de señal útil o un -1 si no es aceptable, en la programacion hay que validar
// con alguna expresión lógica.
int checkSignalStrength(void){
    char gprsBuffer[100];
    int index, count = 0;
    cleanBuffer(gprsBuffer,100);
    while(count < 3){
        sendCmd("AT+CSQ\r\n");
        readBuffer(gprsBuffer,25);
        if(sscanf(gprsBuffer, "AT+CSQ$$$$+CSQ: %d", &index)>0) {
            break;
        }
        count++;
        wait(1);
    }
    if(count == 3){
        return -1;
    }
    return index;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
// Esta funcion de abajo inicaliza el módem. Se compone de un grupo de subfunciones ya definidas previamente
// primero chequea que este vivo,
// segundo chequea el estado de la simcard,
// tercero chequea la intencidad de señal celular,
// cuarto aplica la configuracion
// y si todo sale bien retorna un cero que en la programacion hay que validar
// con alguna expresión lógica.
int init(){
    if (0 != sendCmdAndWaitForResp("AT\r\n", "OK", 3)){
        return -1;
    }
    if (0 != sendCmdAndWaitForResp("AT+CNMI=1,1\r\n", "OK", 3)){
        return -1;
    }
    if (0 != sendCmdAndWaitForResp("AT+CMGF=0\r\n", "OK", 3)){
        return -1;
    }
    if (0 != sendCmdAndWaitForResp("AT+CBST=7,0,1\r\n", "OK", 3)){ //velocidad fija a 9600, modem asincronico no transparente
        return -1;
    }
    if (0 != sendCmdAndWaitForResp("ATE\r\n", "OK", 3)){ //se le quita el eco al modem GSM
        return -1;
    }
    LedVerde=0;
    return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
// Esta funcion de abajo intenta leer un mensaje de texto en formato PDU o HEX
// y si todo sale bien retorna un cero que en la programacion hay que validar
// con alguna expresión lógica.
int readSMSpdu(char *message, int index){
    int i = 0;
    char gprsBuffer[100];
    char *p,*s;
    GSM.printf("AT+CMGR=%d\r\n",index);
    cleanBuffer(gprsBuffer,100);
    readBuffer(gprsBuffer,100);
    if(NULL == ( s = strstr(gprsBuffer,"+CMGR"))) {
        return -1;
    }
    if(NULL != ( s = strstr(gprsBuffer,"+32"))) {
        p = s + 6;
        while((*p != '$')&&(i < 5)) {
            message[i++] = *(p++);
        }
        message[i] = '\0';
    }
    return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función de abajo borra mensajes SMS del modem
// y si todo sale bien retorna un cero que en la programacion hay que validar
// con alguna expresion logica.
int deleteSMS(int index){
    char cmd[32];
    snprintf(cmd,sizeof(cmd),"AT+CMGD=%d\r\n",index);
    sendCmd(cmd);
    return 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Esta función devuelve la confirmacion del mensaje a quien lo envio.
int recibe_ok(){
    pc.printf("AT+CMGS=27\n\r");
    GSM.printf("AT+CMGS=27\n\r");
    wait(1);
    GSM.printf("0011000A91%s0000AA10CDB27B1E569741F2F2382D4E93DF",tel);
    GSM.printf("\n\r");
    pc.printf("0011000A91%s0000AA10CDB27B1E569741F2F2382D4E93DF\n\r",tel);
    pc.printf("\n\r");//control+Z
    wait(1);
    return 0;
}
//*******************************************************************************************************************************
// Programas a ejecutar.
int main(){
    //configuramos los puertos seriales    
    GSM.baud(9600);//configura los baudios de la FRDMKL25Z en 9600
    GSM.format(8,Serial::None,1); //configura el formato de los datos de la UART     
    LedVerde = 1; // APAGO LOS LEDS
    LedRojo = 1; 
    LedAzul = 1;
    LedRojo = 0; // PRENDO EL LED ROJO
    valvula=1;  // se enciende la valvula por defecto
   
//****************** CONFIGURACIÓN DEL MODEM GSM (TELEFONO CELULAR SIEMENS A56i).
inicio1:        
        ret = init();
        if(ret==0){   // esta bien conectado el modem GSM.........................................................................
            LedRojo = 1;  // apagar led rojo 
            LedVerde = 0; // Enciende LED Verde para confirmar la comunicación OK con el módem.
            pc.printf("Modem configurado\n");//envia mensaje a la terminal........................................................
        }
        else{
            wait(1);
            goto inicio1;   // se hace un reintento de conexion o el sistema no funcionara 
        }
        
//Luego se verifica GPS bien conectado (si esta habilitado por dip sw)y recibiendo satelites 
    if(!sin_gps){
        pc.printf("SIN GPS\n\r");//confirma con teminal que no se habilito el gps
        goto seguir9;// de inmediato funcionara sin gps
        }
//*****************************************Test para un GPS bien instalado***********************************************        

//******************************************esta bien el GPS*****************************************************************   
    pc.printf("CON GPS\n\r");
    g=gps.sample(); 
    if(g){
        LedAzul=0;
        pc.printf("GPS--OK\n\r");
          }
   
seguir9:
       
//**********************inicia codigo ciclico**********************************************   
//**********************inicia codigo ciclico********************************************** 
//**********************inicia codigo ciclico********************************************** 
    
//****************DESDE ACA SE LEE CUALQUIER MENSAJE SMS ENTRANTE**************************           
   while(1){ 
        if (GSM.readable()){
            readBuffer(buffer,110);
            pc.printf("%s\r\n",buffer);
            for(i=0; i<5; i++){
                resp[i] = buffer[i];
            }  
             
            pc.printf("%s\r\n", resp);
            if(strcmp("$$+CM", resp) == 0){  //COMPARA resp con "+CMTI"
                pc.printf("Llego MSG\r\n");
                cleanBuffer(buffer,10);
                GSM.printf("AT+CMGL=0\r\n"); // Envío comando para leer mensaje
                pc.printf("AT+CMGL=0\r\n");
                //GSM.printf("AT+CMGD=0\r\n"); // Envío comando para borrar el mensaje.
                readBuffer(buffer,110);
                pc.printf("%s\r\n",buffer);
                
                // Lectura el teléfono emisor
                for(i=0; i<10; i++){
                    tel[i] = buffer[i+40];
                }
                pc.printf("Telefono: %c%c%c%c%c%c%c%c%c%c\r\n", tel[1], tel[0], tel[3], tel[2], tel[5], tel[4], tel[7], tel[6], tel[9], tel[8]);  
                
                // Lectura del tamaño
                for(i=0;i<2;i++){
                    tam[i] = buffer[i + 68];
                }
                pc.printf("%s-\r\n", tam);        
                
                // Lectura del mensaje
                for(i=0;i<26;i++){
                   msg[i] = buffer[i+70]; // Lee un mensaje de 26 caracteres máximo desde la posición 70 del buffer.
                }
                pc.printf("%s-\r\n", msg);
                
                // Decodificación del mensaje
                
                
                // Comparar el mensaje
                deleteSMS(1); // Se borran los mensajes por medio de una función
                readBuffer(buffer, 110);
//*************************SEFGUNDO CASO ACTIVAR SALIDAS************************************                }
//.................activar valvula de combustible...............On..on.......................
    if((strncmp("4F37", msg, 4) == 0) || (strncmp("6F37", msg, 4) == 0)){  
                    recibe_ok();
                    valvula = 1; // Encender valvula.
                    
                }
// ......................................................  off y Off........................
     if((strncmp("4FB319", msg, 6) == 0) || (strncmp("6FB319", msg, 6) == 0)){  
                    recibe_ok();
                    valvula = 0; // apagar valvula.
                    
                }
    
//............................Envia un Pulso Para Puerta Pulso...D03A7BFE06   pulso.F03A7BFE06..............
    if((strncmp("D03A7BFE06", msg, 10) == 0) || (strncmp("F03A7BFE06", msg, 10) == 0)){  
                    recibe_ok();//CONFIRMACION DE RECEPCION REMOTA
                    puerta = 1; // Encender Puerta.
                    wait(7);//pulso de 7 segundos
                    puerta = 0;//apaga puerta
                                     
                }
                
                // COMPARA resp con "E3F75B4E2EBBC3E4F01C" que es "coordenadas", o "C3F75B4E2EBBC3E4F01C" que es "Coordenadas".
                if((strncmp("E3F75B4E2EBBC3E4F01C", msg, 20) == 0) || (strncmp("C3F75B4E2EBBC3E4F01C", msg, 20) == 0)){  
                    recibe_ok();
                    LedVerde = 1; // Encender LED azul.
                    LedAzul = 0;
                    wait(2);
                    
                    if(gps.sample()){
                        lo = gps.longitude;
                        la = gps.latitude;
                        pc.printf("\nLongitud entera = %f, Latitud entera = %f\n", lo, la);
                        //wait(0.5);   
                            
                        //LONGITUD
                        sprintf (clo, "%f", lo); 
                        pc.printf ("\nLongitud = %s\n",clo);
                        //wait(0.5);
                    
                        // LATITUD
                        sprintf (cla, "%f", la); 
                        pc.printf ( "\nLatitud = %s\n",cla);
                        //wait(0.5);
                        
                        // Concatenando las cadenas de Latitud y Longitud
                        strcpy(la_lo,cla);
                        strcat(la_lo,",");
                        strcat(la_lo,clo);
                        pc.printf("\nLatitud, Longitud: %s\n",la_lo);
                        
                        //Ahora se juntan las cadenas obtenidas y se agrega el protocolo de transferencia de hipertextos http
                        strcpy(DE1,http);
                        strcat(DE1,la_lo);         
                        pc.printf("\nDireccion: %s\n",DE1);
                        pc.printf("\n");
                        LENIN1 = strlen(DE1);
                        
                        //Conversión a octetos.
                        K = 0;
                        C = 0;
                        for (i = 0; i < LENIN1; i++){
                            DS1[i] = DE1[i + C] >> K | DE1[i + C + 1] << (7 - K);
                            if(DS1[i] == 0x00) {LENOUT1 = i; goto salir1;}   
                            K++;
                            if (K == 7) {K = 0; C++;} // se chequea que ya se acabaron los bits en un ciclo de conversion.
                        }
                        
                        salir1:
                            for (i = 0; i < LENIN1; i++){
                                pc.printf("%X", DE1[i]);
                            }
                        
                            pc.printf(":\r\n");
                            for (i = 0; i < LENOUT1; i++){
                                pc.printf("%2X", DS1[i]&0x000000FF);
                            }                        
                            pc.printf("\r\nLENOUT GPS: %d, LENIN GPS: %2X\r\n", LENOUT1, LENIN1);
                        
                        // Concatenación del mensaje en formato PDU y envío del mismo.
                        ind = 14 + LENOUT1 - 1;
                        
                        GSM.printf("AT+CMGS=%d\r\n",ind);
                        pc.printf("AT+CMGS=%d\r\n",ind);
                        pc.printf(relle1);
                        GSM.printf(relle1);
                        
                        for (i=0 ;i<=9; i++)  {
                            pc.printf("%c",tel[i]);
                            GSM.printf("%c",tel[i]);
                        }
                        
                        pc.printf(relle2);
                        GSM.printf(relle2);
                        pc.printf("%2X", LENIN1);
                        GSM.printf("%2X", LENIN1);
                         
                        for (i = 0; i < LENOUT1; i++){
                            pc.printf("%02X", DS1[i]&0x000000FF);
                            GSM.printf("%02X", DS1[i]&0x000000FF);
                        }
                        wait(1);
                        GSM.putc((char)0x1A); // Ctrl - Z.
                        GSM.scanf("%s",buf); // Estado del mensaje (Envió o Error).
                        pc.printf(">%s\n",buf);
                        pc.printf("\n");
                    }
                    
                    wait(2);
                    LedAzul = 1;
                    LedVerde = 0;
                    GSM.printf("AT+CMGD=0\r\n"); // Borra el mensaje actual (Posición "0").
                    //pc.printf("\n%s\n\n", "Borro mensaje");
                }
            
                // COMPARA resp con "F6379B1E569701" que es "voltaje", o "F6379B1E569701" que es "Voltaje".
                if((strncmp("F6379B1E569701", msg, 14) == 0) || (strncmp("D6379B1E569701", msg, 14) == 0)){ 
                    //recibe_ok();
                    LedRojo = 0; // Encender LED amarillo.
                    LedVerde = 0;
                    LedAzul = 1; 
                    wait(2);
                    
                    med = v.read()*3.3;
                    medi = v.read();
                    pc.printf("\n%f\n", medi);
                    
                    cleanBuffer(outmed, 16);
                    if (med < 1){ // Se convierte la Medida a caracter.
                        strcat(outmed, "0");
                        ftoa(med, outmedn, 5);
                        strcat(outmed, outmedn);
                    }
                    else{
                        ftoa(med, outmed, 5);
                    }
                    strcpy(DE2,"Voltaje: ");
                    strcat(DE2,outmed);
                    pc.printf("\n%s\n\n", DE2);
                    LENIN2 = strlen(DE2);
                    
                    //Conversión a octetos.
                    K = 0;
                    C = 0;
                    for (i = 0; i < LENIN2; i++){
                        DS2[i] = DE2[i + C] >> K | DE2[i + C + 1] << (7 - K);
                        if(DS2[i] == 0x00) {LENOUT2 = i; goto salir2;}   
                        K++;
                        if (K == 7) {K = 0; C++;} // se chequea que ya se acabaron los bits en un ciclo de conversion.
                    }
                    
                    salir2:
                        for (i = 0; i < LENIN2; i++){
                            pc.printf("%X", DE2[i]);
                        }
                    
                        pc.printf(":\r\n");
                        for (i = 0; i < LENOUT2; i++){
                            pc.printf("%2X", DS2[i]&0x000000FF);
                        }                        
                        pc.printf("\r\nLENOUT VOLTAJE: %d, LENIN VOLTAJE: %2X\r\n", LENOUT2, LENIN2);
                    
                    // Concatenación del mensaje en formato PDU y envío del mismo.
                    ind = 14 + LENOUT2 - 1;
                    
                    GSM.printf("AT+CMGS=%d\r\n",ind);
                    pc.printf("AT+CMGS=%d\r\n",ind);
                    pc.printf(relle1);
                    GSM.printf(relle1);
                    
                    for (i=0; i <= 9; i++)  {
                        pc.printf("%c",tel[i]);
                        GSM.printf("%c",tel[i]);
                    }
                    
                    pc.printf(relle2);
                    GSM.printf(relle2);
                    pc.printf("%2X", LENIN2);
                    GSM.printf("%2X", LENIN2);
                    /*pc.printf("0F");
                    GSM.printf("0F");*/
                     
                    for (i = 0; i < LENOUT2; i++){
                        pc.printf("%02X", DS2[i]&0x000000FF);
                        GSM.printf("%02X", DS2[i]&0x000000FF);
                    }
                    
                    wait(1);
                    GSM.putc((char)0x1A); // Ctrl - Z
                    GSM.scanf("%s",buf); // Estado del mensaje (Envió o Error).
                    pc.printf(">%s\n\n",buf);
                    pc.printf("\n");

                    wait(2);
                    LedRojo=1;
                    LedVerde=0;
                    GSM.printf("AT+CMGD=0\r\n"); // Borra el mensaje actual (Posición "0").
                    //pc.printf("\n%s\n\n", "Borro mensaje");
                }
            } 
        }         
    }
}