GPS NEO-6M: Geolocalización para Proyectos IoT
🛰️ ¿Qué es el NEO-6M?
El NEO-6M es un módulo GPS económico y popular basado en el chip u-blox NEO-6M que permite obtener coordenadas de posición precisas mediante satélites GPS. Es ideal para proyectos IoT que requieren tracking, navegación o monitoreo de ubicación.
📌 Características principales
- Chip: u-blox NEO-6M (50 canales)
- Precisión: 2.5 metros (típica)
- Sensibilidad: -161 dBm
- Tiempo de arranque: 27s (arranque en frío)
- Alimentación: 3.3V a 5V
- Comunicación: UART (9600 baudios por defecto)
- Protocolo: NMEA 0183
- Antena: Cerámica integrada + conector para antena externa
🔌 Pinout del NEO-6M
El módulo típico tiene 4 pines principales:
| Pin | Función | Conexión ESP32 |
|---|---|---|
| VCC | Alimentación | 3.3V o 5V |
| GND | Tierra | GND |
| TX | Transmisión | Pin RX (GPIO16) |
| RX | Recepción | Pin TX (GPIO17) |
Pines adicionales (según modelo):
- PPS: Pulso por segundo (sincronización)
- EN: Enable/Reset
💻 Conexión básica ESP32 + NEO-6M
ESP32 NEO-6M
3.3V ─────── VCC
GND ─────── GND
GPIO16 ─────── TX (RX del ESP32)
GPIO17 ─────── RX (TX del ESP32)
Código básico de lectura
#include <SoftwareSerial.h>
// Crear puerto serie software para GPS
SoftwareSerial gpsSerial(16, 17); // RX, TX
void setup() {
Serial.begin(115200);
gpsSerial.begin(9600);
Serial.println("GPS NEO-6M - Iniciando...");
Serial.println("Esperando señal GPS...");
}
void loop() {
while (gpsSerial.available() > 0) {
String gpsData = gpsSerial.readStringUntil('\n');
Serial.println(gpsData);
}
delay(1000);
}
📡 Entendiendo los datos NMEA
El NEO-6M envía datos en formato NMEA 0183. Las sentencias más importantes:
$GPGGA - Datos de posición
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
- 123519: Hora UTC (12:35:19)
- 4807.038,N: Latitud 48°07.038’ Norte
- 01131.000,E: Longitud 11°31.000’ Este
- 1: Fix quality (0=no fix, 1=GPS fix, 2=DGPS fix)
- 08: Número de satélites
- 0.9: HDOP (dilución horizontal de precisión)
- 545.4,M: Altitud en metros
$GPRMC - Datos recomendados mínimos
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
- A: Status (A=activo, V=void/inválido)
- 022.4: Velocidad en nudos
- 084.4: Rumbo en grados
🎯 Proyecto: Tracker GPS básico
Código completo con parsing
#include <SoftwareSerial.h>
SoftwareSerial gpsSerial(16, 17);
struct GPSData {
float latitude = 0.0;
float longitude = 0.0;
float altitude = 0.0;
float speed = 0.0;
int satellites = 0;
bool fix = false;
String timestamp = "";
};
GPSData gps;
void setup() {
Serial.begin(115200);
gpsSerial.begin(9600);
Serial.println("=== GPS NEO-6M Tracker ===");
Serial.println("Esperando fix GPS...");
}
void loop() {
while (gpsSerial.available() > 0) {
String sentence = gpsSerial.readStringUntil('\n');
if (sentence.startsWith("$GPGGA")) {
parseGPGGA(sentence);
} else if (sentence.startsWith("$GPRMC")) {
parseGPRMC(sentence);
}
}
// Mostrar datos cada 5 segundos
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 5000) {
displayGPSData();
lastUpdate = millis();
}
}
void parseGPGGA(String sentence) {
// Ejemplo simplificado de parsing
int commaIndex[15];
int commaCount = 0;
// Encontrar todas las comas
for (int i = 0; i < sentence.length(); i++) {
if (sentence.charAt(i) == ',') {
commaIndex[commaCount++] = i;
}
}
if (commaCount >= 14) {
// Extraer datos
gps.timestamp = sentence.substring(commaIndex[0] + 1, commaIndex[1]);
// Latitud
String latStr = sentence.substring(commaIndex[1] + 1, commaIndex[2]);
String latDir = sentence.substring(commaIndex[2] + 1, commaIndex[3]);
if (latStr.length() > 0) {
gps.latitude = convertDMSToDecimal(latStr, latDir);
}
// Longitud
String lonStr = sentence.substring(commaIndex[3] + 1, commaIndex[4]);
String lonDir = sentence.substring(commaIndex[4] + 1, commaIndex[5]);
if (lonStr.length() > 0) {
gps.longitude = convertDMSToDecimal(lonStr, lonDir);
}
// Fix quality
String fixStr = sentence.substring(commaIndex[5] + 1, commaIndex[6]);
gps.fix = (fixStr.toInt() > 0);
// Número de satélites
String satStr = sentence.substring(commaIndex[6] + 1, commaIndex[7]);
gps.satellites = satStr.toInt();
// Altitud
String altStr = sentence.substring(commaIndex[8] + 1, commaIndex[9]);
gps.altitude = altStr.toFloat();
}
}
void parseGPRMC(String sentence) {
// Parsing similar para velocidad y otros datos
// Implementación simplificada
}
float convertDMSToDecimal(String dmsStr, String direction) {
if (dmsStr.length() < 4) return 0.0;
// Formato: DDMM.MMMMM (latitud) o DDDMM.MMMMM (longitud)
int dotIndex = dmsStr.indexOf('.');
if (dotIndex == -1) return 0.0;
// Extraer grados y minutos
String degreesStr = dmsStr.substring(0, dotIndex - 2);
String minutesStr = dmsStr.substring(dotIndex - 2);
float degrees = degreesStr.toFloat();
float minutes = minutesStr.toFloat();
float decimal = degrees + (minutes / 60.0);
// Aplicar dirección
if (direction == "S" || direction == "W") {
decimal = -decimal;
}
return decimal;
}
void displayGPSData() {
Serial.println("\n=== Estado GPS ===");
Serial.printf("Fix: %s\n", gps.fix ? "SÍ" : "NO");
Serial.printf("Satélites: %d\n", gps.satellites);
if (gps.fix) {
Serial.printf("Latitud: %.6f\n", gps.latitude);
Serial.printf("Longitud: %.6f\n", gps.longitude);
Serial.printf("Altitud: %.1f m\n", gps.altitude);
Serial.printf("Hora UTC: %s\n", gps.timestamp.c_str());
Serial.printf("Google Maps: https://maps.google.com/?q=%.6f,%.6f\n",
gps.latitude, gps.longitude);
} else {
Serial.println("Esperando fix GPS...");
}
Serial.println("==================");
}
🔧 Optimización y configuración
Configurar baudrate más alto
void setup() {
// Cambiar a 38400 baudios para mayor velocidad
gpsSerial.begin(9600);
delay(1000);
gpsSerial.println("$PUBX,41,1,0007,0003,38400,0*20"); // Cambiar baudrate
delay(500);
gpsSerial.begin(38400);
}
Configurar frecuencia de actualización
void setUpdateRate(int rate) {
// rate: 1000ms = 1Hz, 500ms = 2Hz, etc.
String command = "$PUBX,40,GGA,0,1,0,0,0,0*5A"; // Configurar GGA
gpsSerial.println(command);
}
🛠️ Proyectos prácticos con NEO-6M
1. Data Logger GPS
- Guardar coordenadas en SD card
- Timestamp con RTC
- Crear tracks GPX
2. Tracker IoT
- Enviar posición por WiFi/GSM
- Alertas de geofencing
- Seguimiento en tiempo real
3. Estación meteorológica móvil
- GPS + sensores ambientales
- Mapeo de datos climatológicos
- Análisis geoespacial
🚨 Problemas comunes y soluciones
❌ No obtiene fix GPS
- Ubicación: Usa el GPS en exterior, lejos de edificios
- Antena: Verifica que la antena cerámica esté libre
- Tiempo: Espera 1-5 minutos para cold start
- Alimentación: Asegura voltaje estable 3.3V-5V
❌ Datos corruptos
- Baudrate: Verifica 9600 baudios
- Conexiones: TX del GPS → RX del ESP32
- SoftwareSerial: Usa pines apropiados (evita conflictos)
❌ Precisión baja
- HDOP: Valores < 2.0 son buenos
- Satélites: Mínimo 4 para fix 3D
- Obstrucciones: Evita árboles, edificios, túneles
📈 Mejoras y expansiones
Antena externa
Para mejor recepción en interiores:
NEO-6M ─── Cable coaxial ─── Antena externa GPS
Backup battery
Para hot start más rápido:
- Batería de litio 3V en pin VBAT
- Mantiene almanaque y posición aproximada
Protocolo UBX
Para configuración avanzada:
- Mayor precisión
- Configuración personalizada
- Datos binarios más eficientes
El NEO-6M es el punto de partida perfecto para geolocalización en IoT. Su facilidad de uso, bajo costo y buena precisión lo convierten en la opción ideal para tracking vehicles, data logging geoespacial y sistemas de navegación en proyectos maker y profesionales.