Différence Heure GPS Heure UTC

Bonjour,

J'affiche l'heure reçue par un GPS NEO-6M et je constate que l'heure est en avance de 2 ou 3 secondes sur l'heure d'une horloge pilotée par DCF77 et de 3 ou 4 secondes sur le temps transmis par un seveur NTP
J'utilise la librairie TinyGPS++.

J'ai lu sur internet que la différence entre l'heure GPS et l'heure UTC est transmise dans les infos du GPS. Je suppose que TinyGPS++ la prend en compte car d'après Wikipedia elle est actuellement de 18 s. Je n'ai pas regardé le code de TinyGPS++.

Ce n'est pas que cette différence n’empêche de dormir, mais j'aimerai bien connaitre la raison de ces 2-3s d'avance.

Je mets mon programme, mais je ne pense vraiment pas que ça vienne de mon programme.

// affichage de la date/heure reçue d'un GPS
//
//
#include <SoftwareSerial.h>
#include "TinyGPS++.h"
#include <LiquidCrystal.h>
#include <RTClib.h>

//SoftwareSerial gpsSerial(2, 3, true); // RX, TX
SoftwareSerial gpsSerial(2, 3); // RX, TX
TinyGPSPlus gps;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

const unsigned long  offset = 3600; // offset heure française/heure UTC

const char* libJour[] = {"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};
enum EBtn {btnRIGHT, btnUP, btnDOWN, btnLEFT, btnSELECT, btnNONE};
enum EDisp {dispTime, dispFix, dispNb};

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2);              // start the library
  gpsSerial.begin(9600);
  lcd.setCursor(4, 0);
  lcd.print("Attente");
}

void loop() {
  static unsigned long milliFix = 0;
  static EBtn btnPrec = btnNONE;
  static byte dispPrec = dispNb;
  static byte disp = dispFix;

  static char sDate[20];
  static char sTime[20];

  bool timeChange = false;

  // traitement des boutons
  EBtn btn = read_LCD_buttons();
  if (btn != btnPrec)
  {
    btnPrec = btn;
    if (btn == btnDOWN)
    {
      if (++disp >= dispNb)
        disp = dispTime;
    }
  }

  // traitement du gps
  while (gpsSerial.available())
  {
    char c = gpsSerial.read();
    // Serial.write(c);
    if (gps.encode(c))
    {
      static byte secPrec = 0;
      if (gps.date.isValid() && gps.time.isValid())
      {
        if (gps.time.second() != secPrec)
        {
          if (milliFix == 0)
            milliFix = millis();
          secPrec = gps.time.second();
          DateTime now(gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second());
          now = now + offset;

          sprintf(sDate, "%s %d/%02d/%04d ", libJour[now.dayOfTheWeek()], now.day(), now.month(), now.year());
          sprintf(sTime, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());

          Serial.print(F("Date/Time: "));
          Serial.print(sDate);
          Serial.print(F("  "));
          Serial.println(sTime);
          //          Serial.println(gps.time.centisecond());
          timeChange = true;
        }
      }
      else
      {
        Serial.println(F("INVALID"));
        lcd.setCursor(0, 0);
        lcd.print("    INVALID     ");
      }
    }
  }

  // traitement affichage
  if (disp != dispPrec)
  {
    dispPrec = disp;
    lcd.clear();
  }
  switch (disp)
  {
    case dispTime:
      if (timeChange)
      {
        // affichage sur le lcd
        lcd.setCursor(1, 0);
        lcd.print(sDate);
        lcd.setCursor(4, 1);
        lcd.print(sTime);
      }
      break;

    case dispFix:
      // affichage du temps pour le fix
      {
        unsigned long t = milliFix != 0 ? milliFix : millis();
        t /= 1000;
        char buf[20];
        sprintf(buf, "Fix: %u'%02u\"", (int)(t / 60), (int)(t % 60));
        lcd.setCursor(0, 0);
        lcd.print(buf);
      }
      break;
  }
}

// read the buttons
EBtn read_LCD_buttons()
{
  int adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  // For V1.1 us this threshold
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 650)  return btnLEFT;
  if (adc_key_in < 850)  return btnSELECT;

  return btnNONE;  // when all others fail, return this...
}

kamill:
J'ai lu sur internet que la différence entre l'heure GPS et l'heure UTC est transmise dans les infos du GPS. Je suppose que TinyGPS++ la prend en compte car d'après Wikipedia elle est actuellement de 18 s. Je n'ai pas regardé le code de TinyGPS++.

Oui la correction est disponible sous forme d'une trame d'info mais pas transférée dans une phrase NMEA, donc pas géré par tinyGPS++ mais un cran en dessous.

Généralement les systèmes vendus ont un nombre de secondes d'erreurs (leap second) stocké en EEPROM et la mise à jour du delta s'effectue toutes les 12 minutes environ et ça peut-être mémorisé ou pas suivant les modules. donc normalement au bout d'un quart d'heure vous devriez avoir une info plus précise.

sur votre module GPS NEO-6M si vous vous balancez une commande propriétaire UBX,04 (attention Tx ne supporte que 3.3V même sur les modules vendus pour être alimentés en 5V) et envoyant sur le port série du GPS un [color=purple]$PUBX,04*37<CR><LF>[/color] alors vous devriez voir une phrase réponse du genre

$PUBX,04,hhmmss.ss,ddmmyy,UTC_TOW,UTC_WNO,[color=red]LEAP_SEC[/color],Clk_B,Clk_D,PG,*cs<CR><LF>

le champ LEAP_SEC est ce qui vous intéresse et la doc dit que

Before Firmware 7.01: reserved.

Firmware 7.01 and above: Leap seconds, The number is marked with a ‘D’ if the value is the firmware default value (15 for FW 7.00).

If the value is not marked it has been received from a satellite.

si vous avez un vieux firmware, c'est pas pris en compte

si vous voyez un D après le nombre, c'est que c'est la valeur par défaut et elle date = 15 secondes

--> dans les 2 cas ça expliquerait vos 3 ou 4 secondes d'écart (suivant le moment de lecture)

S'il n'y a pas de D alors la réception de la trame a été correctement traitée et vous devriez voir l'heure correcte.

Merci pour cette réponse. Effectivement ça explique les 3 secondes d'écart.

J'ai essayé de lui envoyer la commande $PUBX,04*37 et il ne répond rien (à part les trames NMEA). Mais j'avais connecté son RX sur une sortie5V, ça l'a peut être détruit.