GPS Tracking using ESP32 and IoT Platform over MQTT

This tutorial shows how to connect the NEO-6M GPS module with the ESP32 development board, get the GPS data and publish latitude and longitude positions to the AskSensors IoT cloud in real time over MQTT protocol.

Note: For the purpose of test, we used a mobile WiFi Hotspot, However, if you intend to implement such kind of GPS tracker in final products, you may need to integrate a GSM LTE/4G module onboard.

1) Prerequisites :

Followings are the prerequisites and backgrounds concepts you need to completely understand this tutorial and build connected GPS tracking and navigation systems with ESP32 and AskSensors.

  • AskSensors account subscription (The map chart used in this tutorial is only available for paid or 15 days free trial accounts).
  • Create a new sensor device with at least one module to show your GPS position.
  • Now after this click on ‘Add graph’ and select a Map graph type.
  • Copy down your Sensor device API KEY IN, we will use it later.
  • Get familiar with the AskSensors MQTT API.

2) GPS receiver specifications

Basically, GPS (Global Positioning System) receivers work by figuring out how far they are from a number of satellites. They are pre-programmed to know where the GPS satellites are at any given time and then calculate the location on Earth using the well known Trilateration process. The more satellites there are above the horizon the more accurately your GPS unit can determine where you are.

This project uses the low power NEO-6M GPS module from u-blox, suitable for battery powered, inexpensive, easy to interface with microcontrollers and insanely popular among hobbyists.

Characteristics:

  • Power supply: 2.7V to 3.6V
  • Default baud rate: 9600 bps
  • Current consumption: 45mA.
  • Up to 22 satellites on 50 channels tracking
  • Up to 5 location updates a second with 2.5m Horizontal position accuracy.
  • Navigation Sensitivity: Up to -161 dBm
  • Navigation Update Rate: 1Hz
  • Comes with an external antenna and built-in EEPROM.
  • Interface: RS232 TTL with Serial Baud Rate 4800-230400 (default 9600)
  • Operating Temperature: -40°C ~ 85°C
  • Communication Protocol: UBX Binary, RTCM and Standard NMEA output: To know what each data field means in each of these sentences, you can consult NMEA data here.

In this tutorial, we are going to use the TinyGPS++ library to convert those NMEA messages into a readable and convenient format.

3) Hardware Used

  • NEO-6M GPS module
  • ESP32 development board.
  • Breadboard
  • Jumper wires
  • Computer running Arduino IDE software.
  • USB micro cable to connect ESP32 development board to the computer.
  • A WiFi Hotspot

4) Hardware Set up

The GPS module will be powered with 3.3V power supply. It communicates with the ESP32 via serial communication using the TX and RX pins available on the 4pins header. The following image shows the schematic diagram of the circuit used in this tutorial.

  • Connect the VCC pin of the GPS module to the ESP32 3.3V pin.
  • Connect the GPS ground pin to the ESP32 ground pin.
  • Now, connect the RX pin of the GPS module to the TX pin of the ESP32. Similarly, connect the TX pin of the GPS module to the RX pin of the ESP32 (RX and TX pins of the ESP32 are defined in the software).
  • Last, connect your ESP32 to the computer through a USB cable. The ESP32 will be powered from the USB 5V.

4) Install the ESP32 in Arduino IDE

The ESP32 will be programmed using Arduino IDE. There’s an add-on for the Arduino IDE (1.8.7 or higher) that allows you to program the ESP32 using the Arduino IDE and its programming language. Follow the instructions below:

  • Open the preferences window from the Arduino IDE : File> Preferences.
  • Go to the “Additional Board Manager URLs” field, Enter the following URL:

https://dl.espressif.com/dl/package_esp32_index.json

  • If you already have the ESP8266 boards URL, separate the URLs with a comma as shown below:

https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.jso

  • Open boards manager (Tools > Board > Boards Manager), search for ESP32 and click the install button for the “ESP32 by Espressif Systems”.

5) Libraries Used

  • TinyGPS++ Library:

This library makes it simple to get the latitude and longitude in a format that is useful and easy to publish to the AskSensors cloud.

    • Download the TinyGPSPlus library. You should have a .zip folder in your Downloads folder
    • Unzip the .zip folder and you should get TinyGPSPlus-master folder
    • Rename your folder from TinyGPSPlus-master to TinyGPSPlus
    • Move the TinyGPSPlus folder to your Arduino IDE installation libraries folder
    • Finally, re-open your Arduino IDE

Note: The NEO-6M GPS module works with 9600 baud rate. The examples provided in the TinyGPS++ library (File > Examples > TinyGPS++) uses a baud rate of 4800 for the GPS module and need to be changed to 9600.

  • EspSoftwareSerial Library:
    • Download the espsoftwareserial library from github.
    • Unzip the .zip folder and you should get espsoftwareserial-master folder
    • Rename your folder from espsoftwareserial-master to espsoftwareserial
    • Move the espsoftwareserial folder to your Arduino IDE installation libraries folder
    • Finally, re-open your Arduino IDE
  • PubSubClient library:

This library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT.

    • Download the PubSubClient library from github.
    • Unzip the .zip folder and you should get pubsubclient-master folder
    • Rename your folder from pubsubclient-master to pubsubclient
    • Move the pubsubclient folder to your Arduino IDE installation libraries folder
    • Then, re-open your Arduino IDE

Note: The library comes with a number of example sketches that are not fully compatible with the ESP32. However, the example provided in this tutorial is working very reliably in the Arduino IDE software.

6) Software Setup

Download this complete demo from the AskSensors github page. You need to edit the following parameters:

const char* ssid = ".................."; // Wifi SSID
const char* password = ".................."; // Wifi Password
const char* username = "................."; // my AskSensors username
const char* pubTopic = "publish/..../....."; // publish/username/apiKeyIn
const unsigned int writeInterval = 25000; // write interval (in ms)
static const int RXPin = 16, TXPin = 17; // UART pinout

The Serial Monitor is left on the code for debugging purposes. They can be removed in the final output to save memory.

7) Running the code

  • First, Make sure that your WiFi Hotspot is powered on.
  • Connect your ESP32 board to your computer through the micro-USB cable. Make sure the power LED goes high on the module to ensure power supply.
  • Open your Arduino IDE and select Tools options for your ESP32 board type and serial port where it’s connected then click upload. The code will be running automatically after Reset.
  • Open the serial terminal to supervise the ESP32 software sequence step by step.
  • Now, we will return back to the AskSensors web application to monitor the GPS Tracker map updated by the ESP32 development board based on data parsed from GPS NEO-M6 Module. You should get a map graph showing your latest GPS position as shown below.

  • In addition, you can  show your trajectory in the map by enabling the “Show line” and “Show location history”. You can also customize the colors as you want.

  • The map below presents an example of locations data logged during a little walk in the street.

 

8) Source code

A basic source code is shown below. Please refer to the AskSensors Github page to get the latest version and updates.

/*
* MQTT and AskSensors IoT Platform
* Description: ESP32 publishes NEO-6M GPS position to AskSensors using MQTT
* Author: https://asksensors.com, 2020
* github: https://github.com/asksensors
*/

#include <WiFi.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

//TODO: ESP32 MQTT user config
const char* ssid = ".................."; // Wifi SSID
const char* password = ".................."; // Wifi Password
const char* username = "................."; // my AskSensors username
const char* pubTopic = "publish/..../....."; // publish/username/apiKeyIn
const unsigned int writeInterval = 25000; // write interval (in ms)

static const int RXPin = 16, TXPin = 17;
static const uint32_t GPSBaud = 9600;
//AskSensors MQTT config
const char* mqtt_server = "mqtt.asksensors.com";
unsigned int mqtt_port = 1883;

// objects
WiFiClient askClient;
PubSubClient client(askClient);
TinyGPSPlus gps; // The TinyGPS++ object
SoftwareSerial ss(RXPin, TXPin); // The serial connection to the GPS device

// setup
void setup() {
Serial.begin(115200);
Serial.println("*****************************************************");
Serial.println("********** Program Start : ESP32 publishes NEO-6M GPS position to AskSensors over MQTT");
Serial.print("********** connecting to WIFI : ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("->WiFi connected");
Serial.println("->IP address: ");
Serial.println(WiFi.localIP());

client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
// GPS baud rate
ss.begin(GPSBaud);

}
// loop
void loop() {

if (!client.connected()) 
reconnect();
client.loop();
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();

if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
}

// GPS displayInfo
void displayInfo() {

if (gps.location.isValid()) {
double latitude = (gps.location.lat());
double longitude = (gps.location.lng());

Serial.println("********** Publish MQTT data to ASKSENSORS");
char mqtt_payload[50] = "";
snprintf (mqtt_payload, 50, "m1=%lf;%lf", latitude, longitude);
Serial.print("Publish message: ");
Serial.println(mqtt_payload);
client.publish(pubTopic, mqtt_payload);
Serial.println("> MQTT data published");
Serial.println("********** End ");
Serial.println("*****************************************************");

delay(writeInterval);// delay 
} else {
Serial.println(F("INVALID"));
}

}

//MQTT callback
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
//MQTT reconnect
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("********** Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP32Client", username, "")) { 
Serial.println("-> MQTT client connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("-> try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

9) Conclusion

The GPS alone is a formidable device. When connected to the cloud, it can be used for smart Navigation and Tracking applications. This tutorial described how to connect the GPS NEO-6M module with the ESP32 to the AskSensors cloud. It can serve as a good launch pad for anyone looking to get into the world of IoT cloud based GPS tracking systems.

Please feel free to comment.

We will be happy to hear your thoughts

      Leave a reply