![]() |
Navigation : Trame NMEA
|
mars 2019 |
Une suite de caractère alphanumérique qui commence soit par un $ soit par un !.
Ce caractère est suivi par 5 autres caractères qui identifient la trame, son utilité, l'appareil qui a généré l'info.
Chaque ligne représente une phrase nmea, les informations sont séparées par une virgule.
La phrase est terminée par une checksum qui permet de valider la trame.
On va essayer de comprendre tout ça ci-dessous.
Commençons par une trame GPRMC, le C++ me permet de représenter la trame sous une forme horizontale un peu plus compréhensible.
GP RMC est l'une des trames NMEA des plus courantes, elle comprend de nombreuse informations...
Un simple tableau en C avec une définition de chaque champ permet de rendre les choses plus compréhensibles.
Cette trame peut regrouper : La date, l'heure, la latitude, la longitude, la vitesse fond, la variation magnétique !
Même chose pour une trame CGA. Plein d'infos... On remarque que dans le champ 8 on a la précision de la position et que dans le champ 9 on a l'altitude. Dans l'exemple les valeurs ne sont pas ajustée, car j'ai capturé la trame seulement quelques instants après avoir allumé le GPS, on voit qu'il n'a encore trouvé que très peu de satellite.
Même chose pour une trame GSV, on voit dans le champ 1 qu'il y a deux trames et dans le champ 2 que c'est la 1ere trame. On sait également qu'il y a 6 satellites en vue. (4 descriptions max par trame donc deux trames).
Voici donc la suivante. C'est la trame 2 de l'information GSV on y trouve la description des deux derniers satellites.
Cette méthode de construction d'un tableau par type de trame ne permettra pas d'être plus ambitieux
dans notre démarche d'analyse, j'ai donc établi une structure nmea qui se décompose comme ceci.
Dans une ligne de detail (struct ligne) (valeur entre deux virgules) nous mémorisons deux infos : le numéro de la ligne et le detail de la description.
Dans une trame (struct trame) nous avons jusqu'à 22 informations (de 0 à 21 pos dans tableau), nous mémorisons également le nb réel de ligne de description.
Puis nous definissons le nb de type de trame que nous allons documenter dans une struct nmea.
Dans un premier temps je limite le nombre de type de trame à 5 (dans les graphiques suivants seulement 3 sont présentées).
Une fonction permet d'initialiser les descriptions, une structure de constante aurait pu convenir, mais j'ai dans l'idée de pouvoir ultérieurement modifier une description en dynamique, en cas d'erreur ou d'évolution.
Deux petites fonctions sont associées à cette structure, l'une pour afficher toutes les lignes d'une description d'une trame et l'autre pour afficher seulement une ligne de description.
On peut maintenant afficher les definitions et décoder une trame comme montré dans main().
Voici ce que donne une exécution.
Pour les trois premières trames, il n'y a que la description de chaque champs qui est affichée.
On retrouve donc le contenu complet de notre structure C++.
Pour la dernière trame, on trouve tout d’abord le numéro du champ puis son contenu et enfin la description correspondante.
(Attention erreur d'affichage dans le titre (on voit la boulette dans le code sur l'image précédente.) sur la dernière trame (celle qui est analysée) :
c'est pas une GSV, c'est une RMC.)
On continue avec l'analyse de trames de type GSV. Dans cet exemple les trames sont mémorisées dans un fichier au format texte,
celui-ci est souligné dans le code C++. On voit également en 1 dans la trame qu'il y a 6 satellites donc comme une trame GSV ne peut décrire que 4 satellites, il faut deux trames.
Comme on peut le voir il y a pas mal de problème dans l'affichage, surtout sur le dernier champ, celui-ci est mélangé avec la checksum.
A ce stade du programme la validité de la trame n'est pas vérifiée par le programme.
Aprés pas mal de boulot sur le code C++, voici donc ma dernière version (avant prochaines évolutions)
qui permet un affichage des trames depuis soit un fichier de trame nmea au format texte, soit depuis une interface série/USB (adaptation de la norme RS422 nmea).
La trame est maintenant clairement représentée sans erreur sur les derniers champs.
La validité de la trame est vérifiée, la checksum est recalculée et comparée avec la valeur reçue (attention cependant,
j'ai lu quelque part que certain multiplexeur nmea modifiaient les trames et ne recalculaient pas forcément la checksum, c'est pourquoi
même si je n'y crois pas trop, si je détecte une erreur dans le calcul, j'affiche la trame et les deux valeurs ( la checksum trouvée et la chcksum calculée)).
On voit dans cet exemple que le GPS a trouvé 11 satellites ce qui permet une bien meilleure précision.
Me voilà donc capable de décoder une trame NMEA 0183, il me reste à enrichir ma bibliothèque de description de trame. Cette première étape m'ouvre la porte
pour de futurs développements, dans un premier temps je ne tenais pas à créer une interface graphique évoluée car mon idée est de porter ce dev vers des
systèmes à base ESP8266 (microprocesseur intégrant des possibilités de serveur/récepteur wifi) ou vers Arduino ou encore Raspberry (avantage du C++ le code passe partout
il suffit de réécrire les bibliothèques de communication). Je prévois également d'intégrer cette base dans une interface graphique afin de pouvoir simuler
les appareils de navigation. J'ai en projet de mettre à dispo sur le site les exécutables mais je ne sais pas trop encore comment procéder, les visiteurs
ayant toujours la peur de chopper un virus (et c'est bien normal).
NOUVEAU : Si vous le souhaitez, vous pouvez télécharger l'exécutable de cette application dans le dernier chapitre de cette analyse sur ce site...