Composants · 13 min de lecture

Module GPS NEO-6M avec Arduino : câblage, NMEA et TinyGPSPlus

Module GPS NEO-6M avec Arduino : câblage TX/RX, temps du premier fix, trames $GPGGA et $GPRMC, code TinyGPSPlus, ESP32 avec écran OLED et Pico en MicroPython.

Le module GPS NEO-6M est un récepteur GPS bon marché et très répandu qui ajoute à ton projet Arduino, ESP32 ou Raspberry Pi Pico la latitude, la longitude, la vitesse, l'altitude et l'heure UTC extrêmement précise fournie par les satellites. Pour l'utiliser avec un Arduino, quatre fils suffisent (VCC, GND, TX, RX) : une fois par seconde, le module envoie à 9600 bauds des lignes de texte appelées trames NMEA, et la bibliothèque TinyGPSPlus les transforme en nombres directement exploitables.

Dans ce guide, tu verras pas à pas comment fonctionne le module, comment le câbler sur un Arduino Uno, un ESP32 et un Pico, pourquoi le premier fix prend parfois plusieurs minutes, ce que signifie chaque champ des trames $GPGGA et $GPRMC, comment transformer la latitude et la longitude en lien Google Maps et comment afficher la position sur un écran OLED. À la fin, un tableau résume les causes et les solutions des deux problèmes les plus fréquents : "aucune donnée" et "pas de fix".

Module GPS NEO-6M (u-blox NEO-6M)
Module GPS NEO-6M : au centre le récepteur u-blox NEO-6M, en haut les broches de connexion, à gauche l'EEPROM qui garde la configuration et la LED PPS ; la pièce dorée à côté est un connecteur SMA pour une antenne externe.

Qu'est-ce que le module GPS NEO-6M et comment fonctionne-t-il ?

Le GPS (Global Positioning System) se compose de plus de 30 satellites qui tournent à environ 20 200 km d'altitude. Chaque satellite diffuse en permanence l'heure de son horloge atomique et ses propres données d'orbite. Le NEO-6M mesure l'écart entre l'instant où le signal a quitté le satellite et celui où il arrive, et en déduit sa distance à chaque satellite ; dès qu'il voit au moins 4 satellites, il calcule la latitude, la longitude, l'altitude et l'erreur de sa propre horloge. Avec seulement 3 satellites, il peut fournir une position en deux dimensions (2D), sans altitude. Les signaux arrivent au sol extrêmement faibles (environ -130 dBm) et le béton, les toits métalliques et même un feuillage dense les bloquent en grande partie. D'où la règle d'or du GPS : l'antenne doit voir le ciel.

CaractéristiqueValeur
Puce réceptriceu-blox NEO-6M (moteur de positionnement u-blox 6)
Canaux et signal50 canaux, GPS L1 C/A (1575,42 MHz), SBAS : EGNOS, WAAS, MSAS
Précision horizontale2,5 m CEP (2,0 m avec SBAS)
Précision vitesse et cap0,1 m/s et 0,5 degré
Temps du premier fix (TTFF)Démarrage à froid 27 s, tiède 27 s, à chaud 1 s
SensibilitéPoursuite -161 dBm, démarrage à froid -147 dBm
Fréquence de mise à jour1 Hz par défaut, jusqu'à 5 Hz
InterfaceUART, 9600 bauds 8N1 par défaut, NMEA 0183
AlimentationCarte : 3,3–5 V (avec régulateur) ; puce : 2,7–3,6 V
Consommation~47 mA en recherche, ~39 mA en poursuite
Température de fonctionnementDe -40 à +85 °C

La carte que tu achètes ne se limite pas à la puce NEO-6M de 16×12 mm. Les cartes GY-NEO6MV2 courantes ajoutent une antenne patch céramique de 25×25 mm, un régulateur qui permet d'alimenter le module en 3,3–5 V, une petite EEPROM qui garde la configuration, une pile de sauvegarde rechargeable qui conserve l'heure et les données des satellites, et une LED qui clignote une fois le fix obtenu. Certaines cartes, comme celle de la photo, ont aussi un connecteur SMA ou un petit u.FL pour une antenne externe et un port micro USB pour la brancher directement à l'ordinateur.

Câblage du NEO-6M : Arduino Uno, ESP32 et Raspberry Pi Pico

Le NEO-6M communique en UART, qui fonctionne comme le port série d'un ordinateur et utilise deux lignes de données. La règle est simple : les lignes se croisent. La broche TX (émission) du module va sur la broche RX (réception) de la carte, et la broche RX du module sur la broche TX de la carte. L'unique port série matériel de l'Arduino Uno (broches 0 et 1) sert au téléversement par USB et au moniteur série, on branche donc le GPS sur D4 et D3 avec SoftwareSerial. Tu trouveras les détails de la liaison série dans l'article Communication série UART.

Broche du NEO-6MArduino UnoESP32Raspberry Pi Pico
VCC5VVIN (5V) ou 3V3VBUS (5V) ou 3V3(OUT)
GNDGNDGNDGND
TXD4 (RX de SoftwareSerial)GPIO 16 (RX2)GP1 (RX de l'UART0)
RXD3, via un pont diviseur 1 kΩ / 2 kΩGPIO 17 (TX2)GP0 (TX de l'UART0)
PPS (si présente)Peut rester librePeut rester librePeut rester libre
Les entrées de la puce NEO-6M supportent au maximum 3,6 V. La broche TX de l'Arduino Uno sort du 5 V : ne relie donc pas D3 directement à la broche RX du module, ajoute un pont diviseur de tension (D3 → 1 kΩ → RX du GPS, RX du GPS → 2 kΩ → GND) ou utilise un convertisseur de niveaux logiques. Si tu veux seulement lire la position, tu peux laisser la broche RX du module débranchée ; elle ne sert qu'à envoyer des commandes de configuration. L'ESP32 et le Pico fonctionnent déjà en 3,3 V et n'ont pas besoin de pont diviseur.
Comme la carte possède son propre régulateur, alimente VCC en 5 V quand c'est possible ; certaines cartes sont instables en 3,3 V à cause de la chute de tension du régulateur. Pendant la recherche de satellites, le module consomme environ 47 mA ; pour un projet sur batterie, calcule l'autonomie à l'avance avec le calculateur d'autonomie de batterie.

Le premier fix : démarrage à froid, tiède et à chaud

Il est tout à fait normal qu'un module GPS ne donne pas de position dès sa toute première mise sous tension. Pour calculer une position, il lui faut les données d'orbite précises (éphémérides) des satellites visibles, et chaque satellite ne les diffuse qu'environ toutes les 30 secondes ; télécharger l'almanach complet, la liste d'orbites approximative de tous les satellites, prend 12,5 minutes. Selon ce qu'il a conservé avant d'être éteint, le module démarre de l'une des trois manières suivantes. Les temps de la fiche technique ont été mesurés en conditions de test avec un signal fort de tous les satellites ; avec la petite antenne céramique fournie, attendre quelques minutes est normal.

Type de démarrageDonnées gardées par le moduleFiche techniqueEn pratique (en extérieur)
Démarrage à froidNi heure, ni position, ni données satellites (première utilisation ou pile de sauvegarde vide)27 s1–5 minutes ; plus de 10 minutes avec un signal faible
Démarrage tièdeAlmanach, heure et position approximatives ; éphémérides périmées (éteint plus d'environ 4 heures)27 s30 secondes – 1 minute
Démarrage à chaudÉphémérides et heure à jour (éteint depuis peu, pile de sauvegarde chargée)1 sQuelques secondes
  • Sors à l'extérieur : En intérieur, surtout dans les bâtiments en béton, le module ne trouve souvent aucune position. Pour tester, utilise un balcon, un jardin ou au moins l'emplacement devant une fenêtre ouverte.
  • Oriente bien l'antenne : La face plate et claire de l'antenne céramique doit regarder le ciel ; la retourner ou la couvrir avec la main affaiblit beaucoup le signal.
  • Éloigne l'antenne de l'électronique : L'antenne Wi-Fi de l'ESP32, les régulateurs à découpage et les longs câbles USB émettent du bruit ; place l'antenne à quelques centimètres des cartes.
  • Sois patient et ne bouge pas le module : Ne coupe pas l'alimentation pendant le premier fix ; chaque redémarrage reprend la recherche à zéro.
  • Surveille la LED : La LED de la carte reste éteinte tant qu'il n'y a pas de fix, puis clignote une fois par seconde.
  • Recharge la pile de sauvegarde : Si elle est vide, chaque mise sous tension est un démarrage à froid. Laisser le module alimenté quelques heures la recharge, et les démarrages suivants ne prennent plus que quelques secondes.

Trames NMEA : comment lire $GPGGA et $GPRMC

Le NEO-6M envoie tout ce qu'il calcule sous forme de lignes de texte séparées par des virgules, selon la norme NMEA 0183. Avec la configuration d'usine, six types de trames arrivent chaque seconde : GGA, GLL, GSA, GSV, RMC et VTG ; les trames TXT n'apparaissent en général qu'à la mise sous tension et contiennent des messages d'information comme la version du firmware. Chaque trame commence par $ ; le préfixe GP indique que les données viennent du GPS et les trois lettres suivantes le type de trame. Les deux caractères après l'* en fin de ligne forment la somme de contrôle (checksum), obtenue par un XOR de tous les caractères entre $ et *, qui permet d'écarter les lignes corrompues. Les deux trames les plus importantes pour la position sont : $GPGGA,092750.00,4100.82500,N,02858.74000,E,1,08,1.01,39.2,M,36.9,M,,*67 et $GPRMC,092750.00,A,4100.82500,N,02858.74000,E,0.512,,281026,,,A*7E

Champ de $GPGGAExempleSignification
Heure (UTC)092750.0009:27:50 UTC (10:27:50 en France en hiver)
Latitude4100.82500,N41 degrés 00,825 minutes Nord
Longitude02858.74000,E28 degrés 58,74 minutes Est
Qualité du fix10 = pas de fix, 1 = GPS, 2 = différentiel (SBAS)
Satellites08Satellites utilisés pour la position
HDOP1.01Dilution horizontale de la précision ; en dessous de 2, c'est très bon
Altitude39.2,M39,2 m au-dessus du niveau moyen de la mer
Séparation du géoïde36.9,MÉcart entre le niveau de la mer et l'ellipsoïde WGS84
Champ de $GPRMCExempleSignification
Heure (UTC)092750.00Heures, minutes, secondes
ÉtatAA = position valide, V = pas de fix
Latitude / longitude4100.82500,N / 02858.74000,EMême format que dans GGA
Vitesse0.512En nœuds (0,512 × 1,852 ≈ 0,95 km/h)
Cap(vide)Direction du déplacement en degrés ; souvent vide à l'arrêt
Date281026Format jjmmaa : 28/10/2026
ModeAA = autonome, D = différentiel, N = pas de données

Dans les trames NMEA, la latitude et la longitude ne sont pas en degrés décimaux mais en degrés et minutes (ddmm.mmmm), alors que Google Maps et la plupart des logiciels attendent des degrés décimaux. Pour convertir, prends les deux premiers chiffres de la latitude (les trois premiers de la longitude) comme degrés, puis ajoute les minutes restantes divisées par 60 : 4100.82500 → 41 + 0,825 / 60 = 41,013750 ; 02858.74000 → 28 + 58,74 / 60 = 28,979000. Les valeurs Sud (S) et Ouest (W) s'écrivent en négatif. La sixième décimale correspond à environ 11 cm et la cinquième à 1,1 m ; avec une précision de 2,5 m pour le NEO-6M, six décimales suffisent largement.

Pas à pas : afficher les données GPS brutes avec un Arduino Uno

  1. Câble le NEO-6M comme dans le tableau : VCC → 5V, GND → GND, TX du GPS → D4, RX du GPS → D3 via le pont diviseur.
  2. Téléverse le code ci-dessous ; aucune bibliothèque supplémentaire n'est nécessaire, SoftwareSerial est fournie avec l'IDE Arduino.
  3. Ouvre le moniteur série et règle la vitesse sur 115200 bauds.
  4. Emmène le module dehors ou près d'une fenêtre et regarde défiler les lignes qui commencent par $GP.
  5. Quand le deuxième champ de la ligne $GPRMC passe de V à A et que la LED se met à clignoter, le module a trouvé sa position.
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}

Dans le moniteur série, un bloc de six à neuf lignes s'affiche chaque seconde (plus il y a de satellites visibles, plus la trame GSV est répartie sur plusieurs lignes). Si le module n'a encore trouvé aucun satellite, les lignes sont remplies de virgules vides, comme $GPRMC,,V,,,,,,,,,,N*53 et $GPGGA,,,,,,0,00,99.99,,,,,,*48 ; ce n'est pas une erreur, cela montre que le module fonctionne mais ne peut pas encore calculer de position. Les lignes $GPGSV indiquent le nombre de satellites visibles et la force du signal (dB-Hz) de chacun ; au-dessus de 30 dB-Hz, le signal est bon. Si aucune ligne n'arrive, vérifie le câblage ; si des caractères bizarres apparaissent, vérifie la vitesse en bauds.

Lire latitude, longitude, vitesse et heure avec TinyGPSPlus

Plutôt que de décoder les lignes NMEA à la main, il est bien plus pratique d'utiliser la bibliothèque TinyGPSPlus de Mikal Hart. Cherche "TinyGPSPlus" dans le gestionnaire de bibliothèques et installe-la ; les étapes sont expliquées dans l'article ajouter une bibliothèque Arduino. Attention : les exemples de la bibliothèque sont réglés sur 4800 bauds, alors que le NEO-6M utilise 9600 bauds. Si tu lances un exemple sans changer la vitesse, la position reste toujours INVALID, car la bibliothèque ne peut décoder aucune trame à partir de caractères corrompus. Le code ci-dessous affiche chaque seconde la position, la vitesse, l'altitude, le nombre de satellites, la date et l'heure, et transforme la position en lien Google Maps à ouvrir dans ton navigateur :

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}
FonctionCe qu'elle renvoie
gps.encode(c)Appelée avec chaque octet reçu ; renvoie true quand une trame valide est complète
gps.location.lat() / lng()Latitude et longitude en degrés décimaux
gps.location.isValid() / age()Position valide ou non / millisecondes depuis la dernière mise à jour
gps.speed.kmph()Vitesse sol en km/h (mps() et knots() existent aussi)
gps.course.deg()Cap en degrés (0 = nord, 90 = est)
gps.altitude.meters()Altitude au-dessus du niveau de la mer en mètres
gps.satellites.value()Nombre de satellites utilisés pour la position
gps.hdop.hdop()Dilution horizontale de la précision (plus petit = meilleur)
gps.date.day() / gps.time.hour()Champs de date et d'heure en UTC
TinyGPSPlus::distanceBetween(...)Distance entre deux coordonnées en mètres
gps.failedChecksum()Nombre de trames corrompues ; s'il augmente sans cesse, des données se perdent

La règle la plus importante de ce code est pas de delay() dans loop(). Le GPS envoie environ 500 octets par seconde, mais le tampon de réception de SoftwareSerial ne fait que 64 octets ; pendant un long delay(), il déborde, les trames sont tronquées et TinyGPSPlus les rejette pour erreur de checksum. C'est pourquoi on affiche une fois par seconde avec millis() ; tous les détails sont dans l'article millis() ou delay(). L'heure GPS est toujours en UTC : en France, ajoute 1 heure en hiver et 2 heures en été. Sur l'Arduino Uno, un double est en réalité un float de 32 bits, donc le dernier chiffre de la latitude et de la longitude est arrondi à environ un demi-mètre ; face aux 2,5 m de précision du module, c'est sans importance.

SoftwareSerial est fiable à 9600 bauds, mais bloque brièvement les interruptions pendant la réception. Si ton projet utilise aussi des bibliothèques sensibles au timing comme Servo, préfère sur l'Uno la bibliothèque AltSoftSerial (RX = D8, TX = D9) ou le port matériel Serial1 de l'Arduino Mega (RX1 = 19, TX1 = 18).

ESP32 avec Serial2 : afficher la position sur un écran OLED

Sur l'ESP32, pas besoin de SoftwareSerial : la puce possède trois UART matérielles et Serial2 peut être affecté aux broches de ton choix. Dans l'exemple ci-dessous, le GPS est relié à GPIO 16 (RX2) et GPIO 17 (TX2) ; comme l'ESP32 fonctionne en 3,3 V, aucun pont diviseur n'est nécessaire. La position, la vitesse et l'heure locale s'affichent sur un écran OLED SSD1306 de 0,96 pouce branché en I2C sur GPIO 21 (SDA) et GPIO 22 (SCL). En plus de TinyGPSPlus, le code utilise les bibliothèques Adafruit SSD1306 et 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 variable UTC_OFFSET convertit l'heure GPS en heure locale ; en France, elle vaut 1 en hiver et 2 en été. La fonction mapsLink() transforme la position en adresse Google Maps avec le paramètre query=latitude,longitude. Tu peux copier ce lien depuis le moniteur série et l'ouvrir dans un navigateur, l'envoyer sur ton téléphone avec un bot Telegram ou par SMS avec un module GSM SIM800L. Sur les cartes ESP32-WROVER avec PSRAM, les GPIO 16 et 17 servent à la mémoire : branche alors le GPS par exemple sur GPIO 26 et 27 ; sur l'ESP32-C3, qui n'a que deux UART, utilise Serial1 au lieu de Serial2.

Lire le GPS avec le Raspberry Pi Pico et MicroPython

Sur le Raspberry Pi Pico, on branche le GPS sur l'UART0 : le TX du module va sur GP1 et son RX sur GP0. En MicroPython, on peut décoder soi-même les lignes NMEA sans installer de bibliothèque, ce qui est aussi un excellent exercice pour comprendre la structure des trames. Le code vérifie la somme de contrôle de chaque ligne, récupère le nombre de satellites dans GGA et la position, la vitesse et l'heure dans RMC, puis convertit les degrés-minutes en degrés décimaux. Le réglage timeout=200 fait attendre readline() jusqu'à 200 ms la fin de la ligne ; si une demi-ligne passe quand même au démarrage, la vérification de la somme de contrôle l'écarte. Comme le type de trame est obtenu avec f[0][3:], le code reconnaît aussi les lignes $GNRMC et $GNGGA des modules qui utilisent plusieurs systèmes de satellites. Si tu ne sais pas encore lancer du code avec Thonny, jette d'abord un œil à l'article les bases 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))

Idées de projets avec le NEO-6M

  • Traceur qui envoie sa position par SMS : Avec un NEO-6M et un SIM800L, un traceur pour voiture ou vélo qui répond à un SMS "POSITION" par un lien Google Maps.
  • Enregistreur de données GPS : Enregistre ton trajet chaque seconde en CSV sur un module carte SD, puis affiche-le sur une carte depuis ton ordinateur.
  • Compteur de vitesse pour vélo : Affiche la vitesse actuelle, la vitesse maximale et la distance totale sur un écran OLED ; additionne la distance entre points successifs avec TinyGPSPlus::distanceBetween().
  • Horloge synchronisée par satellite : Récupère l'heure du GPS et règle à la seconde près un module horloge RTC, sans Internet.
  • Alarme de géorepérage (geofence) : Un système qui déclenche un buzzer ou envoie une notification quand quelque chose s'éloigne de plus de 100 mètres d'un point choisi.
  • Suivi longue portée : Envoie la position à un récepteur situé à plusieurs kilomètres avec un module LoRa et économise l'énergie sur batterie grâce au deep sleep de l'ESP32.

Aucune donnée ou pas de fix : erreurs fréquentes et solutions

SymptômeCause probableSolution
Moniteur série complètement videTX et RX inversés, pas de masse commune ou module non alimentéRelie le TX du GPS à la broche RX de la carte (D4 sur l'Uno), relie les masses, mesure VCC
"No GPS detected: check wiring."Même pas 10 caractères reçus par la bibliothèque en 5 secondesVérifie le câblage et les numéros de broches du code ; essaie d'inverser TX et RX
Caractères incompréhensiblesVitesse en bauds incorrecte9600 pour le GPS et la vitesse du code dans le moniteur série ; sinon essaie 4800 et 38400
Les lignes arrivent mais les champs sont vides (,V,)Le module fonctionne mais n'a pas trouvé de satellitesSors dehors, oriente l'antenne vers le ciel, attends 5 à 15 minutes
Le nombre de satellites reste entre 0 et 3Signal faible, antenne à l'envers, connecteur u.FL mal enfoncé ou source de bruit procheVérifie l'antenne, enfonce bien le connecteur, éloigne l'antenne de l'ESP32 et des régulateurs
Les données brutes ont une position, TinyGPSPlus affiche INVALIDLe delay() dans loop() fait déborder le tampon ; failedChecksum() augmenteSupprime delay(), utilise millis(), appelle encode() en continu
L'heure est décalée de quelques heuresL'heure GPS est en UTCAjoute le décalage de ton fuseau horaire (+1 en hiver, +2 en été en France)
À l'arrêt, la position dérive de quelques mètres et la vitesse n'est pas nulleBruit GPS normal et signaux réfléchis par les bâtimentsConsidère comme nulles les vitesses sous 2 km/h, ignore les mesures à HDOP élevé, fais une moyenne
Attend de nouveau plusieurs minutes à chaque démarragePile de sauvegarde vide ou absenteLaisse le module alimenté quelques heures pour recharger la pile
Pour savoir si le problème vient du module ou de ton code, branche le module directement à l'ordinateur avec un convertisseur USB-TTL et ouvre-le avec le logiciel gratuit u-center de u-blox. Il affiche la force du signal de chaque satellite, l'état du fix et la position sur une carte ; tu peux aussi y changer la vitesse en bauds et la fréquence de mise à jour (jusqu'à 5 Hz) et enregistrer ces réglages de façon permanente dans la mémoire du module.

Le NEO-6M apporte à tes projets, pour un coût très faible, la réponse à "où suis-je, à quelle vitesse je vais et quelle heure est-il" ; le secret est de montrer le ciel à l'antenne et de laisser au premier fix le temps nécessaire. Pour mieux comprendre la liaison série, jette un œil à l'article sur l'UART. Dans l'application BlueGrays, tu trouveras des projets utiles aussi pour tes montages GPS, comme la communication série entre deux Arduino, les écrans OLED, l'enregistrement de données sur microSD, le deep sleep de l'ESP32 et une alarme avec notifications Telegram, chacun avec schéma de câblage et code pas à pas.

Questions fréquentes

Le module GPS NEO-6M fonctionne-t-il en intérieur ?

En général, non. Les signaux des satellites arrivent très faibles et le béton ou les toits métalliques les bloquent presque entièrement. Devant une fenêtre ouverte, il peut capter quelques satellites, mais pour un fix fiable l'antenne doit voir directement le ciel ; si tu as besoin d'une position en intérieur, utilise une antenne active externe placée sur le toit ou à une fenêtre.

Combien de temps le NEO-6M met-il pour obtenir son premier fix ?

D'après la fiche technique, un démarrage à froid prend 27 secondes et un démarrage à chaud 1 seconde. En pratique, avec la petite antenne céramique en extérieur, le premier fix prend généralement 1 à 5 minutes, et jusqu'à 10 à 15 minutes lors de la première utilisation ou avec une pile de sauvegarde vide. Si le module a été éteint il y a peu, il se recale en quelques secondes.

Quelle est la précision du module GPS NEO-6M ?

Le fabricant annonce une précision horizontale de 2,5 m CEP sous ciel dégagé, ou 2,0 m avec la correction SBAS ; la moitié des mesures se trouvent donc à moins de 2,5 m du point réel. En ville, les signaux réfléchis par les bâtiments peuvent porter l'erreur à 5–10 mètres. L'altitude est moins précise que la position horizontale.

Le NEO-6M fonctionne-t-il en 5V et peut-on le brancher directement sur un Arduino ?

Les cartes GY-NEO6MV2 courantes ont un régulateur, donc VCC peut être alimenté en 5 V. En revanche, la broche RX de la puce supporte au maximum 3,6 V : abaisse le signal TX 5 V de l'Arduino Uno avec un pont diviseur de 1 kΩ et 2 kΩ. La sortie TX du module est en 3,3 V et l'Uno la lit sans problème.

Un module GPS a-t-il besoin d'Internet ou d'une carte SIM ?

Non. Le NEO-6M calcule sa position directement à partir des signaux des satellites, gratuitement et sans Internet. Internet ou une carte SIM ne servent que si tu veux envoyer la position ailleurs, par exemple via le Wi-Fi de l'ESP32 ou un module GSM comme le SIM800L.

Quelle est la différence entre le NEO-6M et le NEO-M8N ?

Le NEO-6M n'utilise que les satellites GPS. Le NEO-M8N, plus récent, peut utiliser en même temps que le GPS les satellites GLONASS, Galileo ou BeiDou ; comme il voit plus de satellites, il obtient en ville un fix plus rapide et plus stable. Ses trames commencent souvent par $GN, mais TinyGPSPlus lit les deux avec le même code.

Voir tous les projets
Communication unidirectionnelle entre 2 Arduino
#57Intermédiaire
Premium

Communication unidirectionnelle entre 2 Arduino

Un projet de transfert de données unidirectionnel entre deux Arduinos via une communication série. Il détecte la pression d'un bouton du côté de l'émetteur et apprend à contrôler la LED du côté du réc

4.4(37)
50
Communication bidirectionnelle entre 2 Arduino
#58Intermédiaire
Premium

Communication bidirectionnelle entre 2 Arduino

Un projet qui transfère des données bidirectionnelles entre deux Arduinos via une communication série. Les deux cartes lisent le bouton et envoient des données et reçoivent des données et contrôlent l

4.5(20)
26
Enregistreur de Température ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avancé
Premium

Enregistreur de Température ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Construis un enregistreur de température horodaté avec ESP32 ! Lis la température/humidité du DHT22 toutes les 10 secondes, obtiens l'heure réelle du DS1307 RTC et enregistre sur carte microSD au format CSV. L'OLED affiche en direct la température (grande police), le pourcentage d'humidité, l'horodatage et le compteur. Le fichier `/temp_log.csv` sur la carte SD s'ouvre dans Excel, Google Sheets ou Python pandas pour analyse — parfait pour surveillance de serre, suivi de température à domicile, c

4.7(7)
12
ESP32 HTTPClient + API météo (avec écran OLED SSD1306)
#134Avancé
Premium

ESP32 HTTPClient + API météo (avec écran OLED SSD1306)

Dans ce projet, nous effectuons un appel à l'API REST de la météo (wttr.in) via Internet à l'aide de l'ESP32 et de la bibliothèque `HTTPClient.h`. Contrairement à la version précédente avec écran LCD I2C, nous utilisons ici un écran OLED SSD1306 (128×64) — ce qui permet d’afficher une police de grande taille, des icônes vectorielles et une présentation visuelle riche sur un seul écran. Sept icônes vectorielles différentes représentant les conditions météorologiques (ensoleillé, partiellement nua

4.3(10)
18
Mode veille profonde de l'ESP32 — Économie de batterie (OLED + compteur RAM RTC)
#135Avancé
Premium

Mode veille profonde de l'ESP32 — Économie de batterie (OLED + compteur RAM RTC)

Le mode « Deep Sleep » de l'ESP32 réduit la consommation de courant à environ 10 µA en désactivant le processeur et la plupart des périphériques, ce qui revêt une importance cruciale pour les appareils IoT fonctionnant sur batterie. Dans ce projet, nous utilisons trois sources de réveil différentes : une minuterie (timer, 15 s), une broche externe (EXT0 — bouton GPIO 33) et un capteur tactile (T0/GPIO 4). Les variables marquées avec `RTC_DATA_ATTR` sont conservées pendant le mode Deep Sleep — le

4.3(10)
16
ESP32 : heure réelle depuis Internet via NTP
#128Avancé
Premium

ESP32 : heure réelle depuis Internet via NTP

L'ESP32 se connecte au Wi-Fi et récupère l'heure réelle avec une précision de la milliseconde depuis des serveurs NTP (Network Time Protocol). Grâce à `configTzTime()`, le fuseau horaire de la Turquie (TRT, UTC+3) est appliqué automatiquement et le passage DST est géré via la chaîne POSIX TZ. L'heure est affichée sur le moniteur série et sur un écran LCD I2C en option. `configTzTime()` démarre le service SNTP ; des resynchronisations périodiques ont lieu tant que l'accès au réseau est disponible

4.5(13)
21
Système d'Alarme de Mouvement ESP32 (PIR + Buzzer + LED + Telegram)
#145Avancé
Premium

Système d'Alarme de Mouvement ESP32 (PIR + Buzzer + LED + Telegram)

Un système d'alarme de sécurité intelligent qui active le buzzer et la LED lorsque le capteur PIR détecte un mouvement, tout en envoyant une notification instantanée au propriétaire via Telegram. Il intègre un délai d'attente de 30 secondes pour limiter la fréquence des alarmes répétées ; ce mécanisme ne vérifie pas la validité des détections du capteur PIR et n'élimine pas les faux déclenchements. Idéal pour la sécurité domestique, la surveillance de garage, d'entrepôts ou de bureaux. Avec l'ES

0.0(0)
8
Horloge numérique avec ESP32 et RTC DS1307 (I2C + LCD)
#120Intermédiaire
Premium

Horloge numérique avec ESP32 et RTC DS1307 (I2C + LCD)

Dans ce projet, nous affichons l'heure et la date sur un écran LCD 16x2 I2C à l'aide du module d'horloge en temps réel (RTC) DS1307. Le DS1307 est une RTC avec batterie de secours qui conserve l'heure même si l'ESP32 s'éteint. Les deux modules partagent la même ligne I2C (SDA/SCL), ce qui nous permet d'apprendre à contrôler plusieurs appareils avec seulement deux fils de signal. Vous decouvrirez ainsi le protocole I2C et le fonctionnement des modules RTC en pratique.

4.6(26)
40