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 Arduino Uno — SoftwareSerial wiring and TinyGPSPlus

Wire a NEO-6M GPS to an Arduino Uno R3 on D4/D3 with a divider on its RX, get a first fix outdoors and print position, satellites and IST time.

Arduino C++Verified — core avr 1.8.8, TinyGPSPlus 1.0.3, 3 Nov 2026Compile-only

Community draft — report a mistake

The NEO-6M is the GPS module in most Indian vehicle trackers and student projects (about ₹350 with antenna). It sends standard NMEA text sentences once a second. The TinyGPSPlus library turns them into latitude, longitude, altitude, speed and UTC time.

The Uno’s only hardware serial port is busy with USB, so the GPS connects to SoftwareSerial on D4 (receive) and D3 (transmit). The module’s TX is a 3.3 V signal, which the Uno reads without help. Its RX pin is 3.3 V too, so the Uno’s 5 V transmit line goes through a 1 kΩ / 2 kΩ divider. You only need that wire if you later send configuration commands; reading position needs just TX.

The sketch prints the satellite count, position and Indian time every 2 seconds, and tells you clearly when no data is arriving at all.

Wiring

Arduino Uno R3Only the pins used are shown · 5 V logicNEO-6M GPS module (GY-NEO6MV2)1k│2k5VGNDD3D4VCCRXTXGND
Also needed: 1 kΩ and 2 kΩ resistors, The ceramic patch antenna that comes with the module (plugged into the U.FL socket).
Every connection
Arduino Uno R3NEO-6M GPS module (GY-NEO6MV2)WireNotes
5VVCCredThe GY-NEO6MV2 board has a 3.3 V regulator; 5 V in is right. It draws up to about 50 mA while searching.
GNDGNDblack
D4TXyellowGPS TX (3.3 V) → Uno SoftwareSerial RX. Read fine as HIGH.
D3RXgreenVia 1 kΩ / 2 kΩ divider — Only needed if you send configuration commands; the GPS RX pin is 3.3 V.

3.3–5 V (on-board 3.3 V regulator) part, 5 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

  • GPS needs open sky. Indoors under a concrete roof it usually never gets a fix. Take the Uno to a balcony or terrace on a laptop or power bank for the first fix — a cold start takes 1–5 minutes.
  • The module’s blue LED blinks once a second only after it has a fix. Solid or off means still searching.
  • D0/D1 carry USB serial, so the GPS sits on SoftwareSerial. At the GPS’s 9600 baud this is reliable, but avoid other long interrupt-blocking code (NeoPixel strips, DHT reads) or characters get lost and sentences fail their checksum.
  • GPS time is UTC. The sketch adds 5 h 30 min for IST (it doesn’t roll the date over at midnight — use a time library for that).

Code

neo6m-uno.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// NEO-6M GPS module on an Arduino Uno R3, with TinyGPSPlus and SoftwareSerial.
// GPS TX → D4 (Uno RX), Uno D3 (TX) → 1 kΩ / 2 kΩ divider → GPS RX, VCC → 5V, GND → GND.
// First fix needs open sky: take it outdoors or to a window for 1–5 minutes.
#include <SoftwareSerial.h>
#include <TinyGPSPlus.h>

SoftwareSerial gpsSerial(4, 3);  // RX, TX
TinyGPSPlus gps;
unsigned long lastPrint = 0;

void printTwo(uint8_t v) {
  if (v < 10) Serial.print('0');
  Serial.print(v);
}

void setup() {
  Serial.begin(9600);
  gpsSerial.begin(9600);  // NEO-6M default
  Serial.println(F("NEO-6M on D4/D3 - waiting for satellites..."));
}

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

  if (millis() - lastPrint < 2000) return;
  lastPrint = millis();

  if (gps.charsProcessed() < 10) {
    Serial.println(F("No data from GPS - check GPS TX -> D4 and power"));
    return;
  }
  Serial.print(F("Sats "));
  Serial.print(gps.satellites.isValid() ? gps.satellites.value() : 0);
  if (gps.location.isValid()) {
    Serial.print(F("  Lat "));
    Serial.print(gps.location.lat(), 6);
    Serial.print(F("  Lng "));
    Serial.print(gps.location.lng(), 6);
    Serial.print(F("  Alt "));
    Serial.print(gps.altitude.meters(), 0);
    Serial.print(F(" m"));
  } else {
    Serial.print(F("  no fix yet"));
  }
  if (gps.time.isValid()) {
    // GPS time is UTC; India is UTC+5:30.
    int mins = gps.time.hour() * 60 + gps.time.minute() + 330;
    Serial.print(F("  IST "));
    printTwo((mins / 60) % 24);
    Serial.print(':');
    printTwo(mins % 60);
    Serial.print(':');
    printTwo(gps.time.second());
  }
  Serial.println();
}

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

Expected serial output

Serial Monitor · 9600Output
NEO-6M on D4/D3 - waiting for satellites...
Sats 0  no fix yet
Sats 4  no fix yet  IST 18:42:07
Sats 7  Lat 19.076012  Lng 72.877655  Alt 14 m  IST 18:43:11

Common errors

“No data from GPS”

GPS TX is not on D4 (TX and RX are easy to swap), or the module has no power. Its red power LED should be on.

Satellites show but no fix for 10+ minutes

Weak sky view or the antenna is loose or upside down (ceramic side up). See NEO-6M no GPS fix.

Position jumps by tens of metres when still

Normal for a cheap single-band GPS, especially between tall buildings. Average a few readings, and wait until 6 or more satellites are used.

↑↓ to move · Enter to open