Update: 2021-06-08

Download Sketch

Achtung! EspCore Version 2.6.0 oder höher.

NtpTime.ino

// ****************************************************************
// Sketch Esp8266 WiFi NTP Kalenderzeit
// created: Jens Fleischer, 2020-02-22
// last mod: Jens Fleischer, 2021-06-08
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.6.0 - 3.0.0
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
  Copyright (c) 2020 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Automatische Umstellung zwischen Sommer- und Normalzeit.
// Inclusive Abfrage ob die Zeit vom NTP Server geholt werden konnte.
/**************************************************************************************/

#include <ESP8266WiFi.h>
#include <time.h>

struct tm tm;         // http://www.cplusplus.com/reference/ctime/tm/

const char* ssid = "Netzwerkname";              // << kann bis zu 32 Zeichen haben
const char* password = "PasswortvomNetzwerk";   // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
const uint32_t SYNC_INTERVAL = 24;              // NTP Sync Interval in Stunden

const char* const PROGMEM NTP_SERVER[] = {"fritz.box", "de.pool.ntp.org", "at.pool.ntp.org", "ch.pool.ntp.org", "ptbtime1.ptb.de", "europe.pool.ntp.org"};
const char* const PROGMEM DAY_NAMES[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
const char* const PROGMEM DAY_SHORT[] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
const char* const PROGMEM MONTH_NAMES[] = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
const char* const PROGMEM MONTH_SHORT[] = {"Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"};

extern "C" uint8_t sntp_getreachability(uint8_t);

bool getNtpServer(bool reply = false) {
  uint32_t timeout {millis()};
  configTime("CET-1CEST,M3.5.0/02,M10.5.0/03", NTP_SERVER[0], NTP_SERVER[1], NTP_SERVER[2]);   // Zeitzone einstellen https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
  do {
    delay(25);
    if (millis() - timeout >= 1e3) {
      Serial.printf("Warten auf NTP-Antwort %02ld sec\n", (millis() - timeout) / 1000);
      delay(975);
    }
    sntp_getreachability(0) ? reply = true : sntp_getreachability(1) ? reply = true : sntp_getreachability(2) ? reply = true : false;
  } while (millis() - timeout <= 16e3 && !reply);
  return reply;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\n\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nVerbunden mit: " + WiFi.SSID());
  Serial.println("IP Addresse: " + WiFi.localIP().toString());
  bool timeSync = getNtpServer();
  Serial.printf("NTP Synchronisation %s!\n", timeSync ? "erfolgreich" : "fehlgeschlagen");
}

void loop() {
  char buff[20];                                                   // je nach Format von "strftime" eventuell anpassen
  static time_t lastsec {0};
  time_t now = time(&now);
  localtime_r(&now, &tm);
  if (tm.tm_sec != lastsec) {
    lastsec = tm.tm_sec;
    strftime (buff, sizeof(buff), "%d.%m.%Y %T", &tm);             // http://www.cplusplus.com/reference/ctime/strftime/
    if (!(time(&now) % (SYNC_INTERVAL * 3600))) {
      getNtpServer(true);
    }
    // Verwendungsbeispiele
    Serial.printf("\nLokalzeit:  %s\n", buff);                     // Ausgabe der Kalenderzeit
    Serial.printf("Unix Zeitstempel: %lld\n", (int64_t)time(&now));// Ausgabe Unix Zeitstempel
    Serial.printf("UTC: %.2d:%.2d:%.2d\n", int(time(&now) % 86400L / 3600), int(time(&now) % 3600 / 60), int(time(&now) % 60));  // Ausgabe Koordinierte Weltzeit
    Serial.print("Stunde: "); Serial.println(tm.tm_hour);          // aktuelle Stunde
    Serial.print("Minute: "); Serial.println(tm.tm_min);           // aktuelle Minute
    Serial.print("Sekunde: "); Serial.println(tm.tm_sec);          // aktuelle Sekunde
    Serial.print("Tag: "); Serial.println(tm.tm_mday);             // Tag als Zahl
    Serial.print("Monat: "); Serial.println(tm.tm_mon + 1);        // Monat als Zahl
    Serial.print("Jahr: "); Serial.println(tm.tm_year + 1900);     // Jahr als Zahl
    strftime (buff, sizeof(buff), "Wochentag: %u\n", &tm);         // http://www.cplusplus.com/reference/ctime/strftime/
    Serial.print(buff);                                            // Tag der Woche
    Serial.print("Tag des Jahr: "); Serial.println(tm.tm_yday + 1);// Tag des Jahres
    strftime (buff, sizeof(buff), "Kalenderwoche: %V\n", &tm);     // http://www.cplusplus.com/reference/ctime/strftime/
    Serial.print(buff);                                            // Kalenderwoche
    Serial.println(DAY_NAMES[tm.tm_wday]);                         // aktueller Wochentag
    Serial.println(MONTH_NAMES[tm.tm_mon]);                        // aktueller Monat
    Serial.println(DAY_SHORT[tm.tm_wday]);                         // aktueller Wochentag (Abk.)
    Serial.println(MONTH_SHORT[tm.tm_mon]);                        // aktueller Monat (Abk.)
    Serial.printf("Name der Zeitzone: %s\n", _tzname[0]);
    Serial.printf("Name der Sommerzeitzone: %s\n", _tzname[1]);
    Serial.println(tm.tm_isdst ? "Sommerzeit" : "Normalzeit");
  }
}
13 Kommentare - Kommentar eintragen
MOD1964 ✪ ✪ ✪ 05.12.2021
Hi Fips,

läuft auf anhieb. Echt super.
Kann nun eine Zeitschaltuhr programmieren, auch mit einem ESP-01.

Danke

LG

Antwort:
Danke für dein Feedback.

Gruß Fips
Klaus ✪ ✪ ✪ 06.10.2021
Bei der Eingabe von
Serial.println(esp8266.getCoreVersion());

meldet der Compiler:
'class SoftwareSerial' has no member named 'getCoreVersion'
Serial.println(esp8266.getCoreVersion());



Antwort:
Ja, ist klar.
Was soll der Compiler auch mit deiner Eigenkreation anfangen?
Im Boardverwalter der Arduino IDE kann man die installierte EspCoreVersion auch sehen.

Gruß Fips
Klaus ✪ ✪ ✪ 05.10.2021
Arduino 1.8.15 Hourly Build 2021/08/18
Ich habe ein Arduino Nano Board mit ESP8266

Antwort:
Welche EspCoreVersion nutzt du?
Serial.println(ESP.getCoreVersion());

Gruß Fips
Klaus ✪ ✪ ✪ 05.10.2021
Bei mir meldet der Compiler bei configTime einen Fehler, dass er die Funktion nicht kennt.
Wo ist diese definiert? Habe ich die falschen Dateien inkludiert?

Antwort:
In der "Arduino.h".
Welche EspCoreVersion nutzt du?

Gruß Fips
Ruud ✪ ✪ ✪ 19.07.2021
Hello Fips,

I have made a module (with your software) ESP01 for synchronizing a UNO DS3231 clock.
Works with a textstring by the serial input. Works nice. But..
I have seen that the timestring (i have made) walks further after removing the internet connection.
I have also tested on your (for me) basic software.
How is it possible? How many times synchronized it with the NTP time? Can i see if the time is REAL the NTP time.
In my software i reset the ESP is disappeared for a time.
Also when my internet false out, it connect with another wifi point. So that everything starts again. (and it FOR SURE good works)
Is there logic level where i can see, connection good, NTP time OK??
Thanks for your nice software.
Greeting Ruud from Netherland.


Antwort:

settimeofday_cb(time_is_set); // Rückruf installieren - wird aufgerufen, wenn Settimeofday aufgerufen wird.


Gruß Fips
Ruud ✪ ✪ ✪ 12.06.2021
Hello Fips,

With Version 3.00 it works fine with your code.

Serial.printf("UTC: %.2lld:%.2lld:%.2lld\n", time(&now) % 86400L / 3600, time(&now) % 3600 / 60, time(&now) % 60); // Ausgabe Koordinierte Weltzeit

The software works very good, but how you make it, i dont understand a lot of it. But i am very glad with it.
I use it to set a multifunction clock with 4 max7119 displays.
Thanks for the fantastic SW.

Antwort:
Thanks for feedback.

Gruß Fips
Ruud ✪ ✪ ✪ 08.06.2021
Very usefull, i am testing it.

Serial.printf("UTC: %.2ld:%.2ld:%.2ld\n", time(&now) % 86400L / 3600, time(&now) % 3600 / 60, time(&now) % 60); // Ausgabe Koordinierte Weltzeit

It looks like there is an error in this. The minutes stays always on 0 (zero).
Please can you look at it.

Antwort:
Esp8266 Arduino Core 2.6.0 - 2.7.4
time_t is long int
Serial.printf("UTC: %.2ld:%.2ld:%.2ld\n",

Esp8266 Arduino Core 3.0.0
time_t is long long int
Serial.printf("UTC: %.2lld:%.2lld:%.2lld\n",

Gruß Fips
Johannes ✪ ✪ ✪ 18.02.2021
Danke für deine Mühen. Genau das was ich für meinen Kalender gesucht habe. Weiter so.
VG Johannes

Antwort:
Danke für dein Feedback!

Gruß Fips
AndreasK ✪ ✪ ✪ 29.01.2021
Servus auch von mir!

Sehr vielen Dank für das Programm, genau was ich gesucht hatte!

Bei mir war nur ein Problem, dass fritz.box als ntp server nicht funktioniert hatte, ich musste die IP manuell eintragen. Wollte das nur hinzufügen, sollte jemand das gleiche Problem haben.

Grüße,
Andreas

Antwort:
Sollte das nicht jede Fritz Box auflösen. Ist aber egal, wenns mit der IP klappt.

Gruß Fips
Uwe__K ✪ ✪ ✪ 04.11.2020
Hallo Fips,
deine Seite hat mir schon einige Hinweise gegeben, erst mal danke. Aber mit NtpTime.ino habe ich ein paar Probleme.
1. Was macht %2502ld in der Zeile Serial.printf("Warten auf NTP-Antwort %2502ld sec\n", (millis() - timeout) / 1000); ?
Bei mir schiebt es die Sekunden ziemlich weit nach rechts...

2. Wenn ich einen "falschen" Timeserver eintrage (zum probieren) macht er beim Neustart erst mal
Warten auf NTP-Antwort 15 sec
NTP Synchronisation fehlgeschlagen!

Wenn dann durch SYNC_INTERVAL neu synchronisiert werden soll wird getNtpServer aufgerufen, aber "Warten auf...." kommt nicht mehr.

Was mache ich da falsch?

Gruß Uwe

Antwort:
Die "%25" stammt noch aus der Zeit als das Syntax highlighting der Webseite "%" falsch interpretiert hat.
Danke, für den Hinweis.

Es ist ein gewolltes Verhalten um den Sketch nicht durch "delay(975)" auszubremsen.

Gruß Fips
Kommentar eintragen

*