Zeit mit time.h auf einem TFT anzeigen


Lese­zeit: 8 Minu­ten



Zie­le des Projekts

  • Ein­füh­rung in die Biblio­thek U8g2_for_Adafruit_GFX
  • Dar­stel­lung von Datum und Uhr­zeit in gro­ßer Schrift

Ver­wen­de­te Hardware

  • TFT-Dis­play mit 320×240 Pixeln
  • ESP32-Wroom mit inte­grier­tem TFT-Dis­play mit 320×170 Pixeln (Ide­aS­park)

So sieht es aus:

TFT-Dis­play mit 320×170 Pixeln
TFT-Dis­play 320×240 Pixel

Kon­fi­gu­ra­ti­on der Mikrocontroller

Die Biblio­thek U8g2_for_Adafruit_GFX

Die Biblio­thek U8g2_for_Adafruit_GFX ist eine Ergän­zung der von Adafruit ent­wi­ckel­ten Gra­fik­bi­blio­thek. Sie stellt Funk­tio­nen für die Dar­stel­lung von Text zur Verfügung.

Außer­dem ste­hen eine Viel­zahl von 🔗Schrif­ten bereit.

Schlüs­sel­wortAkti­on
setFontDirection(Parameter);0: von links nach rechts (Stan­dard)
1: von rechts nach links
setForegroundColor(Farbe);Vor­der­grund­far­be
setBackgroundColor(Farbe)Hin­ter­grund­far­be
setFont(Schritart);Schft­art festlegen
setCursor(x, y);Cur­sor setzen
print(Text);Text schrei­ben

Benö­tig­te Biblio­thek installieren

Anmer­kun­gen zum Programm

  • im Kopf des Pro­gramms muss ein Objekt der Biblio­thek erstellt wer­den
    U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;
  • im set­up-Teil wird das Objekt der Biblio­thek (u8g2Schriften) der Gra­fik­bi­blio­thek (tft) zuge­ord­net
    u8g2Schriften.begin(tft);
  • jeder Funk­ti­on zur Dar­stel­lung von Text muss der Name des Objek­tes (u8g2Schriften) vor­an­ge­stellt wer­den:
    Vor­der­grund­far­be: u8g2Schriften.setForegroundColor(Farbe);
    Hin­ter­grund­far­be: u8g2Schriften.setBackgroundColor(Farbe);
    Schrift­art: u8g2Schriften.setFont(Schriftart);
    u8g2Schriften.setCursor(x, y);
  • Vor­der- und Hin­ter­grund­far­be kön­nen für das Pro­gramm indi­vi­du­ell fest­ge­legt werden

Das Pro­gramm

TFT 320×240 Pixel

#ifdef ESP8266
#include "ESP8266WiFi.h"

#else
#include "WiFi.h"
#endif

#include "time.h"
#include "Adafruit_ILI9341.h"
#include "U8g2_for_Adafruit_GFX.h"

// 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

int Vordergrundfarbe = GRUEN;
int Hintergrundfarbe = SILBER;

// Wemos D1 Mini
// #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 ESP 32
// #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

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// WiFi-Daten
char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

// 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;

// Variablen für die Zeit
int Stunden, Minuten, Sekunden;

// Start wird nur beim ersten Start für den Aufbau des TFTs benötigt
bool Start = true;

unsigned long Zeitmessung = 0;

void setup() 
{
  // Schriften von u8g2 tft zuordnen
  u8g2Schriften.begin(tft);

  // Zeitzone: Parameter für die zu ermittelnde Zeit
  configTzTime(Zeitzone, Zeitserver);

  WiFi.mode(WIFI_STA);

  // WiFi starten
  WiFi.begin(Router, Passwort);

  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());

  // 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");

      // 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.print(":");

    if (Zeit.tm_sec < 10) Serial.print("0");
    Serial.println(Zeit.tm_sec);
    Serial.println("-------------------------");
  }

  // Zeit in Stunden, Minuten und Sekunden
  Stunden = Zeit.tm_hour, Minuten = Zeit.tm_min, Sekunden = Zeit.tm_sec;

  // TFT starten Hintergrundfarbeer Hintergrund
  tft.begin();

  // Rotation anpassen Querformat
  tft.setRotation(1);
  tft.fillScreen(Hintergrundfarbe);
  u8g2Schriften.setForegroundColor(Vordergrundfarbe);
  u8g2Schriften.setBackgroundColor(Hintergrundfarbe);

  ZeigeDatum();

  Zeitmessung = millis() + 1000;
}

void loop() 
{
  // Start = true
  // -> Zeit einmalig synchronisieren
  if (Start)
  {
    Start = false;
  
   // Zeit jede Minute mit Zeitserver synchronisieren
    // aktuelle Zeit holen
    time(&aktuelleZeit);

    // localtime_r -> Zeit in die lokale Zeitzone setzen
    localtime_r(&aktuelleZeit, &Zeit);

    // Zeit in Stunden, Minuten und Sekunden
    Stunden = int(Zeit.tm_hour), Minuten = int(Zeit.tm_min), Sekunden = int(Zeit.tm_sec);

    ZeitAnzeigen();
  }

  // Sekunden weiter zählen
  if (Zeitmessung < millis()) 
  {
    Zeitmessung += 1000;
    Sekunden++;

    if (Sekunden == 60) 
    {
      // Zeit jede Minute mit Zeitserver synchronisieren
      // aktuelle Zeit holen
      time(&aktuelleZeit);

      // localtime_r -> Zeit in die lokale Zeitzone setzen
      localtime_r(&aktuelleZeit, &Zeit);

      // Zeit in Stunden, Minuten und Sekunden
      Stunden = int(Zeit.tm_hour), Minuten = int(Zeit.tm_min), Sekunden = int(Zeit.tm_sec);

      // Mitternacht
      // -> Wechsel des Datums anzeigen
      if (Stunden == 0 && Minuten == 0) 
      {
        Serial.println("neues Datum");
        ZeigeDatum();
      }

      ZeitAnzeigen();
    }
  }
}

void ZeitAnzeigen()
{
    // Bereich für die Uhrzeit löschen
    tft.fillRect(1, 80, tft.width(), tft.height(), Hintergrundfarbe);

    u8g2Schriften.setFont(u8g2_font_logisoso78_tn);

    // Cursor setzen
    u8g2Schriften.setCursor(2, 200);

    // Stunde: wenn Stunde < 10 -> 0 davor setzen
    if (Zeit.tm_hour < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_hour);
    u8g2Schriften.print(":");

    // Minuten
    // wenn Minute < 10 -> 0 davor setzen
    if (Zeit.tm_min < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_min);
}

void ZeigeDatum()
{
  tft.fillScreen(Hintergrundfarbe);
  
  u8g2Schriften.setFont(u8g2_font_fub42_tf);

  // Cursor setzen
  u8g2Schriften.setCursor(20, 50);

 // Tag: führende 0 ergänzen
  if (Zeit.tm_mday < 10) 
  {
    Serial.print("0");
    u8g2Schriften.print("0");
  }
  Serial.print(Zeit.tm_mday);
  Serial.print(".");
  u8g2Schriften.print(Zeit.tm_mday);
  u8g2Schriften.print(".");

  // Monat: führende 0 ergänzen
  if (Zeit.tm_mon < 9) 
  {
    Serial.print("0");
    u8g2Schriften.print("0");
  }
  Serial.print(Zeit.tm_mon + 1);
  Serial.print(".");
  u8g2Schriften.print(Zeit.tm_mon + 1);
  u8g2Schriften.print(".");

  // Anzahl Jahre seit 1900
  Serial.print(Zeit.tm_year + 1900);
  Serial.print(" ");
  u8g2Schriften.print(Zeit.tm_year + 1900);

  tft.drawFastHLine(1, 65, tft.width(), Vordergrundfarbe);
  tft.drawFastHLine(1, 66, tft.width(), Vordergrundfarbe);
}

TFT 320×170 Pixel (Ide­aS­park)

#include "WiFi.h"
#include "time.h"
#include "Adafruit_ST7789.h"
#include "U8g2_for_Adafruit_GFX.h"

#define TFT_CS        15
#define TFT_RST        4
#define TFT_DC         2

// 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

int Vordergrundfarbe = WEISS;
int Hintergrundfarbe = SCHWARZ;

#define TFT_CS        15
#define TFT_RST        4
#define TFT_DC         2

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// WiFi-Daten
char Router[] = "Router_SSID";
char Passwort[] = "anea1246";

// 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;

// Variablen für die Zeit
int Stunden, Minuten, Sekunden;

// Start wird nur beim ersten Start für den Aufbau des TFTs benötigt
bool Start = true;

unsigned long Zeitmessung = 0;

void setup() 
{
  // Schriften von u8g2 tft zuordnen
  u8g2Schriften.begin(tft);

  // Zeitzone: Parameter für die zu ermittelnde Zeit
  configTzTime(Zeitzone, Zeitserver);

  WiFi.mode(WIFI_STA);

  // WiFi starten
  WiFi.begin(Router, Passwort);

  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());

  // 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");

      // 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.print(":");

    if (Zeit.tm_sec < 10) Serial.print("0");
    Serial.println(Zeit.tm_sec);
    Serial.println("-------------------------");
  }

  // Zeit in Stunden, Minuten und Sekunden
  Stunden = Zeit.tm_hour, Minuten = Zeit.tm_min, Sekunden = Zeit.tm_sec;

  // TFT starten
  tft.init(170, 320);

  // Rotation anpassen Querformat
  tft.setRotation(1);
  tft.fillScreen(Hintergrundfarbe);
  u8g2Schriften.setForegroundColor(Vordergrundfarbe);
  u8g2Schriften.setBackgroundColor(Hintergrundfarbe);
  u8g2Schriften.setFont(u8g2_font_fub42_tf);

  ZeigeDatum();

  Zeitmessung = millis() + 1000;
}

void loop() 
{
  // Start = true
  // -> Zeit einmalig synchronisieren
  if (Start)
  {
    Start = false;
  
   // Zeit jede Minute mit Zeitserver synchronisieren
    // aktuelle Zeit holen
    time(&aktuelleZeit);

    // localtime_r -> Zeit in die lokale Zeitzone setzen
    localtime_r(&aktuelleZeit, &Zeit);

    // Zeit in Stunden, Minuten und Sekunden
    Stunden = int(Zeit.tm_hour), Minuten = int(Zeit.tm_min), Sekunden = int(Zeit.tm_sec);

    ZeitAnzeigen();
  }

  // Sekunden weiter zählen
  if (Zeitmessung < millis()) 
  {
    Zeitmessung += 1000;
    Sekunden++;

    if (Sekunden == 60) 
    {
      // Zeit jede Minute mit Zeitserver synchronisieren
      // aktuelle Zeit holen
      time(&aktuelleZeit);

      // localtime_r -> Zeit in die lokale Zeitzone setzen
      localtime_r(&aktuelleZeit, &Zeit);

      // Zeit in Stunden, Minuten und Sekunden
      Stunden = int(Zeit.tm_hour), Minuten = int(Zeit.tm_min), Sekunden = int(Zeit.tm_sec);

      // Mitternacht
      // -> Wechsel des Datums anzeigen
      if (Stunden == 0 && Minuten == 0) 
      {
        Serial.println("neues Datum");
        ZeigeDatum();
      }

      ZeitAnzeigen();
    }
  }
}

void ZeitAnzeigen()
{
    // nur den Beriech der Zeit löschen
    tft.fillRect(1, 75, tft.width(), tft.height(), Hintergrundfarbe);

    u8g2Schriften.setFont(u8g2_font_logisoso78_tn);

    // Cursor setzen
    u8g2Schriften.setCursor(2, 160);

    // Stunde: wenn Stunde < 10 -> 0 davor setzen
    if (Zeit.tm_hour < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_hour);
    u8g2Schriften.print(":");

    // Minuten
    // wenn Minute < 10 -> 0 davor setzen
    if (Zeit.tm_min < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_min);
}

void ZeigeDatum()
{
  tft.fillScreen(Hintergrundfarbe);
  
  u8g2Schriften.setFont(u8g2_font_fub42_tf);

  // Cursor setzen
  u8g2Schriften.setCursor(10, 50);

 // Tag: führende 0 ergänzen
  if (Zeit.tm_mday < 10) 
  {
    Serial.print("0");
    u8g2Schriften.print("0");
  }
  Serial.print(Zeit.tm_mday);
  Serial.print(".");
  u8g2Schriften.print(Zeit.tm_mday);
  u8g2Schriften.print(".");

  // Monat: führende 0 ergänzen
  if (Zeit.tm_mon < 9) 
  {
    Serial.print("0");
    u8g2Schriften.print("0");
  }
  Serial.print(Zeit.tm_mon + 1);
  Serial.print(".");
  u8g2Schriften.print(Zeit.tm_mon + 1);
  u8g2Schriften.print(".");

  // Anzahl Jahre seit 1900
  Serial.print(Zeit.tm_year + 1900);
  Serial.print(" ");
  u8g2Schriften.print(Zeit.tm_year + 1900);

  tft.drawFastHLine(1, 65, tft.width(), Vordergrundfarbe);
  tft.drawFastHLine(1, 66, tft.width(), Vordergrundfarbe);
}

Quel­len


Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen

Ver­wand­te Anleitungen


Letzte Aktualisierung: Aug. 8, 2025 @ 11:09