My Cart

Indoor Tracking using 4G and A-GPS mode with Arduino and Raspberry Pi (Geo-Location)September 6, 2016

Indoor Location using 4G and A-GPS mode with Arduino and Raspberry Pi

Most of the major cities are already turning their cellular networks to the new 4G LTE and at the same time shutting down the old technologies such as GPRS and GSM. 3G will survive a couple of years more but it is planned to be completely shut off too. For this reason in Cooking Hacks we have decided to be the first to offer to the Maker community the possibility of using the amazing 4G cellular networks.

The new 4G shield for Arduino and Raspberry Pi enables the connectivity to high speed LTE, HSPA+, WCDMA cellular networks in order to make possible the creation of the next level of worldwide interactivity projects inside the new "Internet of Things" era.

Besides, the GPS / Glonass module can make possible to perform geolocation services using NMEA sentences offering information such as latitude, longitude, altitude and speed what makes it perfect to perform tracking applications.

One of the positioning techniques to provide the localization to end devices that enables this module is A-GPS or AGPS, which is based on the help of a cellular network deploying an A-GPS server.

Assisted GPS enhances the performance of standard GPS in devices connected to the cellular network. A-GPS mode is a feature that allows the GPS receiver, installed on the module, to perform its First Fix using assistance data provided by entities deployed by Cellular Network. It improves the location performance of cell phones (and other connected devices) in two ways:

  • By helping obtain a faster "time to first fix" (TTFF). A-GPS acquires and stores information about the location of satellites via the cellular network so the information does not need to be downloaded via satellite.
  • By helping position a phone or mobile device when GPS signals are weak or not available such as indoor locations. GPS satellite signals may be impeded by tall buildings, and do not penetrate building interiors well. A-GPS uses proximity to cellular towers to calculate position when GPS signals are not available..

The location given by the A-GPS module may vary depending on the spot used to perform the test. The accuracy will improve when the device is situated in a high density or poor cellular antennas area. The detection accuracy may vary from 10 to 100 meters so a real test in each case is mandatory before implementing a final application.

If your are interested in developing projects which include 4G LTE communication, find all the info you need in the 4G + GPS Shield for Arduino and Raspberry Pi Tutorial (LTE / WCDMA / HSPA+ / 3G / GPRS) tutorial and if your are interested in A-GPS location in particular visit Indoor Tracking using 4G and A-GPS mode with Arduino and Raspberry Pi (Geo-Location).

Know all the 4G + GPS Shield available with Arduino and Raspberry Pi in Cooking Hacks store:

In this section, the execution of the A-GPS in MS-Based mode is shown. For this purpose, the corresponding example was used:

Arduino:

Code:
/*
    --------------- 4G_18 - A-GPS (MS-Based GPS)  ---------------

    Explanation: This example shows how to use de A-GPS in MS-Based mode

    Note 1: in Arduino UNO the same UART is used for user debug interface 
    and LE910 AT commands. Handle with care, user interface messages could 
    interfere with AT commands.

    Example: 
          Serial.print("operATo"); 
    It is seen as wrong AT command by the LE910 module.

    Note 2: to run this example properly you must increase the reception 
    serial buffer to 128 bytes. 
    -> go to: <arduino_dir>/hardware/arduino/avr/cores/arduino
    -> edit:  HardwareSerial.h 

     If you are using Arduino Uno:
    -> merge: #define SERIAL_RX_BUFFER_SIZE 128

     If you are using Arduino Mega:
    -> merge: #define SERIAL_TX_BUFFER_SIZE 128
    -> merge: #define SERIAL_RX_BUFFER_SIZE 128

    Copyright (C) 2016 Libelium Comunicaciones Distribuidas S.L.
    http://www.libelium.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Version:           1.1
    Design:            David Gascon
    Implementation:    Alejandro Gallego, Yuri Carmona, Luis Miguel Marti
    Port to Arduino:   Ruben Martin
*/

#include "arduino4G.h"

// APN settings
///////////////////////////////////////
char apn[] = "";
char login[] = "";
char password[] = "";
///////////////////////////////////////

// define variables
uint8_t error;
uint8_t gps_status;
float gps_latitude;
float gps_longitude;
uint32_t previous;
bool gps_autonomous_needed = true;


void setup()
{
  //////////////////////////////////////////////////
  // Set operator parameters
  //////////////////////////////////////////////////
  _4G.set_APN(apn, login, password);

  //////////////////////////////////////////////////
  // Show APN settings via Serial port
  //////////////////////////////////////////////////
  _4G.show_APN();

  //////////////////////////////////////////////////
  // 1. Switch on the 4G module
  //////////////////////////////////////////////////
  error = _4G.ON();

  // check answer
  if (error == 0)
  {
    Serial.println(F("1. 4G module ready..."));

    ////////////////////////////////////////////////
    // 2. Start GPS feature
    ////////////////////////////////////////////////

    // get current time
    previous = millis();

    gps_status = _4G.gpsStart(arduino4G::GPS_MS_BASED);

    // check answer
    if (gps_status == 0)
    {
      Serial.print(F("2. GPS started in MS-BASED. Time(secs) = "));
      Serial.println((millis()-previous)/1000);
    }
    else
    {
      Serial.print(F("2. Error calling the 'gpsStart' function. Code: "));
      Serial.println(gps_status, DEC);
    }
  }
  else
  {
    // Problem with the communication with the 4G module
    Serial.println(F("1. 4G module not started"));
    Serial.print(F("Error code: "));
    Serial.println(error, DEC);
    Serial.println(F("The code stops here."));
    while (1);
  }
}


void loop()
{
  ////////////////////////////////////////////////
  // Wait for satellite signals and get values
  ////////////////////////////////////////////////
  if (gps_status == 0)
  {
    error = _4G.waitForSignal(20000);

    if (error == 0)
    {
      Serial.print(F("3. GPS signal received. Time(secs) = "));
      Serial.println((millis()-previous)/1000);

      Serial.println(F("Acquired position:"));
      Serial.println(F("----------------------------"));
      Serial.print(F("Ltitude: "));
      Serial.print(_4G._latitude);
      Serial.print(F(","));
      Serial.println(_4G._latitudeNS);
      Serial.print(F("Longitude: "));
      Serial.print(_4G._longitude);
      Serial.print(F(","));
      Serial.println(_4G._longitudeEW);
      Serial.print(F("UTC_time: "));
      Serial.println(_4G._time);
      Serial.print(F("UTC_dte: "));
      Serial.println(_4G._date);
      Serial.print(F("Number of stellites: "));
      Serial.println(_4G._numSatellites, DEC);
      Serial.print(F("HDOP: "));
      Serial.println(_4G._hdop);
      Serial.println(F("----------------------------"));

      // get degrees
      gps_latitude  = _4G.convert2Degrees(_4G._latitude, _4G._latitudeNS);
      gps_longitude = _4G.convert2Degrees(_4G._longitude, _4G._longitudeEW);

      Serial.println("Conversion to degrees:");
      Serial.print(F("Ltitude: "));
      Serial.println(gps_latitude, 6);
      Serial.print(F("Longitude: "));
      Serial.println(gps_longitude, 6);
      Serial.println();


      ////////////////////////////////////////////////
      // Change to AUTONOMOUS mode if needed
      ////////////////////////////////////////////////

      if (gps_autonomous_needed == true)
      {
        _4G.gpsStop();

        gps_status = _4G.gpsStart(arduino4G::GPS_AUTONOMOUS);

        // check answer
        if (gps_status == 0)
        {
          Serial.println(F("GPS started in AUTONOMOUS mode"));

          // update variable
          gps_autonomous_needed = false;
        }
        else
        {
          Serial.print(F("Error calling the 'gpsStart' function. Code: "));
          Serial.println(gps_status, DEC);
        }
      }
      delay(10000);
    }
    else
    {
      Serial.print("no stellites fixed. Error: ");
      Serial.println(error, DEC);
    }
  }
  else
  {
    ////////////////////////////////////////////////
    // Restart GPS feature
    ////////////////////////////////////////////////

    Serial.println(F("Restarting the GPS engine"));

    // stop GPS
    _4G.gpsStop();
    delay(1000);

    // start GPS
    gps_status = _4G.gpsStart(arduino4G::GPS_MS_BASED);

    // check answer
    if (gps_status == 0)
    {
      Serial.print(F("GPS started in MS-BASED. Time(ms) = "));
      Serial.println(millis() - previous);
    }
    else
    {
      Serial.print(F("Error calling the 'gpsStart' function. Code: "));
      Serial.println(gps_status, DEC);
    }
  }
}
        

Raspberry Pi:

Code:
/*
 *  --------------- 4G_18 - A-GPS (MS-Based GPS)  ---------------
 *
 *  Explanation: This example shows how to use de A-GPS in MS-Based mode
 *
 *  Copyright (C) 2016 Libelium Comunicaciones Distribuidas S.L.
 *  http://www.libelium.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Version:           1.1
 *  Design:            David Gascón
 *  Implementation:    Alejandro Gállego, Yuri Carmona, Luis Miguel Marti
 *  Port to Raspberry: Ruben Martin
 */

#include "arduPi4G.h"

// APN settings
///////////////////////////////////////
char apn[] = "m2m.tele2.com";
char login[] = "";
char password[] = "";
///////////////////////////////////////

// define variables
uint8_t error;
uint8_t gps_status;
float gps_latitude;
float gps_longitude;
uint32_t previous;
bool gps_autonomous_needed = true;


void setup()
{
  printf("Start program\n");

  //////////////////////////////////////////////////
  // Set operator parameters
  //////////////////////////////////////////////////
  _4G.set_APN(apn, login, password);

  //////////////////////////////////////////////////
  // Show APN settings via USB port
  //////////////////////////////////////////////////
  _4G.show_APN();

  //////////////////////////////////////////////////
  // 1. Switch on the 4G module
  //////////////////////////////////////////////////
  error = _4G.ON();

  // check answer
  if (error == 0)
  {
    printf("1. 4G module ready...\n");

    ////////////////////////////////////////////////
    // 2. Start GPS feature
    ////////////////////////////////////////////////

    // get current time
    previous = millis();

    gps_status = _4G.gpsStart(arduPi4G::GPS_MS_BASED);

    // check answer
    if (gps_status == 0)
    {
      printf("2. GPS started in MS-BASED. Time(secs) = %d\n", (millis()-previous)/1000);
    }
    else
    {
      printf("2. Error calling the 'gpsStart' function. Code: %d\n", gps_status);
    }
  }
  else
  {

    // Problem with the communication with the 4G module
    printf("1. 4G module not started\n");
    printf("Error code: %d\n", error);
    printf("The code stops here.\n");
    while (1);
  }
}


void loop()
{

  ////////////////////////////////////////////////
  // Wait for satellite signals and get values
  ////////////////////////////////////////////////
  if (gps_status == 0)
  {
    error = _4G.waitForSignal(20000);

    if (error == 0)
    {
      printf("3. GPS signal received. Time(secs) = %d\n", (millis()-previous)/1000);

      printf("Acquired position:\n");
      printf("----------------------------\n");
      printf("Latitude: %s, LatitudeNS: %c, Longitude: %s, LongitudeEW: %c, "\
             "UTC_time:%s, date:%s, Number of satellites: %u, HDOP: %f\n",
              _4G._latitude, 
              _4G._latitudeNS, 
              _4G._longitude, 
              _4G._longitudeEW, 
              _4G._time, 
              _4G._date, 
              _4G._numSatellites, 
              _4G._hdop);
      printf("----------------------------\n");

      // get degrees
      gps_latitude  = _4G.convert2Degrees(_4G._latitude, _4G._latitudeNS);
      gps_longitude = _4G.convert2Degrees(_4G._longitude, _4G._longitudeEW);
      
      printf("Conversion to degrees:\n");
      printf("Latitude: %f\n", gps_latitude);
      printf("Longitude: %f\n\n", gps_longitude);

      ////////////////////////////////////////////////
      // Change to AUTONOMOUS mode if needed
      ////////////////////////////////////////////////
      if (gps_autonomous_needed == true)
      {
        _4G.gpsStop();

        gps_status = _4G.gpsStart(arduPi4G::GPS_AUTONOMOUS);

        // check answer
        if (gps_status == 0)
        {
          printf("GPS started in AUTONOMOUS mode\n");

          // update variable
          gps_autonomous_needed = false;
        }
        else
        {
          printf("Error calling the 'gpsStart' function. Code: %d\n", gps_status);
        }
      }

      delay(10000);
    }
    else
    {
      printf("no satellites fixed. Error: %d\n", error);
    }
  }
  else
  {
    ////////////////////////////////////////////////
    // Restart GPS feature
    ////////////////////////////////////////////////
    printf("Restarting the GPS engine\n");

    // stop GPS
    _4G.gpsStop();
    delay(1000);

    // start GPS
    gps_status = _4G.gpsStart(arduPi4G::GPS_MS_BASED);

    // check answer
    if (gps_status == 0)
    {
      printf("GPS started in MS-BASED. Time(ms) = %d\n", millis() - previous);
    }
    else
    {
      printf("Error calling the 'gpsStart' function. Code: %d\n", gps_status);
    }
  }
}


//////////////////////////////////////////////
// Main loop setup() and loop() declarations
//////////////////////////////////////////////
int main()
{
    setup();
    while(1) loop();
    return (0);
}
//////////////////////////////////////////////

        

In this example, the GPS is started in MS-Based mode. Once location is acquired, the GPS is stopped and started again in Standalone mode. In the following figures, it is possible to see how the GPS module gets its first position 41 seconds after switching on the 4G module. The green icon is the true device position. The red icon is the position the 4G module returns along different iterations. Finally, we can see how the module achieves a great location detection after 73 seconds.

First iteration (41 seconds after starting the 4G module). Distance error: 42 meters.


Second iteration (53 seconds after starting the 4G module). Distance error: 28 meters.


Third iteration (63 seconds after starting the 4G module). Distance error: 28 meters.


Fourth iteration (73 seconds after starting the 4G module). Distance error: 7 meters.


The location given by the A-GPS module may vary depending on the spot used to perform the test. The accuracy will improve when the device under test has better GPS satellites coverage. In conclusion, the detection accuracy may vary from 10 to 100 meters if the device has no good satellites coverage. Or worse in the case no satellites can be found.

NOTE: GPS is only available for LE910-EUG, LE910-NAG and LE910-SKG modules not for LE910-AU V2, LE910-JB V2 and LE910-JK V2 modules.

For more info visit the tutorial: 4G + GPS Shield for Arduino and Raspberry Pi Tutorial (LTE / WCDMA / HSPA+ / 3G / GPRS).

Leave a Reply