Lecture octets (d'un module gps) et enregistrement/ NMEA et GPX

Bonjour à tous,

Je voudrais faire un tracker gps qui enregistre les données dans une carte micro sd.

/*
 * Rui Santos 
 * Complete Project Details https://randomnerdtutorials.com
 */
 
#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);

void setup(){
  Serial.begin(9600);
  ss.begin(9600);
  delay(60000);
}

void loop(){
  while (ss.available() > 0){
    // get the byte data from the GPS
    byte gpsData = ss.read();
    Serial.write(gpsData);
  }
}

Avec ce code je peux obtenir des données NMEA, ce qui est intéressant pour ensuite les convertir en tracé, en fichier gpx.

Mais je ne sais pas comment faire pou écrire les données NMEA dans la carte micro SD car je ne peux pas faire:

  • monFichier.write(gpsData)
  • monFichier.print(gpsData)

Je ne sais pas comment procéder pour arriver à enregistrer des données comme dans le moniteur série dans la carte SD.
J'imagine qu'il faudrait peut être enregistrer les octets un par un dans une variable puis ensuite écrire cette variable dans la carte sd.
Pouvez-vous m'aider à faire cela

J'ai besoin d'une mesure toute les 2-10s.

#include <SD.h>
#include <SPI.h>


File monFichier;

void setup(){
  Serial.begin(9600);
  Serial.println("Initialisation...");

  if(!SD.begin(7)){
    Serial.println("Initialisation échouée !");
    return;
  }
  Serial.println("Initialisation réussie !");

  monFichier = SD.open("test.txt", FILE_WRITE);

  if(monFichier){
    Serial.println("Ecris.");
    monFichier.println("Ligne");
    monFichier.close();
  }
  else{
    Serial.println("Erreur ouverture");
  }
  
}

void loop(){
  
}

Ma carte sd fonctionne bien avec ce code.

bonsoir
une bonne base ici avec la lib tinygps+

Bonjour,

Je préfèrerais pouvoir obtenir des données NMEA car c'est plus précis et peut-être plus facile à convertir.
Et j'aimerais bien comprendre comment enregistrer des lectures de données en octets car je pense que ça pourrait m'être utile dans d'autres projets.

Si je ne trouve pas de solution je regarderai celle ci.

Tu peux certainement concaténer les deux codes comme ceci :

#include <SoftwareSerial.h>
#include <SD.h>
#include <SPI.h>

File monFichier;

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);

void setup() {
  Serial.begin(9600);
  ss.begin(9600);
  Serial.println("Initialisation...");

  if (!SD.begin(7)) {
    Serial.println("Initialisation échouée !");
    return;
  }
  Serial.println("Initialisation réussie !");

  monFichier = SD.open("test.txt", FILE_WRITE);
  if (!monFichier) Serial.println("Erreur ouverture fichier");
  delay(60000);
}

void loop() {
  while (ss.available() > 0) {
    // get the byte data from the GPS
    byte gpsData = ss.read();
    Serial.write(gpsData);
    monFichier.write(gpsData);
  }
  monFichier.println();
  Serial.println();
  delay(5000);
}

Je n'ai jamais joué avec les modules GPS, donc je ne sais pas si ce genre de code va capter le début de la trame. @Artouste a raison : tu devrais tester la bibliothèque TinyGPS++, qui gère les trames NMEA.
http://arduiniana.org/libraries/tinygpsplus/

plus precis en quoi ?

La lib tinygps++ s'occupe de tout ce qui est verif et parsing des sentences NMEA

Dans ton cas tu aura donc tout ce travail à gérer , sauf à enregistrer tout ce qui arrive en raw sur ta carte sd sans te soucier de la validité/choix des sentences.

c'est rarement utile de vouloir absolument réinventer la roue :confounded:

Bonjour,

En effet cette librairie est pratique pour convertir les phrases NMEA en texte lisible.

Mais je n'ai pas compris comment faire pour obtenir des phrases NMEA brutes. Ce qui est ensuite plus facile pour les convertir en .gpx puisqu'elle est normée.

Mais comment procéder à ceci sans se limiter à l'afficher dans le moniteur ?

S'il est impossible d'obtenir des données NMEA brutes, comment faire pour obtenir des données convertissables au format GPX ?

Faut-il que j'ouvre un nouveau sujet ?

si tu veux faire un log RAW , il te suffit simplement d'ecrire sur ta carte sd dans un fichier
chaque octet reçu sur le port serie

while (Serial.available()) {
  fichier.write(Serial.read());
}

Bonjour leg2027

Si ce qui est affiché sur le moniteur te convient, pourquoi pas, à ce moment:

void loop(){
  while (ss.available() > 0){
    // get the byte data from the GPS
    byte gpsData = ss.read();
    Serial.write(gpsData);
  }

Créer une String nemaData (Variable globale), dans laquelle tu concatène les gpsData (nemaData += gpsData;) et quand tu reçoit un caractère de fin de ligne ou autre terminaison de ligne, tu enregistres nemaData sur ta carte SD par fichierSd.println(nemaData);; puis tu vides nemaData par nemaData="";

Je n'ai pas essayé "en vrai", mais je peux, dis-moi quel module GPS tu as?

A+
Cordialement
jpbbricole

Bonjour leg2027

Comme je ne connais pas grand chose en données GPS, voici ce que j'ai à la sortie de mon module NEO-6M

$GPRMC,115826.00,A,4628.11839,N,00650.20468,E,1.234,321.89,290921,,,A*62
$GPVTG,321.89,T,,M,1.234,N,2.287,K,A*37
$GPGGA,115826.00,4628.11839,N,00650.20468,E,1,04,5.02,564.8,M,47.2,M,,*59
$GPGSA,A,3,19,04,17,09,,,,,,,,,8.77,5.02,7.18*00
$GPGSV,2,1,06,01,23,147,,02,06,318,,04,82,109,34,09,53,221,44*7F
$GPGSV,2,2,06,17,27,231,36,19,34,257,30*75
$GPGLL,4628.11839,N,00650.20468,E,115826.00,A,A*61

C'est ça que tu veux enregistrer?

Cordialement
jpbbricole

Ca fonctionne pas très bien j'ai l'impression qu'il y a des erreurs dans la fin des phrases, c'est incomplet. De plus il n'y a que la phrase $GPRMC enregistrée

$GPRMC,160711.00,A,4922.70194,V4
$GPRMC,160712.00,A,4922.70200,N,1
$GPRMC,160713.00,A,4922.70204,42
$GPRMC,160714.00,A,4922.70201,N,20
$GPRMC,160715.00,A,4922.70207,VE
$GPRMC,160716.00,A,4922.70214,,7
$GPRMC,160717.00,A,4922.70223,,
$GPRMC,160718.00,A,4922.7022801
$GPRMC,160719.00,A,4922.70239,27
$GPRMC,160720.00,A,4922.70236,0,
$GPRMC,160721.00,A,4922.70239,A3
$GPRMC,160722.00,A,4922.70235,17
$GPRMC,160723.00,A,4922.70236,3

Exactement, je veux enregistrer ça sur la carte SD.

Je n'ai pas besoin des données $GPGSA et $GPGSV mais ce n'est pas grave si elles sont quand même enregistrées car ce sont des fichiers textes sur une carte SD de plusieurs GO.

Penses-tu que cette méthode fonctionne si la méthode de @Artouste ne fonctionne pas parfaitement.

Bonjour leg2027

Je n'en sait rien, je vais te faire un exemple sur carte SD, à toi de comparer.

Cordialement
jpbbricole

si tu enregistre tout en RAW et qu'il n'y a que du $GPRMC d'enregistrer sur ta carte sd c'est que ton module GPS ne sort QUE du $GPRMC (sentence NMEA minimale) .

C'est ton recepteur ?
poste le programme actuel que tu utilise.

Mon module sort toutes les phrases comme celui de @jpbbricole avec le code du message #1.
Au fait c'est un NEO-6M: https://www.ebay.fr/itm/263824374428?var=563174784907

J'ai testé comme ça:

#include <SD.h>
#include <SPI.h>

#include <SoftwareSerial.h>

SoftwareSerial ss(4, 3);

File monFichier;

void setup(){
  Serial.begin(9600);
  ss.begin(9600);
  Serial.println("Initialisation...");

  if(!SD.begin(7)){
    Serial.println("Initialisation échouée !");
    return;
  }
  Serial.println("Initialisation réussie !");

  monFichier = SD.open("test.txt", FILE_WRITE);


}
  


void loop(){
 
  while (Serial.available()) {
  monFichier.write(Serial.read());
}
  
}

là ton programme ne s'occupe pas du tout d'ecouter le GPS

essaye ave ce loop là

void loop(){
 
  while (ss.available()) {
  monFichier.write(ss.read());
}
  
}

Puis ce serait bien d’arrêter proprement en fermant le fichier, par appui sur un bouton par exemple, avant de couper le jus. Cela éviterait de pourrir la table d'allocation de la carte SD.

J'obtiens ça, pas mieux:

$GPRMC,16062$GPRMC,160710.00,A,4922.70189,N,00042.47001,E,0.114,,250921,,,A*P,$GPRMC,160711.00,A,4922.70194,V4$GPRMC,160712.00,A,4922.70200,N,1$GPRMC,160713.00,A,4922.70204,42$GPRMC,160714.00,A,4922.70201,N,20$GPRMC,160715.00,A,4922.70207,VE$GPRMC,160716.00,A,4922.70214,,7$GPRMC,160717.00,A,4922.70223,,
$GPRMC,160718.00,A,4922.7022801$GPRMC,160719.00,A,4922.70239,27$GPRMC,160720.00,A,4922.70236,0,$GPRMC,160721.00,A,4922.70239,A3$GPRMC,160722.00,A,4922.70235,17$GPRMC,160723.00,A,4922.70236,3
$GPRMC,160724.00,A,4922.70237,*G$GPRMC,160725.00,A,4922.70240,90$GPRMC,160726.00,A,4922.70238,,G$GPRMC,160727.00,A,4922.7023820$±,M,0.231,N,0.427,K,A*22
$GPGGA,ªÊr‚‚b¢Ê’’rº‚‚‚br±00042.47083,E,1,06,1.75,137.2,M,45$GPTXT,01,01,02,ANTSTATUS=OK*3B
$GPRMC,161803.00,V,,,,,,,250921$7$GPRMC,161804.00,V,,4$GPRMC,161,9$GPRMC,,Nÿ$GPX9,3,$GPTX$.,$GP4.$GP.4$GP
$GPR
$GP62$GPRMC,161815.00,A50$GPRMC,1682$GPRMC,,1$GPRM.,ÝÉ9b‚,F9$G6$GPRM$$GPRM0$GPR2$GPR7$GP,$GPR1$GP$G2,T0$P17$GPRMC,161831.7$GPRMC,161832.0,N$GPRMC,$GPR$GPTXT,01,01,02,ANTSTATUS=OK*3B
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,$GPRMC,,V,,,,,

J'avais pas trop envie de mettre des fils pour ça. Pensez-vous que ça puisse changer quelque chose (à part couper à n'importe quel endroit) ?

çà c'est typique d'un software serial qui ne tient pas la route, il perd des bytes en chemin.

Bonjour Artouste

J'utilises aussi SoftwareSerial pour ces essais, sans problème!

Cordialement
jpbbricole

Mmh, dommage.

Faut-il que je rouvre un sujet pour la librairie Tiny-gps ?