The NEO-6M GPS module is a cheap, reliable way to give your ESP32 S3 project a sense of place. Wire it up over UART, parse the NMEA sentences with the TinyGPSPlus library, and you get latitude, longitude, altitude, speed, and UTC date-time in your Serial Monitor. From there it's a short step to distance calculations, geofencing, or logging a track.

The full tutorial, with every detail and the line-by-line code explanation, is on our site: ESP32 S3 - GPS

What you need

Wiring

ESP32 S3 - GPS wiring diagram

The NEO-6M has four pins: VCC, GND, TX, and RX. Connect VCC to the ESP32 S3's 5V pin, not 3.3V, so the module's onboard regulator works correctly and gets a reliable satellite lock. Connect GND to ground. The module's TX goes to a Serial RX pin on the ESP32 S3, and its RX goes to a Serial TX pin, since the module talks TTL serial at 3.3V logic which the ESP32 S3 accepts directly.

In the sketch, Serial2 is set up on GPIO 18 and GPIO 17. Place the module near a window or outdoors, since GPS signals don't pass through walls or metal enclosures.

How it works

The NEO-6M is a GPS receiver that locks onto satellite signals and streams standard NMEA-0183 sentences (GGA, RMC, VTG, GLL) over a serial line at 9600 bps by default. It tracks up to 22 satellites across 50 channels and gets you position accuracy around 2.5 meters once it has a fix.

The ESP32 S3 reads that raw text stream on a second hardware serial port, keeping the primary serial port free for the Arduino IDE Serial Monitor. The TinyGPSPlus library does the actual parsing, turning the sentences into usable numbers.

Code

The reading sketch opens Serial2 at the GPS module's baud rate and feeds every incoming byte into a TinyGPSPlus object with gps.encode(). Once that object has a valid fix, the sketch prints latitude, longitude, altitude, speed in km/h, and UTC date-time to the Serial Monitor, checking isValid() on each field since some data may not be ready yet.

A second sketch builds on this by calling TinyGPSPlus's built-in distanceBetween() function to compute the distance from your current position to a fixed reference point, printed in meters and kilometers, no extra math library needed.

esp32-s3-gps.ino

/* * This ESP32 S3 code was developed by newbiely.com * * This ESP32 S3 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3/esp32-s3-gps */ /* * This ESP32-S3 code is created by esp32io.com * * This ESP32-S3 code is released in the public domain * * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-s3-gps */ #include <TinyGPS++.h> #define GPS_BAUDRATE 9600 // The default baudrate of NEO-6M is 9600 TinyGPSPlus gps; // the TinyGPS++ object void setup() { Serial.begin(9600); Serial2.begin(GPS_BAUDRATE, SERIAL_8N1, 18, 17); Serial.println(F("ESP32 - GPS module")); } void loop() { if (Serial2.available() > 0) { if (gps.encode(Serial2.read())) { if (gps.location.isValid()) { Serial.print(F("- latitude: ")); Serial.println(gps.location.lat()); Serial.print(F("- longitude: ")); Serial.println(gps.location.lng()); Serial.print(F("- altitude: ")); if (gps.altitude.isValid()) Serial.println(gps.altitude.meters()); else Serial.println(F("INVALID")); } else { Serial.println(F("- location: INVALID")); } Serial.print(F("- speed: ")); if (gps.speed.isValid()) { Serial.print(gps.speed.kmph()); Serial.println(F(" km/h")); } else { Serial.println(F("INVALID")); } Serial.print(F("- GPS date&time: ")); if (gps.date.isValid() && gps.time.isValid()) { Serial.print(gps.date.year()); Serial.print(F("-")); Serial.print(gps.date.month()); Serial.print(F("-")); Serial.print(gps.date.day()); Serial.print(F(" ")); Serial.print(gps.time.hour()); Serial.print(F(":")); Serial.print(gps.time.minute()); Serial.print(F(":")); Serial.println(gps.time.second()); } else { Serial.println(F("INVALID")); } Serial.println(); } } if (millis() > 5000 && gps.charsProcessed() < 10) Serial.println(F("No GPS data received: check wiring")); } 

Things that go wrong

If the Serial Monitor keeps printing "No GPS data received: check wiring" after five seconds, double check the TX/RX crossover and the 5V connection. If wiring looks right but you're not getting a fix, give the module a clear view of the sky, indoors near a window at minimum, since concrete and metal block satellite signals. A cold start can also just take a while the first time.

Full tutorial

The complete tutorial - wiring diagram, code explanation and troubleshooting - is here: https://newbiely.com/tutorials/esp32-s3/esp32-s3-gps