ARDUINO IDE ESP8266 NTP SERVER TIMEZONE
ARDUINO IDE ESP8266 NTP SERVER TIMEZONE
Heute zeige ich euch wie man mit dem ESP8266 die Zeit von einem Zeitserver mit automatischer Anpassung an Sommer und Winterzeit abholt und ausgibt.
Da wir das Rad hier und heute nicht neu erfinden werden, laden wir uns dazu zwei Bibliotheken aus dem Internet runter und binden Diese in die Arduino IDE ein.
Beide Links führen euch nach Github.
Dort einfach auf „Download ZIP“ klicken und beide Bibliotheken in die Arduino IDE einbinden.
Wer nicht genau weis wie man da vorgehen muss der kann sich hier schlau machen.
Das Programm erscheint recht lang, ist aber simpel.
Bevor Ihr das Programm auf euer ESP ladet gebt Ihr bitte noch in Zeile 13 und 14 eure SSID und das Passwort eures Routers ein.
Nach dem Upload, verbindet sich das ESP8266 mit eurem Router, holt die Zeit ab, stellt Sommer oder Winterzeit ein und gibt Diese dann Seriell aus.
Vergesst nicht die Baudrate in eurem Serial Monitor auf 76400 Baud zu stellen.
/* ESP8266 : NTP Time + Timezone Created 07 May 2016 by Ralf Bohnen - www.Arduinoclub.de This example code is in the public domain. */ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <WiFiUdp.h> #include <TimeLib.h> //by Paul Stoffregen, not included in the Arduino IDE !!! #include <Timezone.h> //by Jack Christensen, not included in the Arduino IDE !!! const char WiFiSSID[] = "deine SSID"; //### your Router SSID const char WiFiPSK[] = "dein Passwort"; //### your Router Password #define DBG_OUTPUT_PORT Serial unsigned long previousMillis = 0; const long interval = 1000; volatile bool wasConnected = false; bool isConnected(long timeOutSec) { timeOutSec = timeOutSec * 1000; int z = 0; while (WiFi.status() != WL_CONNECTED) { delay(200); DBG_OUTPUT_PORT.print("."); if (z == timeOutSec / 200) { return false; } z++; } return true; } //### NTP, TIME & TIMEZONE ################################################################### //UDP WiFiUDP Udp; unsigned int localPort = 123; //NTP Server char ntpServerName1[] = "ntp1.t-online.de"; char ntpServerName2[] = "time.nist.gov"; //Timezone //Central European Time (Frankfurt, Paris) TimeChangeRule CEST = { "CEST", Last, Sun, Mar, 2, 120 }; //Central European Summer Time TimeChangeRule CET = { "CET ", Last, Sun, Oct, 3, 60 }; //Central European Standard Time Timezone CE(CEST, CET); TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev time_t utc, local; 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 bool getNtpTime(char* ntpServerName) { DBG_OUTPUT_PORT.print(F("NTP request...")); if (timeStatus() == timeSet) { DBG_OUTPUT_PORT.println(F("not necessary")); return true; } IPAddress ntpServerIP; // NTP server's ip address while (Udp.parsePacket() > 0); // discard any previously received packets DBG_OUTPUT_PORT.println(F("Transmit NTP Request")); // get a random server from the pool WiFi.hostByName(ntpServerName, ntpServerIP); DBG_OUTPUT_PORT.print(ntpServerName); DBG_OUTPUT_PORT.print(": "); DBG_OUTPUT_PORT.println(ntpServerIP); sendNTPpacket(ntpServerIP); uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = Udp.parsePacket(); if (size >= NTP_PACKET_SIZE) { DBG_OUTPUT_PORT.println(F("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]; setTime(secsSince1900 - 2208988800UL); //setTime(23, 55, 0, 30, 3, 2016); //simulate time for test return true; } } DBG_OUTPUT_PORT.println(F("FATAL ERROR : No NTP Response.")); return false; // 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(); } //Function to return the compile date and time as a time_t value time_t compileTime(void) { #define FUDGE 25 //fudge factor to allow for compile time (seconds, YMMV) char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec"; char chMon[3], *m; int d, y; tmElements_t tm; time_t t; strncpy(chMon, compDate, 3); chMon[3] = '\0'; m = strstr(months, chMon); tm.Month = ((m - months) / 3 + 1); tm.Day = atoi(compDate + 4); tm.Year = atoi(compDate + 7) - 1970; tm.Hour = atoi(compTime); tm.Minute = atoi(compTime + 3); tm.Second = atoi(compTime + 6); t = makeTime(tm); return t + FUDGE; //add fudge factor to allow for compile time } void printTime(time_t t) { sPrintI00(hour(t)); sPrintDigits(minute(t)); sPrintDigits(second(t)); DBG_OUTPUT_PORT.print(' '); DBG_OUTPUT_PORT.print(dayShortStr(weekday(t))); DBG_OUTPUT_PORT.print(' '); sPrintI00(day(t)); DBG_OUTPUT_PORT.print(' '); DBG_OUTPUT_PORT.print(monthShortStr(month(t))); DBG_OUTPUT_PORT.print(' '); DBG_OUTPUT_PORT.print(year(t)); DBG_OUTPUT_PORT.println(' '); } //Print an integer in "00" format (with leading zero). //Input value assumed to be between 0 and 99. void sPrintI00(int val) { if (val < 10) DBG_OUTPUT_PORT.print('0'); DBG_OUTPUT_PORT.print(val, DEC); return; } //Print an integer in ":00" format (with leading zero). //Input value assumed to be between 0 and 99. void sPrintDigits(int val) { DBG_OUTPUT_PORT.print(':'); if (val < 10) DBG_OUTPUT_PORT.print('0'); DBG_OUTPUT_PORT.print(val, DEC); } //############################################################################################ void setup() { DBG_OUTPUT_PORT.begin(76400); DBG_OUTPUT_PORT.setDebugOutput(true); DBG_OUTPUT_PORT.println(F("ArduinoClub-NTP-Timezone")); WiFi.mode(WIFI_STA); WiFi.begin(WiFiSSID, WiFiPSK); if (isConnected(30)) { wasConnected = true; DBG_OUTPUT_PORT.println(F("Starting UDP")); Udp.begin(localPort); DBG_OUTPUT_PORT.print(F("Local port: ")); DBG_OUTPUT_PORT.println(Udp.localPort()); DBG_OUTPUT_PORT.println(F("waiting for sync")); } /* add setup code here */ } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; if (!isConnected(10) && wasConnected) { delay(200); ESP.restart(); } if (!getNtpTime(ntpServerName1)) { getNtpTime(ntpServerName2); } local = CE.toLocal(now(), &tcr); printTime(local); } /* add main program code here */ }
Alles wird gut.
Euer ArduinoClub Team
Es ist in D nicht zielführend den T-Online NTP Server zu nehmen. Gerade auch wenn man einen anderen Provider nutzt. Sinnvoller ist es Provider unabhängige NTP Server zu verwenden wie z.B. diese hier:
https://www.heise.de/ct/hotline/Oeffentliche-Zeitquellen-322978.html
Für CH und A sind es z.B. die Server ntp11.metas.ch und ntp12.metas.ch des Bundesamts für Metrologie.
Einen generellen Überblick der Zeitserver hat http://ntp.isc.org/bin/view/Servers
Greetings; I would love to use this code I have with your library but I am not sure how to put the two together; If you can help me, I thank you very much; Hugs from Brazil
/* UTFT Digital Clock
* http://arduino-project.net/chasy-na-arduino-tft01-22sp/
* https://www.youtube.com/watch?v=l2ZvO5DHExo
*/
#include <DS1307.h>
DS1307 rtc(A4, A5);
#include <UTFT.h>
extern uint8_t DotMatrix_M[];
extern uint8_t SevenSeg_XXXL_Num[];
UTFT myGLCD(TFT01_22SP,9,8,12,11,10);
void setup( )
{
rtc.halt(false);
myGLCD.InitLCD();
myGLCD.fillScr(0, 0, 0);
}
void loop( )
{
String stringOne = rtc.getTimeStr();
myGLCD.setColor(65, 105, 225);
myGLCD.setFont(SevenSeg_XXXL_Num);
myGLCD.print(stringOne.substring(0,2), 12, 60);
myGLCD.print(stringOne.substring(3,5), 180, 60);
myGLCD.fillCircle(160, 88, 7);
myGLCD.fillCircle(160, 133, 7);
myGLCD.setColor(0, 255, 0);
myGLCD.setFont(DotMatrix_M);
myGLCD.print(rtc.getDateStr(), 80, 190);
}
Hallo,
Bin absoluter newbie und hab 2 Fragen zu diesem Tollen Code.
1. ist es möglich da noch den DS3231 mit einzubauen das es die Aktuelle Uhrzeit Speichert.
2. was wenn das Wlan gerade nicht an ist! Versucht es dann nochmal? Kann man das beinflußen wie oft bzw. wann.
Robert
Eine Idee warum dieser Uhrzeitcode nicht mit Timealarms zusammenarbeitet? https://github.com/PaulStoffregen/TimeAlarms
Hallo Ralf !
Danke für das super-tutorial ! Hat gleich funktioniert.
Ich möchte das für meine WS2812-Clock verwenden.
wie kann ich beeinflussen, wann time_Status() wieder „not ok“ meldet ?
Ich möchte die Uhr täglich mehrmals synchronisieren…
LG aus Wien,
Helmut
Hi,
es gibt kein „not ok“ sondern nur „Zeit eingestellt“ oder halt nicht.
Wenn du die Zeit auf verdacht alle paar Stunden einstellen willst, lösche die Zeilen 59 bis 63, dann wird die Abfrage ausgeführt obwohl die Zeit schon vorher eingestellt wurde.
mfg
Ralf
Thanks,
I’ve had some problems getting these to work. You saved me a lot of time and effort.
Ada, Michigan USA