

Ziele des Projekts
- mit der WiFi-Funktion eines ESP32 oder ESP8266 Mikrocontrollers die aktuelle Zeit und das aktuelle Datum holen
- analoge Uhr auf einem runden TFT anzeigen
Das Programm für ein TFT mit 320×240 Pixeln findest du ⇒hier, das für ein TFT mit 480×320 Pixeln gibt es ⇒hier.
Anwendungsbeispiele


Konfiguration der Mikrocontroller
- ESP32-Wroom
- ESP32C6
- ESP32-C6 Zero
- ESP32-S3
- Arduino Nano ESP32
- XIAO-ESP32-C3
- ESP32-C3-Zero
- ESP32-C3 Super Mini
- Wemos D1
- NodeMCU
Schaltplan für ESP32-Wroom

RST (gelb) -> 4
CS (weiß) -> 5
DC ( grün) -> 2
SDA (blau) -> 23
SCL (braun) -> 18
Benötigte Bibliothek

Bibliothek Adafruit GFX Library
Die Bibliothek Adafruit_GC9A01A verwendet die Funktionen der Adafruit GFX Library.
| Schlüsselwort | Parameter | Aktion |
|---|---|---|
| width(); | Bildschirmbreite feststellen | |
| height(); | Bildschirmhöhe feststellen | |
| setRotation(Richtung); | Richtung = 0 → nicht drehen Richtung = 1 → 90° drehen Richtung = 2 → 180° drehen Richtung = 3 → 270 ° drehen | Bildschirm ausrichten |
| fillScreen(Farbe); | Bildschirmhintergrund | |
| drawLine(StartX, StartY, EndeX, EndeY, Farbe); | Linie zeichnen | |
| drawFastHLine(StartX, StartY, Länge, Farbe); | horizontale Linie zeichnen | |
| drawFastVLine(StartX, StartY, Länge, Farbe); | vertikale Linie zeichnen | |
| drawRect(StartX, StartY,, Breite, Höhe, Farbe); | Rechteck zeichnen | |
| drawRoundRect(StartX, StartY, Breite, Höhe, Eckenradius, Farbe); | abgerundetes Rechteck zeichnen | |
| fillRoundRect(StartX, StartY, Breite, Höhe, Eckenradius, Füllfarbe); | ausgefülltes abgerundetes Rechteck zeichnen | |
| fillRect(StartX, StartY, Breite, Höhe, Füllfarbe); | ausgefülltes Rechteck zeichnen | |
| drawCircle(MittelpunktX, MittelpunktY, Radius, Farbe); | Kreis zeichnen | |
| fillCircle(MittelpunktX, MittelpunktY, Radius, Füllfarbe); | Ausgefüllten Kreis zeichnen | |
| drawTriangle(x1, y1, x2, y2, x3, y3, Farbe); | Dreieck zeichnen: x1, y1: 1.Punkt x2, y2: 2.Punkt x3, y3: 3.Punkt |
|
| fillTriangle(x1, y1, x2, y2, x3, y3, Füllfarbe); | ausgefülltes Dreieck zeichnen: x1, y1: 1.Punkt x2, y2: 2.Punkt x3, y3: 3.Punkt |
|
| setCursor(x, y); | Cursor setzen | |
| setTextSize(Textgröße); | Textgröße | Textgröße bestimmen |
| setTextColor(Farbe); | Textfarbe setzen | |
| print("Text"); println("Text"); | Text schreiben | |
| setTextWrap(true/false); | false → Text fließt über den Rand des TFTs hinaus true → Text wird am Ende umgebrochen | Zeilenumbruch |
| invertDisplay(); | 0 → Farben nicht tauschen 1 → Farben tauschen | |
| color565(rot, grün, blau); | rot: 0 - 255 grün: 0 - 255 blau: 0 - 255 | beliebige Mischfarben erstellen |
| drawBitmap(PosX, PosY, Array, ArrayGrößeX, ArrayGrößeY, Farbe); | Array als Bild darstellen | |
Das Programm
Bibliotheken und Variable
Das Programm kann auf vielfältige Weise angepasst werden:
- die Farbe der Zeiger (Zeigerfarbe)
die Farben kannst du dem Kopf des Programms entnehmen - die Farbe des inneren Kreises (Kreisfarbe)
- die Farbe der äußeren Umrandung (Randfarbe)
- Anzeige des Datums (DatumAnzeigen)
true: Datum anzeigen, false: Datum verbergen - die Anzeige der Stundenmarkierungen 12, 3, 6 und 9 (Ziffernanzeigen)
true: Ziffern anzeigen, false: Ziffern verbergen - Anzeige des Sekundenzeigers (SekundenzeigerKreis)
true: Anzeige als Kreis
false: Anzeige mit Linie und Kreis
Die Anzeige des Datums wird abgeschaltet, um das Flackern des TFTs zu vermeiden.
Du musst die SPI-Pins des verwendeten Mikrocontrollers anpassen.
|
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 150 151 152 153 |
#ifdef ESP8266 #include "ESP8266WiFi.h" #else #include "WiFi.h" #endif #include "time.h" #include "Adafruit_GC9A01A.h" // Adafruit-Schriftart einbinden #include "Fonts/FreeSans12pt7b.h" // Wemos D1 Mini/NodeMCU // #define TFT_CS D8 // #define TFT_RST D1 // #define TFT_DC D2 // XIAO // #define TFT_CS D7 // #define TFT_RST D1 // #define TFT_DC D2 // Arduino Nano ESP32 // #define TFT_CS 10 // #define TFT_RST 9 // #define TFT_DC 8 // SPI-Pins ESP32-C6 // #define TFT_CS 18 // #define TFT_RST 3 // #define TFT_DC 2 // ESP32-WROOM // #define TFT_CS 5 // #define TFT_RST 4 // #define TFT_DC 2 // ESP32-S3 // #define TFT_CS 10 // #define TFT_RST 5 // #define TFT_DC 4 // ESP32-C6-Zero // #define TFT_CS 18 // #define TFT_RST 3 // #define TFT_DC 2 // ESP32-C3 Zero/ESP32-C3 Super Mini // #define TFT_CS 7 // #define TFT_RST 3 // #define TFT_DC 2 // ESP32-S3 Super Mini // #define TFT_CS 10 // #define TFT_RST 2 // #define TFT_DC 3 Adafruit_GC9A01A tft(TFT_CS, TFT_DC); // WiFi-Daten char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxxx"; // Variablen des TFTs (Höhe, Breite, Radius) const int MitteHoehe = tft.height() / 2; const int MitteBreite = tft.width() / 2; const int Radius = tft.width() / 2; // Multiplikatoren für x- y-Positionen der Stunden, Minuten und Sekunden float SekundePosX = 0, SekundePosY = 0, MinutePosX = 0, MinutePosY = 0, StundePosX = 0, StundePosY = 0; float GradSekunden = 0, GradMinuten = 0, GradStunden = 0; // x- y-Koordinaten für die Anzeige Stunden, Minuten und Sekunden int SekundenZeigerX = MitteHoehe, SekundenZeigerY = MitteHoehe; int MinutenZeigerX = MitteHoehe, MinutenZeigerY = MitteHoehe; int StundenZeigerX = MitteHoehe, StundenZeigerY = MitteHoehe; // Start wird nur beim ersten Start für den Aufbau des TFTs benötigt bool Start = true; // Variablen für die Markierungen und Punkte und Striche des Ziffernblatts float PosX, PosY; int PunktX, PunktY, PunktX1, PunktX2, PunktY1, PunktY2; // Variablen für die Zeit int Stunden, Minuten, Sekunden; // Farben #define SCHWARZ 0x0000 #define WEISS 0xFFFF #define BLAU 0x001F #define ROT 0xF800 #define GRUEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define GELB 0xFFE0 #define BRAUN 0x9A60 #define GRAU 0x7BEF #define GRUENGELB 0xB7E0 #define DUNKELCYAN 0x03EF #define ORANGE 0xFDA0 #define PINK 0xFE19 #define BORDEAUX 0xA000 #define HELLBLAU 0x867D #define VIOLETT 0x915C #define SILBER 0xC618 #define GOLD 0xFEA0 // Farben innerer Kreis, Randfarbe und Zeigerfarbe // die Farben der Zeiger können aber auch individuell gesetzt werden const int Kreisfarbe = SCHWARZ; const int Zeigerfarbe = WEISS; const int Randfarbe = BORDEAUX; // true -> Datum anzeigen // false -> Datum nicht anzeigen bool DatumAnzeigen = true; // true -> Sekundenzeiger nur als Kreis bool SekundenzeigerKreis = false; // Ziffern 12 3 6 9 anzeigen/nicht anzeigen bool Ziffernanzeigen = true; // 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 SuMinutener 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; unsigned long Zeitmessung = 0; |
Der setup-Teil
Beim Start des Programms zeigen die Meldungen im Seriellen Monitor und auf dem TFT ob Datum und Zeit korrekt sind. Wenn in 90 Sekunden keine Verbindung zu einem Zeitserver hergestellt werden konnte, wird das Programm beendet. Nach einem erneuten Hochladen kommt zumeist die Verbindung schnell zustande.

Möglicherweise entsteht durch die Anzeige der Startmeldungen auf dem TFT eine kurze Verzögerung und die Zeitanzeige „hinkt“ etwas hinterher. Nach einer erneuten Synchronisation spätestens nach einer Minute wird die Zeit korrekt 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 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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
void setup() { Serial.begin(9600); tft.begin(); tft.setRotation(0); tft.fillScreen(Kreisfarbe); // Zeitzone: Parameter für die zu ermittelnde Zeit configTzTime(Zeitzone, Zeitserver); WiFi.mode(WIFI_STA); // WiFi starten WiFi.begin(Router, Passwort); tft.setCursor(30, 50); tft.print("WiFi starten ..."); Serial.println("------------------------"); while (WiFi.status() != WL_CONNECTED) { delay(200); Serial.print("."); } Serial.println(); Serial.print("Verbunden mit "); Serial.println(Router); Serial.print("IP über DHCP: "); Serial.println(WiFi.localIP()); tft.setCursor(30, 80); tft.print(WiFi.localIP()); tft.setCursor(30, 110); tft.print("Warte auf Zeitserver ..."); // Zeit holen time(&aktuelleZeit); // localtime_r -> Zeit in die lokale Zeitzone setzen localtime_r(&aktuelleZeit, &Zeit); // beim Start entspricht das Datum der Unixtime: 1.1.1970 // Datum/Kalender sollen erst angezeigt werden, wenn das Datum korrekt ist String Jahr = String(Zeit.tm_year + 1900); int Zaehler = 0; // String Jahr nach "1970" durchsuchen int Suche = Jahr.indexOf("1970"); Serial.println("-------------------------"); Serial.println("Datum und Zeit holen (maximal 90 Sekunden)..."); // solange die Suche nicht erfolgreich ist while (Suche != -1) { // 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"); // Zeit in Stunden, Minuten und Sekunden Stunden = int(Zeit.tm_hour), Minuten = int(Zeit.tm_min), Sekunden = int(Zeit.tm_sec); delay(1000); Zaehler ++; if (Zaehler >= 90) { Serial.println(); Serial.println("Datum und Zeit konnte innerhalb von " + String(Zaehler) + " Sekunden nicht geholt werden"); Serial.println("Programm wird beendet"); tft.setCursor(30, 140); tft.print("Programm beendet!"); // Programm beenden while(1); } Serial.print("."); } Serial.println(); // Datum/Zeit erfolgreich synchronisiert if (Suche == -1) { Serial.println("-------------------------"); Serial.println("Datum/Zeit erfolgreich synchronisiert ..."); if (Zeit.tm_mday < 10) Serial.print("0"); Serial.print(Zeit.tm_mday); Serial.print("."); // Monat: führende 0 ergänzen if (Zeit.tm_mon < 9) Serial.print("0"); // Zählung beginnt mit 0 -> +1 Serial.print(Zeit.tm_mon + 1); Serial.print("."); // Anzahl Jahre seit 1900 Serial.println(Zeit.tm_year + 1900); if (Zeit.tm_hour < 10) Serial.print("0"); Serial.print(Zeit.tm_hour); Serial.print(":"); if (Zeit.tm_min < 10) Serial.print("0"); Serial.println(Zeit.tm_min); Serial.println("-------------------------"); } // Zeit in Stunden, Minuten und Sekunden Stunden = Zeit.tm_hour, Minuten = Zeit.tm_min, Sekunden = Zeit.tm_sec; tft.fillScreen(Kreisfarbe); // 4 Pixel breiter äußerer Rand, Farbe au der Farbpalette wählen tft.drawCircle(MitteHoehe, MitteBreite, Radius - 1, Randfarbe); tft.drawCircle(MitteHoehe, MitteBreite, Radius - 2, Randfarbe); tft.drawCircle(MitteHoehe, MitteBreite, Radius - 3, Randfarbe); tft.drawCircle(MitteHoehe, MitteBreite, Radius - 4, Randfarbe); // innere Fläche bis auf den Rand von 4 Pixeln vollständig löschen // wenn andere Farbe als äußerer Rand gewählt wird ergibt sich ein schmaler Rand tft.fillCircle(MitteHoehe, MitteBreite, Radius - 4, Kreisfarbe); /* alle 30° Linie am Rand als Stundenmarkierung zeichnen DEG_TO_RAD (= PI/180 = 0.0174532925) -> Winkel in Bogenmaß umrechnen sin/cos berechnen die x-/y-Kordinaten des Punktes auf der Kreislinie */ for (int i = 0; i < 360; i += 30) { PosX = cos((i - 90) * DEG_TO_RAD); PosY = sin((i - 90) * DEG_TO_RAD); // kurze Linien zeichnen, von 114 bis 100 vom äußeren Rand aus // Farbe individuell wählbar int PunktX1 = PosX * 110 + Radius; int PunktY1 = PosY * 110 + Radius; int PunktX2 = PosX * 100 + Radius; int PunktY2 = PosY * 100 + Radius; tft.drawLine(PunktX1, PunktY1, PunktX2, PunktY2, Zeigerfarbe); // keine Striche an der Position der Zahlen if (Ziffernanzeigen) { if (PunktX1 == 10 || PunktX1 == 120 || PunktX1 == 230) { tft.drawLine(PunktX1, PunktY1, PunktX2, PunktY2, Kreisfarbe); } } } // alle 6 Grad Punkte als Sekundenmarkierung zeichnen for (int i = 0; i < 360; i += 6) { PosX = cos((i - 90) * DEG_TO_RAD); PosY = sin((i - 90) * DEG_TO_RAD); // Positionen der Punkte // 108 -> Abstand vom Mittelpunkt PunktX = PosX * 108 + Radius; PunktY = PosY * 108 + Radius; tft.drawPixel(PunktX, PunktY, Zeigerfarbe); } // Markierung 12 3 6 9 if (Ziffernanzeigen) { tft.setFont(&FreeSans12pt7b); tft.setTextColor(Zeigerfarbe); tft.setCursor(tft.height() / 2 - 15, 25); tft.print("12"); tft.setCursor(10, tft.height() / 2 + 7); tft.print("9"); tft.setCursor(220, tft.height() / 2 + 10); tft.print("3"); tft.setCursor(tft.height() / 2 - 7, 230); tft.print("6"); } // wenn der Sekundenzeiger mit Linie angezeigt wird // -> Anzeige des Datums ausschalten if (!SekundenzeigerKreis) DatumAnzeigen = false; if (DatumAnzeigen) ZeigeDatum(); 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 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 |
void loop() { // Sekunden weiter zählen if (Zeitmessung < millis()) { Zeitmessung += 1000; Sekunden++; if (Sekunden == 60) { // aktuelle Zeit holen time(&aktuelleZeit); // localtime_r -> Zeit in die lokale Zeitzone setzen localtime_r(&aktuelleZeit, &Zeit); // Zeit in Stunden, Minuten und Sekunden Stunden = Zeit.tm_hour, Minuten = Zeit.tm_min, Sekunden = Zeit.tm_sec; // Mitternacht // -> Wechsel des Datums anzeigen if (Stunden == 0 && Minuten == 0) { Serial.println("neues Datum"); if (DatumAnzeigen) ZeigeDatum(); } // Zeiger "löschen" Anzeige des Datums -> jede Minute erneuern if (DatumAnzeigen) ZeigeDatum(); } // Vorausberechnung der x- und y-Koordinaten // alle 6° eine Sekunde vorwärts GradSekunden = Sekunden * 6; // alle 6° eine Minute vorwärts GradMinuten = Minuten * 6; // alle 30° eine Stunde vorwärts // 30 / 3600 = 0.0833333 // sorgt dafür, dass der Stundenzeiger entsprechend // der Anzahl der Minuten weiter "wandert" GradStunden = Stunden * 30 + GradMinuten * 0.0833333; StundePosX = cos((GradStunden - 90) * DEG_TO_RAD); StundePosY = sin((GradStunden - 90) * DEG_TO_RAD); MinutePosX = cos((GradMinuten - 90) * DEG_TO_RAD) ; MinutePosY = sin((GradMinuten - 90) * DEG_TO_RAD); SekundePosX = cos((GradSekunden - 90) * DEG_TO_RAD); SekundePosY = sin((GradSekunden - 90) * DEG_TO_RAD); // nach jeder Minute Minuten-/Stundenzeiger löschen // oder einmalig beim Start der Anzeige if (Sekunden == 0 || Start) { Start = false; tft.drawLine(StundenZeigerX, StundenZeigerY, MitteHoehe, MitteHoehe + 1, Kreisfarbe); // 62 Pixel -> Länge des Stundenzeigers // Mittelpunkt + 1 -> Mittelpunkt soll nicht gelöscht werden StundenZeigerX = StundePosX * 62 + MitteHoehe + 1; StundenZeigerY = StundePosY * 62 + MitteHoehe + 1; tft.drawLine(MinutenZeigerX, MinutenZeigerY, MitteHoehe, MitteHoehe + 1, Kreisfarbe); // 84 Pixel -> Länge des Minutenzeigers // Mittelpunkt + 1 -> Mittelpunkt soll nicht gelöscht werden MinutenZeigerX = MinutePosX * 84 + MitteHoehe; MinutenZeigerY = MinutePosY * 84 + MitteHoehe + 1; } // Sekundenzeiger löschen if (!SekundenzeigerKreis) tft.drawLine(SekundenZeigerX, SekundenZeigerY, MitteHoehe, MitteHoehe + 1, Kreisfarbe); // Kreis am Sekundenzeiger löschen, Radius 5 tft.fillCircle(SekundenZeigerX, SekundenZeigerY, 5, Kreisfarbe); // 85 Pixel -> Länge des Sekundenzeigers SekundenZeigerX = SekundePosX * 85 + MitteHoehe + 1; SekundenZeigerY = SekundePosY * 85 + MitteHoehe + 1; // Zeiger neu zeichnen // Sekunden Linie nur anzeigen wenn SekundenzeigerKreis false if (!SekundenzeigerKreis) tft.drawLine(SekundenZeigerX, SekundenZeigerY, MitteHoehe, MitteHoehe + 1, ROT); // Minuten tft.drawLine(MinutenZeigerX, MinutenZeigerY, MitteHoehe, MitteHoehe + 1, Zeigerfarbe); // Stunden tft.drawLine(StundenZeigerX, StundenZeigerY, MitteHoehe, MitteHoehe + 1, Zeigerfarbe); // Kreis an der Spitze des Sekundenzeigers, Radius 5 tft.fillCircle(SekundenZeigerX, SekundenZeigerY, 5, ROT); // Mittelpunkt zeichnen tft.fillCircle(MitteHoehe, MitteHoehe + 1, 3, Zeigerfarbe); } } |
Die Funktion ZeigeDatum
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void ZeigeDatum() { tft.setFont(&FreeSans12pt7b); tft.setCursor(65, 170); tft.setTextColor(GRUEN); // Bildschirmbereich für das Datum löschen tft.fillRect(60, 150, 125, 25, Kreisfarbe); if (Zeit.tm_mday < 10) tft.print("0"); tft.print(Zeit.tm_mday); tft.print("."); // Monat: führende 0 ergänzen if (Zeit.tm_mon < 9) tft.print("0"); // Zählung beginnt mit 0 -> +1 tft.print(Zeit.tm_mon + 1); tft.print("."); // Anzahl Jahre seit 1900 tft.print(Zeit.tm_year + 1900); } |
Quellen
Ähnliche Projekte
- Analoge Uhr mit TFT 240×240 Pixeln und RTC-Modul
- Datum und Zeit mit ESP und time.h anzeigen
- Datum und Zeit mit dem NTP-Protokoll anzeigen
- DHT – Messdaten und Zeit auf TFT anzeigen
- Stoppuhr
- Uhrzeit auf LED-Matrix anzeigen
- Zeit mit time.h auf einem TFT anzeigen
- Wecker mit RTC-Modul DS3231
- Zeit im Seriellen Monitor mit ESP-Mikrocontroller anzeigen
- Datum, Uhrzeit und Temperatur auf einem LCD mit einem RTC-Modul anzeigen
Letzte Aktualisierung: