Programme avec librairie TinyGPS.h

Bonjour bonjour,
Je programme actuellement une Arduino UNO raccorder à un gps SIM28, et mon programme est le suivant :

#include <SoftwareSerial.h>

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(4, 3);

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);

  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

  ss.begin(4800);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();

  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i = flen; i < len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i = strlen(sz); i < len; ++i)
    sz[i] = ' ';
  if (len > 0)
    sz[len - 1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
            month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i = 0; i < len; ++i)
    Serial.print(i < slen ? str[i] : ' ');
  smartdelay(0);
}

C'es un programme que j'ai sélectionné sur Internet étant donné que je ne suis pas un expert en Arduino... Quelqu'un saurait-il me dire comment recevoir les valeurs réelles au lieu des astérisques ? Je vous mets ci-dessous ce que je retrouve dans le moniteur série :

Merci à ceux qui essaieront d'apporter des réponses ^^

Bonjour
Est u certain que TON module GNSS "crache" de la sentence NMEA à 4800 ?

4800 c'est une vitesse de moins en moins utilisée.

https://www.reichelt.com/fr/fr/arduino-grove-gps-sim28-grv-gps-p191289.html
essaie avec 9600

Vitesse de transmission (par défaut) : 9 600

Les astérisque s'affichent lorsque le programme ne reçoit pas de données du GPS.

  • Est-ce que l'antenne du GPS est à l'extérieur et pointe vers le ciel?
  • Est-ce que le shield indique qu'il a accroché des satellites?
  • As-tu essayé de faire afficher les données brutes reçues avant d'essayer de les interpréter?

Le module GPS m'a été fourni par le professeur lui-même, or je ne connaissait rien de lui. C'est aussi une de s raisons du pourquoi je suis venu pour vous demander comment devrai-je le programmer ? A une vitesse de 9600 bauds j'utilisé un autre programme, également trouver sur Internet mais sans pour autant le comprendre dans son intégralité... C'est pourquoi je m'adresse à vous afin de créer un programme à vos côtés si possible ^^

L'antenne du gps est simplement "emboîtée" sur le module, je vous enverrai une photo quand j'aurai à nouveau le module en face de moi (mardi). Le shield ne m'indique pas grand chose malheureusement, j'aimerai bien comprendre le programme que je vous ai mis précédemment dans son intégralité afin de pouvoir le manié plus facilement, mais ce n'est pas chose facile ^^'
J'aurai, comme vous l'avez dit, faire afficher les données brutes, et j'y arrive, or ce n'est pas avec le même programme et je ne vois pas comment combiner les deux ensemble... Je vous mettrai le programme en question mardi en début d'après-midi (14h30 environ).

J'imagine, mais je ne pense pas que les satellites traversent la pièce où tu travailles et le GPS à besoin d'avoir une vue dégagée et directe vers le ciel pour recevoir correctement les informations des satellites.

Voici le programme que j'utilise pour recevoir les trames GPS :

// link between the computer and the SoftSerial Shield
// at 9600 bps 8-N-1
// computer is connected to Hardware UART
// SoftSerial Shield is connected to the Software UART:D2&D3

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(2, 3);
String message = "";
unsigned char buffer[64];                                               // buffer array for data receveive over serial port
int count = 0;                                                          // counter for buffer array


void setup() {
  SoftSerial.begin(9600);                                               // the SoftSerial baud rate
  Serial.begin(9600);                                                   // the Serial port of Arduino baud rate

}

void loop() {
  if (SoftSerial.available())                                           // if date is coming from software serial port ==> data is coming from SoftSerial shield

  {
    while (SoftSerial.available())                                         // reading data into char array

    {

      buffer[count++] = SoftSerial.read();                                   // writing data into array

      if (count == 64)break;
    }
    Serial.write(buffer, count);                                           // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray();                                                    // call clearBufferArray function to clear the stored data from the array
    count = 0;                                                             // set counter of while loop to zero
  }
  if (Serial.available())                                                // if data is available on hardware serial port ==> data is coming from PC or notebook
    SoftSerial.write(Serial.read());                                       // write it to the SoftSerial shield

}



void clearBufferArray()                                                 // function to clear buffer array

{
  for (int i = 0; i < count; i++)
  {
    buffer[i] = NULL; // clear all index of array with command NULL
  }

}



Sauf que le problème, c'est pas le fait que je sois à l'intérieur d'un bâtiment, puisque voici ce que le programme écrit dans le moniteur série :

Le vrai problème est que ces lignes de code :

 print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

possèdent toutes un champs "GPS_INVALID_...". Je ne vois pas quoi mettre à la place de ces champs là pour pouvoir obtenir une valeur qui se trouve dans la trame... Ces lignes de code se trouve dans le premier programme que je vous ai envoyé. Devrai-je utiliser la fonction ?

f_get_position

Les lignes en question ne retournent aucune cordonnées. Donc les coordonnées que tu passes à la fonction print_float sont invalides et c'est ce qui s'affiche. C'est parfaitement normal.

Dans les trames $GPRMC de ta copie d'écran , la longitude et la latitude devrait se trouver dans les champs 3, 4, 5 et 6 de (voir l'image ci-dessous).
Au passage, le V dans le champs 2 indique justement un problème de réception.

Si tu n'es pas encore convaincu:

  • les trames $GPGSA de ta copie d'écran sont vides. Elles devraient contenir l'ID des satellites utilisés pour faire le fix.
  • les trames $GPGGA indiquent que le FIX n'est pas disponible et qu'il n'y a aucun satellite en vue (les 0,0 au milieu de la trame)

Dans ce message, tu trouveras le détail des trames NMEA0183

Et comment faire donc pour relever les différentes valeurs dans les champs que vous avez renseigné ci-dessus ? Auriez-vous une fonction spéciale à me présenter afin de récupérer le champs 1 et afficher celui-ci dans le moniteur série avec sa correspondance ?

Schéma voulu :

CHAMPS1 h
CHAMPS2 valide si CHAMPS2 = A, invalide si CHAMPS2 = V
CHAMPS3 valeur° valeur' valeur"
CHAMPS4 Nord si valeur = N Sud si valeur = S
ETC

C'est ce que tu fais dans ton programme, c'est le premier argument que tu passes à print_float().

  • gps.satellites() retourne le nombre de satellites
  • gps.f_get_position retourne la position

et ainsi de suite.
Mais il faut d'abord que le GPS reçoive quelque chose pour ça.

Alors question essentielle qui m'arrive dans la tête maintenant, que dois-je modifier dans mon programme afin de recevoir les trames. Vous m'aviez dit avant que les coordonnées que je passe à la fonction print_float() sont invalides, que dois-je donc modifier dans mon programme afin de récupérer des coordonnées valides ?

Merci encore de m'accorder votre temps, je ne suis vraiment qu'un débutant par rapport à Arduino, comparé à l'HTML, CSS et Js :sweat_smile: :sweat_smile:

Le problème n'est pas dans le code.
Le GPS ne reçoit aucun satellite donc il ne peut pas délivrer d'informations sur la position.
Il faut d'abord se placer dans des conditions correctes de réception pour que le GPS puisse faire son fixe. Comme expliqué plus haut:

  • antenne à l'extérieur
  • vue dégagé vers le ciel.

Je suis dans ces conditions là... Ce que je ne comprends pas c'est que dans le code certaines lignes comme expliqué plus haut ont une indication du type "TinyGPS: :GPS_INVALID_...

Il y a le mot invalide, donc pour moi, le code est simplement une démonstration et non pas un GPS fonctionnel, si ?

Le code est fonctionnel
Si tu regardes un peu le code que tu utilises tu verras que print_float() n'affiche les valeurs de val (le premier argument de la fonction) que si elles sont valides c'est-à-dire différentes de la valeur invalid (le second argument de la fonction)

En l'état, même si ton antenne est bien dehors et qu'elle pointe vers le ciel, le GPS te dit qu'il ne reçoit les informations d'aucun satellite.
Il est donc parfaitement inutile, voir même stérile, de t'acharner à modifier ton code puisqu'il n'a rien à afficher.
Il faut commencer par faire tourner le code le plus simple qui affiche les trames brutes dans la console. Et attendre de voir passer des trames $GPGGA qui indiquent que la réception est bonne.
Pour une première réception, il faut parfois laisser tourner le GPS pendant un temps assez long (plusieurs minutes consécutives) car il ne sait pas du tout où il se trouve.

Il faut bien évidemment s'assurer en amont que l'antenne est bien raccordée au GPS parce qu'il n'y aura pas de miracle sans antenne il ne se passera rien.... Il faut en particulier vérifier que le connecteur de l'antenne n'est pas abîmé ces petits connecteurs sont fragiles.

// link between the computer and the SoftSerial Shield
// at 9600 bps 8-N-1
// computer is connected to Hardware UART
// SoftSerial Shield is connected to the Software UART:D2&D3

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(2, 3);
String message = "";
unsigned char buffer[64];                                               // buffer array for data receveive over serial port
int count = 0;                                                          // counter for buffer array


void setup() {
  SoftSerial.begin(9600);                                               // the SoftSerial baud rate
  Serial.begin(9600);                                                   // the Serial port of Arduino baud rate

}

void loop() {
  if (SoftSerial.available())                                           // if date is coming from software serial port ==> data is coming from SoftSerial shield

  {
    while (SoftSerial.available())                                         // reading data into char array

    {

      buffer[count++] = SoftSerial.read();                                   // writing data into array

      if (count == 64)break;
    }
    Serial.write(buffer, count);                                           // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray();                                                    // call clearBufferArray function to clear the stored data from the array
    count = 0;                                                             // set counter of while loop to zero
  }
  if (Serial.available())                                                // if data is available on hardware serial port ==> data is coming from PC or notebook
    SoftSerial.write(Serial.read());                                       // write it to the SoftSerial shield

}



void clearBufferArray()                                                 // function to clear buffer array

{
  for (int i = 0; i < count; i++)
  {
    buffer[i] = NULL; // clear all index of array with command NULL
  }

}

Ce code me permet de récupérer les trames brutes, les unes à la suite des autres en ayant un retour à la ligne lorsqu'un nouveau type de trame est acquis :

Maintenant à partir de ce programme, ce qu'il serait bien d'arriver à faire, c'est de séparer les éléments reçus, à chaque virgule par exemple qui serait l'élément séparateur de la trame. Or je ne sais comment faire... J'ai déjà vu certains exemple d'utilisation de fonction avec des séparateurs mais beaucoup de questions me viennent à l'esprit... Par exemple, lorsque dans mon moniteur série, deux virgules se trouvent côte à côte, comment faire pour lui dire de ne pas chercher de valeur et passer à la suivante ? Une autre question aussi, puisque la trame qui m'intéresse est la trame GPRMC, comment faire pour "supprimer" les autres trames ?

Et par rapport à mon programme, quelle est l'instruction qui récupère les trames émises par les satellites ?

Bien le rebonjour :slight_smile:

Je reviens vers vous simplement pour vous dire que j'ai réussi à trouver une solution, qui n'était pas si compliquée que ça après une prise de recul :sweat_smile:

Je voulais tout de même vous remercier pour les conseils, les indications et une partie de votre temps que vous m'avez accordez, ça m'a fait vraiment plaisir !

Bonne soirée à vous,

Coco :grin:

Et la solution est .....

Ah oui excusez-moi ^^'

Donc la solution est la suivante :

#include <SoftwareSerial.h>
#include <TinyGPS.h>

SoftwareSerial SoftSerial(3, 4);
TinyGPS gps;
float longitude, latitude;

void setup() {
  SoftSerial.begin(9600);
  Serial.begin(9600);
}

void loop() {
  while (SoftSerial.available()){

    if(gps.encode(SoftSerial.read())) {

      gps.f_get_position (&longitude, &latitude);
      Serial.println ("Votre position est : ");
      Serial.println ("    ");
      Serial.println ("Longitude :");
      Serial.println (longitude, 5);
      Serial.println ("    ");
      Serial.println ("Latitude :");
      Serial.println (latitude, 5);
      //delay (1000);
    }
  }

}


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.