Componenti · 12 min di lettura

Modulo GPS NEO-6M con Arduino: collegamento, NMEA e TinyGPSPlus

Modulo GPS NEO-6M con Arduino: collegamento TX/RX, tempo al primo fix, stringhe $GPGGA e $GPRMC, codice TinyGPSPlus, ESP32 con display OLED e Pico MicroPython.

Il modulo GPS NEO-6M è un ricevitore GPS economico e molto diffuso che aggiunge al tuo progetto con Arduino, ESP32 o Raspberry Pi Pico latitudine, longitudine, velocità, altitudine e l'ora UTC estremamente precisa trasmessa dai satelliti. Per usarlo con Arduino bastano quattro fili (VCC, GND, TX, RX): una volta al secondo il modulo invia a 9600 baud righe di testo chiamate stringhe NMEA e la libreria TinyGPSPlus le trasforma in numeri che puoi usare subito.

In questa guida vedrai passo dopo passo come funziona il modulo, come collegarlo ad Arduino Uno, ESP32 e Pico, perché il primo fix a volte richiede minuti, cosa significa ogni campo delle stringhe $GPGGA e $GPRMC, come trasformare latitudine e longitudine in un link di Google Maps e come mostrare la posizione su un display OLED. Alla fine troverai una tabella con cause e soluzioni dei due problemi più frequenti: "non arrivano dati" e "non trova la posizione".

Modulo GPS NEO-6M (u-blox NEO-6M)
Modulo GPS NEO-6M: al centro il ricevitore u-blox NEO-6M, in alto i pin di collegamento, a sinistra la EEPROM che conserva le impostazioni e il LED PPS; il pezzo dorato accanto è un connettore SMA per un'antenna esterna.

Cos'è il modulo GPS NEO-6M e come funziona?

Il GPS (Global Positioning System) è formato da oltre 30 satelliti che orbitano a circa 20.200 km di quota. Ogni satellite trasmette di continuo l'ora del suo orologio atomico e i dati della propria orbita. Il NEO-6M misura la differenza tra l'istante in cui il segnale ha lasciato il satellite e quello in cui arriva, e da qui ricava la distanza da ogni satellite; quando ne vede almeno 4 calcola latitudine, longitudine, altitudine e l'errore del proprio orologio. Con soli 3 satelliti può calcolare una posizione bidimensionale (2D) senza altitudine. I segnali arrivano a terra debolissimi (circa -130 dBm) e cemento, tetti metallici e perfino una chioma d'alberi fitta li bloccano in gran parte. Ecco la regola d'oro del GPS: l'antenna deve vedere il cielo.

CaratteristicaValore
Chip ricevitoreu-blox NEO-6M (motore di posizionamento u-blox 6)
Canali e segnale50 canali, GPS L1 C/A (1575,42 MHz), SBAS: EGNOS, WAAS, MSAS
Precisione orizzontale2,5 m CEP (2,0 m con SBAS)
Precisione di velocità e rotta0,1 m/s e 0,5 gradi
Tempo al primo fix (TTFF)A freddo 27 s, a tiepido 27 s, a caldo 1 s
SensibilitàTracking -161 dBm, avvio a freddo -147 dBm
Frequenza di aggiornamento1 Hz di default, fino a 5 Hz
ComunicazioneUART, 9600 baud 8N1 di default, NMEA 0183
AlimentazioneScheda: 3,3–5 V (con regolatore); chip: 2,7–3,6 V
Assorbimento~47 mA durante la ricerca, ~39 mA in tracking
Temperatura di esercizioDa -40 a +85 °C

La scheda che acquisti non è solo il chip NEO-6M da 16×12 mm. Le diffuse schede GY-NEO6MV2 aggiungono un'antenna ceramica a patch da 25×25 mm, un regolatore che permette di alimentare il modulo a 3,3–5 V, una piccola EEPROM che conserva le impostazioni, una batteria tampone ricaricabile che mantiene ora e dati dei satelliti e un LED che lampeggia quando c'è il fix. Alcune schede, come quella nella foto, hanno anche un connettore SMA o un piccolo u.FL per un'antenna esterna e una porta micro USB per collegarle direttamente al computer.

Collegamento del NEO-6M: Arduino Uno, ESP32 e Raspberry Pi Pico

Il NEO-6M comunica tramite UART, che funziona come la porta seriale di un computer e usa due linee dati. La regola è semplice: le linee si incrociano. Il pin TX (trasmissione) del modulo va al pin RX (ricezione) della scheda e il pin RX del modulo al pin TX della scheda. L'unica seriale hardware di Arduino Uno (pin 0 e 1) serve per caricare lo sketch via USB e per il monitor seriale, quindi colleghiamo il GPS ai pin D4 e D3 con SoftwareSerial. Trovi i dettagli della comunicazione seriale nell'articolo Comunicazione seriale UART.

Pin del NEO-6MArduino UnoESP32Raspberry Pi Pico
VCC5VVIN (5V) o 3V3VBUS (5V) o 3V3(OUT)
GNDGNDGNDGND
TXD4 (RX di SoftwareSerial)GPIO 16 (RX2)GP1 (RX della UART0)
RXD3, tramite partitore 1 kΩ / 2 kΩGPIO 17 (TX2)GP0 (TX della UART0)
PPS (se presente)Può restare scollegatoPuò restare scollegatoPuò restare scollegato
I pin di ingresso del chip NEO-6M sopportano al massimo 3,6 V. Il pin TX di Arduino Uno fornisce 5 V, quindi non collegare D3 direttamente al pin RX del modulo: inserisci un partitore di tensione (D3 → 1 kΩ → RX del GPS, RX del GPS → 2 kΩ → GND) oppure usa un convertitore di livelli logici. Se ti serve solo leggere la posizione puoi lasciare scollegato il pin RX del modulo: serve solo per inviargli comandi di configurazione. ESP32 e Pico lavorano già a 3,3 V e non hanno bisogno del partitore.
Dato che la scheda ha un proprio regolatore, alimenta VCC a 5 V quando puoi; alcune schede a 3,3 V funzionano in modo instabile per la caduta di tensione sul regolatore. Mentre cerca i satelliti il modulo assorbe circa 47 mA: nei progetti a batteria calcola prima l'autonomia con il calcolatore di durata della batteria.

Il primo fix: avvio a freddo, a tiepido e a caldo

È del tutto normale che un modulo GPS non fornisca la posizione appena lo accendi per la prima volta. Per calcolarla gli servono i dati orbitali precisi (effemeridi) dei satelliti visibili, e ogni satellite li trasmette solo ogni 30 secondi circa; scaricare l'intero almanacco, l'elenco approssimativo delle orbite di tutti i satelliti, richiede 12,5 minuti. A seconda di quante informazioni ha conservato prima dello spegnimento, il modulo parte in uno di tre modi. I tempi del datasheet sono misurati in condizioni di prova con segnale forte da tutti i satelliti; con la piccola antenna ceramica della scheda è normale aspettare qualche minuto.

Tipo di avvioDati salvati nel moduloDatasheetIn pratica (all'aperto)
Avvio a freddoNessuna ora, posizione o dato dei satelliti (primo utilizzo o batteria tampone scarica)27 s1–5 minuti; con segnale debole anche oltre 10 minuti
Avvio a tiepidoAlmanacco, ora e posizione approssimative; effemeridi scadute (spento da più di circa 4 ore)27 s30 secondi – 1 minuto
Avvio a caldoEffemeridi e ora aggiornate (spento da poco, batteria tampone carica)1 sPochi secondi
  • Esci all'aperto: In casa, soprattutto negli edifici in cemento armato, il modulo spesso non trova alcuna posizione. Per le prove usa un balcone, un giardino o almeno il punto davanti a una finestra aperta.
  • Orienta bene l'antenna: La faccia piatta e chiara dell'antenna ceramica deve guardare il cielo; capovolgerla o coprirla con la mano indebolisce molto il segnale.
  • Tieni l'antenna lontana dall'elettronica: L'antenna Wi-Fi dell'ESP32, i regolatori switching e i cavi USB lunghi generano disturbi; posiziona l'antenna a qualche centimetro dalle schede.
  • Abbi pazienza e non muoverlo: Non togliere l'alimentazione durante il primo fix; ogni riavvio fa ripartire la ricerca da zero.
  • Osserva il LED: Il LED sulla scheda resta spento finché non c'è il fix, poi inizia a lampeggiare una volta al secondo.
  • Ricarica la batteria tampone: Se è scarica, ogni accensione è un avvio a freddo. Lasciare il modulo alimentato per qualche ora la ricarica e gli avvii successivi scendono a pochi secondi.

Stringhe NMEA: come leggere $GPGGA e $GPRMC

Il NEO-6M invia tutto ciò che calcola come righe di testo separate da virgole secondo lo standard NMEA 0183. Con le impostazioni di fabbrica arrivano ogni secondo sei tipi di stringa: GGA, GLL, GSA, GSV, RMC e VTG; le stringhe TXT compaiono di solito solo all'accensione e contengono messaggi informativi come la versione del firmware. Ogni stringa inizia con $; il prefisso GP indica che i dati arrivano dal GPS e le tre lettere successive il tipo di stringa. I due caratteri dopo l'* a fine riga sono il checksum, ottenuto facendo lo XOR di tutti i caratteri tra $ e *, con cui si scartano le righe corrotte. Le due stringhe più importanti per la posizione sono: $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 di $GPGGAEsempioSignificato
Ora (UTC)092750.0009:27:50 UTC (10:27:50 in Italia d'inverno)
Latitudine4100.82500,N41 gradi 00,825 minuti Nord
Longitudine02858.74000,E28 gradi 58,74 minuti Est
Qualità del fix10 = nessun fix, 1 = GPS, 2 = differenziale (SBAS)
Satelliti08Satelliti usati nel calcolo della posizione
HDOP1.01Diluizione orizzontale della precisione; sotto 2 è ottima
Altitudine39.2,M39,2 m sul livello medio del mare
Separazione del geoide36.9,MDifferenza tra livello del mare ed ellissoide WGS84
Campo di $GPRMCEsempioSignificato
Ora (UTC)092750.00Ore, minuti, secondi
StatoAA = posizione valida, V = nessun fix
Latitudine / longitudine4100.82500,N / 02858.74000,EStesso formato di GGA
Velocità0.512In nodi (0,512 × 1,852 ≈ 0,95 km/h)
Rotta(vuoto)Direzione di movimento in gradi; da fermo può restare vuota
Data281026Formato ggmmaa: 28/10/2026
ModoAA = autonomo, D = differenziale, N = nessun dato

Nelle stringhe NMEA latitudine e longitudine non sono in gradi decimali ma in gradi e minuti (ggmm.mmmm), mentre Google Maps e quasi tutti i programmi vogliono i gradi decimali. Per convertire prendi le prime due cifre della latitudine (le prime tre della longitudine) come gradi e aggiungi i minuti rimanenti divisi per 60: 4100.82500 → 41 + 0,825 / 60 = 41,013750; 02858.74000 → 28 + 58,74 / 60 = 28,979000. I valori Sud (S) e Ovest (W) si scrivono con il segno meno. La sesta cifra decimale corrisponde a circa 11 cm e la quinta a 1,1 m; dato che il NEO-6M ha una precisione di 2,5 m, sei decimali bastano e avanzano.

Passo dopo passo: vedere i dati GPS grezzi con Arduino Uno

  1. Collega il NEO-6M come nella tabella: VCC → 5V, GND → GND, TX del GPS → D4, RX del GPS → D3 tramite il partitore.
  2. Carica il codice qui sotto; non servono librerie aggiuntive, SoftwareSerial è inclusa nell'IDE di Arduino.
  3. Apri il monitor seriale e imposta 115200 baud.
  4. Porta il modulo all'aperto o vicino a una finestra e guarda scorrere le righe che iniziano con $GP.
  5. Quando il secondo campo della riga $GPRMC passa da V ad A e il LED inizia a lampeggiare, il modulo ha trovato la posizione.
Arduino (C++)
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}

Nel monitor seriale vedrai ogni secondo un blocco di sei-nove righe (più satelliti sono in vista, più righe occupa la stringa GSV). Se il modulo non ha ancora trovato satelliti, le righe sono piene di virgole vuote, come $GPRMC,,V,,,,,,,,,,N*53 e $GPGGA,,,,,,0,00,99.99,,,,,,*48; non è un errore, significa che il modulo funziona ma non riesce ancora a calcolare la posizione. Nelle righe $GPGSV puoi seguire il numero di satelliti visibili e la potenza del segnale (dB-Hz) di ciascuno; valori sopra i 30 dB-Hz indicano un buon segnale. Se non arriva nessuna riga controlla i collegamenti; se compaiono caratteri strani controlla la velocità in baud.

Leggere latitudine, longitudine, velocità e ora con TinyGPSPlus

Invece di analizzare a mano le righe NMEA, è molto più comodo usare la libreria TinyGPSPlus di Mikal Hart. Cercala come "TinyGPSPlus" nel gestore librerie e installala; spieghiamo i passaggi nell'articolo come aggiungere una libreria Arduino. Attenzione: gli esempi della libreria usano 4800 baud, mentre il NEO-6M lavora a 9600. Se esegui un esempio senza cambiare la velocità, la posizione risulta sempre INVALID, perché la libreria non riesce a decodificare nemmeno una stringa dai caratteri corrotti. Il codice qui sotto stampa ogni secondo posizione, velocità, altitudine, numero di satelliti, data e ora e trasforma la posizione in un link di Google Maps da aprire nel browser:

Arduino (C++)
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}
FunzioneCosa restituisce
gps.encode(c)Si chiama con ogni byte ricevuto; restituisce true quando una stringa valida è completa
gps.location.lat() / lng()Latitudine e longitudine in gradi decimali
gps.location.isValid() / age()Se c'è una posizione valida / millisecondi dall'ultimo aggiornamento
gps.speed.kmph()Velocità al suolo in km/h (esistono anche mps() e knots())
gps.course.deg()Rotta in gradi (0 = nord, 90 = est)
gps.altitude.meters()Altitudine sul livello del mare in metri
gps.satellites.value()Numero di satelliti usati per la posizione
gps.hdop.hdop()Diluizione orizzontale della precisione (più basso = meglio)
gps.date.day() / gps.time.hour()Campi di data e ora in UTC
TinyGPSPlus::distanceBetween(...)Distanza tra due coordinate in metri
gps.failedChecksum()Numero di stringhe corrotte; se continua a salire si stanno perdendo dati

La regola più importante di questo codice è niente delay() dentro loop(). Il GPS invia circa 500 byte al secondo, ma il buffer di ricezione di SoftwareSerial è di soli 64 byte; durante un delay() lungo va in overflow, le stringhe vengono troncate e TinyGPSPlus le scarta per errore di checksum. Per questo stampiamo una volta al secondo con millis(); trovi i dettagli nell'articolo millis() o delay(). L'ora del GPS è sempre UTC: in Italia aggiungi 1 ora d'inverno e 2 d'estate. Su Arduino Uno un double è in realtà un float a 32 bit, quindi l'ultima cifra di latitudine e longitudine viene arrotondata a circa mezzo metro; rispetto ai 2,5 m di precisione del modulo è una differenza trascurabile.

SoftwareSerial è affidabile a 9600 baud, ma durante la ricezione blocca per poco gli interrupt. Se il tuo progetto usa anche librerie sensibili ai tempi come Servo, scegli su Uno la libreria AltSoftSerial (RX = D8, TX = D9) oppure la seriale hardware Serial1 di Arduino Mega (RX1 = 19, TX1 = 18).

ESP32 con Serial2: mostrare la posizione su un display OLED

Con l'ESP32 SoftwareSerial non serve: il chip ha tre UART hardware e Serial2 si può assegnare ai pin che preferisci. Nell'esempio qui sotto il GPS è collegato a GPIO 16 (RX2) e GPIO 17 (TX2); poiché l'ESP32 lavora a 3,3 V, non serve nemmeno il partitore. Posizione, velocità e ora locale compaiono su un display OLED SSD1306 da 0,96 pollici collegato in I2C a GPIO 21 (SDA) e GPIO 22 (SCL). Oltre a TinyGPSPlus, il codice richiede le librerie Adafruit SSD1306 e Adafruit GFX.

Arduino (C++)
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}

La variabile UTC_OFFSET converte l'ora GPS in ora locale; per l'Italia vale 1 d'inverno e 2 d'estate. La funzione mapsLink() trasforma la posizione in un indirizzo di Google Maps con il parametro query=latitudine,longitudine. Puoi copiare il link dal monitor seriale e aprirlo nel browser, inviarlo al telefono con un bot Telegram o spedirlo via SMS con un modulo GSM SIM800L. Sulle schede ESP32-WROVER con PSRAM i GPIO 16 e 17 sono usati dalla memoria, quindi collega il GPS ad esempio a GPIO 26 e 27; sull'ESP32-C3, che ha solo due UART, usa Serial1 invece di Serial2.

Leggere il GPS con Raspberry Pi Pico e MicroPython

Sul Raspberry Pi Pico colleghiamo il GPS alla UART0: il TX del modulo va a GP1 e il suo RX a GP0. In MicroPython possiamo analizzare da soli le righe NMEA senza installare librerie, ed è anche un ottimo esercizio per capire come sono costruite le stringhe. Il codice verifica il checksum di ogni riga, prende il numero di satelliti da GGA e posizione, velocità e ora da RMC, e converte gradi e minuti in gradi decimali. L'impostazione timeout=200 fa sì che readline() attenda fino a 200 ms la fine della riga; se all'avvio passa comunque una riga a metà, il controllo del checksum la scarta. Poiché il tipo di stringa si ricava con f[0][3:], il codice riconosce anche le righe $GNRMC e $GNGGA dei moduli che usano più sistemi satellitari. Se non sai ancora come eseguire il codice con Thonny, dai prima un'occhiata all'articolo basi di 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))

Idee di progetto con il NEO-6M

  • Localizzatore che invia la posizione via SMS: Con un NEO-6M e un SIM800L, un localizzatore per auto o bici che risponde a un SMS con scritto "POSIZIONE" inviando un link di Google Maps.
  • Data logger GPS: Salva il tuo percorso ogni secondo in CSV su un modulo scheda SD e poi visualizzalo su una mappa al computer.
  • Tachimetro per bici: Mostra velocità attuale e massima e distanza totale su un display OLED; somma la distanza tra punti successivi con TinyGPSPlus::distanceBetween().
  • Orologio sincronizzato dai satelliti: Prendi l'ora dal GPS e regola al secondo un modulo orologio RTC senza bisogno di internet.
  • Allarme geofence: Un sistema che fa suonare un buzzer o invia una notifica quando qualcosa si allontana più di 100 metri da un punto scelto da te.
  • Tracciamento a lungo raggio: Invia la posizione a un ricevitore a chilometri di distanza con un modulo LoRa e risparmia energia a batteria con il deep sleep dell'ESP32.

Non arrivano dati o non trova la posizione: errori comuni e soluzioni

SintomoCausa probabileSoluzione
Monitor seriale completamente vuotoTX e RX invertiti, GND non in comune o modulo non alimentatoCollega il TX del GPS al pin RX della scheda (D4 su Uno), unisci le masse, misura VCC
"No GPS detected: check wiring."In 5 secondi alla libreria non sono arrivati nemmeno 10 caratteriControlla i collegamenti e i numeri dei pin nel codice; prova a scambiare TX e RX
Caratteri senza sensoVelocità in baud sbagliata9600 per il GPS e la velocità del codice nel monitor seriale; altrimenti prova 4800 e 38400
Arrivano righe ma con campi vuoti (,V,)Il modulo funziona ma non ha trovato satellitiEsci all'aperto, orienta l'antenna verso il cielo, aspetta 5–15 minuti
Il numero di satelliti resta tra 0 e 3Segnale debole, antenna capovolta, connettore u.FL allentato o fonte di disturbo vicinaControlla l'antenna, inserisci bene il connettore, allontana l'antenna da ESP32 e regolatori
I dati grezzi hanno la posizione, TinyGPSPlus dice INVALIDIl delay() nel loop() manda in overflow il buffer; failedChecksum() aumentaTogli il delay(), usa millis(), chiama encode() di continuo
L'ora è sbagliata di qualche oraL'ora del GPS è UTCAggiungi la differenza del tuo fuso orario (in Italia +1 d'inverno, +2 d'estate)
Da fermo la posizione si sposta di qualche metro e la velocità non è 0Normale rumore GPS e segnali riflessi dagli edificiConsidera 0 le velocità sotto 2 km/h, scarta le letture con HDOP alto, fai la media
A ogni accensione aspetta di nuovo minutiBatteria tampone scarica o assenteLascia il modulo alimentato per qualche ora per ricaricare la batteria
Per capire se il problema è nel modulo o nel codice, collega il modulo direttamente al computer con un convertitore USB-TTL e aprilo con il software gratuito u-center di u-blox. Mostra la potenza del segnale di ogni satellite, lo stato del fix e la posizione su una mappa; da lì puoi anche cambiare la velocità in baud e la frequenza di aggiornamento (fino a 5 Hz) e salvare le impostazioni in modo permanente nella memoria del modulo.

Il NEO-6M porta nei tuoi progetti, con una spesa minima, la risposta a "dove sono, quanto vado veloce e che ore sono"; il segreto è mostrare il cielo all'antenna e concedere al primo fix la pazienza necessaria. Per capire meglio la comunicazione seriale dai un'occhiata all'articolo sulla UART. Nell'app BlueGrays trovi progetti utili anche per i tuoi montaggi con il GPS, come la comunicazione seriale tra due Arduino, i display OLED, la registrazione dati su microSD, il deep sleep dell'ESP32 e un allarme con notifiche Telegram, ognuno con schema elettrico e codice passo dopo passo.

Domande frequenti

Il modulo GPS NEO-6M funziona al chiuso?

Di solito no. I segnali dei satelliti arrivano a terra molto deboli e cemento o tetti metallici li bloccano quasi del tutto. Davanti a una finestra aperta può agganciare qualche satellite, ma per un fix affidabile l'antenna deve vedere direttamente il cielo; se ti serve la posizione al chiuso, usa un'antenna attiva esterna sistemata sul tetto o a una finestra.

Quanto tempo impiega il NEO-6M a trovare il primo fix?

Secondo il datasheet l'avvio a freddo richiede 27 secondi e quello a caldo 1 secondo. In pratica, con la piccola antenna ceramica all'aperto, il primo fix richiede di solito 1–5 minuti, e al primo utilizzo o con la batteria tampone scarica può arrivare a 10–15 minuti. Se il modulo è stato spento da poco, si riaggancia in pochi secondi.

Qual è la precisione del modulo GPS NEO-6M?

Il produttore dichiara una precisione orizzontale di 2,5 m CEP a cielo aperto, 2,0 m con la correzione SBAS; significa che metà delle misure cade a meno di 2,5 m dal punto reale. In città i segnali riflessi dagli edifici possono portare l'errore a 5–10 metri. L'altitudine è meno precisa della posizione orizzontale.

Il NEO-6M funziona a 5V e si può collegare direttamente ad Arduino?

Le comuni schede GY-NEO6MV2 hanno un regolatore, quindi VCC si può alimentare a 5 V. Il pin RX del chip però sopporta al massimo 3,6 V: abbassa il segnale TX a 5 V di Arduino Uno con un partitore di tensione da 1 kΩ e 2 kΩ. L'uscita TX del modulo è a 3,3 V e Uno la legge senza problemi.

Un modulo GPS ha bisogno di internet o di una SIM?

No. Il NEO-6M calcola la posizione direttamente dai segnali dei satelliti, gratis e senza internet. Internet o una SIM servono solo se vuoi inviare la posizione da qualche parte, ad esempio con il Wi-Fi dell'ESP32 o con un modulo GSM come il SIM800L.

Che differenza c'è tra NEO-6M e NEO-M8N?

Il NEO-6M usa solo i satelliti GPS. Il più recente NEO-M8N può usare contemporaneamente anche i satelliti GLONASS, Galileo o BeiDou; vedendo più satelliti, in città ottiene un fix più rapido e stabile. Le sue stringhe di solito iniziano con $GN, ma TinyGPSPlus le legge entrambe con lo stesso codice.

Vedi tutti i progetti
Comunicazione unidirezionale tra 2 Arduino
#57Intermedio
Premium

Comunicazione unidirezionale tra 2 Arduino

Un progetto per il trasferimento unidirezionale di dati tra due Arduino tramite comunicazione seriale. Rileva la pressione del pulsante sul lato trasmettitore e insegna a controllare il LED sul lato r

4.4(37)
50
Comunicazione bidirezionale tra 2 Arduino
#58Intermedio
Premium

Comunicazione bidirezionale tra 2 Arduino

Un progetto che trasferisce dati bidirezionali tra due Arduino tramite comunicazione seriale. Entrambe le schede leggono il pulsante e inviano dati e ricevono dati e controllano il LED.

4.5(20)
26
Data Logger di Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avanzato
Premium

Data Logger di Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Costruisci un data logger di temperatura con timestamp usando ESP32! Leggi temperatura/umidità dal DHT22 ogni 10 secondi, ottieni l'ora reale dal DS1307 RTC e registra su scheda microSD in formato CSV. L'OLED mostra dal vivo temperatura (font grande), percentuale di umidità, timestamp e contatore di log. Il file `/temp_log.csv` sulla scheda SD si apre in Excel, Google Sheets o Python pandas per l'analisi — perfetto per il monitoraggio di serre, tracciamento della temperatura domestica, raccolta

4.7(7)
12
ESP32 HTTPClient + API meteo (con display OLED SSD1306)
#134Avanzato
Premium

ESP32 HTTPClient + API meteo (con display OLED SSD1306)

In questo progetto, utilizzando l'ESP32, effettuiamo una chiamata REST all'API meteo (wttr.in) tramite Internet utilizzando `HTTPClient.h`. A differenza della precedente versione con LCD I2C, qui utilizziamo un display OLED SSD1306 (128×64), che consente di utilizzare caratteri di grandi dimensioni, icone vettoriali e una ricca presentazione visiva su un unico schermo. Per le condizioni meteorologiche, 7 diverse icone vettoriali (soleggiato, parzialmente nuvoloso, nuvoloso, piovoso, nevoso, temp

4.3(10)
18
ESP32 Deep Sleep — Risparmio della batteria (OLED + contatore in RTC RAM)
#135Avanzato
Premium

ESP32 Deep Sleep — Risparmio della batteria (OLED + contatore in RTC RAM)

La modalità Deep Sleep dell'ESP32 riduce il consumo di corrente a circa 10 µA spegnendo la CPU e la maggior parte dei dispositivi periferici ed è di fondamentale importanza per i dispositivi IoT alimentati a batteria. In questo progetto utilizziamo tre diverse fonti di risveglio: il timer (15 secondi), un pin esterno (EXT0 — pulsante GPIO 33) e il sensore tattile (T0/GPIO 4). Le variabili contrassegnate con `RTC_DATA_ATTR` vengono preservate durante la modalità Deep Sleep: il contatore di avvio,

4.3(10)
16
ESP32: ora reale da Internet tramite NTP
#128Avanzato
Premium

ESP32: ora reale da Internet tramite NTP

L'ESP32 si connette al Wi-Fi e recupera l'ora reale con precisione al millisecondo dai server NTP (Network Time Protocol). Grazie a `configTzTime()`, il fuso orario della Turchia (TRT, UTC+3) viene applicato automaticamente e il passaggio all'ora legale è gestito tramite la stringa POSIX TZ. L'ora viene mostrata sul Serial Monitor e su un display LCD I2C opzionale. `configTzTime()` avvia il servizio SNTP; vengono eseguite risincronizzazioni periodiche finché è disponibile l'accesso alla rete, e

4.5(13)
21
Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzato
Premium

Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)

Un sistema di allarme di sicurezza intelligente che attiva buzzer e LED quando il sensore PIR rileva movimento, inviando contemporaneamente una notifica istantanea al proprietario tramite Telegram. Dispone di un tempo di attesa di 30 secondi per limitare la frequenza degli allarmi ripetuti; questo meccanismo non verifica la validità dei rilevamenti del sensore PIR né elimina le false attivazioni. Adatto a sicurezza domestica, monitoraggio di garage, magazzini o studi. Con l'ESP32-CAM è possibile

0.0(0)
8
Orologio digitale con ESP32 e RTC DS1307 (I2C + LCD)
#120Intermedio
Premium

Orologio digitale con ESP32 e RTC DS1307 (I2C + LCD)

In questo progetto, utilizziamo il modulo orologio in tempo reale (RTC) DS1307 per visualizzare l'ora e la data su un display LCD 16x2 I2C. Il DS1307 è un RTC con batteria di supporto che mantiene l'ora anche se l'ESP32 si spegne. Entrambi i moduli condividono la stessa linea I2C (SDA/SCL), permettendoci di imparare a controllare più dispositivi utilizzando solo due cavi di segnale. Cosi imparerai il protocollo I2C e il funzionamento dei moduli RTC nella pratica.

4.6(26)
40