NTP mit UNO / W5100 - (Variante)

Ich hab aktuell das Problem, das die Arduino UNO / W5100 Beispiele für NTP keine Ergebnis bringen.
Nicht funktionieren heißt: sie laufen in das 1500 millis timeout.

Probiert hab ich das Standard Ethernet Beispiel (mit DNS)
Ethernet Beispiel
https://www.arduino.cc/en/Tutorial/LibraryExamples/UdpNtpClient

und die Timelib - mit fixer lokaler IP:

name=Time
version=1.6.1
author=Michael Margolis

https://github.com/PaulStoffregen/Time/tree/master/examples/TimeNTP

jeweils verschiedene NTP pools bzw. IPs

Wie sicher bei den meisten von euch auch sind meine Arduinos hinter einem Router. Keiner meiner ESP's brauchte bisher für SNTP (UDP) ein besondere Firewallfreischaltung.

Trotzdem hab mich mal den Eingangsport (lt. Sketchbeispiele 8888) weitergeleitet auf meinen Arduino ... brachte aber auch nichts.

Wenn ich mit Wireshark ins LAN schaue, scheint es als käme wirklich kein UDP zum Arduino retour.

Wie ihr mir helfen könntet: Probiert doch bitte mal einen (oder beide ^^) Sketche aus und schreibt ob das bei euch klappt. Wenn wer einen abweichenden funktionierenden Sketch hat den er teilen will - gern (etwas mit sync auf eine time.h wäre mir am liebsten).

Der hat 2016 mit MEGA und Ethernetshield funktioniert:

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 192, 4 };  // vom Arduino
byte dnsIp[] = { 192, 168, 192, 1 };
byte gwIp[] = { 192, 168, 192, 1 };

// NTP Servers:
IPAddress timeServer(178,63,61,67); // 
//const int timeZone = 2;      // Central European Time Sommerzeit
const int timeZone = 1;     // Central European Time

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


boolean sleep = false;

unsigned long currentMillis;
unsigned long previousMillis = 0;
unsigned long interval=30*60UL*1000;
unsigned long interval_min;
int Start = 1;


void setup()
{
  Ethernet.begin(mac, ip, dnsIp, gwIp);
 
  Serial.begin(115200);
 
  while (!Serial) ; // Needed for Leonardo only
   
  interval_min=interval/60/1000;
  Serial.print ("Intervlall in Minuten :" );
  Serial.println (interval_min);
  Serial.println("TimeNTP Example");
  Serial.print("IP number is ");
  Serial.println(Ethernet.localIP());
  digitalClockDisplay();
  Udp.begin(localPort);
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
 
}

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


void loop()
{  
  if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();  
    }
  }
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  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();
}

Gruß Tommy

1 Like

nein, geht auch nicht.
Dafür funktioniert auf einmal der eigentlich unveränderte UdpNtpClient von oben.

Misteriös...

zugegeben nur zusammengepfuscht aber so klappts jetzt mit der TimeLib.h

Ich lass das mal für Google da.
NTP Abfrageintervall muss man halt vernünfigt setzen:

/*
  Udp NTP Client - new 
  
  - without delay in loop
  - uses TimeLib.h
  - sets time for TimeLib.h

*/

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <TimeLib.h>  // library manager Version 1.6.1

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(172, 18, 67, 96);
byte dns[] = { 8, 8, 8, 8 };
byte gateway[] = { 172, 18, 67, 230 };
byte subnet[] = {255, 255, 255, 0 };

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() {
  Serial.begin(115200);
  Serial.println(F("UdpNtpClient NEW"));
  // start Ethernet and UDP
  //Ethernet.begin(mac);  // DNS
  //Ethernet.begin(mac, ip, subnet, gateway);  // lange benutzt - geht warum auch immer
  //Ethernet.begin(mac, ip, dns, gateway);  // 
  Ethernet.begin(mac, ip, dns, gateway, subnet);
  //delay(1000); // angst delay ... geben wir dem W5100 etwas zeit.
  Udp.begin(localPort);
  Serial.println(F("End Setup"));
}

void loop() {
  timerClock();        // print the current time
  timerNtp();          // check if it is time to sync with NTP
  checkIncommingUdp(); // check if we received some UDP packet
  //Ethernet.maintain(); // only if IP optained by DHCP: renew lease time
}

void checkIncommingUdp()
{
  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

    // machma was draus für die timelib
    setTime(epoch);  // use the epoch, not the secSince1900
  }
}

void timerClock()
{
  static uint32_t previousMillis = -1000;
  if (millis() - previousMillis > 1000)
  {
    previousMillis = millis();
    Serial.print(hour());
    Serial.print(":");
    Serial.print(minute());
    Serial.print(":");
    Serial.print(second());
    Serial.print(" ");
    Serial.print(day());
    Serial.print(" ");
    Serial.print(month());
    Serial.print(" ");
    Serial.print(year());
    if (timeStatus() == timeNotSet) Serial.print(" not set"); else Serial.print(" set");
    Serial.println();
  }
}

void timerNtp()
{
  static uint32_t previousMillis = -30000;
  if (millis() - previousMillis > 30000)
  {
    previousMillis = millis();
    while (Udp.parsePacket() > 0) ; // discard any previously received packets  - aus dem time.h beispiel
    sendNTPpacket(timeServer); // send an NTP packet to a time server
  }
}

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