LILYGO T-SIM7000G ESP32: Get GPS Data (Latitude, Longitude, Altitude, and more)

In this quick guide, you’ll learn how to get GPS data with the LILYGO T-SIM7000G ESP32 board using Arduino IDE. This tutorial is also compatible with a “regular” ESP32 connected to a SIM7000G module.

LILYGO T-SIM7000G ESP32 Get GPS Data Latitude Longitude Altitude

Compatibility

This board supports 2G, LTE CAT-M1, and NB-IoT protocols. You can go to the following links to check if any of these protocols are supported in your country:

Check network protocols supported in your country;

Check NB-IoT providers in your country.

Introducing the LILYGO T-SIM7000G ESP32

The LILYGO T-SIM7000G is an ESP32 development board with a SIM7000G chip. This adds GPS, GPRS, LTE CAT-M1, and NB-IoT protocols to your board. This means that with this board you can send SMS, get location and time using GPS, and connect it to the internet using a SIM card data plan. This board doesn’t support phone calls.

LILYGO T-SIM7000G ESP32

Besides the SIM7000G module, the board also comes with some interesting features like a battery holder for a 18650 battery, a battery charging circuit where you can connect solar panels to recharge the battery, and a microSD card slot that can be useful for data logging projects or to save configuration settings.

For a more in-depth introduction, we recommend following the getting started guide:

Where to buy LILYGO T-SIM7000G ESP32?

Check the following link:

All stores in the previous link should sell the latest version, but double-check the product page, just in case the seller changes something.

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Libraries

The ESP32 communicates with the SIM7000G chip by sending AT commands via serial communication. You don’t need a library, you can simply establish a serial communication with the module and start sending AT commands. There’s a manual with all the SIM7000G AT commands:

However, it might be more practical to use a library. For example, the TinyGSM library knows which commands to send, and how to handle AT responses, and wraps that into the standard Arduino Client interface—that’s the library we’ll use in this tutorial.

Installing the TinyGSM Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for TinyGSM. Select the TinyGSM library by Volodymyr Shymanskyy.

Arduino IDE 2 Install TinyGSM Library using Libraries Manager

You also need to install the StreamDebugger library. Go to Sketch Include Library > Manage Libraries, search for StreamDebugger, and install it.

Arduino IDE 2 Install StreamDebugger Library using Libraries Manager

Preparing the LILYGO T-SIM7000G ESP32 Board

To get GPS data with your board, you don’t need to connect a SIM card. You only need to connect the GPS antenna to the board.

ESP32 SIM7000G GPS antenna connected

LILYGO T-SIM7000G ESP32 Board—Get GPS Data

Copy the following code to your Arduino IDE.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/lilygo-t-sim7000g-esp32-gps-data/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#define TINY_GSM_MODEM_SIM7000
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb

#include <TinyGsmClient.h>

// LilyGO T-SIM7000G Pinout
#define UART_BAUD   115200
#define PIN_DTR     25
#define PIN_TX      27
#define PIN_RX      26
#define PWR_PIN     4

#define LED_PIN     12

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands
#define SerialAT  Serial1

TinyGsm modem(SerialAT);

void setup(){
  SerialMon.begin(115200);
  SerialMon.println("Place your board outside to catch satelite signal");

  // Set LED OFF
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  //Turn on the modem
  pinMode(PWR_PIN, OUTPUT);
  digitalWrite(PWR_PIN, HIGH);
  delay(300);
  digitalWrite(PWR_PIN, LOW);

  delay(1000);
  
  // Set module baud rate and UART pins
  SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  if (!modem.restart()) {
    Serial.println("Failed to restart modem, attempting to continue without restarting");
  }
  
  // Print modem info
  String modemName = modem.getModemName();
  delay(500);
  SerialMon.println("Modem Name: " + modemName);

  String modemInfo = modem.getModemInfo();
  delay(500);
  SerialMon.println("Modem Info: " + modemInfo);
}

void loop(){
  // Set SIM7000G GPIO4 HIGH ,turn on GPS power
  // CMD:AT+SGPIO=0,4,1,1
  // Only in version 20200415 is there a function to control GPS power
  modem.sendAT("+SGPIO=0,4,1,1");
  if (modem.waitResponse(10000L) != 1) {
    SerialMon.println(" SGPIO=0,4,1,1 false ");
  }

  modem.enableGPS();
  
  delay(15000);
  float lat      = 0;
  float lon      = 0;
  float speed    = 0;
  float alt     = 0;
  int   vsat     = 0;
  int   usat     = 0;
  float accuracy = 0;
  int   year     = 0;
  int   month    = 0;
  int   day      = 0;
  int   hour     = 0;
  int   min      = 0;
  int   sec      = 0;
  
  for (int8_t i = 15; i; i--) {
    SerialMon.println("Requesting current GPS/GNSS/GLONASS location");
    if (modem.getGPS(&lat, &lon, &speed, &alt, &vsat, &usat, &accuracy,
                     &year, &month, &day, &hour, &min, &sec)) {
      SerialMon.println("Latitude: " + String(lat, 8) + "\tLongitude: " + String(lon, 8));
      SerialMon.println("Speed: " + String(speed) + "\tAltitude: " + String(alt));
      SerialMon.println("Visible Satellites: " + String(vsat) + "\tUsed Satellites: " + String(usat));
      SerialMon.println("Accuracy: " + String(accuracy));
      SerialMon.println("Year: " + String(year) + "\tMonth: " + String(month) + "\tDay: " + String(day));
      SerialMon.println("Hour: " + String(hour) + "\tMinute: " + String(min) + "\tSecond: " + String(sec));
      break;
    } 
    else {
      SerialMon.println("Couldn't get GPS/GNSS/GLONASS location, retrying in 15s.");
      delay(15000L);
    }
  }
  SerialMon.println("Retrieving GPS/GNSS/GLONASS location again as a string");
  String gps_raw = modem.getGPSraw();
  SerialMon.println("GPS/GNSS Based Location String: " + gps_raw);
  SerialMon.println("Disabling GPS");
  modem.disableGPS();

  // Set SIM7000G GPIO4 LOW ,turn off GPS power
  // CMD:AT+SGPIO=0,4,1,0
  // Only in version 20200415 is there a function to control GPS power
  modem.sendAT("+SGPIO=0,4,1,0");
  if (modem.waitResponse(10000L) != 1) {
    SerialMon.println(" SGPIO=0,4,1,0 false ");
  }

  delay(200);
  // Do nothing forevermore
  while (true) {
      modem.maintain();
  }
}

View raw code

How the Code Works

Let’s take a quick look at the relevant parts of the code.

First, you need to define the module you’re using. The library is compatible with many different modules. To use the SIM7000G, include the following line:

#define TINY_GSM_MODEM_SIM7000

Include the TinyGSM library.

#include <TinyGsmClient.h>

The following lines set the board pins to control the modem:

// LilyGO T-SIM7000G Pinout
#define UART_BAUD   115200
#define PIN_DTR     25
#define PIN_TX      27
#define PIN_RX      26
#define PWR_PIN     4

#define LED_PIN     12

You need to create two Serial instances. One for the Serial Monitor which we’ll call SerialMon, and another to communicate with the modem via AT commands, which we call SerialAT.

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands
#define SerialAT  Serial1

Create a TinyGSM instance called modem on the SerialAT.

TinyGsm modem(SerialAT);

Initialize the Serial Monitor at a baud rate of 115200.

SerialMon.begin(115200);

Turn on the modem by setting the power pin to HIGH and LOW at a specific interval.

//Turn on the modem
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, HIGH);
delay(300);
digitalWrite(PWR_PIN, LOW);

Initialize a Serial communication with the modem on the RX and TX pins we defined earlier.

SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);

Restart or init the modem:

// Restart takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
if (!modem.restart()) {
  Serial.println("Failed to restart modem, attempting to continue without restarting");
}

Get some modem info using the getModemName() and getModemInfo() methods. These lines are optional and you don’t actually need them to get GPS data.

// Print modem info
String modemName = modem.getModemName();
delay(500);
SerialMon.println("Modem Name: " + modemName);

String modemInfo = modem.getModemInfo();
delay(500);
SerialMon.println("Modem Info: " + modemInfo);

There are two versions of the LILYGO SIM7000G ESP32 board. The latest comes with active GPS antenna power control—when the module GPIO 4 is not turned on the antenna consumes only the static current of the LDO. This means we need to turn GPIO 4 on before getting GPS data to power the antenna. That’s what the next lines do:

// Set SIM7000G GPIO4 HIGH ,turn on GPS power
// CMD:AT+SGPIO=0,4,1,1
// Only in version 20200415 is there a function to control GPS power
modem.sendAT("+SGPIO=0,4,1,1");
if (modem.waitResponse(10000L) != 1) {
  SerialMon.println(" SGPIO=0,4,1,1 false ");
}

You can start GPS using the enableGPS() method.

modem.enableGPS();

Then, we create variables where we’ll save the GPS data. We’ll get latitude, longitude, speed, altitude, visible satellites, used satellites, accuracy, and date and time.

delay(15000);
float lat      = 0;
float lon      = 0;
float speed    = 0;
float alt     = 0;
int   vsat     = 0;
int   usat     = 0;
float accuracy = 0;
int   year     = 0;
int   month    = 0;
int   day      = 0;
int   hour     = 0;
int   min      = 0;
int   sec      = 0;

The following line gets GPS data using the getGPS() method and saves the values on the right variables.

if (modem.getGPS(&lat, &lon, &speed, &alt, &vsat, &usat, &accuracy,
                     &year, &month, &day, &hour, &min, &sec))

Then, we simply print the values on the Serial Monitor. Now that you have the relevant information saved on variables, it’s easy to modify this project for your own needs. For example, a GPS tracker, GPS data logger, etc.

SerialMon.println("Latitude: " + String(lat, 8) + "\tLongitude: " + String(lon, 8));
SerialMon.println("Speed: " + String(speed) + "\tAltitude: " + String(alt));
SerialMon.println("Visible Satellites: " + String(vsat) + "\tUsed Satellites: " + String(usat));
SerialMon.println("Accuracy: " + String(accuracy));
SerialMon.println("Year: " + String(year) + "\tMonth: " + String(month) + "\tDay: " + String(day));
SerialMon.println("Hour: " + String(hour) + "\tMinute: " + String(min) + "\tSecond: " + String(sec));

You can also get all raw data returned by the GPS using the getGPRSraw() method.

String gps_raw = modem.getGPSraw();
SerialMon.println("GPS/GNSS Based Location String: " + gps_raw);

When you’re done using GPS, you can turn it off using the disableGPS() method:

modem.disableGPS();

And finally, turn off the power to the antenna by turning GPIO 4 off:

// Set SIM7000G GPIO4 LOW ,turn off GPS power
// CMD:AT+SGPIO=0,4,1,0
// Only in version 20200415 is there a function to control GPS power
modem.sendAT("+SGPIO=0,4,1,0");
if (modem.waitResponse(10000L) != 1) {
  SerialMon.println(" SGPIO=0,4,1,0 false ");
}

Demonstration

In your Arduino IDE, go to Tools > Boards and select the ESP32 Dev Module. Select the COM port in Tools > Port.

Then, upload the code to your board.

Arduino 2.0 Upload Button

Open the Serial Monitor at a baud rate of 115200 and press the on-board RST button to restart the board. Place your board outside or next to a window or door so that it can catch satellite signals.

It may take some time until it can get some GPS data, as you can see in the screenshot of my Serial Monitor.

ESP32 T-SIM7000G get GPS data

As you can see, it gets latitude, longitude, speed, altitude, visible satellites, number of used satellites to get position, accuracy, and UTC date and time. The longitude and latitude I got were very accurate. So, in my case, it was working pretty well to get the location.

It also outputs the complete GNSS navigation information parsed from NMEA sentences (that you can’t see above because the Serial Monitor window is too small). NMEA stands for National Marine Electronics Association, and in the world of GPS, it is a standard data format supported by GPS manufacturers. The output is as follows. The commas separate different values.

1,1,20220809173458.000,41.12XXXX,-8.52XXXX,140.200,0.00,237.6,1,,2.3,2.5,1.0,,20,5,1,,48,,

Here’s what each value means, in order:

  1. GNSS run status
  2. Fix status
  3. UTC date and time
  4. Latitude
  5. Longitude
  6. MSL altitude
  7. Speed over ground
  8. Course over ground
  9. Fix mode
  10. Reserver1
  11. HDOP
  12. PDOP
  13. VDOP
  14. Reserved2
  15. GNSS Satellites in View
  16. GPS Satellites used
  17. GLONASS Satellites used
  18. Reserver3
  19. C/N0 max
  20. HPA
  21. VPA

You can learn more about these parameters and possible values by checking the AT+CGNSINF AT command on the SIM7000G AT commands manual.

Wrapping Up

In this tutorial, you learned how to use the LILYGO T-SIM7000G ESP32 board to get GPS data. We showed you a simple example that prints the GPS data in the Serial Monitor. The idea is to modify the example and apply it to your own projects. It should also be compatible with a “regular” ESP32 board connected to a separate SIM7000G module.

The ESP32 T-SIM7000G board features will allow you to build a wide variety of projects taking into account that it can connect to the internet in remote locations using a SIM card data plan and send SMS. The fact that it can use a battery and solar panels for charging is also great, and the microSD card can also be handy for datalogging or saving configuration settings.

We hope you found this tutorial useful. Have you developed any projects with this board? Let us know in the comments section below.

You may also like the following tutorials (that with minor changes can be used with the SIM7000G board):

Learn more about the ESP32 with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

16 thoughts on “LILYGO T-SIM7000G ESP32: Get GPS Data (Latitude, Longitude, Altitude, and more)”

  1. Cool one!
    I am enjoying all tutorial on this board.
    I think what remains now is the use of the on-board SD-card and then to wrap things up by making a BME weather station with capability to locally datalog as well as send the data to cloud.
    Great job

    Reply
  2. Hello.
    Great work. Can you make a tutorial for how to send the data collected using the SIM7000G LTE modem to a webserver using REST method (GET or POST)?. For example, a webserver who has a php file as a receiver. Greetings.

    Reply
  3. Olá Sara !
    Espero que tudo esteja bem aĂ­ com vcs!!
    Por favor, se eu quisesse fazer um logger GPS ou quisesse transmitir em tempo real, qual seria o intervalo mĂ­nimo entre amostragens? Obrigado!!!

    Reply
  4. Is it possible to send sms (text) to the Lilygo, to trigger a response?
    can Lilygo attach a file to a text (data from SD
    card)?

    Reply
  5. Very nice tutorial !

    For my part i’ve an issue, every time i used

    modem.sendAT(“+SGPIO=0,4,1,1″);
    if (modem.waitResponse(10000L) != 1) {
    SerialMon.println(” SGPIO=0,4,1,1 false “);
    }

    It’s fall in the println :/

    You have an idea why ?

    Kr,

    Reply
  6. Awesome Project! I just picked up a board and am wondering if anyone has an App or an interface where I can see my GPS from a web server?

    Reply
  7. Achei o exemplo excelente!!! me ajudou muito… porĂ©m, gostaria de saber como fazer com a biblioteca TinyGPS++ dividindo em OS_GPS.cpp , Ops.h e MeuTesteGps.ino?
    isso é tudo que sei Digamos que você tenha um Arduino conectado a um dispositivo GPS comum e queira exibir sua altitude. Você simplesmente criaria uma instância do TinyGPS++ assim:
    #include “TinyGPS++.h”
    TinyGPSPlus gps;
    Alimente repetidamente os caracteres do seu dispositivo GPS:

    while (ss.available() > 0)
    gps.encode(ss.read());
    Em seguida, consulte-o para obter as informações desejadas:

    if (gps.altitude.isUpdated())
    Serial.println(gps.altitude.meters());
    referĂŞncia: http://arduiniana.org/libraries/tinygpsplus/
    Se alguĂ©m puder me ajudar eu agradeço…

    Reply
  8. Hello Sarah, this is a great tutorial. However, I am having a little problem with your example code, my longitude results are preceded by a “-” which is different from my actual position. I’m curious how I should get rid of this “-“

    Reply
  9. This is great tutorial but I am having a serious problem using it. I have a “-” in front of my latitude, which puts me badly out of position. How do I fix this please?

    Sincerely
    Chen

    Reply
  10. Thank you very much for the great tutorial that worked perfectly for me!
    In the output of AT+CGNSINF, fractional seconds are always “000” I guess there is no way to request sub-second time precision from this board? Is there another board that you can recommend that has that?

    Reply
  11. This program publishes CAT-M or NB-IoT RSSI values with the GNSS location at which they were measured to the Adafruit IO MQTT broker. You can set up a free Adafruit IO account, and set up a feed and a dashboard to test it out.


    /*
    This is a program to demonstrate the use of SIM7000 MQTT commands to send
    data to Adafruit IO. You can set up a free Adafruit IO account to test it.

    The SIM7000 MQTT commands are documented in the following SIMCom application note:
    https://simcom.ee/documents/SIM7000x/SIM7000%20Series_MQTT_Application%20Note_V1.00.pdf

    They are not documented in the SIM7000 AT command manual at:
    https://simcom.ee/documents/SIM7000x/SIM7000%20Series_AT%20Command%20Manual_V1.04.pdf

    I strongly recommend you have a copy of the above two documents close at hand when
    reading this program.

    For the full set of SIM7000 documentation see:
    https://simcom.ee/documents/?dir=SIM7000x

    I used the TinyGSM library code as a starting point for this program. But the only functions
    from that library that this program uses are the GPS-related functions. I used a
    trial-and-error process to figure out what AT commands are necessary to bring the SIM7000
    online on an LTE CAT-M or NB-IoT network. I then referred to the SIMCom SIM7000 MQTT
    application note to figure out how to connect the SIM7000 to the Adafruit IO MQTT broker
    and publish data to the broker.

    This program is currently set up to work with a Hologram SIM. It seems to work on the
    T-Mobile and AT&T networks in the USA, or at least in Prescott and Sedona, Arizona.

    This version of the program is set up to report the cellular network received signal strength
    indicator (RSSI) on the Adafruit IO feed.

    Copyright 2024 Robert F. Fleming, III

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the “Software”), to deal in the Software without restriction,
    including without limitation the rights to use, copy, modify, merge, publish, distribute,
    sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
    is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice must be included in all copies
    or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    */

    #include <ArduinoTrace.h>

    // Defined the ESP32 pins that are connected to the SIM7000
    #define PWR_PIN 4
    #define PIN_RX 26
    #define PIN_TX 27

    #define TINY_GSM_MODEM_SIM7000

    // Define some C string buffer sizes
    #define BUFSIZE1 65
    #define BUFSIZE2 35
    #define BUFSIZE3 121

    // MQTT details
    // Sign up for a free Adafruit IO account.
    // While signed into your account, you can click on the gold circle with the
    // black key in the upper right corner of the Adafruit IO web page to get your
    // IO_USERNAME (mqttUser[]) and IO_KEY (mqtt_Pass) and fill them in below.
    const char* broker = "io.adafruit.com";
    const uint16_t port = 1883;
    const char mqttUser[] = "";
    const char mqttPass[] = "your IO_KEY";

    // The TinyGSM library is only used for the GPS functions, which I'm too
    // lazy to try to reinvent right now.
    #include <TinyGsmClient.h>
    TinyGsm modem(Serial1);
    TinyGsmClient client(modem);

    unsigned long t_zero, t_one;

    // Read and parse the response from the SIM7000. If E1 command echo is turned on,
    // the first token returned by strtok()is the command just sent.
    // In that case, we want to skip everything up to the first newline
    // and then start processing.
    char * checkResponse(uint8_t tokenNr, char * delimiters, bool skipCmd) {

    while (Serial1.available() == 0) {} //wait for data available
    String response = Serial1.readString();

    // Serial.print("Response from Serial1 = ");
    // Serial.println(response);
    // Serial.print("Response length = ");
    // Serial.println(response.length());

    char resp[BUFSIZE3] = "";
    response.toCharArray(resp, BUFSIZE3);
    char * p_resp = resp;

    char newLine[2] = "\n";
    char * tok;

    if (skipCmd) {
    tok = strtok_r(p_resp, newLine, &p_resp);
    }
    else {
    tok = strtok_r(p_resp, delimiters, &p_resp);
    tokenNr--;
    }

    while ((tok != NULL) && (tokenNr > 0)) {
    tok = strtok_r(NULL, delimiters, &p_resp); // next please!
    if (tok == NULL) { break; }
    tokenNr--;
    }

    // Serial.print("tok = ");
    // Serial.println(tok);

    static char staticTok[BUFSIZE1] = "";
    if (tok != NULL) { strncpy(staticTok, tok, BUFSIZE1); }
    return staticTok;
    }

    // When the SIM7000 first comes out of reset, it spits out what may
    // be some Chinese characters before it starts responding to AT commands
    // with an "OK" response. This function waits for the "OK".
    boolean areWeAwakeYet() {
    // Send the modem "AT". Read the string from the SIM7000. If it contains "OK",
    // the SIM7000 is awake.
    unsigned long t_0 = millis();

    // Give it a minute to wake up
    while (millis() < t_0 + 60000) {
    Serial1.println("AT");
    while (Serial1.available() == 0) {} //wait for data available
    String response = Serial1.readString();

    // Serial.print("Response from Serial1 = ");
    // Serial.println(response);
    // Serial.print("Response length = ");
    // Serial.println(response.length());

    char resp[BUFSIZE1] = "";
    response.toCharArray(resp, BUFSIZE1);

    if (strstr(resp, "OK") != NULL) {
    return true;
    }

    }

    return false;
    }

    // This function issues the commands necessary to first connect the SIM7000
    // to an LTE CAT-M or NB-IoT network, then issues the commands necessary
    // to connect the SIM7000 to the Adafuit IO MQTT broker.
    boolean bringMQTTOnline(void) {
    for (int i = 10; i > 0; i--) {
    Serial1.println("AT");
    }
    Serial1.println("ATE1");
    Serial1.readStringUntil('\n');

    // Turn on GPS power
    Serial.println("Enabling GPS power...");

    Serial1.println("AT+SGPIO=0,4,1,1");
    char delimiters[2] = "\n";

    char result[6] = "";
    strcpy(result, checkResponse(1, delimiters, true));
    if (strstr(result, "OK") != NULL) {Serial.println("GPS power supply enabled!"); }

    delay(2000);

    if (!modem.enableGPS()) {
    Serial.println("Failed to enable GPS");
    // Continue anyway, but the results won't be spectacular
    }

    // AT+SAPBR=3,1,"APN","hologram" Use the Hologram SIM for the APN
    Serial1.println("AT+SAPBR=3,1,\"APN\",\"hologram\"");
    printResponse(1000);

    // AT+CNMP=38 set preferred connection type to LTE
    Serial1.println("AT+CNMP=51");
    printResponse(1000);

    // AT+CMNB=3 set preferred connection type to CAT-M and NB-IoT
    Serial1.println("AT+CMNB=3");
    printResponse(2000);

    // AT+CIPMUX=1
    Serial1.println("AT+CIPMUX=0"); // start a single IP connection
    printResponse(1000);

    // AT+CSTT="hologram","",""
    Serial1.println("AT+CSTT=\"hologram\",\"\",\"\"");
    printResponse(1000);

    // AT+CNACT=1,"hologram" Make the network active using the supplied APN (I think)
    Serial1.println("AT+CNACT=1,\"hologram\"");
    printResponse(1000);

    // AT+COPS?" query network information
    // a response like +COPS: 0,0,"AT&T Hologram",7 or +COPS: 0,0,"T-Mobile Hologram",7 seems good
    // the '7' in the response means User-specified LTE M1 A GB access technology
    // a '9' in the response would mean User-specified LTE NB S1 access technology
    Serial1.println("AT+COPS?");
    printResponse(1000);

    // AT+CGNAPN query CAT-M or NB-IOT network after the successful registration of APN
    // Basically, if we get a response like +CGNAPN: 1,"hologram" back, we're connected
    Serial1.println("AT+CGNAPN");
    printResponse(1000);

    // AT+SMCONF="URL","io.adafruit.com"
    Serial1.println("AT+SMCONF=\"URL\",\"io.adafruit.com\"");
    printResponse(1000);

    // AT+SMCONF="USERNAME","cf20855"
    Serial1.println("AT+SMCONF=\"USERNAME\",\"cf20855\"");
    printResponse(1000);

    // AT+SMCONF="PASSWORD","aio_zesx89GzAjUC6AYtbh4Uj4eEBfxW"
    Serial1.println("AT+SMCONF=\"PASSWORD\",\"aio_zesx89GzAjUC6AYtbh4Uj4eEBfxW\"");
    printResponse(1000);

    // AT+SMCONN
    Serial1.println("AT+SMCONN");
    printResponse(10000);

    return true;
    }

    // This function parses the SIM7000 +CPSI response to retrieve the
    // Received Signal Strength Indicator (RSSI) value
    int getRSSI(char * cpsiResp) {
    char respCopy[BUFSIZE3];
    char * p_respCopy = respCopy;
    strcpy(respCopy, cpsiResp);
    //Serial.println(respCopy);

    char* tok = strtok_r(p_respCopy, ",", &p_respCopy);
    for (int i = 0; i < 13; i++) {
    tok = strtok_r(NULL, ",", &p_respCopy);
    }
    return atoi(tok);
    }

    // This function generates and publishes a CSV feed message to Adafruit IO
    // containing a parameter and the location at which the parameter was measured.
    // The Adafruit IO documentation on how to send data with location can be found
    // at https://io.adafruit.com/api/docs/mqtt.html#mqtt-data-format .
    void updateParameter() {
    // Variables to hold GPS data
    float latitude = 0.0;
    float longitude = 0.0;
    float speed = 0.0;
    float altitude = 0.0;

    // Get GPS data
    Serial1.readStringUntil('n');
    Serial.println("Getting GPS data...");
    if (modem.getGPS(&latitude, &longitude, &speed, &altitude)) {
    Serial.println("GPS data acquired");
    } else {
    Serial.println("Failed to get GPS data");
    // You may want to handle this case differently
    }

    // Get RSSI
    Serial1.println("AT+CPSI?");
    char delimiters[2] = ",";

    char result[6] = "";
    strcpy(result, checkResponse(14, delimiters, true));
    int rssi = atoi(result);

    char buf1[BUFSIZE1] = "";
    snprintf(buf1, BUFSIZE1, "RSSI = %d, lat = %2.6f, lon = %3.6f, alt = %4.1f", rssi, latitude, longitude, altitude);
    Serial.println(buf1);

    // Prepare MQTT publish content
    // Refer to the SIMCom SIM7000 MQTT appnote to see how to do this.
    // First you issue the command, then the SIM7000 prompts for the data to publish.
    char buf2[BUFSIZE2] = "";
    int size2 = snprintf(buf2, BUFSIZE2, "%d,%2.6f,%3.6f,%4.1f", rssi, latitude, longitude, altitude);
    strncpy(buf1, "", sizeof(buf1));
    snprintf(buf1, BUFSIZE1, "AT+SMPUB=\"cf20855/feeds/update/csv\",\"%d\",1,1", size2);

    // Send MQTT publish
    Serial1.println(buf1);
    printResponse(1000);
    Serial1.println(buf2);
    printResponse(1000);

    }

    // This function is useful for looking at whatever serial data comes out of the SIM7000.
    void printResponse(int delay) {
    t_zero = millis();
    while (millis() < t_zero + delay) {
    if (Serial1.available()) { // If anything comes in Serial1 (pins 0 & 1)
    Serial.write(Serial1.read()); // read it and send it out Serial (USB)
    }
    }
    }

    void setup() {
    // Power up the SIM7000G
    pinMode(PWR_PIN, OUTPUT);
    digitalWrite(PWR_PIN, HIGH);
    delay(300);
    // digitalWrite(PWR_PIN, LOW);

    Serial.begin(115200);
    Serial1.begin(115200, SERIAL_8N1, PIN_RX, PIN_TX);

    // Wait for the SIM7000 to wake up
    delay(2000);
    if (areWeAwakeYet()) {
    Serial.println("SIM7000 woke up! Yay!");
    }
    else {
    Serial.println("SIM7000 never woke up. Groan.");
    }

    bringMQTTOnline();
    Serial1.println("AT+CPSI?");
    printResponse(2000);

    t_zero = millis();
    t_one = millis();

    }

    void loop() {
    // The following two "if" statements are useful for manual control
    // of the SIM7000.
    // if (Serial.available()) { // If anything comes in Serial (USB),
    // Serial1.write(Serial.read()); // read it and send it out Serial1 (pins 0 & 1)
    // }

    // if (Serial1.available()) { // If anything comes in Serial1 (pins 0 & 1)
    // Serial.write(Serial1.read()); // read it and send it out Serial (USB)
    // }

    // Check the connection status every 13 seconds
    if (millis() > t_zero + 13000) {
    // Check the MQTT connection status
    Serial1.println("AT+SMSTATE?");
    char delimiters[2] = ":";

    char result[6] = "";
    strcpy(result, checkResponse(2, delimiters, true));

    // Serial.print("MQTT state response token = ");
    // Serial.println(result);

    if (atoi(result) != 1) {
    Serial.println("MQTT connection lost, restarting modem!");
    Serial1.println("AT+CFUN=1,1");
    while (!areWeAwakeYet()) {};
    bringMQTTOnline();
    t_zero = millis();
    t_one = millis();
    }

    }

    // Send a report every 17 seconds (I like prime numbers)
    if (millis() > t_one + 17000) {
    t_one = millis();
    updateParameter();
    }
    }

    Reply
  12. If you like the LilyGo TTGO SIM7000x, and you like Arduino IO, you might like
    github.com/CF20852/LilyGo-SIM7000-Adafruit-IO-Client

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.