Uno EthernetTest : Time - Network Time Protocol (NTP)

Mise à l'heure depuis un serveur web NTP avec une carte Arduino-Ethernet (W5100)

Ce test Utilise les bibliothèques :

  • Ethernet.h
  • SPI.h

Tout fonctionne bien avec la carte Uno-Ethernet, cela va être utile de connaitre l'heure pour la gestion de la domotique, créer des scénario en fonction de la date, de l'heure, enregistrer des statistiques...

Fonctionne également avec le Mega2560+ w5100 dé-commenter les 2 lignes en rouge //

/* TimeNTP1.ino tests sur Arduino ETHERNET
   Example syncho de l'heure sur un serveur internet  NTP time source
   à partir du fichier exemple de IDE Arduino 1.0.5 */

#include <Time.h> // librairie pour la gestion des dates/heures
#include <Ethernet.h> // librairie pour la carte ethernet W5100
#include <EthernetUdp.h> // librairie pour la gestion UDP
#include <SPI.h> // librairie pour la communication avec la carte ethernet

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // mac de l'arduino, à modifier voir sur la carte ethernet
byte ip[] = { 192, 168, 1, 60}; // ip fixe de l'arduino à choisir

// NTP Servers : a choisir
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
const int timeZone = 2;     // Central European Time : CET = GMT +1  ou +2 en été
EthernetUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets

// ********************** debut du setup **************************
void setup()
{
  Serial.begin(9600); // moniteur serie : 9600 baud

  // pinMode(4,OUTPUT); // pour le Mega2560
  // digitalWrite(4, HIGH); // pour le Mega2560 déactive le lecteur SD
  // while (!Serial) ; // Needed for Leonardo only
  delay(250);
  Serial.println("TimeNTP Example");
  Ethernet.begin(mac, ip);    // demarage : Ethernet
  Udp.begin(localPort);  // demarage : UDP
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime); // lancement de la fonction
}

time_t prevDisplay = 0; // when the digital clock was displayed

// ********************** debut de la boucle **************************
void loop()           
{  
  if (timeStatus() != timeNotSet) {  //  != si differend de timeNotSet
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();  // fonction affichage de l'heurre
    }
  }
}

// ********************** fin de la boucle **************************

/* ********************** debut de la Fonction  affichage de l heure ********
*********************** format 13:07:04 6/8/2013 ************************** */
void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  Serial.print (":");
  printDigits(minute());
  Serial.print (":");
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print("/");
  Serial.print(month());
  Serial.print("/");
  Serial.print(year());
  Serial.println();
}
// sous fonction : utilité pour l'affichage de l'horloge numérique: imprime  le 0 si <10
void printDigits(int digits){
    if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void 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
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}