Wow, vielen Dank für eure Unterstützung!
Hier mal mein Beispielsketch:
#include <Arduino.h>
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#ifndef WifiConfig
#define YOUR_WIFI_SSID ""
#define YOUR_WIFI_PASSWD ""
#endif
char lastSyncStr[] = "00:00:00 00.00.0000";
char actualTime[] = "00:00:00 00.00.0000";
char zeit[] = "00:00";
char startzeit [] = "18:55";
// den 5 gibt es nicht, der ist nur zum Fehlertest drin
static const char ntpServerName[][20] = {"1.de.pool.ntp.org","2.de.pool.ntp.org", "3.de.pool.ntp.org","4.de.pool.ntp.org","5.de.pool.ntp.org"};
time_t lastSyncTime;
time_t prevDisplay = 0; // when the digital clock was displayed
const int timeZone = 2; // Central European Time + Sommerzeit
boolean newSync = false;
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
// das muss ins setup
void setup() {
Serial.begin(115200);
//We start by connecting to a WiFi network
Serial.print("Connecting to: ");
Serial.println(YOUR_WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(YOUR_WIFI_SSID, YOUR_WIFI_PASSWD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP adress: ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(3600); // einmal pro Stunde
}
void printDigits_Time(int digits) {
//utility for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printDigits_Date(int digits) {
if(digits < 10) {
Serial.print('0');
}
Serial.print(digits);
}
void digitalClockDisplay() {
Serial.print(hour());
printDigits_Time(minute());
printDigits_Time(second());
Serial.print(" ");
printDigits_Date(day());
Serial.print(".");
printDigits_Date(month());
Serial.print(".");
Serial.print(year());
Serial.println();
}
char *timeToStr(time_t t, char * buf) {
int ja;
buf[0] = (hour(t) / 10) + '0'; // Zehner
buf[1] = (hour(t) % 10) + '0'; // Einer
buf[2] = ':';
buf[3] = (minute(t) / 10) + '0';
buf[4] = (minute(t) % 10) + '0';
buf[5] = ':';
buf[6] = (second(t) / 10) + '0';
buf[7] = (second(t) % 10) + '0';
buf[8] = ' '; // die abschließende 0
buf[9] = (day(t) / 10) + '0'; // Zehner
buf[10] = (day(t) % 10) + '0'; // Einer
buf[11] = '.';
buf[12] = (month(t) / 10) + '0';
buf[13] = (month(t) % 10) + '0';
buf[14] = '.';
ja = year(t);
buf[15] = (ja / 1000) + '0'; // Tausender
ja = ja % 1000; // Rest 3-stellig
buf[16] = (ja / 100) + '0'; // Hunderter
ja = ja % 100; // Rest 2-stellig
buf[17] = (ja / 10) + '0'; // Zehner
buf[18] = (ja % 10) + '0'; // Einer
buf[19] = 0; // die abschließende 0
return buf;
}
/*-------- NTP code ----------*/
void loop() {
if (timeStatus() != timeNotSet) {
//vergleiche mit Vorstellung Weihnachtssten von Tommy56 und bezogen auf NTP Client Example
if (newSync) {
timeToStr(lastSyncTime, lastSyncStr);
newSync = false;
}
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay=now();
timeToStr(prevDisplay, actualTime);
digitalClockDisplay();
}
}
//Auswertung Uhrzeit
zeit[0] = actualTime[0];
zeit[1] = actualTime[1];
zeit[3] = actualTime[3];
zeit[4] = actualTime[4];
Serial.println(zeit);
}
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
// return 0 wenn kein Sync
time_t getNtpTime(){
IPAddress ntpServerIP; // NTP server's ip address
static uint8_t num = 0; // Nummer des NTP-Pool-Servers 4 für Fehlertest
while (Udp.parsePacket() > 0) ; // discard any previously received packets
WiFi.hostByName(ntpServerName[num], ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
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];
lastSyncTime = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
newSync = true;
return lastSyncTime;
}
}
Serial.println("No NTP Response");
num = ++num %4;
now();
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();
}
Wie kann ich in einem Array in der Form 00:00 zB die Stunden (array[0] und array[1]) extrahieren und zu einer Zahl verketten? Habe bei meiner Suche im www nichts gefunden:-/
Tommy56:
Sind alle Zeiten immer im gleichen Tag? Dann genügt die Minuten-des-Tages-Rechnung.
Wenn nicht, ist es sinnvoller, gleich den UNIX-Timestamp zu benutzen (Sekunden seit 01.01.1970)
Gruß Tommy
Hi Tommy,
TIMESTAMP habe ich eben mal getestet, da ich einen ähnlichen Vergleich nutzen möchte, das nützt einem aber nur was, wenn der µc mit dem PC verbunden ist, dann wird so ausgegeben: Sun May 19 21:55:53 2019. Im standalone Betrieb bleibt das Makro(?) leer, wahrscheinlich genauso wie TIME und DATE. Was ja auch logisch ist, woher soll der µc auch die Zeit wissen.
Gibt es eine Möglichkeit die Makros (wenn es welche sind) mit einem RTC zu füllen? Oder lieber mittels Variable und Timer, Zeit setzen und im Sekundentakt hochzählen?
Ansonsten bleibt wohl nur noch die angesprochene Möglichkeit der Umrechnung.
Wie jetzt auch 'sagst' Du dem Arduino, welcher Timestamp gerade ist - also irgend wann.
Diese Zahl sollte dann aber dem Timestamp entsprechen - damit auch verschiedene Arduino die gleiche Zeit haben.
Die internen Berechnungen laufen dann in Timestamp, ist nicht anders, als mit millis() - nur, daß millis() die Millisekunden seit Start sind und der Timestamp die Sekunden seit 1.1.1970 (?) angibt.
Beides 32 Bit (deshalb wird's ja in naher Zukunft Probleme mit dem Timestamp beim Überlauf auf Null geben, dutzende Toaster werden Amog laufen und was sonst noch so ausgemalt wurde)
TIME und DATE (mit zwei oder drei _ davor/dahinter, müsste nachsehen) weisen NUR den Kompiler an, dort die jetzt gerade aktuelle Zeit einzutragen - für den Arduino ist Das fester Text!
Synchronisieren musst Du den Arduino also auch beim Timestamp, ab dann kannst Du per RTC die Sekunden zählen und 'alle Jubeljahr Mal' Außen anfragen, welcher Timestamp denn dort gerade aktuell ist - also den Arduino wieder synchronisieren - sollte bei DS3231 oder vergleichbar aber nur selten nötig sein.
Du kannst Dir im Arduino merken, daß noch nicht synchronisiert wurde (Start-Zustand) bzw. WANN zuletzt erfolgreich synchronisiert wurde.
postmaster-ino:
.
Die internen Berechnungen laufen dann in Timestamp, ist nicht anders, als mit millis() - nur, daß millis() die Millisekunden seit Start sind und der Timestamp die Sekunden seit 1.1.1970 (?) angibt.
Beides 32 Bit (deshalb wird's ja in naher Zukunft Probleme mit dem Timestamp beim Überlauf auf Null geben, dutzende Toaster werden Amog laufen und was sonst noch so ausgemalt wurde)
Wenn ich mich jetzt nicht vollkommen verrechnet haben sollte, bleiben "uns" noch gut 87 Jahre, bis der uint32_t Sekundenzähler überläuft, sehe ich momentan nicht so kritisch.
Wobei wenn ich überlege, wie viele Leute heute noch Windows XP nutzen, würde es mich nicht wundern wenn die heutige Hardware in 80 Jahren noch genutzt würde... Falls uns nicht vorher was aus dem All trifft! 8)
Wenn ich mich jetzt nicht vollkommen verrechnet haben sollte, bleiben "uns" noch gut 87 Jahre, bis der uint32_t Sekundenzähler überläuft
19.01.2038 wird diese Zahl erstmal negativ, das ist eher ein Problem in Programmiersprachen, die sich mit vorzeichenlosen Zahlen schwer tun (Java), und bei eventuellen unentdeckten Fehlern in Uralt-Programmen.
michael_x: 19.01.2038 wird diese Zahl erstmal negativ, das ist eher ein Problem in Programmiersprachen, die sich mit vorzeichenlosen Zahlen schwer tun (Java), und bei eventuellen unentdeckten Fehlern in Uralt-Programmen.
2038, ja da war mal was! Gut ich bin jetzt nur vom größtmöglichen Wert in uint32_t, in Sekunden ausgegangen.
Auszug:
!strcmp(switchTime*, buf)* Wäre bei dir dann: if (!strcmp(zeit[0], actualTime[0)) > LOOIIS: > -Wie kann ich den Unterschied zwischen Sommer- und Winterzeit abfragen bzw. diesen zB durch ein Symbol auf dem Display darstellen? Meine Lösung hat dir nicht gefallen. > LOOIIS: > const int timeZone = 2; // Central European Time + Sommerzeit Ob es damit klappt? Vielleicht jurs seine Formel umdrehen, im Winter einfach eine Stunde abziehen! Gruß Fips
ich würde erstmal nichts rechnen sondern nur vergleichen.
Stunde-A mit Stunde-B und Minute-A mit Minute-B.
Vorausgesetzt die Zeiten sind vom gleichen Tag.
Wenn Stunde-A größer wie Stunde-B, kann ich mir den Vergleich der Minuten schenken.
Nach Vergleich auf eine bestimmte Differenzzeit wurde nicht gefragt.
Ich selbst würde keine Arrays sondern für jede Zeit ein struct verwenden mit 3 Variablen.
Für Stunde, Minute, Unixzeit. Byte, Byte, unsigned long.
Erstere für die optische Anzeige, und letztere für irgendwelche Zeitenberechnungen falls notwendig.
Alles beisammen, nichts kommt durcheinander.
@Derfips:
Ich bin gerade beim Experimentieren und dabei halte ich mir alle Türen offen .
Der gepostete Sketch soll nur als Beispiel dienen um besser zu veraunschaulichen was ich tun möchte.
Vielen Dank für deinen Lösungsansatz! Wie kann ich aber mit deiner strcmp-Abfrage überprüfen ob die aktuelle Uhrezeit größer ist als die Startzeit. Mein Problem ist nämlcih, dass beide Uhrzeiten nicht vom selben Tag sein könnten. Siehe Beispiel unten.
@Doc_Arduino:
Danke für deinen Lösungsansatz und den Verbesserungsvorschlägen. Werde deine Tipps in meinem Sketch einbauen.
Das Problem ist, dass es sein könnte, dass die Uhrzeiten nicht vom selben Tag sind... zB aktuelle Uhrezit 01:25 und Startzeit 23:55 und da ist eben ein herkömmlicher Zeitvergleich nicht so einfach.
Bin ebenfalls für Unix-Timestamp!
Zum Rechnen und gerade für die Unterscheidung, was wohl vorher war, ist DAS der Weg.
Erst die Anzeige für's poplige Volk wird in Ortszeit umgerechnet - vom mir aus dort dann auch mit Zeitzone.
Aber ganz bestimmt würde ich mir keine Inkonsistenz in das Struct rein bringen - die Uhrzeit lässt sich aus dem Timestamp ableiten.
Wenn Beides nicht zusammen passt, 'ist Polen offen' - was soll dann gelten?
Sorry, für die späte Antwort.
Vielen Dank für eure Beiträge bzw. Lösungsansätze.
Wie ich jetzt mitbekommen habe gibt es 2 Lösungsansätze:
Lösungsansatz 1:
Derfips:
Dann schreib doch den Tag des Monats mit ins Array.
Auszug:
!strcmp(switchTime*, buf)* Wäre bei dir dann: if (!strcmp(zeit[0], actualTime[0)) [/quote] Lösungsansatz 2: > Tommy56: > Sind alle Zeiten immer im gleichen Tag? Dann genügt die Minuten-des-Tages-Rechnung. > Wenn nicht, ist es sinnvoller, gleich den UNIX-Timestamp zu benutzen (Sekunden seit 01.01.1970) > > Gruß Tommy Wie kann ich aber der Funktion einen Wert (Zeit und Datum) übergeben? War der Meinung, dass diese Funktion die interne Zeit als unixtime berechnet. > Doc_Arduino: > Hallo, > > die Lib von Stoffregen haste ja schon, darin gibts eine Funktion now() die dir die unixtime liefert.
Danke für deinen Tipp.
Habe es mit der aktuellen Uhrzeit bereits geschafft mit der Funktion makeTime() zu arbeiten.
Wie kann ich aber aus einem Array (Format: 00:00:00 00.00.0000 hh:mm:ss dd.MM.JJJJ) gewisse Bereiche zB das Jahr herausfiltern, damit ich es der genannten Funktion übergeben kann?
ich würde erstmal nichts rechnen sondern nur vergleichen.
Stunde-A mit Stunde-B und Minute-A mit Minute-B.
Vorausgesetzt die Zeiten sind vom gleichen Tag.
Wenn Stunde-A größer wie Stunde-B, kann ich mir den Vergleich der Minuten schenken.
Nach Vergleich auf eine bestimmte Differenzzeit wurde nicht gefragt.
Ich selbst würde keine Arrays sondern für jede Zeit ein struct verwenden mit 3 Variablen.
Für Stunde, Minute, Unixzeit. Byte, Byte, unsigned long.
Erstere für die optische Anzeige, und letztere für irgendwelche Zeitenberechnungen falls notwendig.
Alles beisammen, nichts kommt durcheinander.
struct Zeiten
{
byte stunde;
byte minute;
unsigned long unix;
};
Wenn du mit "Array" einen Text meinst, kannst du entweder darauf vertrauen, dass er automatisch formatrichtig mit führenden Nullen erzeugt wurde, und das Jahr also immer in text+15 anfängt.
Oder du zählst die Trennzeichen ':' ' ' '.'
char Beispiel[] = "00:00:00 01.01.2001";
Serial.println(Beispiel+15); // "2001"
int jahr = atoi(Beispiel+15);
Serial.println (jahr); // 2001
Dank eurer Unterstützung, dem wertvollen Tipp von Serenifly und meinem Eifer habe ich es jetzt hinbekommen.
Nochmals großes Danke an euch ALLEN!!!
Serenifly:
Auch das ist wieder ein Fall wo Zeiger völlig überflüssig sind und man stattdessen Referenzen verwenden sollte. Siehe auch die Time Library (makeTime() und breakTime())
#include <Arduino.h>
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#ifndef WifiConfig
#define YOUR_WIFI_SSID ""
#define YOUR_WIFI_PASSWD ""
#endif
//Zeitstruktur der Timelib
tmElements_t Startzeit;
tmElements_t lastSyncStr;
tmElements_t actualTime;
// den 5 gibt es nicht, der ist nur zum Fehlertest drin
static const char ntpServerName[][20] = {"1.de.pool.ntp.org","2.de.pool.ntp.org", "3.de.pool.ntp.org","4.de.pool.ntp.org","5.de.pool.ntp.org"};
time_t lastSyncTime;
time_t prevDisplay = 0; // when the digital clock was displayed
const int timeZone = 1; // Central European Time
boolean newSync = false;
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
// das muss ins setup
void setup() {
Serial.begin(115200);
//We start by connecting to a WiFi network
Serial.print("Connecting to: ");
Serial.println(YOUR_WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(YOUR_WIFI_SSID, YOUR_WIFI_PASSWD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP adress: ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(3600); // einmal pro Stunde
//Uhrzeit Startzeit
Startzeit.Hour = 15;
Startzeit.Minute = 0;
Startzeit.Second = 0;
}
void digitalClockDisplay() {
Serial.println();
Serial.print("Actual Time: ");
Serial.print(actualTime.Hour);
Serial.print(":");
Serial.print(actualTime.Minute);
Serial.print(":");
Serial.print(actualTime.Second);
Serial.print("---");
Serial.print(actualTime.Day);
Serial.print(".");
Serial.print(actualTime.Month);
Serial.print(".");
Serial.print(actualTime.Year + 1970);
}
//https://forum.arduino.cc/index.php?topic=508716.0
void unixdiff(uint32_t zeit1, uint32_t zeit2) {
uint32_t diff;
uint8_t sec, mi, hr;
if (zeit1 > zeit2) diff = zeit1 - zeit2;
else diff = zeit2 - zeit1;
sec = diff % 60;
diff /= 60;
mi = diff % 60;
diff /=60;
hr = diff % 24;
diff /= 24;
Serial.print(F("Tage: ")); Serial.print(diff);
Serial.print(F(" Stunden: ")); Serial.print(hr);
Serial.print(F(" Minuten: ")); Serial.print(mi);
Serial.print(F(" Sekunden: ")); Serial.println(sec);
}
/*-------- NTP code ----------*/
void loop() {
if (timeStatus() != timeNotSet) {
//vergleiche mit Vorstellung Weihnachtsstern von Tommy56 und bezogen auf NTP Client Example
if (newSync) {
breakTime(lastSyncTime, lastSyncStr); // break time_t into elements; see TimeLib
newSync = false;
}
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay=now();
breakTime(prevDisplay, actualTime); // break time_t into elements; see TimeLib
//Startzeit soll mit aktuellen Datum ergänzt werden
Startzeit.Day = actualTime.Day;
Startzeit.Month = actualTime.Month;
Startzeit.Year = actualTime.Year;
digitalClockDisplay();
}
}
Serial.println();
Serial.println("-----------------");
//// makeTime convert time elements into time_t; see TimeLib
Serial.println(makeTime(actualTime));
Serial.println(makeTime(Startzeit));
unixdiff(makeTime(actualTime), makeTime(Startzeit)); //Zeitdifferenz zwischen zwei Unix Time Stamps
Serial.println();
Serial.print("Last Sync Time: ");
Serial.print(lastSyncStr.Hour);
Serial.print(":");
Serial.print(lastSyncStr.Minute);
Serial.print(":");
Serial.print(lastSyncStr.Second);
Serial.print("---");
Serial.print(lastSyncStr.Day);
Serial.print(".");
Serial.print(lastSyncStr.Month);
Serial.print(".");
Serial.println(lastSyncStr.Year + 1970);
Serial.println("-----------------");
delay(1000);
}
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
// return 0 wenn kein Sync
time_t getNtpTime(){
IPAddress ntpServerIP; // NTP server's ip address
static uint8_t num = 0; // Nummer des NTP-Pool-Servers 4 für Fehlertest
while (Udp.parsePacket() > 0) ; // discard any previously received packets
WiFi.hostByName(ntpServerName[num], ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
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];
lastSyncTime = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
newSync = true;
return lastSyncTime;
}
}
Serial.println("No NTP Response");
num = ++num %4;
now();
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();
}