Giorno mese anno su NTPClient e ethernet shield

Salve a tutti, sto usando Arduino UNO, la ethernet shield e lo sketch ufficiale per avere l'orario esatto ed utilizzarlo. Il problema è che mi servirebbe anche giorno mese e anno ed è davvero un rompicapo.

Di seguito il codice che non è altro che quello ufficiale:

/*
 Udp NTP Client

 Get the time from a Network Time Protocol (NTP) time server
 Demonstrates use of UDP sendPacket and ReceivePacket
 For more on NTP time servers and the messages needed to communicate with them,
 see https://en.wikipedia.org/wiki/Network_Time_Protocol

 created 4 Sep 2010
 by Michael Margolis
 modified 9 Apr 2012
 by Tom Igoe
 modified 02 Sept 2015
 by Arturo Guadalupi

 This code is in the public domain.

 */

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

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

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

const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

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;

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  //Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH Shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit FeatherWing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit FeatherWing Ethernet

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
    // no point in carrying on, so do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
  Udp.begin(localPort);
}

void loop() {
  sendNTPpacket(timeServer); // send an NTP packet to a time server

  // wait to see if a reply is available
  delay(1000);
  if (Udp.parsePacket()) {
    // 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, extract 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.print("Seconds since Jan 1 1900 = ");
    Serial.println(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.println(epoch);


    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');
    if (((epoch % 3600) / 60) < 10) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':');
    if ((epoch % 60) < 10) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch % 60); // print the second
  }
  // wait ten seconds before asking for the time again
  delay(10000);
  Ethernet.maintain();
}

// send an NTP request to the time server at the given address
void sendNTPpacket(const char * 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();
}

Funziona tutto ma mi manca la data con giorno mese è anno.
Non riesco a trovare la documentazione (se esiste) relativa a questo sketch.
Grazie Alberto

Prova a guardare qui

Oppure qui

Ho visto questi sketch ma sono per esp32.

Io ho la ethernet shield classica.

Contento tu contenti tutti

Vero, ma ... uno "Unix time" come quello che viene usato negli esempi per ESP è lo stesso che recupera il tuo programma ovvero è un numero intero, non segnato a 32 bit che indica il numero di secondi passati dal 1 Gennaio 1970, sapendo il quale, usando le varie librerie, si ricava tutto quello che a te occorre.

Quindi, se ti studi come fanno su ESP, puoi sicuramente fare una cosa simile su Arduino UNO.

Guglielmo

1 Like

Ok grazie Guglielmo, ci provo.

Alberto

Per prima cosa ti consiglio di usare la libreria "NTPClient". Come ti ha suggerito Guglielmo, devi ottenere un "epoch time" e se leggi nel README della libreria, in fondo trovi il riferimento alla funzione getEpochTime(). Quindi una volta ottenuto l'"epoch time" puoi ottenere la data chiamando la funzione gmtime() che restituisce una struct tm.
Esempio:

    struct tm *ptm = gmtime ((time_t *)&epochTime);
    // Giorno = (int)ptm->tm_mday;  
    // Mese = (int)ptm->tm_mon+1;  
    // Anno = (int)ptm->tm_year-100+2000;

Altrimenti devi comunque tu calcolare la data partendo da "epochTime" che se non ricordo male è un valore unsigned long che rappresenta l'offset dal 1 Gennaio 1970.

Prova a scrivere un tuo codice di test che alla partenza mostri la data corrente (dopo ovviamente aveer aggiornato il "timeClient") e facci sapere se ti funziona.

docdoc la libreria alla quale ti riferisci è la prima che ho provato purtroppo però è legata ai moduli ESP8266 o ESP32 che io non ho mai usato e comunque in questo caso sono vincolato alla ethernet shield.

Alberto.

Problema risolto e come sempre era dentro l'IDE.

Ho usato la TimeLib e lo sketch TimeNTP.

All'interno c'è tutto. Bisogna aver cura di modificare l'IP del server NTP. Io ho usato questo:
(132, 163, 96, 6); //time-e-b.nist.gov

Alberto

Guarda la time.h che fa parte di AVRlibc (... libreria che è sempre disponibile in Arduino AVR) ... trovi tutto quello che serve.

Guglielmo

P.S.: Ok, hai scritto di aver risolto mentre io scrivevo questo :grin: :grin: :grin:

Grazie Guglielmo, ho dato un'occhiata veloce e domani darò un'occhiata più approfondita.

Alberto

Hai ragione, davo per scontato che bastasse l'UDP, invece serve un ESP o WiFi shield o una MKR1000.

Comunque per la Ethernet shield hai provato a vedere anche QUI? Una volta che ottieni l'epoch, puoi calcolare la data con il metodo che ti avevo indicato.

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