Arduino arduino_goodfields_64.jpg24 récupérer l'heure sur internet : NTP
 
Sommaire

24  récupérer l 24 récupérer l'heure sur internet : NTP Adresses  IP Adresses IP protocole  NTP protocole NTP
Programme Programme
La page principale ... La page principale ...
   
Vers le début Vers Page 2 Vers sommaire 24 récupérer l'heure sur internet : NTP
cliquez pour agrandir : photo/ArduinoEthernetFront.jpg Arduino Ethernet
Sur internet, on peut récupérer l'heure sur des machines dites 'serveurs NTP'. NTP est un protocole qui permet de synchroniser l'heure entre ma machine et des horloges atomiques très précises. Des serveurs 'secondaires' sont à disposition de tous pour synchroniser tout type d'horloge, celles des ordinateurs (y compris le vôtre à la maison, les dernières versions de Windows l'intègrent automatiquement), mais aussi des horloges ou stations météo connectées.

Donc, on va partir sur notre ARDUINO Ethernet. Dans la plupart des maisons, on a maintenant une BOX reliée sur internet. La plupart des box comportent un switch ethernet à plusieurs prises, cela va nous permettre de connecter notre ARDUINO dessus.

   
Vers le début Vers Page 2 Vers sommaire Adresses IP
Le plus simple est d'utiliser le système DHCP qui permet à notre ARDUINO de demander une adresse IP valide au routeur, en l'occurence la BOX. Cette adresse va être attribué avec un bail de durée donnée, ce qui garanti une certaine 'stabilité' de cette adresse, mais ...

Dans certains cas d'utilisation d'Ethernet, on aura besoin que cette adresse soit fixe (pas pour notre NTP, mais plutôt pour un serveur Web). Deux solutions :
- fixer dans votre programme ADRDUINO votre adresse IP, mais il vous faudra aussi fixer le masque de réseau et la passerelle par défaut.
- dans le routeur, déclarer la MAC adresse de votre ARDUINO, et lui 'réserver' une adresse IP (c'est très bien, car cela est un gestion centralisée et déterministe), et là le routeur se chargera de donner à l'ARDUINO les paramètres supplémentaires.

CONCLUSION : Dans la pratique, et en particulier avec les interfaces ENC28J60, il s'avère plus économique au niveau de l'ARDUINO d'avoir une adresse fixe. Dans le concept 'GerDom', j'ai finalement opté pour cette solution, le 6° octet de la MAC adresse et le 4° octet de l'adresse IP dépendant du NUMERO de module. Voir chapitre(s) GER Domotique.

Pour plus d'infos : un cours sur TCP/IP et ses détails
   
Vers le début Vers Page 2 Vers sommaire protocole NTP
L'observatoire de MEUDON (près de Paris) est notre serveur NTP préféré. Vous trouverez sur le site suivant toutes explications sur ce site et les serveurs NTP installés :
http://syrte.obspm.fr/informatique/ntp_infos.php
ntp.obspm.fr (alias, IP: 145.238.203.10):

Les bibliothèques suivantes nous facilitent vraiment la tâche :
#include <Ethernet.h>
#include <EthernetUdp.h>

   
Vers le début Vers Page 2 Vers sommaire Programme
// récupération temps par NTP à l'observatoire de MEUDON

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Streaming.h>
#include <Time.h>

// Enter a MAC address, IP address and Portnumber for your Server below.
// The IP address will be dependent on your local network:
byte mac[] = {0x90,0xA2,0xDA,0x00,0xF0,0xDD} ; // Arduino Ethernet 'A' (shieldisé) 
//byte mac[] = {0x90,0xA2,0xDA,0x0D,0x62,0x46} ; // Arduino Ethernet 'B' 
// IPAddress monIP(192,168,42,101);    // réservée dans le DHCP FreeBox

// ne pas envoyer plus d'une requête toutes les 4 secondes, sinon on se fait blacklister !
 IPAddress timeServer(145, 238, 203, 10); // ntp.obspm.fr (alias, IP: 145.238.203.10):
// IPAddress timeServer(207,46,197,32); // time.windows.com 207.46.197.32 Microsoft, Redmond, Washington
// IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server

// local port to listen for UDP packets
unsigned int localPort = 8888;      // local port to listen for UDP packets

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

//**************************************************************************************
// Pin 9 has an LED connected on Arduino Ethernet :
//int lamp=9;
int lamp=12;
boolean cligno = false;

/*
   byte send_message_trame[23];
   int  send_message_length;
   int cs_temp;
*/


int grafcet_ntp = 1;
// forcage mise à l'heure GMT
int    gmt_decalage=-2;    // heure d'été
// int   gmt_decalage=-1;    // heure d'hiver

// variables à tout faire
int i;

//**************************************************************************************
void setup() 
{
 // Open serial communications
  Serial.begin(9600); Serial << "Starting ..." << endl;

// start Ethernet and UDP
//  Ethernet.begin(mac, monIP);    // fixed address
// DHCP

   if (Ethernet.begin(mac) == 0) {
    Serial << "Failed to configure Ethernet using DHCP"<< endl;
// no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
/**/
Udp.begin(localPort);
}

//**************************************************************************************
void loop()
{
int ok;
switch (grafcet_ntp) {
// Ne pas faire plus d'une requête toutes les 4 secondes, au risque de se faire blacklister !
// Dans la pratique, l'horloge ADRDUINO dérive de quelques secondes par jour, 
//          une synchro horaire est très suffisante, voire trop !
// On peut tenter d'ajuster l'horloge de l'arduino en mettant en paralèlle sur l'une des
//      2 capacités du quartz de 16 Mhz un condensateur ajustable de 20 à 40 pF
//      Si l'horloge va trop lentement enlver cette capacité et la remplacer par 
//      le condensateur ajustable.

  case 1:
    if ( minute() == 59 && second() == 55) grafcet_ntp++;
    if ( second()%15 == 10) grafcet_ntp++;    // pour test, toutes les 15 secondes
    break;
  
  case 2:
    sendNTPpacket(timeServer); // send an NTP packet to a time server
    grafcet_ntp++;
    break;
  
  case 3:
  // wait to see if a reply is available
  if ( Udp.parsePacket() ) {  
    grafcet_ntp++;

// print the ARDUINO hour, minute and second:
    Serial << day() << "/" << month() << "/" << i << " " << hour() << ":" << minute() << ":" << second() << " " ;

    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    Serial << " Time= " << secsSince1900 ;               

    // now convert NTP time into everyday time:
    Serial.print(" Unix_time= ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;     
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;  
    // print Unix time:
    Serial << epoch;                               


// UTC is the time at Greenwich Meridian (GMT)
    Serial << " UTC=" << (epoch  % 86400L) / 3600 << ':';  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial << '0';
    }
    Serial << (epoch  % 3600) / 60 << ':'; 
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial << epoch %60 << endl; // print the second

// mise à l'heure ARDUINO
    setTime(epoch-gmt_decalage*3600);

  }
  break;
  
  case 4:
    if (second()%15 == 0) grafcet_ntp = 1;
    break;
 } // end switch gracfet_ntp

}

//**************************************************************************************
//**************************************************************************************
// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress& address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:         
  Udp.beginPacket(address, 123); //NTP requests are to port 123
//  Serial << "envoi=" << Udp.write(packetBuffer,NTP_PACKET_SIZE) << endl;
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}
//**************************************************************************************

La page principale ... La page principale ...
Photos de la page :

Dernière mise à jour : 11:40:07 18/09/2020