

Ziele des Projekts
- die aktuelle Zeit alle 60 Sekunden vom NTP-Server holen
- ⇒millis() sorgt für die fortlaufende Zeit
- Wochentag, Datum und Uhrzeit auf dem 4-zeiligen LCD mit I²C-Schnittstelle anzeigen
- im 60 Sekunden Rhythmus die Messwerte des BME280 ermitteln und aktualisieren

Benötigte Bauteile
- ⇒4-zeiliges LCD mit I²C-Schnittstelle
- ⇒BME280
- Leitungsdrähte
Board installieren
Als Mikrocontroller können beliebige Module aus der Familie der ESP-Mikrocontroller verwendet werden.
- ESP32-Wroom
- Arduino Nano ESP32
- ESP32-C6
- XIAO-ESP32-C3
- ESP32-C3 Zero
- ESP32-C3 Super Mini
- ESP32-C6 Zero
- Wemos D1 Mini
- NodeMCU
NTP-Server
Die korrekte Zeit ist für die Bearbeitung vielfältiger Aufgaben in der Datenverarbeitung notwendig. Daher muss die Zeit regelmäßig mit im Internet zur Verfügung stehenden NTP (Network Time Protocol)-Servern synchronisiert werden.
In Europa sind Zeitserver zu einem länderspezifischen Pool zusammen geschlossen. In Deutschland heißt der Pool de.pool.ntp.org
Als zusätzliche Information muss dem Programm die Zeitzone mitgeteilt werden:
Der Schaltplan
ESP32-Wroom
Die Module werden über I²C angeschlossen: die SCL-Pins werden mit 22, die SDA-Pins mit 21 verbunden.

I²C-Pins anderer Mikrocontroller
- ESP32C6
- ESP32-C6 Zero
- Arduino Nano ESP32
- XIAO-ESP32-C3
- ESP32-C3 Zero
- ESP32-C3 Super Mini
- ESP32-S3
- ESP32 Super Mini
- Wemos D1 Mini
- NodeNCU
Benötigte Bibliotheken


Das Programm
Bibliotheken und Variable
- die ifdef-Abfrage sorgt dafür, dass je nach verwendeten Mikrocontroller die korrekte WiFi-Bibliothek verwendet wird
- das ⇒Array daysOfTheWeek sorgt für die Darstellung der Wochentage
da die Namen unterschiedlich lang sind, müssen sie mit Leerzeichen aufgefüllt werden - Die ⇒Struktur tm besteht aus verschiedenen Elementen:
tm_hour -> Stunde: 0 bis 23
tm_min -> Minuten: 0 bis 59
tm_sec -> Sekunden 0 bis 59
tm_mday -> Tag 1 bis 31
tm_mon -> Monat: 0 (Januar) bis 11 (Dezember)
tm_year -> Jahre seit 1900
tm_yday -> vergangene Tage seit 1. Januar des Jahres
tm_isdst -> Wert > 0 = Sommerzeit (dst = daylight saving time) - define Zeitzone „CET-1CEST,M3.5.0/02,M10.5.0/03“
definiert die Zeitzone
CET = Central European Time -1 -> 1 Stunde zurück
CEST = Central European Summer Time von
M3 = März, 5.0 = Sonntag 5. Woche, 02 = 2 Uhr
bis M10 = Oktober, 5.0 = Sonntag 5. Woche 03 = 3 Uhr - SekundenAnzeigen entscheidet darüber, ob die Sekunden bei der Darstellung der Uhrzeit fortlaufend angezeigt werden
true/false
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#ifdef ESP32 #include "WiFi.h" #else #include "ESP8266WiFi.h" #endif #include "time.h" #include "LCDIC2.h" #include "Adafruit_BME280.h" #define MeeresHoehe (1013.25) // Name des BME280 Adafruit_BME280 bme; // 4-zeiliges LCD LCDIC2 lcd(0x27, 20, 4); char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxx"; // NTP-Server aus dem Pool #define Zeitserver "de.pool.ntp.org" /* Liste der Zeitzonen https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv Zeitzone CET = Central European Time -1 -> 1 Stunde zurück CEST = Central European Summer Time von M3 = März, 5.0 = Sonntag 5. Woche, 02 = 2 Uhr bis M10 = Oktober, 5.0 = Sonntag 5. Woche 03 = 3 Uhr */ #define Zeitzone "CET-1CEST,M3.5.0/02,M10.5.0/03" // time_t enthält die Anzahl der Sekunden seit dem 1.1.1970 0 Uhr time_t aktuelleZeit; /* Struktur tm tm_hour -> Stunde: 0 bis 23 tm_min -> Minuten: 0 bis 59 tm_sec -> Sekunden 0 bis 59 tm_mday -> Tag 1 bis 31 tm_mon -> Monat: 0 (Januar) bis 11 (Dezember) tm_year -> Jahre seit 1900 tm_yday -> vergangene Tage seit 1. Januar des Jahres tm_isdst -> Wert > 0 = Sommerzeit (dst = daylight saving time) */ tm Zeit; int Sekunden = 0; // Anzeige der WiFi-Verbindung/NTP-Server mit Punkten int Zaehler = 0; int Zeile = 0; bool SekundenAnzeigen = true; unsigned long Zeitmessung = 0; bool BMEStart; |
Der setup-Teil
Beim Start des Programms werden Statusmeldungen angezeigt:


- Der BME280 wird in verschiedenen Ausführungen und mit unterschiedlichen HEX-Adressen angeboten: 0x76 oder 0x77
Du musst in Zeile 59 die korrekte Adresse einsetzen.
die HEX-Adresse kannst du mit diesem Programm ⇒herausfinden. - beim ersten Kontakt mit dem NTP-Server entspricht die übermittelte Zeit noch dem UNIX-Zeitstempel, der Zeit in Sekunden, die seit dem 1.1.1970 vergangen sind.
es wird für maximal 40 Sekunden im Sekundentakt die Zeit solange abgefragt, bis die Jahreszahl nicht mehr 1970 ist, also die Zeit korrekt ist
bei Misserfolg wird das Programm beendet
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
void setup() { Serial.begin(9600); // Schalter für erfolgreiche Synchronisierung der Zeit int Suche = -1; // LCD starten lcd.begin(); // Cursor "verstecken" lcd.setCursor(false); lcd.clear(); // WiFi starten // Stations-Modus WiFi.mode(WIFI_STA); WiFi.begin(Router, Passwort); Zaehler = 0; Zeile = 0; lcd.setCursor(Zaehler, Zeile); while (WiFi.status() != WL_CONNECTED) { delay(200); lcd.print("."); // wenn . Zeilenende erreichen -> nächste Zeile Zaehler ++; if(Zaehler > 19) { Zeile ++; Zaehler = 0; } lcd.setCursor(Zaehler, Zeile); // keine WiFi-Verbindung if(Zeile > 3) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("WiFi-Verbindung"); lcd.setCursor(0, 1); lcd.print("fehlgeschlagen!"); lcd.setCursor(0, 3); lcd.print("Programmende"); while(1); } } lcd.clear(); lcd.setCursor(0, 0); lcd.print("WiFi gestartet!"); // Zeitzone: Parameter für die zu ermittelnde Zeit configTzTime(Zeitzone, Zeitserver); lcd.setCursor(0, 1); // BME280 starten Hex-Adressen ox76 oder 0x77 if(bme.begin(0x76)) { lcd.print("BME280 gestartet!"); BMEStart = true; } else { BMEStart = false; lcd.print("BME nicht vorhanden "); } time(&aktuelleZeit); // localtime_r -> Zeit in die lokale Zeitzone setzen localtime_r(&aktuelleZeit, &Zeit); // nur ESP32 #ifdef ESP32 { // beim Start entspricht das Datum der Unixtime: 1.1.1970 // das Datum soll erst angezeigt werden, wenn es korrekt ist String Jahr = String(Zeit.tm_year + 1900); int Zaehler = 0; // String Jahr nach "1970" durchsuchen int Suche = Jahr.indexOf("1970"); Zaehler = 0; Zeile = 2; lcd.setCursor(Zaehler, Zeile); // solange die Suche nicht erfolgreich ist // maximal 40 Sekunden while (Suche != -1 && Zaehler < 40) { // aktuelle Zeit holen time(&aktuelleZeit); // localtime_r -> Zeit in die lokale Zeitzone setzen localtime_r(&aktuelleZeit, &Zeit); Jahr = String(Zeit.tm_year + 1900); // String Jahr nach "1970" durchsuchen Suche = Jahr.indexOf("1970"); delay(1000); lcd.setCursor(Zaehler, Zeile); lcd.print("."); Zaehler ++; if(Zaehler > 19) { Zeile ++; Zaehler = 0; } // Zeit konnte innerhalb 40 Sekunden nicht geholt werden if(Zeile > 3) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Verbindung zum"); lcd.setCursor(0, 1); lcd.print("Zeitserver"); lcd.setCursor(0, 2); lcd.print("fehlgeschlagen!"); lcd.setCursor(0, 3); lcd.print("Programmende"); while(1); } } } #endif // Datum/Zeit erfolgreich synchronisiert lcd.setCursor(0, 3); lcd.print("Zeit synchronisiert"); delay(3000); lcd.clear(); if(BMEStart)MessungAnzeigen (); // Datum/Zeit erfolgreich synchronisiert if (Suche == -1) ZeitAnzeigen(); Zeitmessung = millis() + 1000; } |
Der loop-Teil
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void loop() { if (Zeitmessung < millis()) { Zeitmessung += 1000; Sekunden++; if (Sekunden == 60) { if(BMEStart) MessungAnzeigen(); ZeitAnzeigen(); } } lcd.setCursor(16, 1); if(SekundenAnzeigen) { lcd.print(":"); if(Sekunden < 10) lcd.print("0"); lcd.print(String(Sekunden)); } else lcd.print(" "); } |
Funktionen
Im loop-Teil werden zwei ⇒Funktionen aufgerufen:
- ZeitAnzeigen()
die Zeit wird alle 60 Sekunden mit dem NTP-Server synchronisiert - MessungAnzeigen()
nach jeder vollen Minute werden die Messwerte des BME280 abgefragt und angezeigt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
void ZeitAnzeigen() { // aktuelle Zeit holen time(&aktuelleZeit); // localtime_r -> Zeit in die lokale Zeitzone setzen localtime_r(&aktuelleZeit, &Zeit); lcd.setCursor(0, 0); // Wochentage mitt Leerzeichen (Donnerstag 10 Zeichen) switch (Zeit.tm_wday) { case 0: lcd.print("Sonntag "); break; case 1: lcd.print("Montag "); break; case 2: lcd.print("Dienstag "); break; case 3: lcd.print("Mittwoch "); break; case 4: lcd.print("Donnerstag"); break; case 5: lcd.print("Freitag "); break; case 6: lcd.print("Samstag "); break; } lcd.setCursor(0, 1); // Tag: führende 0 ergänzen if (Zeit.tm_mday < 10) lcd.print("0"); lcd.print(String(Zeit.tm_mday)); lcd.print("."); // Monat: führende 0 ergänzen if (Zeit.tm_mon < 9) lcd.print("0"); lcd.print(String(Zeit.tm_mon + 1)); lcd.print("."); // Anzahl Jahre seit 1900 lcd.print(String(Zeit.tm_year + 1900)); lcd.setCursor(11, 1); // Stunde: wenn Stunde < 10 -> 0 davor setzen if (Zeit.tm_hour < 10) lcd.print("0"); lcd.print(String(Zeit.tm_hour)); lcd.print(":"); // Minuten if (Zeit.tm_min < 10) lcd.print("0"); lcd.print(String(Zeit.tm_min)); Sekunden = Zeit.tm_sec; lcd.setCursor(16, 1); if(SekundenAnzeigen) { lcd.print(":"); // Sekunden if (Zeit.tm_sec < 10) lcd.print("0"); lcd.print(String(Zeit.tm_sec)); } else lcd.print(" "); } void MessungAnzeigen() { String Temperatur = String(bme.readTemperature(), 1); String Luftfeuchtigkeit = String(bme.readHumidity(), 1); String Luftdruck = String(int(bme.readPressure() / 100.0)); // float verwendet den . als Dezimaltrennzeichen // . mit replace durch , ersetzen Temperatur.replace(".", ","); Luftdruck.replace(".", ","); Luftfeuchtigkeit.replace(".", ","); lcd.setCursor(0, 2); lcd.print(Temperatur + "\337C "); lcd.setCursor(8, 2); lcd.print(Luftdruck + " hPa "); lcd.setCursor(0, 3); lcd.print(Luftfeuchtigkeit + "%"); } |
Quellen
Letzte Aktualisierung: