{"id":166652,"date":"2025-04-11T13:22:35","date_gmt":"2025-04-11T13:22:35","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=166652"},"modified":"2025-04-11T13:22:38","modified_gmt":"2025-04-11T13:22:38","slug":"esp32-neo-m8n-gps-logger-google-earth","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-neo-m8n-gps-logger-google-earth\/","title":{"rendered":"ESP32 with NEO-M8N GPS Module: GPS Logger and Display on Google Earth"},"content":{"rendered":"\n<p>Learn to interface the NEO-M8N GPS Module with the ESP32 programmed with Arduino IDE to get GPS data: latitude, longitude, altitude, UTC time, number of visible satellites, and more. Finally, we&#8217;ll show you how to log GPS data to a file on a microSD card and how to handle that data to display a path on Google Earth.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with NEO-8M GPS Module: GPS Logger and Display on Google Earth\" class=\"wp-image-166799\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>In summary, in this tutorial you\u2019ll learn how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Wire the NEO-M8N GPS module to the ESP32 via serial;<\/li>\n\n\n\n<li>Get raw GPS data;<\/li>\n\n\n\n<li>Parse raw data to obtain selected and readable GPS information;<\/li>\n\n\n\n<li>Get your current location;<\/li>\n\n\n\n<li>Log the location to a file on the microSD card;<\/li>\n\n\n\n<li>Transform your data into a <em>.kml<\/em> file that Google Earth can read;<\/li>\n\n\n\n<li>Upload the <em>.kml<\/em> file to Google Earth to display a path.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Table of Contents<\/h2>\n\n\n\n<p>We&#8217;ll cover the following subjects:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#intro-neom8n\" title=\"\">Introducing the NEO-M8N GPS Module<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-m8n-wiring\" title=\"\">Wiring the NEO-M8N GPS Module to the ESP32<\/a><\/li>\n\n\n\n<li><a href=\"#test-neo-m8n-esp32-raw-data\" title=\"\">Getting Raw GPS Data &#8211; Testing the NEO-M8N GPS Module with the ESP32<\/a><\/li>\n\n\n\n<li><a href=\"#parsing-nmea-sentences\" title=\"\">Parsing NMEA Sentences with TinyGPSPlus Library<\/a><\/li>\n\n\n\n<li><a href=\"#ESP32-neo-m8n-gps-logger-google-earth\" title=\"\">GPS Logger and Display Path on Google Earth<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>This tutorial focuses on programming the ESP32 using the Arduino core. Before proceeding, you should have the ESP32 Arduino core installed in your Arduino IDE. Follow the next tutorial to install the ESP32 on the Arduino IDE, if you haven\u2019t already.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing the ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux instructions)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intro-neom8n\">Introducing the NEO-M8N GPS Module<\/h2>\n\n\n\n<p>The NEO-M8N GPS module is one of the most popular GPS receivers used with microcontrollers in navigation and tracking projects. It can get data about latitude, longitude, altitude, and time.<\/p>\n\n\n\n<p>It supports multiple satellite systems, including GPS, Galileo, GLONASS, and BeiDou. It offers better satellite tracking than the <a href=\"https:\/\/randomnerdtutorials.com\/esp32-neo-6m-gps-module-arduino\/\" title=\"\">NEO-6M<\/a>, making it more reliable in challenging conditions.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/M8N-GPS-Module.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"NEO-M8N-GPS-Module\" class=\"wp-image-166757\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/M8N-GPS-Module.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/M8N-GPS-Module.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>According to the datasheet, it has a horizontal position accuracy of 2.5 to 4 meters and quick startup times (1 second for hot start, 26\u201357 seconds for cold start\u2014expect longer times if you&#8217;re close to buildings).<\/p>\n\n\n\n<p>The module includes a backup battery, built-in EEPROM, and an LED indicator that blinks when a position fix is achieved.<\/p>\n\n\n\n<p>This module typically comes with a ceramic GPS antenna. But, you can change it to any other compatible antenna that might suit your project better. For example, I like to use the one at the right in the picture below because it is waterproof, and the antenna comes with a long cable which allows for more flexibility.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/antennas-for-GPS-Modules.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"antennas for GPS modules\" class=\"wp-image-160852\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/antennas-for-GPS-Modules.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/antennas-for-GPS-Modules.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The NEO-M8N GPS Module communicates with a microcontroller using Serial communication protocol, and works with standard NMEA sentences. NMEA stands for National Marine Electronics Association, and in the world of GPS, it is a standard data format supported by GPS manufacturers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Where to buy?<\/h3>\n\n\n\n<p>You can check our Maker Advisor Tools page to compare the NEO-M8N GPS receiver module price in different stores:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/neo-m8n-gps-module\/\" target=\"_blank\" rel=\"noopener\" title=\"\">NEO-M8N GPS Receiver Module<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-m8n-wiring\">Wiring the NEO-M8N GPS Module to the ESP32<\/h2>\n\n\n\n<p>We\u2019ll connect the NEO-M8N GPS Module using the <a href=\"https:\/\/randomnerdtutorials.com\/esp32-uart-communication-serial-arduino\/\" title=\"\">ESP32 default UART2 pins<\/a>. You can use the following picture and table as a reference.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"777\" height=\"779\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit.png?resize=777%2C779&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 wiring to M8N\" class=\"wp-image-166693\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit.png?w=777&amp;quality=100&amp;strip=all&amp;ssl=1 777w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit.png?resize=300%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit.png?resize=768%2C770&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 777px) 100vw, 777px\" \/><\/figure><\/div>\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>NEO-M8N GPS Module<\/strong><\/td><td><strong>ESP32<\/strong><\/td><\/tr><tr><td>VCC<\/td><td><span class=\"rnthl rntcred\">3V3<\/span><\/td><\/tr><tr><td>RX<\/td><td>TX2 (<span class=\"rnthl rntclgreen\">GPIO 17<\/span>)<\/td><\/tr><tr><td>TX<\/td><td>RX2 (<span class=\"rnthl rntcyellow\">GPIO 16<\/span>)<\/td><\/tr><tr><td>GND<\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"test-neo-m8n-esp32-raw-data\">Getting Raw GPS Data &#8211; Testing the NEO-M8N GPS Module with the ESP32<\/h2>\n\n\n\n<p>To get raw GPS data you need to start a serial communication with the GPS module and read the available data.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Get-Raw-Data.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with NEO-M8N GPS Module - Get Raw Data\" class=\"wp-image-166758\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Get-Raw-Data.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Get-Raw-Data.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The following code establishes a serial communication with the GPS module and reads the available data.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp32-neo-m8n-gps-logger-google-earth\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*********\/\n\n \/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17\n\n#define GPS_BAUD 9600\n\n\/\/ Create an instance of the HardwareSerial class for Serial 2\nHardwareSerial gpsSerial(2);\n\nvoid setup(){\n  \/\/ Serial Monitor\n  Serial.begin(115200);\n  \n  \/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\n  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\n  Serial.println(&quot;Serial 2 started at 9600 baud rate&quot;);\n}\n\nvoid loop(){\n  while (gpsSerial.available() &gt; 0){\n    \/\/ get the byte data from the GPS\n    char gpsData = gpsSerial.read();\n    Serial.print(gpsData);\n  }\n  delay(1000);\n  Serial.println(&quot;-------------------------------&quot;);\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_NEO_M8N_GPS_Testing.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>This sketch assumes you are using <span class=\"rnthl rntcyellow\">GPIO 16<\/span> and <span class=\"rnthl rntclgreen\">GPIO 17<\/span> as RX and TX serial pins to establish serial communication with the GPS module. If you&#8217;re using other pins you should edit that on the following lines:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17<\/code><\/pre>\n\n\n\n<p>Also, if your module uses a different default baud rate than 9600 bps, you should modify the code on the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define GPS_BAUD 9600<\/code><\/pre>\n\n\n\n<p>Then, we create an instance of the <span class=\"rnthl rntliteral\">HardwareSerial<\/span> to use UART 2 called <span class=\"rnthl rntliteral\">gpsSerial<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create an instance of the HardwareSerial class for Serial 2\nHardwareSerial gpsSerial(2);<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we initiate the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Serial Monitor\nSerial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Then, we initialize a serial communication with the GPS module.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\ngpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\nSerial.println(\"Serial 2 started at 9600 baud rate\");<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, the code listens to the GPS serial port, and when data is received from the module, it is printed in the serial monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop(){\n  while (gpsSerial.available() &gt; 0){\n    \/\/ get the byte data from the GPS\n    char gpsData = gpsSerial.read();\n    Serial.print(gpsData);\n  }\n  delay(1000);\n  Serial.println(\"-------------------------------\");\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the Code<\/h3>\n\n\n\n<p>Upload the code to your board. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"36\" height=\"39\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?resize=36%2C39&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Upload Button\" class=\"wp-image-146269\"\/><\/figure><\/div>\n\n\n<p>Make sure the antenna is connected and that the module or antenna is placed outside or next to a window so that it can get data from the satellites.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/active-GPS-antenna-for-NEO-6M.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"active GPS antenna for NEO-6M\" class=\"wp-image-160850\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/active-GPS-antenna-for-NEO-6M.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/active-GPS-antenna-for-NEO-6M.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The module&#8217;s blue LED will start blinking when it finds a position fix.<\/p>\n\n\n\n<p>The Serial Monitor will display NMEA sentences with GPS data. <\/p>\n\n\n\n<p class=\"rntbox rntcred\"><strong>Important: <\/strong> if you&#8217;re running this sketch for the first time, it may take a few minutes until the module gets a position fix. You&#8217;ll start getting actual data when the blue LED starts blinking. If you&#8217;re inside a building, it is very unlikely that you can get GPS data. Go outside or place your antenna outside to maximize your chances of catching a satellite signal.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"366\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-get-raw-data.png?resize=750%2C366&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Getting Raw GPS Data with ESP32 and NEO-M8N\" class=\"wp-image-166654\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-get-raw-data.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-get-raw-data.png?resize=300%2C146&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>You should get a bunch of information in the GPS standard language, NMEA. Each line you get in the serial monitor is an NMEA sentence.<\/p>\n\n\n\n<p>NMEA stands for National Marine Electronics Association, and in the world of GPS, it is a standard data format supported by GPS manufacturers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"NMEA-sentences\">NMEA Sentences<\/h3>\n\n\n\n<p>NMEA sentences start with the $ character, and each data field is separated by a comma.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>$GNRMC<\/strong>,115209.00,A,4114.5500,N,00861.4900,W,0.129,,160125,,,D*XX<br><strong>$GNVTG<\/strong>,,T,,M,0.129,N,0.239,K,D*XX<br><strong>$GNGGA<\/strong>,115209.00,4114.5500,N,00861.4900,W,2,10,0.93,130.6,M,50.1,M,,0000*XX<br><strong>$GNGSA<\/strong>,A,3,24,25,28,32,29,,,,,,,,1.65,0.93,1.37*XX<br><strong>$GNGSA<\/strong>,A,3,78,66,67,77,,86,26,083,20*XX<br><strong>$GLGSV<\/strong>,3,3,09,87,13,131,*XX<br><strong>$GNGLL<\/strong>,4114.5500,N,00861.4900,W,115209.00,A,D*XX<\/pre>\n\n\n\n<p>There are different types of NMEA sentences. The type of message is indicated by the characters before the first comma.<\/p>\n\n\n\n<p>The <strong>GN <\/strong>after the <strong>$<\/strong> indicates it is a GPS position.&nbsp;The <strong>$GNGGA<\/strong> is the basic GNSS NMEA message, that provides 3D location and accuracy data.<\/p>\n\n\n\n<p>In the following sentence:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>$GNGGA<\/strong>,110827.00,4114.32485,N,00831.79799,W,1,10,0.93,130.6,M,50.1,M,,*5F<\/pre>\n\n\n\n<p>Here\u2019s how the fields look for the M8N:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>$GNGGA: Global GNSS location data.<\/li>\n\n\n\n<li>110827.00: Time in UTC (11:08:27).<\/li>\n\n\n\n<li>4114.32485,N: Latitude.<\/li>\n\n\n\n<li>00831.79799,W: Longitude.<\/li>\n\n\n\n<li>1: Fix quality (1 = GPS fix, 2 = DGPS, etc.).<\/li>\n\n\n\n<li>10: Number of satellites tracked (higher for M8N compared to NEO-6M).<\/li>\n\n\n\n<li>0.93: Horizontal dilution of precision (lower is better).<\/li>\n\n\n\n<li>130.6,M: Altitude above mean sea level (in meters).<\/li>\n\n\n\n<li>50.1,M: Height of geoid above the WGS84 ellipsoid.<\/li>\n\n\n\n<li>*5F: Recalculated checksum for the NEO-M8N.<\/li>\n<\/ul>\n\n\n\n<p>The other NMEA sentences provide additional information:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>$GNRMC<\/strong> \u2013 Essential GNSS PVT (Position, Velocity, Time) data<\/li>\n\n\n\n<li><strong>$GNVTG<\/strong> \u2013 Velocity and track information<\/li>\n\n\n\n<li><strong>$GNGGA<\/strong> \u2013 GNSS Fix Information<\/li>\n\n\n\n<li><strong>$GNGSA <\/strong>\u2013 GNSS DOP and active satellites<\/li>\n\n\n\n<li><strong>$GLGSV<\/strong> \u2013 Detailed satellite information (GLONASS)<\/li>\n\n\n\n<li><strong>$GNGLL<\/strong> \u2013 Geographic Latitude and Longitude.<\/li>\n<\/ul>\n\n\n\n<p>For more information about NMEA sentences, I found <a href=\"https:\/\/campar.in.tum.de\/twiki\/pub\/Chair\/NaviGpsDemon\/nmea.html\" target=\"_blank\" rel=\"noopener\" title=\"\">this website with very detailed information<\/a>.<\/p>\n\n\n\n<p>You can use this <a href=\"https:\/\/swairlearn.bluecover.pt\/nmea_analyser\" target=\"_blank\" rel=\"noopener\" title=\"\">Online NME Analyser <\/a>and paste your sentences there to interpret the GPS data.<\/p>\n\n\n\n<p>However, the easiest way to get and interpret the GPS data you want is to parse your NMEA sentences directly in the code. For that, we can use the <a href=\"https:\/\/github.com\/mikalhart\/TinyGPSPlus\" target=\"_blank\" rel=\"noopener\" title=\"\">TinyGPSPlus <\/a>library that provides methods to extract data from the NMEA sentences easily.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"parsing-nmea-sentences\">Parsing NMEA Sentences with TinyGPSPlus Library<\/h2>\n\n\n\n<p>The TinyGPSPlus library makes it simple to get GPS data in a format that is easy to understand.&nbsp;You can click&nbsp;<a href=\"http:\/\/arduiniana.org\/libraries\/tinygpsplus\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>&nbsp;for more information about the TinyGPSPlus Library.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installing the TinyGPSPlus Library<\/h3>\n\n\n\n<p>In the Arduino IDE, go to <strong>Sketch <\/strong>&gt; I<strong>nclude Library<\/strong> &gt; <strong>Manage Libraries<\/strong> or click on the Library Manager icon at the left sidebar.<\/p>\n\n\n\n<p>Search for <strong>TinyGPSPlus<\/strong> and install the library by Mikal Hart.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"497\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/install-tiny-gps-plus-library-arduino-ide.png?resize=750%2C497&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing TinyGPSPlus Library Arduino IDE\" class=\"wp-image-160832\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/install-tiny-gps-plus-library-arduino-ide.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/07\/install-tiny-gps-plus-library-arduino-ide.png?resize=300%2C199&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"get-gps-data\">Getting GPS Data Using the NEO-M8N GPS Module and the TinyGPSPlus Library<\/h2>\n\n\n\n<p>The following code shows how to get GPS data using the <span class=\"rnthl rntliteral\">TinyGPSPlus<\/span> library. We&#8217;ll get date, time, speed, altitude, number of visible satellites, and HDOP (a measurement of how precise the signal is).<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp32-neo-m8n-gps-logger-google-earth\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*********\/\n\n#include &lt;TinyGPS++.h&gt;\n\n\/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17\n\n#define GPS_BAUD 9600\n\n\/\/ The TinyGPS++ object\nTinyGPSPlus gps;\n\n\/\/ Create an instance of the HardwareSerial class for Serial 2\nHardwareSerial gpsSerial(2);\n\nvoid setup() {\n  \/\/ Serial Monitor\n  Serial.begin(115200);\n  \n  \/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\n  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\n  Serial.println(&quot;Serial 2 started at 9600 baud rate&quot;);\n}\n\nvoid loop() {\n  \/\/ This sketch displays information every time a new sentence is correctly encoded.\n  unsigned long start = millis();\n\n  while (millis() - start &lt; 1000) {\n    while (gpsSerial.available() &gt; 0) {\n      gps.encode(gpsSerial.read());\n    }\n    if (gps.location.isUpdated()) {\n      Serial.print(&quot;LAT: &quot;);\n      Serial.println(gps.location.lat(), 6);\n      Serial.print(&quot;LONG: &quot;); \n      Serial.println(gps.location.lng(), 6);\n      Serial.print(&quot;SPEED (km\/h) = &quot;); \n      Serial.println(gps.speed.kmph()); \n      Serial.print(&quot;ALT (min)= &quot;); \n      Serial.println(gps.altitude.meters());\n      Serial.print(&quot;HDOP = &quot;); \n      Serial.println(gps.hdop.value() \/ 100.0); \n      Serial.print(&quot;Satellites = &quot;); \n      Serial.println(gps.satellites.value()); \n      Serial.print(&quot;Time in UTC: &quot;);\n      Serial.println(String(gps.date.year()) + &quot;\/&quot; + String(gps.date.month()) + &quot;\/&quot; + String(gps.date.day()) + &quot;,&quot; + String(gps.time.hour()) + &quot;:&quot; + String(gps.time.minute()) + &quot;:&quot; + String(gps.time.second()));\n      Serial.println(&quot;&quot;);\n    }\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_NEO_M8N_GPS_TinyGPSPlus.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>You start by importing the <span class=\"rnthl rntliteral\">TinyGPSPlus<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;TinyGPS++.h&gt;\n#include &lt;SoftwareSerial.h&gt;<\/code><\/pre>\n\n\n\n<p>Then, you define the UART 2 RX and TX pins and the GPS baud rate. If your board uses different UART 2 pins, or if the GPS module uses a different baud rate, you can modify them on the following lines.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17\n\n#define GPS_BAUD 9600<\/code><\/pre>\n\n\n\n<p>Then, you create a <span class=\"rnthl rntliteral\">TinyGPSPlus<\/span> object:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>TinyGPSPlus gps;<\/code><\/pre>\n\n\n\n<p>Create an instance of the <span class=\"rnthl rntliteral\">HardwareSerial<\/span> class for Serial 2 called <span class=\"rnthl rntliteral\">gpsSerial<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>HardwareSerial gpsSerial(2);<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor and the serial communication with the GPS module.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  \/\/ Serial Monitor\n  Serial.begin(115200);\n  \n  \/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\n  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\n  Serial.println(\"Serial 2 started at 9600 baud rate\");\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span> is where you request the information. Parse the data from the GPS module into the <span class=\"rnthl rntliteral\">TinyGPSPlus<\/span> object using the <span class=\"rnthl rntliteral\">encode()<\/span> method as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>while (gpsSerial.available() &gt; 0) {\n  gps.encode(gpsSerial.read());\n}<\/code><\/pre>\n\n\n\n<p>Then, you can query the <span class=\"rnthl rntliteral\">gps<\/span> object to see if any data fields have been updated:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (gps.location.isUpdated()) {<\/code><\/pre>\n\n\n\n<p>If there is new data, we can get it as follows:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>Latitude<\/td><td><span class=\"rnthl rntliteral\">gps.location.lat()<\/span><\/td><\/tr><tr><td>Longitude<\/td><td><span class=\"rnthl rntliteral\">gps.location.lng()<\/span><\/td><\/tr><tr><td>Speed (km\/h)<\/td><td><span class=\"rnthl rntliteral\">gps.speed.kmph()<\/span><\/td><\/tr><tr><td>Altitude (meters)<\/td><td><span class=\"rnthl rntliteral\">gps.altitude.meters()<\/span><\/td><\/tr><tr><td>HDOP<\/td><td><span class=\"rnthl rntliteral\">gps.hdop.value()<\/span><\/td><\/tr><tr><td>The number of visible satellites<\/td><td><span class=\"rnthl rntliteral\">gps.satellites.value()<\/span><\/td><\/tr><tr><td>Year<\/td><td><span class=\"rnthl rntliteral\">gps.date.year()<\/span><\/td><\/tr><tr><td>Month<\/td><td><span class=\"rnthl rntliteral\">gps.date.month()<\/span><\/td><\/tr><tr><td>Day<\/td><td><span class=\"rnthl rntliteral\">gps.date.day()<\/span><\/td><\/tr><tr><td>Hour<\/td><td><span class=\"rnthl rntliteral\">gps.time.hour()<\/span><\/td><\/tr><tr><td>Minutes<\/td><td><span class=\"rnthl rntliteral\">gps.time.minute()<\/span><\/td><\/tr><tr><td>Seconds<\/td><td><span class=\"rnthl rntliteral\">gps.time.second()<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>In the code, we get the data and print all the information in the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.print(\"LAT: \");\nSerial.println(gps.location.lat(), 6);\nSerial.print(\"LONG: \"); \nSerial.println(gps.location.lng(), 6);\nSerial.print(\"SPEED (km\/h) = \"); \nSerial.println(gps.speed.kmph()); \nSerial.print(\"ALT (min)= \"); \nSerial.println(gps.altitude.meters());\nSerial.print(\"HDOP = \"); \nSerial.println(gps.hdop.value() \/ 100.0); \nSerial.print(\"Satellites = \"); \nSerial.println(gps.satellites.value()); \nSerial.print(\"Time in UTC: \");\nSerial.println(String(gps.date.year()) + \"\/\" + String(gps.date.month()) + \"\/\" + String(gps.date.day()) + \",\" + String(gps.time.hour()) + \":\" + String(gps.time.minute()) + \":\" + String(gps.time.second()));\nSerial.println(\"\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the Code<\/h3>\n\n\n\n<p>Upload the code to your ESP32 board. Open the Serial Monitor at a baud rate of 115200. Make sure your GPS module is placed outside or next to a window to get data from satellites.<\/p>\n\n\n\n<p class=\"rntbox rntrced\">Note: you may need to wait a few seconds or minutes until the module can get a position fix.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"371\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-TinyGPS-plus.png?resize=730%2C371&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with NEO-M8N Get Parsed Data with TinyGPSPlus\" class=\"wp-image-166657\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-TinyGPS-plus.png?w=730&amp;quality=100&amp;strip=all&amp;ssl=1 730w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-testing-TinyGPS-plus.png?resize=300%2C152&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 730px) 100vw, 730px\" \/><\/figure><\/div>\n\n\n<p>You&#8217;ll get data on the Serial Monitor about your current location, speed, altitude, number of visible satellites HDOP, and time.<\/p>\n\n\n\n<p>HDOP stands for Horizontal Dilution of Precision. This is a measurement of position-fixing accuracy. The higher the HDOP value is, the less accurate the position fix will be. Ideally, you should get a value lower than 2. A lower value means a better accuracy.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"ESP32-neo-m8n-gps-logger-google-earth\">GPS Logger and Display Path on Google Earth<\/h2>\n\n\n\n<p>Now that you&#8217;re more familiar with using the NEO-M8N GPS module with the ESP32, let&#8217;s create a GPS logger that records your location over time to a file on a microSD card. Then, you can modify and use that file on Google Earth to visualize how the location changed over time (path).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-logger-SD-Card-circuit.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 GPS logger M8N microSD card\" class=\"wp-image-166756\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-logger-SD-Card-circuit.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-logger-SD-Card-circuit.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Project Overview<\/h3>\n\n\n\n<p>Here&#8217;s a quick overview of how this project works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The ESP32 is connected to the NEO-M8N GPS Module and gets data about the location;<\/li>\n\n\n\n<li>When the location changes at least one meter, we save the location data (latitude, longitude, and altitude) to a file on the microSD card;<\/li>\n\n\n\n<li>To visualize the data on Google Earth, we&#8217;ll show you how to manually convert a <em>.txt<\/em> file with the location coordinates to a <em>.kml<\/em> file that Google Earth can read;<\/li>\n\n\n\n<li>We&#8217;ll show you how to upload the <em>.kml<\/em> to Google Earth to visualize that path.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>Here&#8217;s a list of the parts required for this project:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noopener\" title=\"\">ESP32 Board<\/a> &#8211; read <a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Best ESP32 Development Boards<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/neo-m8n-gps-module\/\" target=\"_blank\" rel=\"noopener\" title=\"\">NEO-M8N GPS Module<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/sd-card-module\/\" target=\"_blank\" rel=\"noopener\" title=\"\">MicroSD card Module<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/microsd-card-raspberry-pi-16gb-class-10\/\" target=\"_blank\" rel=\"noopener\" title=\"\">MicroSD card<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Wiring the Circuit<\/h3>\n\n\n\n<p>Wire the GPS Module to the ESP32 default UART2 pins (as we did previously) and the microSD card module to the <a href=\"https:\/\/randomnerdtutorials.com\/esp32-spi-communication-arduino\/\" title=\"\">ESP32 default SPI pins<\/a>. You can use the following diagram or the next tables as a reference.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"928\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit-micro-sd-card.jpg?resize=750%2C928&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 GPS logger Circuit NEO-8M GPS Module circuit diagram\" class=\"wp-image-166700\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit-micro-sd-card.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-NEO-M8N-GPS-Circuit-micro-sd-card.jpg?resize=242%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 242w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgreen\">You may also like reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/\" title=\"\">ESP32: Guide for MicroSD Card Module using Arduino IDE<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>NEO-M8N GPS Module<\/strong><\/td><td><strong>ESP32<\/strong><\/td><\/tr><tr><td>VCC<\/td><td><span class=\"rnthl rntcred\">3V3<\/span><\/td><\/tr><tr><td>RX<\/td><td>TX2 (<span class=\"rnthl rntclgreen\">GPIO 17<\/span>)<\/td><\/tr><tr><td>TX<\/td><td>RX2 (<span class=\"rnthl rntcyellow\">GPIO 16<\/span>)<\/td><\/tr><tr><td>GND<\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>MicroSD Card Module<\/strong><\/td><td><strong>ESP32<\/strong><\/td><\/tr><tr><td>3V3*<\/td><td><span class=\"rnthl rntcred\">3V3<\/span><\/td><\/tr><tr><td>CS<\/td><td><span class=\"rnthl rntclgray\">GPIO 5<\/span><\/td><\/tr><tr><td>MOSI<\/td><td><span class=\"rnthl rntcbrown\">GPIO 23<\/span><\/td><\/tr><tr><td>CLK<\/td><td><span class=\"rnthl rntcorange\">GPIO 18<\/span><\/td><\/tr><tr><td>MISO<\/td><td><span class=\"rnthl rntclblue\">GPIO 19<\/span><\/td><\/tr><tr><td>GND<\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">* some microSD card modules require 5V instead of 3V3<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/h3>\n\n\n\n<p>The following code initializes the microSD card and the GPS module and saves GPS data as soon as the data points are available and the new point is at least 1 meter from the previous one.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp32-neo-m8n-gps-logger-google-earth\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*********\/\n\n#include &lt;TinyGPS++.h&gt;\n#include &lt;FS.h&gt;\n#include &lt;SD.h&gt;\n#include &lt;SPI.h&gt;\n\n\/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17\n\n#define GPS_BAUD 9600\n\n\/\/ The TinyGPS++ object\nTinyGPSPlus gps;\n\n\/\/ Create an instance of the HardwareSerial class for Serial 2\nHardwareSerial gpsSerial(2);\n\nString GPSdataToAppend;\n\n\/\/ Previous GPS coordinates\ndouble lastLat = 0.0;\ndouble lastLng = 0.0;\n\n\/\/ Initialize SD card\nvoid initSDCard() {\n  if (!SD.begin()) {\n    Serial.println(&quot;Card Mount Failed&quot;);\n    return;\n  }\n  uint8_t cardType = SD.cardType();\n\n  if (cardType == CARD_NONE) {\n    Serial.println(&quot;No SD card attached&quot;);\n    return;\n  }\n  Serial.print(&quot;SD Card Type: &quot;);\n  if (cardType == CARD_MMC) {\n    Serial.println(&quot;MMC&quot;);\n  } else if (cardType == CARD_SD) {\n    Serial.println(&quot;SDSC&quot;);\n  } else if (cardType == CARD_SDHC) {\n    Serial.println(&quot;SDHC&quot;);\n  } else {\n    Serial.println(&quot;UNKNOWN&quot;);\n  }\n  uint64_t cardSize = SD.cardSize() \/ (1024 * 1024);\n  Serial.printf(&quot;SD Card Size: %lluMB\\n&quot;, cardSize);\n}\n\n\/\/ Append data to the SD card\nvoid appendFile(fs::FS &amp;fs, const char *path, const char *message) {\n  Serial.printf(&quot;Appending to file: %s\\n&quot;, path);\n\n  File file = fs.open(path, FILE_APPEND);\n  if (!file) {\n    Serial.println(&quot;Failed to open file for appending&quot;);\n    return;\n  }\n  if (file.print(message)) {\n    Serial.println(&quot;Message appended&quot;);\n  } else {\n    Serial.println(&quot;Append failed&quot;);\n  }\n  file.close();\n}\n\nvoid setup() {\n  \/\/ Serial Monitor\n  Serial.begin(115200);\n\n  \/\/ Initialize the microSD card\n  initSDCard();\n\n  \/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\n  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\n  Serial.println(&quot;Serial 2 started at 9600 baud rate&quot;);\n}\n\nvoid loop() {\n  unsigned long start = millis();\n\n  while (millis() - start &lt; 1000) {\n    while (gpsSerial.available() &gt; 0) {\n      gps.encode(gpsSerial.read());\n    }\n    if (gps.location.isUpdated()) {\n      double currentLat = gps.location.lat();\n      double currentLng = gps.location.lng();\n\n      \/\/ Check if the distance from the last point is at least 1 meter\n      double distance = TinyGPSPlus::distanceBetween(lastLat, lastLng, currentLat, currentLng);\n\n      if (distance &gt;= 1.0) {\n        lastLat = currentLat;\n        lastLng = currentLng;\n\n        \/\/ Prepare data to append\n        GPSdataToAppend = String(currentLng, 6) + &quot;,&quot; + String(currentLat, 6) + &quot;,&quot; + String(gps.altitude.meters());\n        Serial.println(GPSdataToAppend);\n\n        \/\/ Append to file\n        appendFile(SD, &quot;\/data.txt&quot;, GPSdataToAppend.c_str());\n      }\n    }\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_NEO_M8N_GPS_TinyGPSPlus_Logger.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>To save data in a format that Google Earth can read, we need to save longitude, latitude, and altitude in this order separated by commas. That&#8217;s what we do in this example. Later, we need to convert that information to a <em>.kml<\/em> file.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How Does the Code Work?<\/h4>\n\n\n\n<p>We start by importing the required libraries.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;TinyGPS++.h&gt;\n#include &lt;FS.h&gt;\n#include &lt;SD.h&gt;\n#include &lt;SPI.h&gt;<\/code><\/pre>\n\n\n\n<p>Then, we define the pins that will be used to communicate with the GPS module via serial communication protocol. As we&#8217;ve seen previously, we are using UART2 default pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Define the RX and TX pins for Serial 2\n#define RXD2 16\n#define TXD2 17<\/code><\/pre>\n\n\n\n<p>We define the GPS baud rate, create a <span class=\"rnthl rntliteral\">TinyGPSPlus<\/span> instance called <span class=\"rnthl rntliteral\">gps<\/span>, and start Hardware Serial 2.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define GPS_BAUD 9600\n\n\/\/ The TinyGPS++ object\nTinyGPSPlus gps;\n\n\/\/ Create an instance of the HardwareSerial class for Serial 2\nHardwareSerial gpsSerial(2);<\/code><\/pre>\n\n\n\n<p>We create a String variable that will hold all the information to store on the microSD card (longitude, latitude, and altitude in this order).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String GPSdataToAppend;<\/code><\/pre>\n\n\n\n<p>Then, we initialize the following variables to save the last latitude and longitude values. We need these variables to compare the current position to the last one.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Previous GPS coordinates\ndouble lastLat = 0.0;\ndouble lastLng = 0.0;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initSDCard()<\/span> function calls all the necessary methods to initialize the microSD card.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Initialize SD card\nvoid initSDCard() {\n  if (!SD.begin()) {\n    Serial.println(\"Card Mount Failed\");\n    return;\n  }\n  uint8_t cardType = SD.cardType();\n\n  if (cardType == CARD_NONE) {\n    Serial.println(\"No SD card attached\");\n    return;\n  }\n  Serial.print(\"SD Card Type: \");\n  if (cardType == CARD_MMC) {\n    Serial.println(\"MMC\");\n  } else if (cardType == CARD_SD) {\n    Serial.println(\"SDSC\");\n  } else if (cardType == CARD_SDHC) {\n    Serial.println(\"SDHC\");\n  } else {\n    Serial.println(\"UNKNOWN\");\n  }\n  uint64_t cardSize = SD.cardSize() \/ (1024 * 1024);\n  Serial.printf(\"SD Card Size: %lluMB\\n\", cardSize);\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">appendFile()<\/span> function appends data to a file on the microSD card. It creates that file if it doesn&#8217;t exist yet.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Append data to the SD card\nvoid appendFile(fs::FS &amp;fs, const char *path, const char *message) {\n  Serial.printf(\"Appending to file: %s\\n\", path);\n\n  File file = fs.open(path, FILE_APPEND);\n  if (!file) {\n    Serial.println(\"Failed to open file for appending\");\n    return;\n  }\n  if (file.print(message)) {\n    Serial.println(\"Message appended\");\n  } else {\n    Serial.println(\"Append failed\");\n  }\n  file.close();\n}<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclgreen\">For more information about microSD card functions, check this tutorial: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/\" title=\"\">ESP32: Guide for MicroSD Card Module using Arduino IDE<\/a>.<\/p>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we initialize the Serial Monitor, the microSD card, and the GPS module.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  \/\/ Serial Monitor\n  Serial.begin(115200);\n\n  \/\/ Initialize the microSD card\n  initSDCard();\n\n  \/\/ Start Serial 2 with the defined RX and TX pins and a baud rate of 9600\n  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, RXD2, TXD2);\n  Serial.println(\"Serial 2 started at 9600 baud rate\");\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we check if new data is available from the GPS module every second. If there is, we encode the available data and get the current latitude and longitude.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long start = millis();\n\nwhile (millis() - start &lt; 1000) {\n  while (gpsSerial.available() &gt; 0) {\n    gps.encode(gpsSerial.read());\n  }\n  if (gps.location.isUpdated()) {\n    double currentLat = gps.location.lat();\n    double currentLng = gps.location.lng();<\/code><\/pre>\n\n\n\n<p>Then, we check if the current position is at least one meter from the previous one.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Check if the distance from the last point is at least 1 meter\ndouble distance = TinyGPSPlus::distanceBetween(lastLat, lastLng, currentLat, currentLng);<\/code><\/pre>\n\n\n\n<p>If they are, we update the <span class=\"rnthl rntliteral\">lastLat<\/span> and <span class=\"rnthl rntliteral\">lastLng<\/span> variables to the current position.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (distance &gt;= 1.0) {\n  lastLat = currentLat;<\/code><\/pre>\n\n\n\n<p>We also prepare the data in a String to be saved on the microSD card.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>GPSdataToAppend = String(currentLng, 6) + \",\" + String(currentLat, 6) + \",\" + String(gps.altitude.meters());<\/code><\/pre>\n\n\n\n<p>We print the data in the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.println(GPSdataToAppend);<\/code><\/pre>\n\n\n\n<p>And finally, we append the data to a file called <em>data.txt<\/em> on the microSD card.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>appendFile(SD, \"\/data.txt\", GPSdataToAppend.c_str());<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the Project<\/h3>\n\n\n\n<p>Upload the code to your board. It should initialize the microSD card and after a few seconds, it should start appending data to the microSD card (make sure you&#8217;re outside or close to a window).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"701\" height=\"329\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-append-gps-data-to-microsd-card.png?resize=701%2C329&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Append GPS Data to microSD card\" class=\"wp-image-166724\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-append-gps-data-to-microsd-card.png?w=701&amp;quality=100&amp;strip=all&amp;ssl=1 701w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-append-gps-data-to-microsd-card.png?resize=300%2C141&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 701px) 100vw, 701px\" \/><\/figure><\/div>\n\n\n<p>If everything seems to be working as expected, disconnect the ESP32 from your computer and apply power using a portable charger or battery. Go for a walk with your circuit so that it starts recording your coordinates over time and you can obtain a considerable amount of points to design a path.<\/p>\n\n\n\n<p>After recording some data, disconnect the microSD card from the module and connect it to your computer. The microSD card should have a <em>data.txt<\/em> file with the coordinates of your path.<\/p>\n\n\n\n<p>For you to upload that data to Google Earth and design a path, we need to convert that file to <em>.kml<\/em> format.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">KML Files<\/h3>\n\n\n\n<p>KML is a file format used to display geographic data in an Earth browser such as Google Earth. KML uses a tag-based structure with nested elements and attributes and is based on the XML standard. We won&#8217;t go into detail about the structure of this file. If you want to learn more you can <a href=\"https:\/\/developers.google.com\/kml\/documentation\/kml_tut\" target=\"_blank\" rel=\"noopener\" title=\"\">check this tutorial about KML files by Google<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Converting your data.txt file to .kml format<\/h4>\n\n\n\n<p><strong>1)<\/strong> Open the <em>data.txt<\/em> file with the GPS data gathered from the GPS module.<\/p>\n\n\n\n<p><strong>2)<\/strong> Edit your file so that your coordinates are between the <span class=\"rnthl rntliteral\">&lt;coordinates&gt;&lt;\/coordinates&gt;<\/span> tags as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;<br>&lt;kml xmlns=\"http:\/\/www.opengis.net\/kml\/2.2\"&gt;<br>&lt;Document&gt;<br>&lt;Style id=\"yellowPoly\"&gt;<br>&lt;LineStyle&gt;<br>&lt;color&gt;7f00ffff&lt;\/color&gt;<br>&lt;width&gt;4&lt;\/width&gt;<br>&lt;\/LineStyle&gt;<br>&lt;PolyStyle&gt;<br>&lt;color&gt;7f00ff00&lt;\/color&gt;<br>&lt;\/PolyStyle&gt;<br>&lt;\/Style&gt;<br>&lt;Placemark&gt;&lt;styleUrl&gt;#yellowPoly&lt;\/styleUrl&gt;<br>&lt;LineString&gt;<br>&lt;extrude&gt;1&lt;\/extrude&gt;<br>&lt;tesselate&gt;1&lt;\/tesselate&gt;<br>&lt;altitudeMode&gt;absolute&lt;\/altitudeMode&gt;<br>&lt;coordinates&gt;<br><strong>YOUR COORDINATES GO HERE<br><\/strong>&lt;\/coordinates&gt;<br>&lt;\/LineString&gt;&lt;\/Placemark&gt;<br>&lt;\/Document&gt;&lt;\/kml&gt;<\/pre>\n\n\n\n<p><strong>3)<\/strong> Save that file.<\/p>\n\n\n\n<p><strong>4)<\/strong> Edit its name from <strong><em>data.txt<\/em><\/strong> to <strong><em>data.kml.<\/em><\/strong> You&#8217;ll receive a warning about changing the file format. Accept it. Now, the file should be usable to upload to Google Earth.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Display the Path on Google Earth<\/h3>\n\n\n\n<p>Now, follow the next steps to display and visualize your path on Google Earth.<\/p>\n\n\n\n<p><strong>1) <\/strong>Go to the <a href=\"https:\/\/earth.google.com\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Google Earth Website<\/a>.<\/p>\n\n\n\n<p><strong>2)<\/strong> Create a new project and give it a name.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"242\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/1-google-earth-create-project.png?resize=750%2C242&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Google Earth - Create Project\" class=\"wp-image-166721\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/1-google-earth-create-project.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/1-google-earth-create-project.png?resize=300%2C97&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p><strong>3)<\/strong> Go to <strong>File<\/strong> &gt; <strong>Import File to Project<\/strong> &gt; <strong>Upload from device<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"841\" height=\"440\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/2-file-upload-google-earth.png?resize=841%2C440&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload file to Google Earth\" class=\"wp-image-166722\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/2-file-upload-google-earth.png?w=841&amp;quality=100&amp;strip=all&amp;ssl=1 841w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/2-file-upload-google-earth.png?resize=300%2C157&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/2-file-upload-google-earth.png?resize=768%2C402&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 841px) 100vw, 841px\" \/><\/figure><\/div>\n\n\n<p><strong>4) <\/strong>Select the <em>.kml<\/em> file created previously.<\/p>\n\n\n\n<p><strong>5)<\/strong> Your path will be displayed on Google Earth with a yellow outline.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"483\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/Display-ESP32-GPS-data-Google-Earth.png?resize=750%2C483&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Display path on Google Earth\" class=\"wp-image-166723\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/Display-ESP32-GPS-data-Google-Earth.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/Display-ESP32-GPS-data-Google-Earth.png?resize=300%2C193&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this guide, you learned how to use the NEO-M8N GPS module with the ESP32 and how to get information about location and time.<\/p>\n\n\n\n<p>We also showed you how to log GPS data to a microSD card and how to edit that data in a format that Google Earth can interpret to display your path.<\/p>\n\n\n\n<p>We hope you&#8217;ve found this guide useful. We have other projects you may like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-tft-lvgl-gps-data\/\">ESP32 TFT with LVGL: Display GPS Location, Date, and Time<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-wi-fi-car-robot-arduino\/\">ESP32 Remote-Controlled Wi-Fi Car Robot (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-datalogger-download-data-file\/\">ESP32 Datalogger: Download Data File via Web Server (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you&#8217;d like to learn more about the ESP32, make sure to check out our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\" title=\"\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" title=\"\">All our ESP32 Projects and Guides<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn to interface the NEO-M8N GPS Module with the ESP32 programmed with Arduino IDE to get GPS data: latitude, longitude, altitude, UTC time, number of visible satellites, and more. Finally, &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 with NEO-M8N GPS Module: GPS Logger and Display on Google Earth\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-neo-m8n-gps-logger-google-earth\/#more-166652\" aria-label=\"Read more about ESP32 with NEO-M8N GPS Module: GPS Logger and Display on Google Earth\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":166799,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,281,277,299,264],"tags":[],"class_list":["post-166652","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP32-M8N-GPS-Module-Display-Google-Earth-f.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/166652","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=166652"}],"version-history":[{"count":25,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/166652\/revisions"}],"predecessor-version":[{"id":168839,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/166652\/revisions\/168839"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/166799"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=166652"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=166652"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=166652"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}