Componentes · 13 min de leitura

Módulo GPS NEO-6M com Arduino: ligação, NMEA e TinyGPSPlus

Como usar o módulo GPS NEO-6M com Arduino: ligação TX/RX, tempo até a primeira posição, sentenças $GPGGA e $GPRMC, código com TinyGPSPlus, ESP32 com OLED e Pico com MicroPython.

O módulo GPS NEO-6M é um receptor GPS barato e muito popular que acrescenta ao seu projeto com Arduino, ESP32 ou Raspberry Pi Pico latitude, longitude, velocidade, altitude e uma hora UTC extremamente precisa vinda dos satélites. Para usá-lo com um Arduino você só precisa de quatro fios (VCC, GND, TX, RX): uma vez por segundo, o módulo envia linhas de texto chamadas sentenças NMEA a 9600 baud, e a biblioteca TinyGPSPlus transforma essas linhas em números que você pode usar na hora.

Neste guia você vai ver, passo a passo, como o módulo funciona, como ligá-lo a um Arduino Uno, a um ESP32 e a um Pico, por que a primeira posição às vezes demora minutos, o que significa cada campo das sentenças $GPGGA e $GPRMC, como transformar latitude e longitude em um link do Google Maps e como mostrar a posição em um display OLED. No final, você encontra uma tabela com as causas e soluções dos dois problemas mais comuns: “sem dados” e “sem posição”.

Módulo GPS NEO-6M (u-blox NEO-6M)
Módulo GPS NEO-6M: o receptor u-blox NEO-6M no meio, os pinos em cima, a EEPROM que guarda as configurações e o LED de PPS à esquerda; a peça dourada ao lado é um conector SMA para antena externa.

O que é o módulo GPS NEO-6M e como ele funciona?

O GPS (Sistema de Posicionamento Global) é formado por mais de 30 satélites em órbita a uma altitude de cerca de 20.200 km. Cada satélite transmite o tempo todo a hora do seu relógio atômico de bordo e os dados da sua própria órbita. O NEO-6M mede a diferença entre o momento em que um sinal saiu do satélite e o momento em que chegou e, a partir disso, calcula a sua distância até cada satélite; quando enxerga pelo menos 4 satélites, ele consegue resolver latitude, longitude, altitude e o erro do seu próprio relógio. Com só 3 satélites, ele calcula uma posição bidimensional (2D), sem altitude. Os sinais dos satélites chegam ao chão extremamente fracos (cerca de -130 dBm), e concreto, telhados metálicos e até copas densas de árvores bloqueiam a maior parte deles. Por isso a regra de ouro do GPS é simples: a antena precisa ver o céu.

CaracterísticaValor
Chip receptoru-blox NEO-6M (motor de posicionamento u-blox 6)
Canais e sinal50 canais, GPS L1 C/A (1575,42 MHz), SBAS: EGNOS, WAAS, MSAS
Precisão horizontal2,5 m CEP (2,0 m com SBAS)
Precisão de velocidade e rumo0,1 m/s e 0,5 grau
Tempo até a primeira posição (TTFF)A frio 27 s, morno 27 s, a quente 1 s
SensibilidadeRastreamento -161 dBm, partida a frio -147 dBm
Taxa de atualização1 Hz por padrão, até 5 Hz
InterfaceUART, 9600 baud 8N1 por padrão, NMEA 0183
AlimentaçãoPlaca: 3,3–5 V (com regulador); chip: 2,7–3,6 V
Corrente~47 mA procurando, ~39 mA rastreando
Temperatura de operação-40 a +85 °C

A placa que você compra é mais que o chip NEO-6M de 16×12 mm. As placas GY-NEO6MV2 comuns acrescentam uma antena cerâmica tipo patch de 25×25 mm, um regulador que permite alimentar o módulo com 3,3–5 V, uma pequena EEPROM que guarda as configurações, uma bateria de reserva recarregável que mantém a hora e os dados dos satélites e um LED que pisca quando uma posição é encontrada. Algumas placas, como a da foto acima, também têm um conector SMA ou um minúsculo u.FL para antena externa e uma porta micro USB para ligar direto em um computador.

Ligação do NEO-6M: Arduino Uno, ESP32 e Raspberry Pi Pico

O NEO-6M se comunica por UART, que funciona como a porta serial de um computador e usa duas linhas de dados. A regra é simples: as linhas de dados são cruzadas. O pino TX (transmissão) do módulo vai ao pino RX (recepção) da placa, e o pino RX do módulo vai ao pino TX da placa. A única porta serial de hardware do Arduino Uno (pinos 0 e 1) é usada para o carregamento pelo USB e para o Monitor Serial, então ligamos o GPS aos pinos D4 e D3 com SoftwareSerial. Você encontra os detalhes da comunicação serial no artigo Comunicação serial UART.

Pino do NEO-6MArduino UnoESP32Raspberry Pi Pico
VCC5VVIN (5V) ou 3V3VBUS (5V) ou 3V3(OUT)
GNDGNDGNDGND
TXD4 (RX da SoftwareSerial)GPIO 16 (RX2)GP1 (RX da UART0)
RXD3, através de um divisor de 1 kΩ / 2 kΩGPIO 17 (TX2)GP0 (TX da UART0)
PPS (se houver)Pode ficar desligadoPode ficar desligadoPode ficar desligado
Os pinos de entrada do chip NEO-6M aguentam no máximo 3,6 V. O pino TX do Arduino Uno fornece 5 V, então não ligue o D3 direto no pino RX do módulo: acrescente um divisor de tensão (D3 → 1 kΩ → RX do GPS, RX do GPS → 2 kΩ → GND) ou use um conversor de nível lógico. Se você só quer ler a posição, pode deixar o pino RX do módulo desligado; ele só é necessário para enviar comandos de configuração ao módulo. O ESP32 e o Pico já trabalham em 3,3 V, então não precisam de divisor.
Como a placa tem o seu próprio regulador, alimente o VCC com 5 V sempre que puder; algumas placas funcionam de forma instável com 3,3 V por causa da queda de tensão no regulador. Procurando satélites, o módulo consome cerca de 47 mA, então, em projetos a bateria, calcule a autonomia com antecedência na calculadora de duração da bateria.

A primeira posição: partida a frio, morna e a quente

É totalmente normal que um módulo GPS não informe a posição no instante em que você o liga pela primeira vez. Para calcular a posição, o módulo precisa dos dados precisos de órbita (efemérides) dos satélites visíveis, e cada satélite os transmite mais ou menos a cada 30 segundos; baixar o almanaque completo, a lista aproximada das órbitas de todos os satélites, leva 12,5 minutos. Dependendo do quanto guardou de antes de ser desligado, o módulo parte de uma de três formas. Os tempos do datasheet foram medidos em condições de teste, com sinais fortes de todos os satélites; com a pequena antena cerâmica que vem com a placa, esperar alguns minutos é normal.

Tipo de partidaDados guardados no móduloDatasheetNa prática (ao ar livre)
Partida a frioSem hora, posição nem dados dos satélites (primeiro uso ou bateria de reserva descarregada)27 s1–5 minutos; pode passar de 10 minutos com sinais fracos
Partida mornaAlmanaque, hora e posição aproximadas; efemérides desatualizadas (desligado por mais de cerca de 4 horas)27 s30 segundos – 1 minuto
Partida a quenteEfemérides e hora atuais (desligado há pouco tempo, bateria de reserva carregada)1 sAlguns segundos
  • Vá para fora: em ambientes fechados, principalmente em prédios de concreto, o módulo muitas vezes não encontra posição nenhuma. Para testar, use uma varanda, um quintal ou pelo menos a frente de uma janela aberta.
  • Aponte a antena do jeito certo: a face plana e clara da antena cerâmica precisa ficar virada para o céu; virá-la de cabeça para baixo ou cobri-la com a mão enfraquece muito o sinal.
  • Mantenha a antena longe da eletrônica: a antena Wi-Fi do ESP32, os reguladores chaveados e cabos USB longos emitem ruído; coloque a antena a alguns centímetros das placas.
  • Tenha paciência e mantenha parado: não corte a alimentação durante a primeira posição; cada reinício recomeça a busca do zero.
  • Observe o LED: o LED da placa fica apagado até encontrar uma posição e depois começa a piscar uma vez por segundo.
  • Carregue a bateria de reserva: se a bateria estiver descarregada, toda energização é uma partida a frio. Deixar o módulo ligado por algumas horas a carrega, e as partidas seguintes caem para segundos.

Sentenças NMEA: como ler $GPGGA e $GPRMC

O NEO-6M envia tudo o que encontra como linhas de texto simples, separadas por vírgulas, no padrão NMEA 0183. Com as configurações padrão, chegam seis tipos de sentença por segundo: GGA, GLL, GSA, GSV, RMC e VTG; as sentenças TXT normalmente só aparecem na energização e trazem mensagens informativas, como a versão do firmware. Cada sentença começa com $; o prefixo GP significa que os dados vêm do GPS, e as três letras seguintes dão o tipo da sentença. Os dois caracteres depois do * no fim da linha são o checksum, obtido fazendo XOR de todos os caracteres entre $ e *, e é com ele que as linhas corrompidas são filtradas. As duas sentenças mais importantes para a posição são: $GPGGA,092750.00,4100.82500,N,02858.74000,E,1,08,1.01,39.2,M,36.9,M,,*67 e $GPRMC,092750.00,A,4100.82500,N,02858.74000,E,0.512,,281026,,,A*7E

Campo do $GPGGAExemploSignificado
Hora (UTC)092750.0009:27:50 UTC
Latitude4100.82500,N41 graus e 00,825 minuto Norte
Longitude02858.74000,E28 graus e 58,74 minutos Leste
Qualidade da posição10 = sem posição, 1 = GPS, 2 = com correção diferencial (SBAS)
Satélites08Satélites usados no cálculo da posição
HDOP1.01Diluição horizontal da precisão; abaixo de 2 é muito bom
Altitude39.2,M39,2 m acima do nível médio do mar
Separação do geoide36.9,MDiferença entre o nível do mar e o elipsoide WGS84
Campo do $GPRMCExemploSignificado
Hora (UTC)092750.00Horas, minutos, segundos
StatusAA = posição válida, V = sem posição
Latitude / longitude4100.82500,N / 02858.74000,EMesmo formato do GGA
Velocidade0.512Em nós (0,512 × 1,852 ≈ 0,95 km/h)
Rumo(vazio)Direção do movimento em graus; pode ficar vazio quando parado
Data281026Formato ddmmaa: 28 de outubro de 2026
ModoAA = autônomo, D = diferencial, N = sem dados

A latitude e a longitude no NMEA não estão em graus decimais, mas em graus e minutos (ddmm.mmmm), enquanto o Google Maps e a maioria dos programas querem graus decimais. Para converter, pegue os dois primeiros dígitos da latitude (os três primeiros da longitude) como graus, depois divida os minutos restantes por 60 e some: 4100.82500 → 41 + 0,825 / 60 = 41,013750; 02858.74000 → 28 + 58,74 / 60 = 28,979000. Valores ao Sul (S) e a Oeste (W) são escritos como números negativos. A sexta casa decimal corresponde a cerca de 11 cm e a quinta a 1,1 m; como o NEO-6M tem precisão de 2,5 m, seis casas decimais são mais que suficientes.

Passo a passo: vendo os dados brutos do GPS com um Arduino Uno

  1. Ligue o NEO-6M como na tabela: VCC → 5V, GND → GND, TX do GPS → D4, RX do GPS → D3 através do divisor.
  2. Carregue o código abaixo; não é preciso nenhuma biblioteca extra, a SoftwareSerial vem com a Arduino IDE.
  3. Abra o Monitor Serial e ajuste a velocidade para 115200 baud.
  4. Leve o módulo para fora ou para perto de uma janela e veja as linhas que começam com $GP passarem.
  5. Quando o segundo campo da linha $GPRMC mudar de V para A e o LED começar a piscar, o módulo encontrou a posição.
C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial gpsSerial(4, 3);   // RX, TX → GPS TX D4'e, GPS RX D3'e / GPS TX to D4, GPS RX to D3
4
5void setup() {
6  Serial.begin(115200);           // Seri Monitör hızı / Serial Monitor speed
7  gpsSerial.begin(9600);          // NEO-6M varsayılan hızı / NEO-6M default baud rate
8  Serial.println(F("NEO-6M ham NMEA / raw NMEA"));
9}
10
11void loop() {
12  while (gpsSerial.available()) {
13    Serial.write(gpsSerial.read());   // gelen her baytı aynen aktar / pass every byte through
14  }
15}

No Monitor Serial você vai ver um bloco de seis a nove linhas a cada segundo (quanto mais satélites à vista, em mais linhas a sentença GSV é dividida). Se o módulo ainda não encontrou nenhum satélite, as linhas ficam cheias de vírgulas vazias, como $GPRMC,,V,,,,,,,,,,N*53 e $GPGGA,,,,,,0,00,99.99,,,,,,*48; isso não é erro, mostra que o módulo está funcionando, mas ainda não consegue calcular a posição. Nas linhas $GPGSV você pode acompanhar o número de satélites visíveis e a intensidade do sinal (dB-Hz) de cada um; valores acima de 30 dB-Hz significam sinal bom. Se nenhuma linha chegar, confira a ligação; se aparecerem caracteres estranhos, confira o baud rate.

Lendo latitude, longitude, velocidade e hora com a TinyGPSPlus

Em vez de analisar as linhas NMEA na mão, é muito mais prático usar a biblioteca TinyGPSPlus, de Mikal Hart. Busque “TinyGPSPlus” no Gerenciador de Bibliotecas e instale; explicamos os passos no artigo como adicionar uma biblioteca no Arduino. Atenção: os exemplos da biblioteca usam 4800 baud, enquanto o NEO-6M usa 9600 baud. Se você rodar um exemplo sem mudar a velocidade, a localização sempre aparece como INVALID, porque a biblioteca não consegue decodificar nenhuma sentença a partir dos caracteres embaralhados. O código abaixo mostra a posição, a velocidade, a altitude, o número de satélites, a data e a hora uma vez por segundo e transforma a posição em um link do Google Maps que você pode abrir no navegador:

C++ (Arduino IDE)
1#include <TinyGPSPlus.h>
2#include <SoftwareSerial.h>
3
4const int RX_PIN = 4;              // GPS TX → D4
5const int TX_PIN = 3;              // GPS RX ← D3 (bölücü üzerinden / through a divider)
6const uint32_t GPS_BAUD = 9600;    // NEO-6M varsayılanı / NEO-6M default
7
8TinyGPSPlus gps;
9SoftwareSerial gpsSerial(RX_PIN, TX_PIN);
10unsigned long lastPrint = 0;
11
12void setup() {
13  Serial.begin(115200);
14  gpsSerial.begin(GPS_BAUD);
15  Serial.println(F("NEO-6M + TinyGPSPlus"));
16}
17
18void loop() {
19  while (gpsSerial.available()) {
20    gps.encode(gpsSerial.read());        // her baytı ayrıştırıcıya ver / feed every byte to the parser
21  }
22  if (millis() - lastPrint >= 1000) {    // delay() yok, saniyede bir yaz / no delay(), print once per second
23    lastPrint = millis();
24    printInfo();
25  }
26}
27
28void printInfo() {
29  if (gps.charsProcessed() < 10) {
30    Serial.println(F("GPS verisi yok: kablolari ve baud hizini kontrol et / No GPS data: check wiring and baud"));
31    return;
32  }
33  Serial.print(F("Uydu / Sats: "));
34  Serial.println(gps.satellites.value());
35
36  if (gps.location.isValid()) {
37    Serial.print(F("Enlem / Lat: "));
38    Serial.println(gps.location.lat(), 6);
39    Serial.print(F("Boylam / Lng: "));
40    Serial.println(gps.location.lng(), 6);
41    Serial.print(F("Hiz / Speed: "));
42    Serial.print(gps.speed.kmph(), 1);
43    Serial.println(F(" km/h"));
44    Serial.print(F("Yukseklik / Alt: "));
45    Serial.print(gps.altitude.meters(), 1);
46    Serial.println(F(" m"));
47    // Google Haritalar bağlantısı / Google Maps link
48    Serial.print(F("https://www.google.com/maps/search/?api=1&query="));
49    Serial.print(gps.location.lat(), 6);
50    Serial.print(',');
51    Serial.println(gps.location.lng(), 6);
52  } else {
53    Serial.println(F("Konum yok, uydu araniyor / No fix yet, searching"));
54  }
55
56  if (gps.date.isValid() && gps.time.isValid()) {
57    char buf[32];
58    snprintf(buf, sizeof(buf), "%02d.%02d.%04d %02d:%02d:%02d UTC",
59             gps.date.day(), gps.date.month(), (int)gps.date.year(),
60             gps.time.hour(), gps.time.minute(), gps.time.second());
61    Serial.println(buf);                 // saat UTC'dir / time is UTC
62  }
63  Serial.println();
64}
FunçãoO que retorna
gps.encode(c)Chamada a cada byte recebido; retorna true quando uma sentença válida está completa
gps.location.lat() / lng() (posição)Latitude e longitude em graus decimais
gps.location.isValid() / age() (validade)Se há uma posição válida / milissegundos desde a última atualização
gps.speed.kmph() (velocidade)Velocidade em relação ao solo em km/h (também existem mps() e knots())
gps.course.deg() (rumo)Direção do movimento em graus (0 = norte, 90 = leste)
gps.altitude.meters() (altitude)Altitude acima do nível do mar em metros
gps.satellites.value() (satélites)Número de satélites usados para a posição
gps.hdop.hdop() (precisão)Diluição horizontal da precisão (menor = melhor)
gps.date.day() / gps.time.hour() (data e hora)Campos de data e hora em UTC
TinyGPSPlus::distanceBetween(...)Distância entre duas coordenadas em metros
gps.failedChecksum()Número de sentenças corrompidas; se não parar de subir, dados estão se perdendo

A regra mais importante deste código é nunca usar delay() dentro do loop(). O GPS envia cerca de 500 bytes por segundo, mas o buffer de recepção da SoftwareSerial tem só 64 bytes; durante um delay() longo, o buffer transborda, as sentenças são cortadas e a TinyGPSPlus as descarta com erro de checksum. Por isso mostramos os dados uma vez por segundo usando millis(); veja o artigo millis() vs delay() para os detalhes. A hora do GPS é sempre UTC, então some a diferença do seu fuso horário (por exemplo, −3 horas para o horário de Brasília, +1 para a Europa Central no inverno ou +3 para a Turquia). No Arduino Uno, um double na verdade é um float de 32 bits, então o último dígito da latitude e da longitude é arredondado para cerca de meio metro; perto da precisão de 2,5 m do módulo, essa diferença não importa.

A SoftwareSerial é confiável a 9600 baud, mas bloqueia as interrupções por um instante enquanto recebe. Se o seu projeto também usa bibliotecas sensíveis a temporização, como a Servo, escolha a biblioteca AltSoftSerial no Uno (RX = D8, TX = D9) ou a porta de hardware Serial1 do Arduino Mega (RX1 = 19, TX1 = 18).

ESP32 com Serial2: mostrando a posição em um display OLED

No ESP32 você não precisa da SoftwareSerial: o chip tem três UARTs de hardware, e a Serial2 pode ser associada a qualquer par de pinos. No exemplo abaixo, o GPS está ligado ao GPIO 16 (RX2) e ao GPIO 17 (TX2); como o ESP32 trabalha em 3,3 V, também não é preciso divisor. A posição, a velocidade e a hora local aparecem em um display OLED de 0,96 polegada (SSD1306) ligado por I2C ao GPIO 21 (SDA) e ao GPIO 22 (SCL). Além da TinyGPSPlus, o código também precisa das bibliotecas Adafruit SSD1306 e Adafruit GFX.

C++ (Arduino IDE)
1#include <TinyGPSPlus.h>
2#include <Wire.h>
3#include <Adafruit_GFX.h>
4#include <Adafruit_SSD1306.h>
5
6#define GPS_RX 16                 // ESP32 RX2 ← GPS TX
7#define GPS_TX 17                 // ESP32 TX2 → GPS RX
8const int UTC_OFFSET = 3;         // Türkiye UTC+3, kendi saat dilimini yaz / set your own time zone
9
10TinyGPSPlus gps;
11Adafruit_SSD1306 display(128, 64, &Wire, -1);   // OLED: SDA 21, SCL 22
12unsigned long lastDraw = 0;
13
14String mapsLink() {
15  // Google Haritalar bağlantısı üret / build a Google Maps link
16  return "https://www.google.com/maps/search/?api=1&query=" +
17         String(gps.location.lat(), 6) + "," + String(gps.location.lng(), 6);
18}
19
20void drawScreen() {
21  display.clearDisplay();
22  display.setTextSize(1);
23  display.setCursor(0, 0);
24  display.print(F("Uydu/Sat: "));
25  display.print(gps.satellites.value());
26
27  if (gps.time.isValid()) {
28    int h = (gps.time.hour() + UTC_OFFSET + 24) % 24;   // yerel saat / local time
29    char t[12];
30    snprintf(t, sizeof(t), "%02d:%02d:%02d", h, gps.time.minute(), gps.time.second());
31    display.setCursor(80, 0);
32    display.print(t);
33  }
34
35  if (gps.location.isValid()) {
36    display.setCursor(0, 16);
37    display.print(F("Lat: "));
38    display.println(gps.location.lat(), 6);
39    display.print(F("Lng: "));
40    display.println(gps.location.lng(), 6);
41    display.setTextSize(2);                  // hız büyük yazılsın / speed in large digits
42    display.setCursor(0, 44);
43    display.print(gps.speed.kmph(), 1);
44    display.print(F(" km/h"));
45  } else {
46    display.setCursor(0, 24);
47    display.println(F("Uydu araniyor..."));
48    display.println(F("Searching for fix"));
49  }
50  display.display();
51}
52
53void setup() {
54  Serial.begin(115200);
55  Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);    // donanım UART2 / hardware UART2
56  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
57    Serial.println(F("OLED bulunamadi / OLED not found"));
58    while (true) delay(10);
59  }
60  display.setTextColor(SSD1306_WHITE);
61}
62
63void loop() {
64  while (Serial2.available()) {
65    gps.encode(Serial2.read());              // NMEA baytlarını çöz / decode NMEA bytes
66  }
67  if (millis() - lastDraw >= 1000) {         // saniyede bir güncelle / refresh once per second
68    lastDraw = millis();
69    drawScreen();
70    if (gps.location.isValid()) {
71      Serial.println(mapsLink());            // Telegram ya da SMS ile gönderilebilir / can be sent via Telegram or SMS
72    }
73  }
74}

A variável UTC_OFFSET converte a hora do GPS em hora local; ela vale 3 para a Turquia, 1 para o horário de inverno da Europa Central e -3 para o horário de Brasília. A função mapsLink() transforma a posição em um endereço do Google Maps com o parâmetro query=latitude,longitude. Você pode copiar esse link do Monitor Serial e abri-lo em um navegador, enviá-lo ao celular com um bot do Telegram ou mandá-lo por SMS com um módulo GSM SIM800L. Em placas ESP32-WROVER com PSRAM, os GPIO 16 e 17 são usados pela memória, então ligue o GPS, por exemplo, aos GPIO 26 e 27; no ESP32-C3, que tem só duas UARTs, use a Serial1 em vez da Serial2.

Lendo o GPS com o Raspberry Pi Pico e MicroPython

No Raspberry Pi Pico, ligamos o GPS à UART0: o TX do módulo vai ao GP1 e o RX ao GP0. No MicroPython, podemos analisar as linhas NMEA nós mesmos, sem instalar nenhuma biblioteca, o que também é um ótimo exercício para entender como as sentenças são montadas. O código confere o checksum de cada linha, tira o número de satélites do GGA e a posição, a velocidade e a hora do RMC e converte graus e minutos em graus decimais. A configuração timeout=200 faz o readline() esperar até 200 ms pelo fim de uma linha; se mesmo assim uma meia linha passar na inicialização, a verificação do checksum a descarta. Como o tipo de sentença é obtido com f[0][3:], o código também reconhece as linhas $GNRMC e $GNGGA enviadas por módulos que usam vários sistemas de satélites. Se você ainda não sabe rodar código com o Thonny, dê uma olhada antes no artigo Fundamentos de MicroPython.

MicroPython
1from machine import UART, Pin
2
3# GP0 (TX) → GPS RX, GP1 (RX) ← GPS TX
4gps = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1), timeout=200, rxbuf=1024)
5
6def checksum_ok(line):
7    # $ ile * arasındaki karakterlerin XOR'u / XOR of the characters between $ and *
8    try:
9        body, cs = line[1:].split('*')
10        x = 0
11        for ch in body:
12            x ^= ord(ch)
13        return x == int(cs[:2], 16)
14    except ValueError:
15        return False
16
17def to_deg(value, hemi):
18    # ddmm.mmmm → ondalık derece / decimal degrees
19    dot = value.index('.')
20    deg = int(value[:dot - 2]) + float(value[dot - 2:]) / 60
21    return -deg if hemi in ('S', 'W') else deg
22
23sats = '0'
24while True:
25    raw = gps.readline()                       # bir NMEA satırı / one NMEA line
26    if not raw:
27        continue
28    try:
29        line = raw.decode().strip()
30    except UnicodeError:
31        continue                               # bozuk bayt / corrupted byte
32    if not line.startswith('$') or not checksum_ok(line):
33        continue
34    f = line.split('*')[0].split(',')
35    kind = f[0][3:]                            # GPRMC ya da GNRMC → RMC / GPRMC or GNRMC → RMC
36    if kind == 'GGA':
37        sats = f[7]                            # kullanılan uydu sayısı / satellites in use
38    elif kind == 'RMC':
39        if f[2] != 'A':
40            print('Uydu araniyor / searching, uydu/sats:', sats)
41            continue
42        lat = to_deg(f[3], f[4])
43        lon = to_deg(f[5], f[6])
44        kmh = float(f[7] or 0) * 1.852        # knot → km/sa / knots → km/h
45        t = f[1]
46        print('UTC {}:{}:{}  uydu/sats: {}'.format(t[0:2], t[2:4], t[4:6], sats))
47        print('Konum / position: {:.6f}, {:.6f}  {:.1f} km/h'.format(lat, lon, kmh))
48        print('https://www.google.com/maps/search/?api=1&query={:.6f},{:.6f}'.format(lat, lon))

Ideias de projetos com o NEO-6M

  • Rastreador que manda a posição por SMS: com um NEO-6M e um SIM800L, monte um rastreador de carro ou bicicleta que responde a um SMS com “LOCATION” enviando um link do Google Maps.
  • Registrador de dados GPS: salve a sua rota a cada segundo em CSV em um módulo de cartão SD e depois desenhe-a em um mapa no computador.
  • Velocímetro de bicicleta: mostre a velocidade atual, a máxima e a distância total em um display OLED; some a distância entre pontos consecutivos com TinyGPSPlus::distanceBetween().
  • Relógio sincronizado com satélites: pegue a hora do GPS e acerte um módulo de relógio RTC no segundo, sem internet.
  • Alarme de cerca virtual: um sistema que toca um buzzer ou manda uma notificação quando algo se afasta mais de 100 metros de um ponto que você escolher.
  • Rastreamento de longo alcance: envie a posição a um receptor a quilômetros de distância com um módulo LoRa e economize energia na bateria com o deep sleep do ESP32.

Sem dados ou sem posição: problemas comuns e como resolver

SintomaCausa provávelSolução
Monitor Serial completamente vazioTX e RX trocados, sem GND comum ou módulo sem alimentaçãoLigue o TX do GPS ao pino RX da placa (D4 no Uno), una os GNDs, meça o VCC
“No GPS detected: check wiring.” (nenhum GPS detectado)Nem 10 caracteres chegaram à biblioteca em 5 segundosConfira a ligação e os números dos pinos no código; experimente trocar TX e RX
Caracteres estranhosBaud rate diferenteUse 9600 para o GPS e a velocidade do código no Monitor Serial; se não der certo, experimente 4800 e 38400
As linhas chegam, mas os campos estão vazios (,V,)O módulo funciona, mas não encontrou satélitesVá para fora, aponte a antena para o céu, espere 5–15 minutos
Número de satélites parado em 0–3Sinal fraco, antena de cabeça para baixo, conector u.FL frouxo ou uma fonte de ruído por pertoConfira a antena, encaixe bem o conector, afaste a antena do ESP32 e dos reguladores
Os dados brutos mostram uma posição, a TinyGPSPlus diz INVALIDUm delay() no loop() faz o buffer transbordar; failedChecksum() não para de subirTire o delay(), use millis(), chame encode() continuamente
A hora está algumas horas erradaA hora do GPS é UTCSome a diferença do seu fuso horário
A posição oscila alguns metros e a velocidade não é 0 paradoRuído normal do GPS e sinais refletidos em prédiosConsidere 0 as velocidades abaixo de 2 km/h, ignore leituras com HDOP alto, tire médias
Espera vários minutos de novo a cada energizaçãoBateria de reserva descarregada ou ausenteDeixe o módulo ligado por algumas horas para carregar a bateria
Para descobrir se o problema está no módulo ou no seu código, ligue o módulo direto ao computador com um conversor USB-TTL e abra-o no u-center, o software gratuito da u-blox. Ele mostra a intensidade do sinal de cada satélite, o status da posição e a posição em um mapa; lá você também pode mudar o baud rate e a taxa de atualização (até 5 Hz) e salvar as configurações de forma permanente na memória do módulo.

O NEO-6M acrescenta aos seus projetos, a um custo muito baixo, as respostas para “onde estou, com que velocidade estou indo e que horas são”; o segredo é mostrar o céu à antena e ter a paciência de que a primeira posição precisa. Para entender melhor a comunicação serial, dê uma olhada no artigo sobre UART. No app BlueGrays você encontra projetos que também ajudam em montagens com GPS, como comunicação serial entre dois Arduinos, displays OLED, registro de dados em microSD, deep sleep do ESP32 e um alarme com notificações no Telegram, cada um com esquemas do circuito e código passo a passo.

Perguntas frequentes

O módulo GPS NEO-6M funciona em ambientes fechados?

Normalmente não. Os sinais dos satélites chegam ao chão muito fracos, e telhados de concreto ou de metal bloqueiam a maior parte deles. Na frente de uma janela aberta ele pode captar alguns satélites, mas, para uma posição confiável, a antena precisa ver o céu diretamente; se você precisa de posição em ambiente fechado, use uma antena ativa externa colocada no telhado ou em uma janela.

Quanto tempo o NEO-6M leva para obter a primeira posição?

Segundo o datasheet, uma partida a frio leva 27 segundos e uma partida a quente, 1 segundo. Na prática, com a pequena antena cerâmica ao ar livre, a primeira posição costuma levar 1–5 minutos e, no primeiro uso ou com a bateria de reserva descarregada, pode levar 10–15 minutos. Se o módulo foi desligado há pouco tempo, ele volta a travar em alguns segundos.

Qual é a precisão do módulo GPS NEO-6M?

O fabricante especifica uma precisão horizontal de 2,5 m CEP com céu aberto, ou 2,0 m com correção SBAS; isso significa que metade das leituras fica a menos de 2,5 m do ponto real. Nas cidades, sinais refletidos em prédios podem elevar o erro para 5–10 metros. A altitude é menos precisa que a posição horizontal.

O NEO-6M funciona com 5V? Posso ligá-lo direto em um Arduino?

As placas GY-NEO6MV2 comuns têm regulador, então o VCC pode ser alimentado com 5 V. Porém, o pino RX do chip aguenta no máximo 3,6 V, então baixe o sinal TX de 5 V do Arduino Uno com um divisor de tensão de 1 kΩ e 2 kΩ. A saída TX do módulo é de 3,3 V, que o Uno lê sem problema.

Um módulo GPS precisa de internet ou chip de celular?

Não. O NEO-6M calcula a posição diretamente pelos sinais dos satélites, de graça e sem internet. Você só precisa de internet ou de um chip quando quer enviar a posição para outro lugar, usando o Wi-Fi do ESP32 ou um módulo GSM como o SIM800L.

Qual é a diferença entre o NEO-6M e o NEO-M8N?

O NEO-6M só usa satélites GPS. O NEO-M8N, mais novo, pode usar satélites GLONASS, Galileo ou BeiDou ao mesmo tempo que o GPS; como enxerga mais satélites, ele obtém uma posição mais rápida e estável nas cidades. As sentenças do M8N costumam começar com $GN, mas a TinyGPSPlus lê as duas com o mesmo código.

Ver todos os projetos
Comunicação unidirecional entre 2 Arduinos
#57Intermediário
Premium

Comunicação unidirecional entre 2 Arduinos

Faça dois Arduinos conversarem por um único fio: ao pressionar o botão de um, o LED do outro acende; ao pressionar de novo, ele apaga. A placa transmissora informa que o botão foi pressionado com uma

4.4(37)
50
Comunicação bidirecional entre 2 Arduinos
#58Intermediário
Premium

Comunicação bidirecional entre 2 Arduinos

Dois Arduinos se conectam por fios e conversam entre si: ao pressionar o botão de um, a luz do outro acende; ao pressionar novamente, ela apaga. As duas placas executam o mesmo programa, então ambas e

4.5(20)
26
Registrador de temperatura com ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avançado
Premium

Registrador de temperatura com ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Monte um registrador de temperatura com data e hora usando ESP32! Leia a temperatura e a umidade do DHT22 a cada minuto, obtenha a hora real do DS1307 RTC e grave os dados em CSV no cartão microSD. O OLED exibe a temperatura atual em letras grandes, a porcentagem de umidade, a data e a hora e o contador de registros. O arquivo /temp_log.csv no cartão SD pode ser aberto no Excel, Google Sheets ou pandas do Python para análise — ideal para monitorar estufas, acompanhar a temperatura de casa ou…

4.7(7)
12
ESP32 HTTPClient + API de clima (com display OLED SSD1306)
#134Avançado
Premium

ESP32 HTTPClient + API de clima (com display OLED SSD1306)

Neste projeto, usamos o ESP32 para fazer uma chamada REST à API de clima wttr.in pela internet com HTTPClient.h. Diferentemente da versão anterior com LCD I2C, aqui usamos um display OLED SSD1306 (128×64), que permite usar fontes grandes, ícones vetoriais e uma apresentação visual rica em uma única tela. Sete ícones vetoriais de condições do tempo (ensolarado, parcialmente nublado, nublado, chuvoso, com neve, com tempestade e com neblina) são desenhados durante a execução, sem arquivos bitmap.

4.3(10)
19
ESP32 em sono profundo — Economia de bateria (OLED + contador na RAM RTC)
#135Avançado
Premium

ESP32 em sono profundo — Economia de bateria (OLED + contador na RAM RTC)

O modo de sono profundo do ESP32 reduz o consumo de corrente para ~10 µA ao desligar a CPU e a maioria dos periféricos, sendo essencial para dispositivos IoT alimentados por bateria. Neste projeto, usamos três fontes de despertar: um temporizador (15 segundos), um pino externo (EXT0 — botão no GPIO 33) e toque (T0/GPIO 4). As variáveis marcadas com RTC_DATA_ATTR são preservadas durante o sono profundo, mantendo os contadores de inicializações e de despertares por temporizador e botão.

4.3(10)
16
Hora exata pela internet com ESP32 e NTP
#128Avançado
Premium

Hora exata pela internet com ESP32 e NTP

O ESP32 se conecta ao Wi-Fi e obtém a hora exata com precisão de milissegundos de servidores NTP (Network Time Protocol). Com a função configTzTime(), o fuso horário configurado (TRT, UTC+3 neste exemplo) é aplicado automaticamente, e as mudanças nos países que adotam horário de verão são gerenciadas automaticamente por uma string POSIX TZ. A hora é exibida tanto no Monitor Serial quanto em um LCD I2C opcional.

4.5(13)
21
Alarme de movimento com ESP32 (PIR + buzzer + LED + Telegram)
#145Avançado
Premium

Alarme de movimento com ESP32 (PIR + buzzer + LED + Telegram)

Um sistema de alarme de segurança inteligente que aciona o buzzer e o LED quando o sensor PIR detecta movimento e, ao mesmo tempo, envia uma notificação instantânea ao proprietário pelo Telegram. Inclui um intervalo de espera de 30 segundos para limitar a frequência dos alarmes repetidos; esse mecanismo não valida as detecções do PIR nem elimina disparos falsos. Pode ser usado na segurança de casas, no monitoramento de garagens, depósitos ou salas de trabalho.

0.0(0)
9
Relógio digital com ESP32 e RTC DS1307 (I2C + LCD)
#120Intermediário
Premium

Relógio digital com ESP32 e RTC DS1307 (I2C + LCD)

Neste projeto, exibimos a hora e a data em um display LCD I2C 16x2 usando o módulo de relógio de tempo real (RTC) DS1307. O DS1307 é um RTC com bateria de reserva que mantém a hora mesmo quando o ESP32 é desligado. Os dois módulos compartilham o mesmo barramento I2C (SDA/SCL), permitindo aprender a controlar vários dispositivos com apenas dois fios de sinal. Você aprenderá na prática o protocolo de comunicação I2C, o funcionamento dos módulos RTC e a exibição de dados dinâmicos em um LCD.

4.6(26)
40