GPS juste pour rester à l'heure : quelle librairie ?

Bonjour à tous

Voilà, vu le prix dérisoire des modules GPS qu’on trouve désormais chez les vendeurs asiatiques (4€ livré…) je me dis que plutôt que d’utiliser un ds3231 quasiment au même prix, mais qu’il faut mettre à l’heure, qui des fois la perd ou se décale suite à une fausse manip, etc, je vais désormais utiliser un module GPS pour obtenir l’heure.

Mais je n’ai jamais utilisé ça jusqu’à maintenant, et pour le moment je ne les ai pas encore reçus.

Du coup je commence à regarder ce qui existe comme librairies pour parser le NMEA et en extraire l’heure, mais il y en a beaucoup et je suis un peu perdu

Avez-vous une recommandation particulière à me proposer ?

Merci

TinyGPS++

lesept:
TinyGPS++

+1
simple facile d'utilisation

Sinon sans lib , tu peux juste parser la sentence minimale RMC

Salut

Suis passé par la même phase l’an dernier :slight_smile:
Je te propose mon dev perso en pièce jointe, bibliothèque + ino d’exemple

Me suis amusé à pondre une classe en pur c++, sans adhérence avec le monde arduino (donc portable) qui décode le flux GPRMC au fur et à mesure de la réception des caractères. Cela économise ainsi un buffer de stockage de la trame entière, pour la parser une fois intégralement reçue.

  • une classe driver qui implémente ce décodage en gérant les io propres à arduino.

Ca donne l’heure ET la position gps

Tu peux encore reduire le code si tu ne veux que l’heure

driverNEO6M.zip (3.48 KB)

gpsdriver.ino (2.39 KB)

+1 pour la tinyGps

Tiens j’ai retrouvé ça aussi, juste pour décoder la trame gprmc, je vois pas comment faire plus minimaliste

gps_decodage_gprmc.ino (1.63 KB)

Merci beaucoup à tous

Dès que je reçois le module je vais faire des essais.

A vue de nez, bricoleau ton système semble moins lourd que tinyGPS, non ? (j'ai pas encore essayé de compiler un truc)

Si c'est juste pour avoir l'heure, je pense que oui.

Et tu peux alléger encore en virant tout ce qui concerne la lecture de latitude et longitude dans decodeurGPRMC.h.

oui j'étais justement en train de le regarder

ne serait-il pas faisable sinon de regarder les trames GPZDA plutot que GPRMC ? Il y a seulement des infos de temps dedans. Par contre je pige pas bien d'où sort l'info "local zone" le satellite émet une info différente selon la zone qu'il survole ?

Effectivement gpzda semble plus appropriée, si elle est délivrée par le module.
J'ai pris gprmc car j'avais aussi besoin des coordonnées.

Pour la zone locale j'avais posé la même question au puits de science pepe mais il n'avait pas la réponse (!!)

A mon avis :
Non les satellites ne peuvent pas filer l'info car ils emettent un signal commun pour tous les récepteurs.
Il faudrait

  1. déterminer les coordonnées
  2. croiser avec une base de données géographique définissant les frontières et chargée dans le module
    Cela ne semble pas réaliste.

C'est peut-être juste une conf de décalage utc qu'il faut d'abord charger dans le module, et qu'il applique ensuite bêtement.

Il suffit d'accrocher un seul satellite pour avoir l'heure.
Ca se voit dans les trames au demarrage du module. L'heure apparaît d'abord, avant la localisation.
Je ne sais pas si tinyGPS délivre l'heure tout de suite ou attend d'avoir toutes les infos.

Dernier point : pour éviter d'avoir le module gps actif en permanence, j'ai préféré commander son alim via un transistor piloté par l'arduino. Avec un esp tu peux avoir une horloge de precision basée sur millis en recalant sur le gps seulement une fois par heure.

là je m'en fous d'alimenter le module tout le temps, c'est pour une régul de ventilation avec datalog sur carte SD des températures et humidité toutes les 5 minutes, j'ai besoin de l'heure pour horodater les mesures

et c'est avec un atmega328, donc il me faut l'horloge tout le temps

bricoleau:
Salut

Suis passé par la même phase l’an dernier :slight_smile:
Je te propose mon dev perso en pièce jointe, bibliothèque + ino d’exemple

Alors, je me suis basé sur ton truc pour décoder seulement la trame GPZDA
Ça donne donc les deux fichiers en PJ

Sauf que… ça ne marche pas. Plus exactement la vérification du checksum ne marche pas. Mais comme j’ai rien (mais alors RIEN) compris à ta manière de le faire, je me suis contenté d’adapter “au pif” ton code à la longueur de la trame GPZDA mais manifestement, j’ai loupé un truc (forcément, sinon c’était trop facile).

Du coup je voudrais bien quelques explications sur la manière de vérifier le checksum… en particulier je ne comprends pas :

        case 12 : //check code
        {
          switch (_ind2)
          {
            case 2 :
            {
              if (c != '*') _raz();
              break;
            }

pourquoi la vérification commence à l’index 2 et non pas 1 comme dans les autres cas de lecture de valeur ?

et ensuite (et surtout !) je ne pige pas la conversion entre le code calculé et sa division en deux parties pour comparer les deux caractères de celui de la trame.

pourquoi ne pas avoir converti ces deux caractères hexa en leur valeur décimale et juste comparer avec la valeur calculée à la fin après avoir lu les deux ?

et surtout pourquoi dans mon cas ça ne fonctionne pas ? parceque pourtant mis à part que le checksum est en 7e position au lieu de 12e dans le cas d’une trame GPZDA ça ne devrait pas différer du GPRMC ? (qui lui fonctionne très bien…)

merci

decodeurGPZDA.h (875 Bytes)

decodeurGPZDA.cpp (3.76 KB)

Hello

bricofoy:
...comme j'ai rien (mais alors RIEN) compris à ta manière de le faire, ...

hihi
Pourtant c'est juste une fonction qui manipule quelques variables, avec des if et des switch :smiling_imp:

Mais c'est vrai que comme je ne pensais pas publier ce bout de code que j'ai écrit pour m'amuser, il n'est pas pensé pour être facilement compréhensible par tout un chacun.

Ok je vais regarder ce soir
Est-ce que tu peux publier 2 ou 3 trames GPZDA, telles que reçues du module ?
En exécutant un petit programme qui Serial.print() tous les caractères reçus du module.

Cela m'évitera de fouiller dans ma boîte à grouilles pour refaire le montage.

bonjour

bon, désolé pour le "ce soir" j'ai pas eu le temps de répondre à temps

alors voila quelques trames :

$GPZDA,071308.00,17,01,2020,00,00*6C
$GPRMC,071309.00,V,,,,,,,170120,,,N*74
$GPZDA,071309.00,17,01,2020,00,00*6D
$GPRMC,071310.00,V,,,,,,,170120,,,N*7C
$GPZDA,071310.00,17,01,2020,00,00*65
$GPRMC,071311.00,V,,,,,,,170120,,,N*7D

$GPRMC,072030.00,A,4234.86458,N,00225.59691,E,0.111,,170120,,,A*73
$GPZDA,072030.00,17,01,2020,00,00*67
$GPRMC,072031.00,A,4234.86457,N,00225.59697,E,0.111,,170120,,,A*7B
$GPZDA,072031.00,17,01,2020,00,00*66

trames obtenues ainsi :

 if (gps.available()) {
    char c=gps.read();
    Serial.write(c);
    if(gpzda.traiterCar(c)) 
    {
      lcd.setCursor(0,1);
      lcd.print("         ");
      lcd.setCursor(0,1);
      lcd.print(gpzda.heureUTC());      
      lcd.print(":");
      lcd.print(gpzda.minuteUTC());
      lcd.print(":");
      lcd.print(gpzda.secondeUTC());
    }
  }

sauf que le second if n'est jamais validé. Si je le vire, j'ai bien des valeurs qui semblent correctes qui s'affichent (vite ! ) au fur à mesure du décodage, mais c'est la validation du checksum qui ne fonctionne pas

pourtant à force de le lire et le relire, j'ai fini par comprendre ton système, du moins il me semble.

déjà je suppose que la séparation en deux plutôt que de lire toute la valeur de la trame c'est pour éviter une variable globale de plus, j'ai bon ?

Ensuite il me semble aussi avoir compris la technique, le décalage de >>4 c'est pour virer l'unité (en hexa) et garder la "seizaine" pour faire la première comparaison, le+1c'est pour être sûr que la comparaison soit fausse si on n'a rien lu, j'ai toujours bon ?

En revanche pour la seconde partie, le & 15 je pige pas pourquoi ça vire la "seizaine" c'est équivalent à faire
uint8_t demi1 = _chk - (_chk >> 4); finalement ?

bref quoi qu'il en soit y'a par contre un truc que j'ai pas pigé c'est pourquoi démarrer la lecture à l'index 2 et non 1 comme dans les autres cas ?

merci

Salut

Le nombre 15 s’écrit 0b00001111 en binaire.
toto & 15 revient à effectuer un “et” binaire pour ne garder que les 4 bits de poids faible de la variable toto

  • toto & 15
  • toto % 16
  • toto - ((toto >> 4) << 4)
    donnent le même résultat :wink:

Laisse tomber le décodeur GPRMC. La trame GPZDA est vraiment basique, donc pas la peine de s’embêter à essayer d’adapter le code initial, qui utilise deux indices, avec quelques subtilités sournoises.

Je t’ai refait un truc spécifique pour GPZDA, beaucoup plus simple à comprendre, toujours selon le même principe de prioriser la performance et l’économie de RAM, au détriment d’un certain esthétisme de code.

Voir lib en pièce jointe, accompagnée du programme de test avec les exemples que tu as indiqués ci-dessus.
Suis un peu déçu, ça a compilé à la deuxième tentative et fonctionné du premier coup. Même pas drôle :grinning:

Enjoy

Test_GPZDA.ino (1.42 KB)

decodeurGPZDA.h (850 Bytes)

decodeurGPZDA.cpp (1.99 KB)

bricofoy:
alors voila quelques trames :

$GPRMC,072030.00,A,4234.86458,N,00225.59691,E,0.111,,170120,,,A*73

$GPZDA,072030.00,17,01,2020,00,0067
$GPRMC,072031.00,A,4234.86457,N,00225.59697,E,0.111,,170120,,,A
7B
$GPZDA,072031.00,17,01,2020,00,00*66

Heureux d'avoir aidé un catalan

Hihi

Wow, merci beaucoup ! Avec même un bug pour dans 10 ans exactement, manière que je m'ennuie pas :slight_smile:

Effectivement comme il n'y a que l'heure/date forcément toutes les infos apparaissent d'un coup et ça simplifie la lecture.

Ta manière d'organiser les lignes du switch est extrèmement rusée J'admire et même je me prosterne

Pour autant, je reste quand même un peu frustré de ne pas comprendre pourquoi ma modif de ta première version ne fonctionne pas, et aussi pourquoi pour lire le checksum tu démarrais à l'index 2 et non 1...

bricoleau:
Le nombre 15 s'écrit 0b00001111 en binaire.
toto & 15 revient à effectuer un "et" binaire pour ne garder que les 4 bits de poids faible de la variable toto

Pfff j'avais vraiment pas les yeux en face des trous, où les neurones en face des synapses, ou... bref.

Laisse tomber le décodeur GPRMC. La trame GPZDA est vraiment basique, donc pas la peine de s'embêter à essayer d'adapter le code initial, qui utilise deux indices, avec quelques subtilités sournoises.

Bah j'avais pigé (à part pour le checksum ??? )le coup des deux indices, remarquablement rusé là aussi, d'ailleurs.

bricofoy:
Avec même un bug pour dans 10 ans exactement, manière que je m'ennuie pas :slight_smile:

Bon, je me croyais malin mais plus je relis ton code et plus j'en doute... y'a un truc pas clair autour de la lecture de la date, mais pour ce soir j'abandonne.

bricoleau:
Heureux d'avoir aidé un catalan

Je suis surpris que gogole n'ait pas posé un repère sur ma baraque avec les coordonnées. Le village, c'est vaste :stuck_out_tongue:

Ben disons que dans le lien vers gogole j'ai mis une altitude "pudique" :slight_smile:

Le coin a l'air bien sympa.
Tu dois quand même manger un peu de neige en hiver, non ?

guère, c'est fini ça la neige. quand j'étais gamin on en avait une trentaine de cm tous les hivers, là ça doit bien faire 10 ans qu'il n'en tombe plus, ou du moins qu'elle fond dans la journée