LoRa Enabled GPS Tracker with ESP8266 & Nuvoton N032LE3AE

21.03.24 06:30 AM By AKB



In industrial applications like logistics and inventory management tracking applications are used on a large level. GPS Tracking is also used in cab services, vehicle monitoring, human tracking, asset management, and public transport surveillance. However, traditional vehicle tracking systems that rely on GSM technology often encounter challenges in areas with poor signal coverage, limiting their effectiveness. The introduction of ESP8266 with a LoRa-based GPS tracker is the solution to this problem, where you can track your asset from any remote location in the world. In this project article we will build a LoRa Based Low Power GPS Tracker with ESP8266 and also look at how you can integrate the same with Nuvoton N032LE3AE module.

Components Required

LoRa GPS Tracker Working

In our previous blogs we have discussed how LoRa modules work and how they are ideal for low power wireless applications. To establish a connection between any LoRa module and The Things Network, a primary prerequisite is a LoRa gateway. Learn more about LoRa in IOT.

GPS Tracking Working

The project has simple working: the ESP8266 serves as the primary controller. It gets/collects information from the Neo-6M GPS Module, transforming Latitude and Longitude data into a LoRa Packet. This packet is then transmitted to the HPD13A LoRa module, establishing a connection with a nearby gateway. Once linked to a LoRa gateway, the packet is forwarded to The Things Network, where the raw data can be viewed on the Things Network Dashboard. To enhance functionality, we've implemented a webhook integration, allowing the position data to be seamlessly sent to Ubidots. Leveraging this information on Ubidots enables us to create a user-friendly map interface for visualizing our location data.

ESP8266 integrated with LoRa GPS Tracker Circuit Diagram is shown below

GPS Tracker Circuit Diagram

The connections for the Nodemcu LoRa GPS Tracker with ESP8266 are shown above in the circuit diagram. We use an LM2596 Step-Down Converter to lower the input voltage, ranging from 9-12V from a Li-Po Battery, to 4.2V. This lower voltage powers both the ESP8266 and the Neo-6M GPS Module. The LoRa module receives power from the ESP8266 at 3.3V and communicates through the SPI Pins. When uploading the code to the ESP8266, ensure the Neo-6M is disconnected since it is connected to the hardware serial pins of the ESP8266 during this process.


Setting Up End Node on The Things Network

To begin, sign up on The Things Network by creating either an individual or a student account, both are free. When choosing the LoRa Cluster, opt for the EU Cluster if you're not situated in North America or Australia. After successfully creating your account and completing the email verification, you'll gain access to the TTN Console, which is as shown below.


Things Network Dashboard


Click -> create application -> Enter unique application ID -> application name -> create.

Things Network Add Application


When your application gets created go to add an end device.

Things Network Add End Device


Click -> Manually ->  Enter parameters -> generate the DevUI, AppEUI, AppKey, -> complete the end device creation.

Things Network Register End Device

Switch to “Payload Formatters” once your device gets created

Things Network Payload Formatters Tab


Choose "Custom JavaScript formatter" under the Formatters Type option, and insert the provided code below:.

function Decoder(bytes, port) {

 var result = "";

 var result1 = "";

 var result2 = "";

 for (var i = 0; i < bytes.length; i++) {

 if(String.fromCharCode(bytes[i])=='X') {

 break;

 }

 else {

 result += (String.fromCharCode(bytes[i]));

 }

 }

 var myArray = result.split(",");

 result1=myArray[0];

 result2=myArray[1];

 return {

 "position": { "value":1, "context":{"lat":result1.trim(),"lng":result2.trim()}} 

 };

}


Things Network Payload Formatters Code


Now that we've set up our end device on the Things Network, let's move on to programming the ESP8266. Open the device overview and copy the DevUI, AppEUI, and AppKey. Make sure to set the LSB order for DevUI and AppEUI, and the MSB order for AppKey.


Things Network Device Overview


Open the ESP8266 code (given at the end of the blog) in  Arduino IDE and paste those IDs in their respective fields in the code.

Arduino IDE


After uploading the ESP8266 code, your device will begin transmitting LoRa data to The Things Network, and you can track this activity in the "Live Data" tab.

Things Network Live Data


Ubidots Connection Setup For Data Visualization

Now that our data is reaching TTN, let's integrate a Ubidots Dashboard. Since our data includes Latitude and Longitude Coordinates, we can use Ubidots' Maps Widget. To begin, create a Ubidots STEM account and open your dashboard.

Select -> Devices Menu -> Select Plugins.


Ubidots Dashboard


Search and select -> “The Things Stack” option


Ubidots Plugins


Leave the rest of settings to default and select the Ubidots Token as Default Token


Ubidots Token


Add the name and description of the plug-in -> Click on Create.


Ubidots Name and Description


Your plugin is now active next click on the "Edit Plugin" option.


Ubidots Plugin Edit


In the decoder settings, find the HTTPs Endpoint URL. This URL is where we'll set up the TTN Server to send data packets. Copy the Plugin ID, which is the part of the URL that comes after the /api/webhook/ section.


Ubidots Decoder Settings


After completing the previous steps, scroll down to the Decoder Function panel and uncomment the following line of code.

//var decoded_payload = args['uplink_message']['decoded_payload'];

//Also, comment on the following two lines.

//let bytes =  Buffer.from(args['uplink_message']['frm_payload'], 'base64');

//var decoded_payload = decodeUplink(bytes)['data'];



Ubidots Decoding Function


Select the "Save & Make Live" button. Our integration is now set up on the Ubidots side. Before going to TTN, navigate to the API credentials option in your profile menu and copy the default token this will be useful later on.


Ubidots API credentials

Open TTN Application -> Integrations panel -> Webhooks -> Add Webhook button.

Things Network Webhooks

Select the Ubidots plugin from the given options.

Things Network Ubidots plugin

Further enter your Plugin ID and your Ubidots Token.

Things Network Setup Webhooks for Ubidots

And that’s it your integration webhook is successfully created

Things Network Webhooks Integration


After completing this integration, our LoRa device will transmit data to our TTN Server. Open your Ubidots dashboard, and on the Devices page, your device will be seen here.


Ubidots Server


Final step is to add a Map Widget to your dashboard. Select -> Data Tab -> Dashboards -> Create Widget Button.


Ubidots Map Widget


Add new Widget -> Map


Ubidots Add Widget


Select Add Marker Group.


Ubidots Add Marker Group


Select your LoRa Device.


Ubidots LoRa Devices


Customize the Map Trace settings as per your preferences and then click on the Save button.Top of Form


Ubidots Map Trace settings


That's all! Now, all the location and tracking data from the LoRa device will appear on the map widget as location markers. You can also edit your dashboard by adding other widgets like tables to display appropriate coordinate values.


Ubidots GPS Tracking


Working Of Our LoRA Based Low power GPS Tracker with ESP8266

The image below depicts the physical setup and shows how the latitude and longitude values are updated on Ubidots. The range of our LoRa GPS tracker relies on the availability of LoRa Gateways available in the area. As long as a gateway is within reach of your LoRa module, you'll be able to successfully send data to Ubidots.


GPS Tracker Demo

ESP8266 Code

#include <lmic.h>

#include <hal/hal.h>

#include <SPI.h>

#include <TinyGPSPlus.h>

TinyGPSPlus gps; String ProcData="Hello,World";

#ifdef COMPILE_REGRESSION_TEST

# define FILLMEIN 0

#else

# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"

# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)

#endif

// This EUI must be in little-endian format, so least-significant-byte

// first. When copying an EUI from ttnctl output, this means to reverse // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,

// 0x70. static const u1_t PROGMEM APPEUI[8]= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

// This should also be in little endian format, see above.

static const u1_t PROGMEM DEVEUI[8]= {0x36, 0x52, 0x05, 0xD0, 0x7E, 0xD5, 0xB3, 0x70};

void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

// This key should be in big endian format (or, since it is not really a

// number but a block of memory, endianness does not really apply). In

// practice, a key taken from ttnctl can be copied as-is.

static const u1_t PROGMEM APPKEY[16] = {0x97, 0x7B, 0x4B, 0xA3, 0x9A, 0x8D, 0x33, 0x5E, 0x42, 0x13, 0x9C, 0x6B, 0xE9, 0xF9, 0x5E, 0xE1};

void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}

uint8_t mydata[25] ;

static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty

// cycle limitations). const unsigned TX_INTERVAL = 2;

// Pin mapping

const lmic_pinmap lmic_pins = {

 .nss = 15,

 .rxtx = LMIC_UNUSED_PIN,

 .rst = 16,

 .dio = {5, 4, LMIC_UNUSED_PIN},

};

void printHex2(unsigned v) {

 v &= 0xff;

 if (v < 16)

  Serial1.print('0');

 Serial1.print(v, HEX);

}

void onEvent (ev_t ev) {

 Serial1.print(os_getTime());

 Serial1.print(": ");

 switch(ev) {

  case EV_SCAN_TIMEOUT:     Serial1.println(F("EV_SCAN_TIMEOUT"));

  break;

  case EV_BEACON_FOUND: Serial1.println(F("EV_BEACON_FOUND"));

  break;

  case EV_BEACON_MISSED: Serial1.println(F("EV_BEACON_MISSED"));

  break;

  case EV_BEACON_TRACKED: Serial1.println(F("EV_BEACON_TRACKED"));

  break;

  case EV_JOINING: Serial1.println(F("EV_JOINING"));

  break;

  case EV_JOINED: Serial1.println(F("EV_JOINED")); {

   u4_t netid = 0; devaddr_t devaddr = 0;

   u1_t nwkKey[16];

   u1_t artKey[16];

   LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);

   Serial1.print("netid: ");

   Serial1.println(netid, DEC);

   Serial1.print("devaddr: ");

   Serial1.println(devaddr, HEX);

   Serial1.print("AppSKey: ");

   for (size_t i="0;" i<sizeof(artKey); ++i) {

    if (i != 0) Serial1.print("-");

    printHex2(artKey[i]);

   }

  Serial1.println("");

  Serial1.print("NwkSKey: ");

  for (size_t i="0;" i<sizeof(nwkKey); ++i) {

   if (i != 0) Serial1.print("-");

   printHex2(nwkKey[i]);

  }

  Serial1.println(); }

// Disable link check validation (automatically enabled

// during join, but because slow data rates change max TX

// size, we don't use it in this example. LMIC_setLinkCheckMode(0); break;

/* || This event is defined but not used in the code. No || point in wasting codespace on it. || || case EV_RFU1: || Serial1.println(F("EV_RFU1")); || break; */

case EV_JOIN_FAILED: Serial1.println(F("EV_JOIN_FAILED"));

break;

case EV_REJOIN_FAILED: Serial1.println(F("EV_REJOIN_FAILED"));

break;

case EV_TXCOMPLETE: Serial1.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));

if (LMIC.txrxFlags & TXRX_ACK) Serial1.println(F("Received ack"));

if (LMIC.dataLen) {

Serial1.print(F("Received "));

Serial1.print(LMIC.dataLen); Serial1.println(F(" bytes of payload"));

}

// Schedule next transmission

os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);

break;

case EV_LOST_TSYNC: Serial1.println(F("EV_LOST_TSYNC"));

break;

case EV_RESET: Serial1.println(F("EV_RESET"));

break;

case EV_RXCOMPLETE: // data received in ping slot Serial1.println(F("EV_RXCOMPLETE"));

break;

case EV_LINK_DEAD: Serial1.println(F("EV_LINK_DEAD"));

break;

case EV_LINK_ALIVE: Serial1.println(F("EV_LINK_ALIVE")); break;

/* || This event is defined but not used in the code. No || point in wasting codespace on it. || || case EV_SCAN_FOUND: || Serial1.println(F("EV_SCAN_FOUND")); || break; */

case EV_TXSTART: Serial1.println(F("EV_TXSTART"));

break;

case EV_TXCANCELED: Serial1.println(F("EV_TXCANCELED"));

break;

case EV_RXSTART: /* do not print anything -- it wrecks timing */

break;

case EV_JOIN_TXCOMPLETE: Serial1.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));

break;

default: Serial1.print(F("Unknown event: "));

Serial1.println((unsigned) ev);

break;

}

}

void do_send(osjob_t* j){

// Check if there is not a current TX/RX job running

if (LMIC.opmode & OP_TXRXPEND) {

Serial1.println(F("OP_TXRXPEND, not sending"));

}

else {

// Prepare upstream data transmission at the next possible

time. unsigned long start = millis();

do {

while (Serial.available())

gps.encode(Serial.read());

}

while (millis() - start < 1000);

float flat="gps.location.lat();

float flon="gps.location.ln"g();

char charLat[20];

char charLong[20];

Serial1.print("Cords: ");

Serial1.print(flat); Serial1.print(" , ");

Serial1.println(flon);

dtostrf(flat, 10, 7, charLat);

dtostrf(flon, 10, 7, charLong);

sprintf((char *)mydata, "%s,%sX", charLat,charLong);

LMIC_setTxData2(1, mydata,25, 0);

Serial1.println(F("Packet queued"));

//int x="ProcData.len"gth();

//ProcData.toCharArray((char *)mydata,sizeof(mydata));

}

// Next TX is scheduled after TX_COMPLETE event.

}

void setup() {

Serial1.begin(9600);

Serial1.println(F("Starting"));

Serial.begin(9600);

// LMIC init os_init();

// Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

// Start job (sending automatically starts OTAA too) do_send(&sendjob);}

void loop() {

os_runloop_once();

}

Conclusion

Thus we have implemented a LoRa based low power GPS tracker with ESP8266, you can track any of your device location using this setup in your project. The same process as above will be followed if you are building a GPS tracker using Nuvoton N032LE3AE. The LoRa-based Low Power GPS Tracker with ESP8266 gives multiple options and ways to enhance your IoT devices. Offering extended battery life, precise location tracking, real-time monitoring, cost-effectiveness, and versatile connectivity.

If you are looking for LoRa Module and GPS module from brands such as Smatech and Hoperf or microcontrollers from brands like Nuvoton and Espressif reach out to Campus Component an electronic components distributor today!

Added to cart
- There was an error adding to cart. Please try again.
Quantity updated
- An error occurred. Please try again later.
Deleted from cart
- Can't delete this product from the cart at the moment. Please try again later.