Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

NEO-6M GPS with ESP32 DevKit V1 — Serial2 wiring and IST time

Connect a NEO-6M (GY-NEO6MV2) GPS to an ESP32 DevKit V1 on Serial2 with pins 16/17 set for core 3.x, parse it with TinyGPSPlus and print location and IST time.

Arduino C++Verified — core esp32 3.3.12, TinyGPSPlus 1.0.3, 3 Nov 2026Compile-only

Community draft — report a mistake

The NEO-6M is the GPS module in most Indian kits, sold as the GY-NEO6MV2 with a square patch antenna. It sends standard NMEA sentences at 9600 baud, and TinyGPSPlus turns them into latitude, longitude, satellites and time.

The ESP32 DevKit V1 has a spare hardware UART for this: Serial2 on GPIO16 (RX2) and GPIO17 (TX2). Core 3.x needs those pins named in Serial2.begin(). The module’s logic is 3.3 V, so it wires straight in. The sketch prints the position and Indian Standard Time every two seconds once it has a fix.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicNEO-6M GPS module (GY-NEO6MV2)GNDVINTX2 · 17RX2 · 16VCCRXTXGND
Also needed: The ceramic patch antenna that comes with the module (plugged into the u.FL socket).
Every connection
ESP32 DevKit V1NEO-6M GPS module (GY-NEO6MV2)WireNotes
VINVCCredThe module has its own 3.3 V regulator; 5 V on VCC gives it headroom. 3V3 also works on most boards.
GNDGNDblack
RX2TXyellowGPS TX → ESP32 RX2 (GPIO16). The GPS chip runs at 3.3 V, so no divider.
TX2RXgreenESP32 TX2 (GPIO17) → GPS RX. Only needed to change GPS settings; reading works without it.

3.3–5 V (on-board 3.3 V regulator) part, 3.3 V board. The module’s TX is a 3.3 V signal, which every board reads fine. Its RX pin is 3.3 V logic: from a 5 V Arduino TX, add a 1 kΩ / 2 kΩ divider. You only need RX if your sketch sends configuration commands.

Board quirks

  • Arduino-ESP32 3.x moved the default Serial2 pins to RX 4 / TX 25. Without Serial2.begin(9600, SERIAL_8N1, 16, 17) the sketch hears nothing on the pins printed RX2/TX2.
  • The ESP32 has three hardware UARTs, so there’s no SoftwareSerial here. UART0 (TX0/RX0) stays free for USB and uploads.
  • First fix after power-up (cold start) takes 1–5 minutes with a clear view of the sky. Indoors, under a concrete roof, it often never gets one. The blue LED blinks once a second when it has a fix.
  • GPS time is UTC. The sketch adds 5 h 30 min for IST. The date can be a day off between 18:30 and midnight UTC if you print it — add the offset to the date as well.
  • The backup cell on the module keeps the almanac, so warm starts take seconds. If the cell is flat (common on cheap boards), every start is a cold start.

Code

neo6m-gps-esp32.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// NEO-6M GPS (GY-NEO6MV2) on an ESP32 DevKit V1 with TinyGPSPlus.
// GPS TX → RX2 (GPIO16), GPS RX ← TX2 (GPIO17), VCC → VIN, GND → GND. Module logic is 3.3 V.
#include <TinyGPSPlus.h>

constexpr uint8_t RX_PIN = 16, TX_PIN = 17;
TinyGPSPlus gps;

void setup() {
  Serial.begin(115200);
  // Name the pins: arduino-esp32 3.x would otherwise put Serial2 on RX 4 / TX 25.
  Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
  Serial.println("NEO-6M on Serial2 — first fix takes 1–5 min outdoors");
}

void loop() {
  while (Serial2.available()) gps.encode(Serial2.read());

  static uint32_t last = 0;
  if (millis() - last < 2000) return;
  last = millis();

  if (gps.charsProcessed() < 10 && millis() > 5000) {
    Serial.println("No data from GPS — swap TX/RX, check 9600 baud and power");
    return;
  }
  if (!gps.location.isValid()) {
    Serial.printf("Waiting for fix… satellites %lu\n", (unsigned long)gps.satellites.value());
    return;
  }
  // GPS time is UTC; India is UTC+5:30.
  int mins = (gps.time.hour() * 60 + gps.time.minute() + 330) % 1440;
  Serial.printf("Lat %.6f  Lon %.6f  Sats %lu  HDOP %.1f  %02d:%02d:%02d IST\n", gps.location.lat(),
                gps.location.lng(), (unsigned long)gps.satellites.value(), gps.hdop.hdop(), mins / 60, mins % 60,
                gps.time.second());
}

Library: TinyGPSPlus (Mikal Hart) — compiled with TinyGPSPlus 1.0.3.

Expected serial output

Serial Monitor · 115200Output
NEO-6M on Serial2 — first fix takes 1–5 min outdoors
Waiting for fix… satellites 0
Waiting for fix… satellites 3
Lat 12.971599  Lon 77.594566  Sats 7  HDOP 1.2  14:32:08 IST
Lat 12.971602  Lon 77.594561  Sats 8  HDOP 1.1  14:32:10 IST

Common errors

“No data from GPS”

TX/RX crossed the wrong way (GPS TX must go to RX2), Serial2 started without the pin numbers, or the wrong baud — the NEO-6M ships at 9600.

Data arrives but never a fix

Take it outdoors or to a window, antenna side up, and wait 5 minutes. Keep it away from the ESP32’s Wi-Fi antenna and USB cables, which add noise.

Satellites seen but location jumps by tens of metres

Normal with HDOP above 2 or near tall buildings. Wait for more satellites, or average a few readings.

↑↓ to move · Enter to open