Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Gartenautomation
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Deutsch
  • English
Menu

Arduino UNO R4 Projekt: Weltzeituhr mit LCD Keypad Shield

Posted on 13. Mai 202413. Mai 2024 by Stefan Draeger

Wie du das LCD Keypad Shield programmierst, habe ich dir bereits im Beitrag LCD Keypad Shield für Arduino: Einsteigerfreundliches Display mit Tastensteuerung ausführlich erläutert. In diesem Beitrag soll es nun darum gehen, wie du dir eine Weltzeituhr am Arduino UNO R4 programmierst. Der Arduino UNO R4 verfügt über einen ESP32 Chip und mit dem Formfaktor des alten UNO R3 ist dieser bestens geeignet für dieses Projekt.

Arduino UNO R4 Projekt: Weltzeituhr mit LCD Keypad Shield
Dieses Video auf YouTube ansehen.

Der Aufbau einer Schaltung ist recht einfach, denn das LCD Keypad Shield wird lediglich auf den Mikrocontroller gesteckt.

Das LCD Display verfüg über zwei Zeilen mit je 16 Zeichen, das ist für die Anzeige von Datum, Uhrzeit und der Zeitzone etwas wenig, daher habe ich das auf den Tag, die Uhrzeit und die Zeitzone in Kurzform komprimiert.

Inhaltsverzeichnis

  • Benötigte Ressourcen für dieses kleine Projekt
  • NTP Timeserver für die Abfrage von Zeiten
    • Liste mit Zeitzonen und TimeOffsets
  • Programmieren einer Weltzeituhr mit einem NTP Zeitserver
    • Schritt 1 – Installation der benötigten Bibliotheken
    • Schritt 2 – Aufbau einer WiFi Verbindung
    • Schritt 3 – Abfrage einer Zeit von einem NTPServer
    • Schritt 4 – Ausgeben der Daten auf dem LCD Display
    • Schritt 5 – Anzeigen von unterschiedlichen Weltzeiten auf dem Display
  • Arbeiten mit dem Timestamp

Benötigte Ressourcen für dieses kleine Projekt

Wenn du das kleine Projekt nachbauen möchtest, dann benötigst du:

  • einen Arduino UNO R4 WiFi*,
  • ein USB-C Datenkabel*,
  • ein LCD Keypad Shield*

Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!

NTP Timeserver für die Abfrage von Zeiten

Es gibt im Internet einige NTP Timeserver welche für dieses Projekt verwendet werden können, für dieses Projekt verwende ich ptbtime1.ptb.de von der Physikalisch-technische Bundesanstalt.

Wir müssen lediglich für die jeweilige Zeitzone noch Stunden dazu oder abzählen.

Liste mit Zeitzonen und TimeOffsets

Nachfolgend gebe ich dir eine Tabelle, aus welcher du entnehmen kannst, welchen Offset du für die Zeit verwenden musst.

Rechenbeispiele:

  • für Pacific Standard Time (PST) musst du von der aktuellen Uhrzeit -8h rechnen,
  • für Japan Standard Time (JST) musst du von der aktuellen Uhrzeit +9h rechnen
KontinentZeitzoneUTC Zeit
NordamerikaEastern Standard Time (EST)UTC-5
Central Standard Time (CST)UTC-6
Mountain Standard Time (MST)UTC-7
Pacific Standard Time (PST)UTC-8
Alaska Standard Time (AKST)UTC-9
Hawaii-Aleutian Standard Time (HAST)UTC-10
SüdamerikaBrasília Time (BRT)UTC-3
Argentina Standard Time (ART)UTC-3
Chile Standard Time (CLT)UTC-4
Venezuela Standard Time (VET)UTC-4:30
EuropaGreenwich Mean Time (GMT)UTC+0
Central European Time (CET)UTC+1
Eastern European Time (EET)UTC+2
British Summer Time (BST)UTC+1
AfrikaWest Africa Time (WAT)UTC+1
Central Africa Time (CAT)UTC+2
East Africa Time (EAT)UTC+3
South Africa Standard Time (SAT)UTC+2
AsienIndian Standard Time (IST)UTC+5:30
China Standard Time (CST)UTC+8
Japan Standard Time (JST)UTC+9
Australian Eastern Standard Time (AEST)UTC+10
Australian Central Standard Time (ACST)UTC+9:30
Australian Western Standard Time (AWST)UTC+8
OzeanienNew Zealand Standard Time (NZST)UTC+12
Fiji Standard Time (FST)UTC+12
Tonga Standard Time (TST)UTC+13

Programmieren einer Weltzeituhr mit einem NTP Zeitserver

Wie du dich mit einem Mikrocontroller zu einem WiFi Netzwerk verbindest, habe ich dir bereits in einigen Beiträgen ausführlich erläutert. Jedoch nehme ich dich in der nachfolgenden Schritt-für-Schritt-Anleitung an die Hand, sodass du alle Informationen in diesem Beitrag findest.

Schritt 1 – Installation der benötigten Bibliotheken

Für die Abfrage der Zeit aus dem Internet benötigen wir eine Bibliothek, ich verwende hier NTPClient welche als ZIP-Datei vom GitHub Repository arduino-libraries/NTPClient heruntergeladen werden kann.

Schritt 2 – Aufbau einer WiFi Verbindung

Im ersten richtigen Schritt programmieren wir die WiFi Verbindung, dieses ist recht einfach und mit wenigen Zeilen Code erledigt.

//Bibliotheken zum aufbau einer WiFi Verbindung
#include <WiFi.h>
#include <WiFiUdp.h>

//Die Zugangsdaten zum WiFi-Netzwerk
const char *ssid = "*****";
const char *password = "*****";

void setup() {
  //beginn der seriellen Kommunikation
  Serial.begin(115200);
  //Aufbau der WiFi Verbindung
  WiFi.begin(ssid, password);

  //solange noch keine Verbindung hergestellt wurde, soll
  //eine Pause von 500ms eingelegt werden,
  //ein Punkt auf der seriellen Schnittstelle ausgegeben werden
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  //Wenn die Verbindung erfolgreich aufgebaut wurde, dann
  //wird der nchfolgende Text angezeigt.
  Serial.print("Erfolgreich zu ");
  Serial.print(ssid);  
  Serial.println(" verbunden!");
  

}

void loop() {
   //bleibt leer
}

Wenn die Verbindung zum Netzwerk hergestellt wurde, dann erscheint auf der seriellen Schnittstelle die Ausgabe vom Text „Erfolgreich zu <ssid> verbunden!“.

Schritt 3 – Abfrage einer Zeit von einem NTPServer

Wie erwähnt möchte ich die Daten vom Zeitserver der Physikalisch-technische Bundesanstalt abrufen. Die Adresse von diesem ist ptbtime1.ptb.de.

//Bibliotheken zum aufbau einer WiFi Verbindung
#include <WiFi.h>
#include <WiFiUdp.h>

//Die Zugangsdaten zum WiFi-Netzwerk
const char *ssid = "*****";
const char *password = "*****";

void setup() {
  //beginn der seriellen Kommunikation
  Serial.begin(115200);
  //Aufbau der WiFi Verbindung
  WiFi.begin(ssid, password);

  //solange noch keine Verbindung hergestellt wurde, soll
  //eine Pause von 500ms eingelegt werden,
  //ein Punkt auf der seriellen Schnittstelle ausgegeben werden
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  //Wenn die Verbindung erfolgreich aufgebaut wurde, dann
  //wird der nchfolgende Text angezeigt.
  Serial.print("Erfolgreich zu ");
  Serial.print(ssid);  
  Serial.println(" verbunden!");
  

}

void loop() {
   //bleibt leer
}

Die Ausgabe auf der seriellen Schnittstelle ist wiefolgt:

  • erste Zeile, der Hinweis das die WiFi-Verbindung aufgebaut wurde,
  • zweite bis n-te Zeile, die Uhrzeit vom NTPServer

Wenn noch keine Verbindung zum Server hergestellt wurde, dann kann auch einmal die Uhrzeit mit 01:00:00 geliefert werden. Hier muss man lediglich ein paar Sekunden warten.

In der Grafik ist ersichtlich, dass die Uhrzeit um eine Stunde verschoben ist, bedingt durch die europäische Sommerzeit. Um dies anzupassen, wird die Funktion setTimeOffset am Objekt timeClient aufgerufen, welches in der setup-Funktion initialisiert wird. Dabei wird der Funktion einmalig ein Parameter von 7200 Sekunden übergeben, was zwei Stunden entspricht.

  timeClient.setTimeOffset(7200);

Schritt 4 – Ausgeben der Daten auf dem LCD Display

Das LCD Display hat maximal 16 Zeichen für je zwei Zeilen zur Verfügung, anders als bei OLED Displays kann man hier nicht durch die Auswahl einer kleineren Schriftart für mehr Platz sorgen. Man muss quasi Abstriche machen.

Damit wir mit dem LCD Display kommunizieren können, importieren wir die LiquidCrystal Bibliothek welche bei der Arduino IDE 2.x dabei ist.

//Bibliotheken zum aufbau einer WiFi Verbindung
#include <WiFi.h>
#include <WiFiUdp.h>

//Bibliothek zum kommunizieren mit einem Zeitserver
#include <NTPClient.h>

//Bibliothek zum kommunizieren mit dem LCD Display
#include <LiquidCrystal.h>

//Objekt vom Typ LiquidCrystal initialisieren
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//Die Zugangsdaten zum WiFi-Netzwerk
const char *ssid = "*****";
const char *password = "******";

WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "ptbtime1.ptb.de", 3600, 60000);

void setup() {
  //beginn der seriellen Kommunikation
  Serial.begin(115200);
  //Aufbau der WiFi Verbindung
  WiFi.begin(ssid, password);

  //solange noch keine Verbindung hergestellt wurde, soll
  //eine Pause von 500ms eingelegt werden,
  //ein Punkt auf der seriellen Schnittstelle ausgegeben werden
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //Wenn die Verbindung erfolgreich aufgebaut wurde, dann
  //wird der nchfolgende Text angezeigt.
  Serial.print("Erfolgreich zu ");
  Serial.print(ssid);
  Serial.println(" verbunden!");

  //beginn der Kommunikation mit dem Zeitserver
  timeClient.begin();

  //Zeitoffset von 1h für die europäische Sommerzeit
  timeClient.setTimeOffset(7200);

  //Das verbaute LCD Display hat 16 Zeichen mit zwei Zeilen.
  //Die Bibliothek kann für viele weitere verwendet werden, daher müssen
  //diese Daten übergeben werden.
  lcd.begin(16, 2);
}

void loop() {
  //aktualisieren der Daten
  timeClient.update();
  //Ausgeben eines formatierten Zeitstempels
  String formattedTime = timeClient.getFormattedTime();
  Serial.println(formattedTime);

  //Daten im LCD Display leeren
  lcd.clear();
  //Anzeigen der Uhrzeit
  lcd.print(formattedTime);

  //eine Pause von 1 Sekunde
  delay(1000);
}

Die Uhrzeit wird nun nicht nur auf der seriellen Schnittstelle ausgegeben, sondern auch auf dem LCD Display.

Schritt 5 – Anzeigen von unterschiedlichen Weltzeiten auf dem Display

Im nächsten Schritt wollen wir jetzt eine Liste von Weltzeiten anlegen und diese nacheinander anzeigen lassen. In der zweiten noch leeren Zeile möchte ich die Zeitzone und die Differenz anzeigen lassen.

Weltzeituhr am Arduino UNO R4 WiFi mit dem LCD Keypad ShieldHerunterladen

Am einfachsten geht dieses mit einem MenuItem welches nachfolgende Eigenschaften hat:

struct MenuItem {
  double timeOffset; //die Zeit welche abgezogen/addiert werden soll
  String timezone;   //die Bezeichnung der Zeitzone
};

Von diesem neuen Datentyp MenuItem können wir uns nun beliebig viele anlegen und in ein Array ablegen.

MenuItem item1 = { 1, "CEST (UTC +2)" };       //Central European Summer Time (CEST)
MenuItem item2 = { 0, "GMT (UTC +0)" };        //Greenwich Mean Time (GMT)
MenuItem item3 = { -4, "CLT (UTC -4)" };       //Chile Standard Time (CLT)
MenuItem item4 = { 12, "NZST (UTC +12)" };     //New Zealand Standard Time (NZST)
MenuItem item5 = { 9.5, "ACST (UTC +9:30)" };  //Australian Central Standard Time (ACST)
MenuItem item6 = { -10, "HAST (UTC -10)" };    //Hawaii-Aleutian Standard Time (HAST)

const int NUM_MENUITEMS = 6;

MenuItem menu[NUM_MENUITEMS] = {
  item1, item2, item3, item4, item5, item6
};

Wir entnehmen ein MenuItem mit dem aktuellen index aus dem Array. Im Anschluss berechnen wir den Offset. Dieser Offset wird in Sekunden übergeben (1h = 3600 Sekunden).

Die nächsten Zeilen dienen dann lediglich um den Zeitstempel wie zuvor zu laden und auf dem Display anzuzeigen.

MenuItem item = menu[index];

double timeOffset = item.timeOffset * 3600;
timeClient.setTimeOffset(timeOffset);

//aktualisieren der Daten
timeClient.update();
//Ausgeben eines formatierten Zeitstempels
String formattedTime = timeClient.getFormattedTime();
Serial.println(formattedTime);

//Daten im LCD Display leeren
lcd.clear();

//Anzeigen der Uhrzeit
lcd.print(formattedTime);
//Anzeigen der Zeitzone
lcd.setCursor(0, 1);
lcd.print(item.timezone);

Die Weltzeiten sollen immer jeweils für 5 Sekunden angezeigt werden, dafür nutze ich eine bekannte Lösung mit einer Pause ohne Delay. Da ich auf die Werte im Array mit der Variable index zugreife erhöhe ich diese damit alle 5 Sekunden jedoch läuft das Programm im Hintergrund weiter.

long lastAction = -1;
const long PAUSE = 3000;

 //Alle 5 Sekunden die Zeitzone wechseln
  long currentMillis = millis();
  if (lastAction + PAUSE < currentMillis) {
    lastAction = currentMillis;
    if (index < NUM_MENUITEMS-1) {
      index++;
    } else {
      index = 0;
    }
  }

Arbeiten mit dem Timestamp

Von der Bibliothek erhalten wir mit der Funktion getEpochTime() einen Zeitstempel in Sekunden. Dieser repräsentiert die vergangenen Sekunden seit dem 01.01.1970. Aus diesem können wir zusätzlich auch das Datum berechnen und somit auf dem Display zusätzlich das Datum anzeigen. Ich habe hier bei der Uhrzeit die Sekunden abgeschnitten und das Jahr auf zweistellig gekürzt.

Das fertige Programm kannst du nachfolgend herunterladen:

Anzeige von Datum & Uhrzeit von verschiedenen Zeitzonen am LCD Keypad Shield mit dem Arduino UNO R4 WiFiHerunterladen
// Funktion zur Umwandlung eines Unix-Timestamps in ein Datum
String formatiereDatum(unsigned long timestamp) {
  unsigned long days = timestamp / 86400; // Tage seit dem Unix-Epoch
  unsigned long years = 1970; // Beginn des Unix-Epoch
  unsigned long remainingDays = days;
  
  // Jahr berechnen
  while (remainingDays >= 365) {
    if (istSchaltjahr(years)) {
      remainingDays -= 366;
    } else {
      remainingDays -= 365;
    }
    years++;
  }
  
  // Monat und Tag berechnen
  unsigned long months = 0;
  unsigned long monthLength = 0;
  while (remainingDays > monthLength) {
    monthLength = tageImMonat(months, years);
    remainingDays -= monthLength;
    months++;
  }
  return zweistellig(remainingDays + 1) + "." + zweistellig(months + 1) + "." + String(years % 100);
}

// Funktion zur Überprüfung, ob ein Jahr ein Schaltjahr ist
bool istSchaltjahr(unsigned long year) {
  return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// Funktion zur Rückgabe der Anzahl der Tage in einem Monat
unsigned long tageImMonat(unsigned long month, unsigned long year) {
  if (month == 1) { // Februar
    if (istSchaltjahr(year)) {
      return 29;
    } else {
      return 28;
    }
  } else if (month == 3 || month == 5 || month == 8 || month == 10) { // April, Juni, September, November
    return 30;
  } else {
    return 31;
  }
}

// Funktion zur Umwandlung eines Unix-Timestamps in eine Uhrzeit
String formatiereUhrzeit(unsigned long timestamp) {
  unsigned long minutes = (timestamp % 3600) / 60;
  unsigned long hours = (timestamp % 86400) / 3600;

  return zweistellig(hours) + ":" + zweistellig(minutes);
}

// Funktion zur Formatierung von Zahlen auf zwei Stellen
String zweistellig(unsigned long zahl) {
  if (zahl < 10) {
    return "0" + String(zahl);
  } else {
    return String(zahl);
  }
}

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen
Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

link zu Fabook
link zu LinkedIn
link zu YouTube
link zu TikTok
link zu Pinterest
link zu Instagram
  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}