Handle URCs manually with MKRGSM library

Hello everyone,

I'm trying to get an Unsolicited Response Code (URC) from the SARA-U201 module, in string form for taking out some pieces of information.

Using the <MKRGSM.h> library we can use MODEM.send([AT command]) to send the SARA-U201 module the needed AT commands. And using MODEM.waitForResponse() we could get the direct response from the module as in the next example:

String  imei;
MODEM.send("AT+CGSN");
MODEM.waitForResponse(1000, &imei);
Serial.println("IMEI: " + imei);

Getting the IMEI number from the module.

Now, some AT commands has URCs as second response (being the first one "OK") and may take some time to get them. For example: AT+ULOC, "If <response_type>=0", has an URC as follows:

+UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>

MODEM.waitForResponse() doesn't get the URCs and I need to get the URC as a String variable to stract the longitude and latitude.

The GSMLocation class, from the <MKRGSM.h> library, already have a function for handling with URCs by his own means and functions for getting the longitude and latitude, but it's necessary to perform the GSMLocation.available() function before, and I don't want to use the programmed AT command:

MODEM.send("AT+ULOC=2,2,0,1,1");

because it's 'timeout' is set for 1 second and I need at least 60 seconds for my project.

Can someone, please, tell me how to get the URC as a String variable if I use the +ULOC command?

For these kinds of program, the best way to handle it is using state-machines.

  • You send the command

  • Go to wait-state

  • check response, if no response yet, go back to wait-state

  • if there is response, proceed to next state

Thanks @hzrnbgy.

Update:

I have found another way to send AT commands to the SARA-U201 module using the Arduino MKR GSM 1400 board. I could send via SerialGMS the AT command required, as for example:

SerialGSM.write("<AT command here>\r\n");

Example:
SerialGSM.write("AT+ULOC=2,2,0,60,1\r\n");

And using this useful project: How to Get String Data from Computer via Serial Port, I managed to edit it in a way that it matches my project and needs, and so, read all the responses from the module and search the URC I was looking for (+UULOC: ...)

Here's my project so far, hope it helps anyone with the same issues I was when creating this forum:

//Librerías a usar:
#include <MKRGSM.h>

//Instancias de las librerías a inicializar:
GSM gsmAccess;        //Clase base para todas las funciones basadas en GSM
GPRS gprs;            //Clase base para todas las funciones GPRS

//Definición de constantes:
#define LF  0x0A

//Constantes secretas a utilizar en el código:
const char PIN[]            = SECRET_SIM_PIN;         //Rellenar con el PIN de la tarjeta SIM.
const char GPRS_APN[]       = SECRET_GPRS_APN;        //Rellenar con el APN de la red que se quiere conectar.
const char UBLOX_APIKEY[]   = SECRET_UBLOX_APIKEY;    //Rellenar con el Token para hacer uso de CellLocate.

//Constantes a utilizar en el código:
const char GPRS_LOGIN[]     = ""; //Usuario del APN.
const char GPRS_PASSWORD[]  = ""; //Contraseña del usuario del APN.
unsigned long baud = 9600;      //Tasa de baudios usada para ambos puertos seriales.

//Variables:
boolean Conectado = false;  //Variable booleana para comprobar luego el estado de la conexión
char    respuesta_char[10]; //Variable para guardar la respuesta recibida del módulo.
int     Contador = 0;       //Llevará un contéo de las veces que se reciban datos de CellLocate.
int     indx = 0;           //Índice para concadenar la respuesta recibida del módulo.
int     lastCommaIndex;     //Va a ser el índice que permita cortar el string del URC.
String  Respuesta_str;      //Variable para guardar la respuesta del módulo.
String  Incertidumbre;      //Variables que guardan info del URC dado por el módulo.
String  Latitud, Longitud;  //Variables que guardan info del URC dado por el módulo.

void setup() {
  
  Serial.begin(baud);     //"Serial" es para el Monitor Serial de las plataformas de Arduino.
  SerialGSM.begin(baud);  //"SerialGSM" está definido para comunicarse con el módulo celular.
  delay(9000);            //Este delay es para que le de tiempo al Monitor serial conectarse al Arduino.
  Serial.println("Comenzando sketch...");

  /*
    La siguiente función se corre una y otra vez hasta que se logre la conexión con:
    1) La red GSM
    2) La red GPRS
  */
  while (!Conectado) {
    if ((gsmAccess.begin(PIN) == GSM_READY) &
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { //Se conecta al APN dado.
      Conectado = true;
      Serial.println("Conectado a la red GPRS");
    }
    else {
      Serial.println("No conectado");
      delay(1000);
    }
  }

  MODEM.send("AT+UGSRV=\"cell-live1.services.u-blox.com\",\"cell-live2.services.u-blox.com\",\"" + String(UBLOX_APIKEY) + "\"");
  MODEM.waitForResponse(100);
  MODEM.send("AT+ULOCCELL=1");
  MODEM.waitForResponse(100);
  Serial.println("Configuración del módulo lista...");
}

void loop() {

  SerialGSM.write("AT+ULOC=2,2,0,30,1\r\n");

  while (true) {
    
    if (SerialGSM.available() > 0) {
      
      respuesta_char[indx] = SerialGSM.read();
      
      if (respuesta_char[indx] == LF) {
        
        Serial.print("Recibí: ");
        respuesta_char[indx - 1] = 0;
        Serial.println(respuesta_char);
        
        indx = -1;
        
        Respuesta_str = String(respuesta_char);
        
        if (Respuesta_str.startsWith("+UULOC: ") && Respuesta_str.endsWith(",95")) {
          
          Respuesta_str.remove(Respuesta_str.lastIndexOf(','));
          Respuesta_str.remove(Respuesta_str.lastIndexOf(','));
          Respuesta_str.remove(Respuesta_str.lastIndexOf(','));
          
          lastCommaIndex = Respuesta_str.lastIndexOf(',');
          Incertidumbre = Respuesta_str.substring(lastCommaIndex + 1);
          Respuesta_str.remove(lastCommaIndex);
          
          lastCommaIndex = Respuesta_str.lastIndexOf(',');
          Longitud = Respuesta_str.substring(lastCommaIndex + 1);
          Respuesta_str.remove(lastCommaIndex);
          
          lastCommaIndex = Respuesta_str.lastIndexOf(',');
          Latitud = Respuesta_str.substring(lastCommaIndex + 1);
          Respuesta_str.remove(lastCommaIndex);
          
          Contador++;
          
          Serial.println();
          Serial.println("Solicitud #: "    + String(Contador));
          Serial.println("Latitud(95%): "  + Latitud);
          Serial.println("Longitud(95%): " + Longitud);
          Serial.println("Incertidumbre(95%): " + Incertidumbre + "m");
          Serial.println();
          
          indx++;
          break;
          
        }
        //Manejo de URCs con problemas en su escritura:
        else if (Respuesta_str.startsWith("+UULOC") | Respuesta_str.startsWith("+UUOC") |
                 Respuesta_str.startsWith("UULOC") | Respuesta_str.startsWith("+ULOC")) {
          
          indx++;
          break;

        }
      }
      indx++;
    }
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.