Trames NMEA : GxRMC et GxGGA#

Pourquoi#

Le PPS donne un top de seconde d’une précision autour de la microseconde, mais il ne dit pas quelle seconde vient de sonner (chapitre Constellations GNSS). Cette information (la date et l’heure du calendrier) arrive par le second flux du récepteur : les trames NMEA, lues par gpsd et transmises à chrony en mémoire partagée (chapitre Chrony). Un récepteur GNSS émet spontanément toute une famille de trames (GGA, GSA, GSV, VTG, GLL, ZDA…) ; ce projet n’en exploite volontairement que deux : GxRMC et GxGGA.

Ce choix n’est pas qu’une question d’économie de bande passante sur la liaison série. Il tient surtout à un principe de reproductibilité. Le NMEA 0183 est une norme publique et indépendante du constructeur, éditée à l’origine pour l’électronique marine : tout récepteur GNSS du marché la parle, du module u-blox à n’importe quelle puce SiRF ou MediaTek. À l’inverse, le protocole binaire UBX du récepteur utilisé ici (u-blox NEO-M9N) est plus riche mais propriétaire, lié à l’outillage d’un seul fabricant. En ne dépendant que de GxRMC et GxGGA, deux trames que tout récepteur standard sait produire, la méthode entière de ce guide se transpose telle quelle sur n’importe quel autre matériel, sans rien réécrire.

Comment#

Anatomie d’une trame NMEA#

Une trame NMEA 0183 est une simple ligne de texte ASCII :

$ GN RMC ,champ,champ,... *HH
│ │  │                    │
│ │  │                    └─ somme de contrôle (XOR de
│ │  │                       tout ce qui précède, en hexadécimal)
│ │  └──────────────────── type de trame (3 lettres : RMC, GGA...)
│ └─────────────────────── identifiant d'émetteur (2 lettres)
└───────────────────────── début de trame

L’identifiant d’émetteur (talker ID) est le “Gx” du titre : ces deux lettres désignent la constellation qui a fourni la solution.

Talker IDSource
GPGPS seul
GLGLONASS seul
GAGalileo seul
GBBeiDou seul
GNsolution combinée (plusieurs constellations à la fois)

Un récepteur multi-constellation comme celui de ce projet émet le plus souvent des trames GN (par exemple $GNRMC), puisqu’il calcule une solution unique à partir de plusieurs systèmes. C’est pourquoi on note GxRMC avec un x générique plutôt que GPRMC : figer GP dans une configuration passerait à côté des trames réellement émises.

GxRMC : la date, l’heure et la validité#

RMC signifie Recommended Minimum specific GNSS data, la trame minimale recommandée par la norme. C’est la seule trame courante qui porte la date du calendrier :

$GNRMC,182017.00,A,xxxx.xxxxx,N,xxxxx.xxxxx,E,0.002,,260726,,,A,V*hh
       │         │                                   │
       │         │                                   └─ date : 26/07/26 (JJMMAA)
       │         └─────────────────────────────────── statut : A = valide,
       │                                              V = invalide
       └───────────────────────────────────────────── heure UTC : 18:20:17

Les champs de position (latitude, longitude) et la somme de contrôle sont masqués (xxxx.xxxxx, *hh) : seuls comptent ici l’heure, la date et le statut. Les deux dernières lettres avant la somme de contrôle (A,V) sont l’indicateur de mode et le statut de navigation ajoutés par la norme NMEA 4.1, sans usage pour ce projet.

Deux champs sont décisifs pour un serveur de temps :

  • L’heure UTC + la date : c’est le couple complet qui lève l’ambiguïté de seconde du PPS. Le PPS dit “c’est maintenant, une transition de seconde exacte” ; GxRMC dit “et ce maintenant, c’est le 26 juillet 2026 à 18:20:17 UTC”.
  • Le statut A/V : A (Active) signale un point de navigation valide, V (Void) un récepteur sans fix exploitable. Ce champ est ce qui distingue “je reçois des trames” de “j’ai une heure fiable” : c’est lui qui fonde la directive lock GPS de chrony (chapitre Chrony), laquelle refuse de discipliner l’horloge tant que le statut n’est pas A.

GxGGA : la qualité du fix#

GGA signifie Global Positioning System Fix Data. Elle ne porte pas la date (seulement l’heure du jour), mais apporte les indicateurs de qualité que GxRMC n’a pas :

$GNGGA,182017.00,xxxx.xxxxx,N,xxxxx.xxxxx,E,1,12,0.87,xx.x,M,xx.x,M,,*hh
       │                                    │ │  │
       │                                    │ │  └─ HDOP : 0,87 (qualité géométrique)
       │                                    │ └── satellites utilisés : 12
       │                                    └──── qualité du fix : 1 = fix GPS
       └──────────────────────────────────── heure UTC : 18:20:17

Le nombre de satellites utilisés et le HDOP sont les métriques que l’on surveille pour juger de la santé de la réception (chapitre Vérification finale), et le champ qualité de fix distingue un point standard d’un point dégradé. gpsd s’appuie sur GxGGA pour renseigner le mode de fix et le compte de satellites qu’affiche cgps.

Ce que chaque trame apporte#

InformationGxRMCGxGGA
Heure UTC (du jour)ouioui
Date du calendrierouinon
Statut de validité A/Vouinon
Qualité du fixnonoui
Nombre de satellites utilisésnonoui
HDOP, altitudenonoui

La lecture du tableau donne la raison du couple : GxRMC fournit l’horodatage complet et le verrou de validité dont chrony a besoin, GxGGA fournit le diagnostic de réception. Aucune des deux ne suffit seule : un récepteur qui n’émettrait que GxGGA priverait gpsd de la date, et donc de tout horodatage UTC complet.

Réduire le récepteur à ces deux trames#

Émettre uniquement GxRMC et GxGGA allège la liaison série et supprime des trames inutiles au projet (les GSV, qui listent chaque satellite en vue, sont les plus verbeuses). La sélection des trames actives se fait côté récepteur ; gpsd, lui, se contente d’exploiter ce qui arrive et extrait l’heure de n’importe quelle trame standard datée. Le principe reste volontairement générique : sur un u-blox on ajuste les cadences par UBX-CFG-MSG, mais l’idée (“ne garder que la trame datée et la trame de qualité”) vaut pour tout récepteur, quel que soit son outil de configuration.

Erreurs à éviter#

  • Ne compter que sur GxGGA. Sans GxRMC (ni ZDA), aucune trame ne porte la date : gpsd ne peut pas reconstruire un horodatage UTC complet, et la lecture de seconde échoue silencieusement.
  • Figer le talker ID sur GP. Un récepteur multi-constellation émet des trames GN ; un filtre ou un test qui cherche littéralement $GPRMC ne verra jamais rien passer. Toujours raisonner en GxRMC.
  • Prendre l’heure NMEA pour une source de précision. La trame arrive par la liaison série avec une latence de l’ordre de ±10 ms, non déterministe (chapitre Matériel et câblage). Elle ne sert qu’à dire quelle seconde ; la précision vient du PPS. C’est exactement pour cela que la source correspondante est déclarée noselect côté chrony.
  • Ignorer la somme de contrôle. Une trame tronquée ou corrompue sur la liaison série a une somme de contrôle fausse ; un consommateur qui ne la vérifie pas peut lire une heure erronée. gpsd effectue cette vérification, mais tout parsing maison doit la refaire.

Vérifier#

# Flux NMEA brut : on doit voir défiler des trames RMC et GGA, une fois
# par seconde. Le talker ID (GN, GP...) dépend du récepteur.
gpspipe -r -n 20 | grep -E '(RMC|GGA)'

# Isoler le statut de validité de la trame RMC (3e colonne, virgule) : A attendu
gpspipe -r -n 20 | grep -m1 'RMC' | cut -d, -f3
# A = fix valide, V = pas de fix exploitable

# Nombre de satellites utilisés, lu dans la trame GGA (8e colonne, virgule)
gpspipe -r -n 20 | grep -m1 'GGA' | cut -d, -f8

Tant que le statut de GxRMC reste V, c’est que le récepteur n’a pas encore de fix exploitable (antenne masquée, ou cold start en cours) : chronyd ne disciplinera pas l’horloge, conformément à lock GPS.


📚 Pour aller plus loin

  • Le format des trames est défini par la norme NMEA 0183 (Standard for Interfacing Marine Electronic Devices), National Marine Electronics Association. La norme est payante, mais le sous-ensemble des trames GNSS courantes (RMC, GGA, GSA, GSV, ZDA) est abondamment documenté dans les manuels des récepteurs et la documentation de gpsd.
  • La liste exacte des trames reconnues par gpsd, champ par champ, est tenue à jour dans sa page de manuel gpsd_json et dans le fichier NMEA.txt du projet gpsd.
  • Chapitres liés : Constellations GNSS (comment le récepteur obtient l’heure), Acquisition GNSS/PPS (mise en place de gpsd), Chrony (consommation de la trame via refclock SHM).