Zeit mit Biblio­thek TFT_eSPI

// ESP32
#include "WiFi.h"

// ESP8266
// #include "ESP8266WiFi.h"

#include "time.h"
#include "TFT_eSPI.h"

TFT_eSPI tft = TFT_eSPI();

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;

const unsigned char Uhr [] PROGMEM = {
	// 'Uhr, 80x80px
	0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 
	0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 
	0xe0, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 
	0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 
	0x01, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x0f, 
	0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x03, 0xc0, 0x00, 0x0f, 
	0xf8, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xc0, 0x00, 
	0x01, 0x80, 0x00, 0x03, 0xfe, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x0e, 0x01, 0xff, 0x00, 
	0x00, 0xff, 0x00, 0x70, 0x00, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x01, 0xfe, 0x00, 0x70, 0x00, 0x00, 
	0x0e, 0x00, 0x7f, 0x80, 0x03, 0xfc, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x03, 0xf8, 
	0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xc0, 0x07, 0xf0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 
	0x0f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x00, 0x00, 
	0x01, 0x80, 0x00, 0x00, 0x07, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xf0, 
	0x1f, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0x80, 0xe0, 0x00, 0x01, 0x80, 
	0x00, 0x03, 0x81, 0xf8, 0x3f, 0x80, 0xe0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x81, 0xfc, 0x3f, 0x80, 
	0xe0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x81, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 
	0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xfe, 0x7e, 0x00, 0x00, 0x00, 
	0x01, 0x80, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x7e, 
	0x7e, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x01, 0x80, 
	0x00, 0x00, 0x00, 0x7e, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 
	0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 
	0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x0c, 0x00, 0x00, 
	0x01, 0x80, 0x00, 0x00, 0x30, 0x3f, 0xfc, 0x1c, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x78, 0x3f, 
	0xfc, 0x1c, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x78, 0x3f, 0xfc, 0x0c, 0x00, 0x00, 0x1f, 0x80, 
	0x00, 0x00, 0x30, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 
	0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 
	0x00, 0x3f, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7e, 0x00, 0x00, 0x3f, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 
	0x7e, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x07, 0xe0, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x7e, 0x7f, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 
	0x80, 0xfc, 0x3f, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0xfc, 0x1f, 0x80, 0xc0, 0x00, 
	0x00, 0x00, 0x00, 0x03, 0x81, 0xf8, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 
	0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x07, 0xf0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xf0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x1f, 0xc0, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x01, 0xfe, 0x00, 0x70, 
	0x00, 0x00, 0x0e, 0x00, 0x7f, 0x80, 0x00, 0xff, 0x00, 0x70, 0x00, 0x00, 0x0e, 0x00, 0xff, 0x00, 
	0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x0e, 0x01, 0xff, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x01, 0x80, 
	0x00, 0x03, 0xfe, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x1f, 
	0xf0, 0x00, 0x03, 0xc0, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 
	0xf0, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x03, 0xff, 0x80, 
	0x00, 0x00, 0x01, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 
	0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x07, 
	0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 
	0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00
};

const unsigned char Kalender [] PROGMEM = {
	// 'Kalender, 51x60px
	0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xe0, 0xff, 0xff, 
	0xff, 0x1f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 
	0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0xf0, 
	0x00, 0x00, 0x01, 0xe0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 
	0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 
	0x60, 0x80, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
	0x80, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 
	0x00, 0x00, 0x03, 0xf0, 0x60, 0xc1, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0xc1, 0xf8, 0x00, 0x00, 
	0x03, 0xf0, 0x60, 0xc0, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0
};

// Intervall anpassen
unsigned long Intervall = 10000;

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

  Serial.begin(9600);

  // WiFi starten und Verbindung aufbauen
  WiFi.begin(Router, Passwort);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(200);
    Serial.print(".");
  }

  // SSID des Routers anzeigen
  Serial.println();
  Serial.print("Verbunden mit ");
  Serial.println(WiFi.SSID());

  // IP anzeigen
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

   // TFT starten
  tft.begin();

  // Rotation anpassen Querformat
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // Kalender-Symbol anzeigen
  tft.drawBitmap(20, 10, Kalender, 51, 60, TFT_DARKGREEN);  

  // Cursor setzen
  tft.setCursor(120, 20);
  tft.setTextFont(7);
  tft.setTextColor(TFT_DARKGREEN);

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

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

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

  // Trennlinien
  tft.drawFastHLine(1, 80, tft.width(), TFT_WHITE);
  tft.drawFastHLine(1, 81, tft.width(), TFT_WHITE);
  tft.drawFastHLine(1, 82, tft.width(), TFT_WHITE);

  // Uhr-Symbol anzeigen
  tft.drawBitmap(20, 150, Uhr, 80, 80, TFT_WHITE);

  // Cursor setzen
  tft.setCursor(120, 150);
  tft.setTextFont(8);
  tft.setTextColor(TFT_WHITE);

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

  // Minuten
  // wenn Minute < 10 -> 0 davor setzen
  if (Zeit.tm_min < 10) 
  {
    Serial.print("0");
    tft.print("0");
  }
  Serial.println(Zeit.tm_min);
  tft.print(Zeit.tm_min);
  delay(Intervall);
}

Letzte Aktualisierung: Wei­ter lesen ...

DHT11/DHT22 - Mess­da­ten und Zeit auf TFT anzeigen

TFT 128×160

// ESP8266
// #include "ESP8266WiFi.h"

// ESP32
// #include "WiFi.h"

#include "time.h"
#include "Adafruit_ST7735.h"
#include "U8g2_for_Adafruit_GFX.h"
#include "DHT.h"

// freier digitaler Pin für DHT
int SENSOR_DHT = 11;

// Sensortyp festlegen
// DHT22
#define SensorTyp DHT22

// DHT11
// #define SensorTyp DHT11

// Sensor einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

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

// 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_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

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;
WiFiServer Server(80);
WiFiClient Client;

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// Bitmaps
const unsigned char Kalender [] PROGMEM = {
	// 'Kalender_30x35, 30x35px
	0x7f, 0xff, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 
	0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 
	0xff, 0xff, 0xff, 0xfc, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x8e, 0x00, 0x01, 0xc4, 
	0x8e, 0x00, 0x01, 0xc4, 0x8e, 0x00, 0x01, 0xc4, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 
	0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 
	0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 
	0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 
	0x8e, 0x00, 0x01, 0xc4, 0x8e, 0x00, 0x01, 0xc4, 0x8e, 0x00, 0x01, 0xc4, 0x80, 0x00, 0x00, 0x04, 
	0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xfc
};

const unsigned char Uhr [] PROGMEM = {
	// 'Uhr_30x30, 30x30px
	0x00, 0x1f, 0xe0, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x01, 0xf0, 0x3e, 0x00, 0x07, 0x80, 0x07, 0x80, 
	0x0f, 0x03, 0x03, 0xc0, 0x1c, 0x60, 0x18, 0xe0, 0x18, 0x00, 0x00, 0x60, 0x38, 0x01, 0x00, 0x70, 
	0x30, 0x01, 0x00, 0x30, 0x63, 0x01, 0x01, 0x98, 0x60, 0x01, 0x00, 0x18, 0xe0, 0x01, 0x00, 0x1c, 
	0xc0, 0x01, 0x00, 0x0c, 0xc0, 0x01, 0x00, 0x0c, 0xcc, 0x01, 0x00, 0xcc, 0xc0, 0x02, 0x00, 0x0c, 
	0xc0, 0x0c, 0x00, 0x0c, 0xc0, 0x30, 0x00, 0x0c, 0xe0, 0xc0, 0x00, 0x1c, 0x66, 0x00, 0x01, 0x98, 
	0x60, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x70, 0x18, 0x60, 0x10, 0x60, 
	0x1c, 0x00, 0x00, 0xe0, 0x0f, 0x03, 0x03, 0xc0, 0x07, 0x80, 0x07, 0x80, 0x01, 0xf0, 0x3e, 0x00, 
	0x00, 0x7f, 0xfc, 0x00, 0x00, 0x1f, 0xe0, 0x00
};

const unsigned char Thermometer [] PROGMEM = {
	// 'Thermometer_19x40, 19x40px
	0x01, 0xe0, 0x00, 0x03, 0xf8, 0x00, 0x06, 0x0c, 0x00, 0x04, 0x04, 0x00, 0x08, 0x04, 0x00, 0x08, 
	0x04, 0x00, 0x18, 0x04, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x18, 0x04, 
	0x00, 0x08, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x18, 0x04, 0x00, 0x08, 0x04, 0x00, 
	0x00, 0xe4, 0x00, 0x00, 0xe4, 0x00, 0x38, 0xe4, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe4, 0x00, 0x00, 
	0xe4, 0x00, 0x00, 0xe4, 0x00, 0x18, 0xe7, 0x00, 0x30, 0xe3, 0x80, 0x21, 0xe1, 0x80, 0x63, 0xf8, 
	0xc0, 0x47, 0xf8, 0xc0, 0x47, 0xfc, 0x40, 0xc7, 0xfc, 0x60, 0xc7, 0xfc, 0x60, 0xc7, 0xfc, 0x60, 
	0x47, 0xfc, 0x40, 0x63, 0xf8, 0xc0, 0x61, 0xf0, 0xc0, 0x30, 0x01, 0x80, 0x10, 0x03, 0x00, 0x0e, 
	0x0e, 0x00, 0x07, 0xfc, 0x00, 0x00, 0xe0, 0x00
};

const unsigned char Regen [] PROGMEM = {
	// 'Regen_43x35, 43x35px
	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x22, 0x22, 0x21, 0x00, 0x00, 0x00, 0x66, 0x22, 0x23, 0x20, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
	0x03, 0x11, 0x11, 0x19, 0x10, 0x00, 0x02, 0x00, 0x01, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x08, 0x08, 0x88, 0x80, 0x31, 0x11, 
	0x19, 0x18, 0x89, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x88, 0x8c, 0x88, 0xc4, 0xcc, 0xc0, 0x08, 0x88, 0x88, 0x04, 
	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
	0x00, 0x00, 0x80, 0x00, 0x23, 0x33, 0x11, 0x11, 0x99, 0x00, 0x20, 0x20, 0x11, 0x10, 0x11, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x88, 0x88, 0x88, 
	0x88, 0x00, 0x01, 0x08, 0x98, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x46, 0x00, 0x00, 
	0x00, 0x04, 0x44, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00
};

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

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

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

  // Zufallsgenerator starten
  randomSeed(analogRead(A0));
  Serial.begin(9600);
  delay(500);
  Serial.println("Bildschirm: " + String(tft.height()) + " x " + String(tft.width()));

  // TFT starten
  tft.initR(INITR_BLACKTAB);

  // Rotation anpassen
  tft.setRotation(2);

  // Bitmaps anzeigen
  tft.fillScreen(ST77XX_BLACK);
  tft.drawBitmap(1, 1, Kalender, 30, 35, ST77XX_WHITE);  
  tft.drawBitmap(1, 40, Uhr, 30, 30, ST77XX_WHITE);
  tft.drawBitmap(10, 75, Thermometer, 19, 40, ST77XX_WHITE);
  tft.drawBitmap(1, 121, Regen, 43, 35, ST77XX_WHITE);

  // Sensor starten
  dht.begin();
}

void loop()
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // Temperatur lesen
  String Temperatur = String(dht.readTemperature());

  // replace -> . durch , ersetzen
  Temperatur.replace(".", ",");

  // Luftfeuchtigkeit lesen
  String Luftfeuchtigkeit = String(dht.readHumidity());

  // replace -> . durch , ersetzen
  Luftfeuchtigkeit.replace(".", ",");

  // nur den Bereich der Daten schwärzen 
  tft.fillRect(45, 1, tft.width(), tft.height(), ST77XX_BLACK);

  u8g2Schriften.setForegroundColor(ST77XX_WHITE);   
  u8g2Schriften.setBackgroundColor(ST77XX_BLACK);
  u8g2Schriften.setFont(u8g2_font_helvB12_te); 
  u8g2Schriften.setCursor(48, 20); 
    
    // Tag: führende 0 ergänzen
  if (Zeit.tm_mday < 10) 
  {
    u8g2Schriften.print("0");
  }

  u8g2Schriften.print(Zeit.tm_mday);
  u8g2Schriften.print(".");

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

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

  u8g2Schriften.setCursor(48, 60);

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

  // Minuten
  if (Zeit.tm_min < 10) u8g2Schriften.print("0");
  u8g2Schriften.print(Zeit.tm_min);

  // Messdaten anzeigen
  u8g2Schriften.setCursor(48, 100);
  u8g2Schriften.print(Temperatur + " °C");
  u8g2Schriften.setCursor(48, 140);
  u8g2Schriften.print(Luftfeuchtigkeit + " %");

  delay(10000);
}

TFT 240×320

// ESP8266
// #include "ESP8266WiFi.h"

// ESP32
// #include "WiFi.h"

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

// freier digitaler Pin für DHT
int SENSOR_DHT = D3;

// Sensortyp festlegen
// DHT22
#define SensorTyp DHT22

// DHT11
// #define SensorTyp DHT11

// Sensor einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

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

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

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;
WiFiServer Server(80);
WiFiClient Client;

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// Bitmaps
const unsigned char Uhr [] PROGMEM = {
	// 'Uhr, 50x50px
	0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x03, 
	0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x01, 
	0xfe, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0, 
	0x00, 0x01, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf0, 0x00, 0xc0, 0x03, 0xf0, 0x00, 0x07, 
	0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x07, 0x80, 0xc0, 0x00, 0x40, 0x78, 0x00, 0x0f, 0x80, 0x00, 
	0x00, 0x00, 0x7c, 0x00, 0x1f, 0x00, 0x00, 0x80, 0x00, 0x3e, 0x00, 0x1e, 0x00, 0x00, 0xc0, 0x00, 
	0x1e, 0x00, 0x3e, 0x00, 0x00, 0xc0, 0x00, 0x1f, 0x00, 0x3c, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0x00, 
	0x38, 0x30, 0x00, 0xc0, 0x01, 0x07, 0x00, 0x78, 0x00, 0x00, 0xc0, 0x00, 0x07, 0x80, 0x78, 0x00, 
	0x00, 0xc0, 0x00, 0x07, 0x80, 0x70, 0x00, 0x00, 0xc0, 0x00, 0x03, 0x80, 0xf0, 0x00, 0x00, 0xc0, 
	0x00, 0x03, 0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 
	0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 0xc0, 0xf1, 0x80, 0x00, 0xc0, 0x00, 0x63, 0xc0, 0xf1, 
	0x80, 0x01, 0x80, 0x00, 0x63, 0xc0, 0xf0, 0x00, 0x07, 0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x1c, 
	0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x78, 0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0xe0, 0x00, 0x00, 
	0x03, 0xc0, 0x70, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x78, 0x07, 0x00, 0x00, 0x00, 0x07, 0x80, 
	0x78, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x78, 0x20, 0x00, 0x00, 0x01, 0x07, 0x80, 0x3c, 0x00, 
	0x00, 0x00, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x00, 
	0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x7c, 
	0x00, 0x07, 0x80, 0x80, 0x00, 0xc0, 0x78, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x03, 
	0xf0, 0x00, 0xc0, 0x03, 0xf0, 0x00, 0x01, 0xf8, 0x00, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0xfe, 0x00, 
	0x00, 0x1f, 0xc0, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x1f, 0xe0, 0x01, 0xfe, 
	0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf0, 0x00, 0x00, 
	0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00
};

const unsigned char Thermometer [] PROGMEM = {
	// 'Thermometer, 34x70px
	0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 
	0x7c, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x07, 0x80, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0x00, 0x00, 0xe0, 
	0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 
	0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 
	0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 
	0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 
	0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 
	0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 
	0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc3, 0xe1, 0xc0, 
	0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x0f, 0xc3, 0xf1, 0xc0, 0x00, 
	0x0f, 0xc3, 0xf1, 0xc0, 0x00, 0x0f, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 
	0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 
	0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x03, 0xc3, 0xf1, 0xf0, 0x00, 0x07, 0xc3, 0xf0, 
	0xf8, 0x00, 0x0f, 0x03, 0xf0, 0x7c, 0x00, 0x0e, 0x03, 0xe0, 0x3c, 0x00, 0x1c, 0x07, 0xf0, 0x1e, 
	0x00, 0x3c, 0x1f, 0xfc, 0x0f, 0x00, 0x38, 0x3f, 0xfe, 0x0f, 0x00, 0x78, 0x7f, 0xff, 0x07, 0x80, 
	0x70, 0x7f, 0xff, 0x87, 0x80, 0x70, 0x7f, 0xff, 0x83, 0x80, 0xf0, 0xff, 0xff, 0x83, 0xc0, 0xf0, 
	0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 
	0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0x83, 0xc0, 0x70, 0x7f, 0xff, 0x83, 0x80, 0x70, 0x7f, 0xff, 
	0x87, 0x80, 0x78, 0x3f, 0xff, 0x07, 0x80, 0x38, 0x3f, 0xfe, 0x0f, 0x00, 0x3c, 0x0f, 0xfc, 0x0f, 
	0x00, 0x1e, 0x03, 0xe0, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x00, 0x00, 0x7c, 0x00, 
	0x07, 0xe0, 0x01, 0xf8, 0x00, 0x03, 0xf8, 0x07, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x00, 
	0x7f, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00
};

const unsigned char Regen [] PROGMEM = {
	// 'Regen, 60x49px
	0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x02, 0x08, 0x21, 0x04, 0x10, 0x00, 0x00, 0x00, 0x06, 0x18, 0x63, 0x0c, 0x30, 0x80, 0x00, 
	0x00, 0x06, 0x10, 0x63, 0x0c, 0x31, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x20, 0x84, 0x10, 0x41, 0x08, 0x20, 0x00, 0x00, 0x61, 0x8c, 0x30, 0xc3, 0x18, 0x60, 0x00, 
	0x08, 0xc1, 0x8c, 0x30, 0xc3, 0x18, 0x61, 0x00, 0x00, 0x41, 0x04, 0x20, 0x82, 0x08, 0x40, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30, 0x86, 0x18, 0x43, 0x04, 0x30, 0x80, 
	0x18, 0x71, 0x86, 0x18, 0xc3, 0x0c, 0x31, 0x80, 0x18, 0x21, 0x84, 0x10, 0xc3, 0x0c, 0x21, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x18, 0x21, 0x04, 0x10, 0x42, 0x18, 0x40, 
	0x86, 0x18, 0x63, 0x0c, 0x30, 0xc6, 0x18, 0xc0, 0x86, 0x10, 0x63, 0x0c, 0x30, 0xc6, 0x18, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x18, 0x21, 0x04, 0x10, 0xc2, 0x0c, 0x21, 0x00, 0x30, 0x63, 0x0c, 0x31, 0xc6, 0x0c, 0x63, 0x00, 
	0x30, 0x63, 0x0c, 0x31, 0x86, 0x18, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x06, 0x10, 0x43, 0x08, 0x20, 0x86, 0x10, 0x00, 0x06, 0x30, 0xc3, 0x18, 0x61, 0x86, 0x30, 0x00, 
	0x04, 0x30, 0xc2, 0x18, 0x61, 0x8c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x0c, 0x30, 0xc6, 0x18, 0x61, 0x00, 0x00, 
	0x00, 0x00, 0x61, 0xc6, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x60, 0x86, 0x10, 0x60, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char Kalender [] PROGMEM = {
	// 'Kalender, 51x60px
	0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xe0, 0xff, 0xff, 
	0xff, 0x1f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 
	0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0xf0, 
	0x00, 0x00, 0x01, 0xe0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 
	0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 
	0x60, 0x80, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
	0x80, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x81, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0x81, 0xf8, 
	0x00, 0x00, 0x03, 0xf0, 0x60, 0xc1, 0xf8, 0x00, 0x00, 0x03, 0xf0, 0x60, 0xc1, 0xf8, 0x00, 0x00, 
	0x03, 0xf0, 0x60, 0xc0, 0xf0, 0x00, 0x00, 0x01, 0xe0, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xc0
};

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

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

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

  // Zufallsgenerator starten
  randomSeed(analogRead(A0));
  Serial.begin(9600);
  delay(500);
  Serial.println("Bildschirm: " + String(tft.height()) + " x " + String(tft.width()));

  // TFT starten
  tft.begin();

  // Rotation anpassen
  tft.setRotation(2);

  // Bitmaps anzeigen
  tft.fillScreen(ILI9341_BLACK);
  tft.drawBitmap(1, 1, Kalender, 51, 60, ILI9341_WHITE);  
  tft.drawBitmap(1, 90, Uhr, 50, 50, ILI9341_WHITE);
  tft.drawBitmap(10, 170, Thermometer, 34, 70, ILI9341_WHITE);
  tft.drawBitmap(1, 270, Regen, 60, 49, ILI9341_WHITE);

  // Sensor starten
  dht.begin();
}

void loop()
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // Temperatur lesen
  String Temperatur = String(dht.readTemperature());

  // replace -> . durch , ersetzen
  Temperatur.replace(".", ",");

  // Luftfeuchtigkeit lesen
  String Luftfeuchtigkeit = String(dht.readHumidity());

  // replace -> . durch , ersetzen
  Luftfeuchtigkeit.replace(".", ",");

  // nur den Bereich der Daten schwärzen 
  tft.fillRect(60, 1, tft.width(), tft.height(), ILI9341_BLACK);

  u8g2Schriften.setForegroundColor(ILI9341_WHITE);   
  u8g2Schriften.setBackgroundColor(ILI9341_BLACK);
  u8g2Schriften.setFont(u8g2_font_helvB24_tf); 
  u8g2Schriften.setCursor(70, 45); 
    
    // Tag: führende 0 ergänzen
  if (Zeit.tm_mday < 10) 
  {
    u8g2Schriften.print("0");
  }

  u8g2Schriften.print(Zeit.tm_mday);
  u8g2Schriften.print(".");

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

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

  u8g2Schriften.setCursor(70, 120);

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

    // Minuten
    if (Zeit.tm_min < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_min);

     // Messdaten anzeigen
    u8g2Schriften.setCursor(70, 210);
    u8g2Schriften.print(Temperatur + " °C");
    u8g2Schriften.setCursor(70, 300);
    u8g2Schriften.print(Luftfeuchtigkeit + " %");

    delay(10000);
}

Letzte Aktualisierung: Wei­ter lesen ...

DHT11/DHT22 Mess­da­ten auf Wavesha­re 1,54 E-Ink anzeigen

Anzei­ge nur Text

#include "GxEPD2_3C.h"
#include "DHT.h"
#include "U8g2_for_Adafruit_GFX.h"

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// freien Pin auf dem Board wählen
int SENSOR_DHT = 9;

// Sensortyp festlegen
// DHT22
#define SensorTyp DHT22

// DHT11
// #define SensorTyp DHT11

// Sensor einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

// Display-Parameter
// GxEPD2_154_Z90c: Chip SSD1681 Bildschirm: 200x200
#define GxEPD2_DISPLAY_CLASS GxEPD2_3C
#define GxEPD2_DRIVER_CLASS GxEPD2_154_Z90c  

// Board wählen:
// ESP32-Wroom
// Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC -> 2, RST -> 22, BUSY -> 4
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ 5, /*DC=*/ 2, /*RST=*/ 22, /*BUSY=*/ 4));

// NodeMCU
// CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/D4, /*DC=*/ D6, /*RST=*/ D2, /*BUSY=*/ D1));

// ESP32-C6
// Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC -> 3, RST -> 10, BUSY -> 11
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ 18, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 11));

// Nano ESP32
// Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D8, BUSY -> D9
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ D10, /*DC=*/ D6, /*RST=*/ D7, /*BUSY=*/ D9));

void setup() 
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // Sensor starten
  dht.begin();

  // Bildschirm starten
  display.init(115200, true, 2, false); 

  // Bildschirm um 90° drehen
  display.setRotation(1);

  // vollständigen Bildschirm nutzen
  display.setFullWindow();

  // weißer Hintergrund
  display.fillScreen(GxEPD_WHITE);

  // Schriften von u8g2 display zuordnen
  u8g2Schriften.begin(display); 
}

void loop() 
{
  // Temperatur lesen
  String Temperatur = String(dht.readTemperature());

  // replace -> . durch , ersetzen
  Temperatur.replace(".", ",");

  // Luftfeuchtigkeit lesen
  String Luftfeuchtigkeit = String(dht.readHumidity());

  // replace -> . durch , ersetzen
  Luftfeuchtigkeit.replace(".", ",");

  // Anzeige aufbauen
  display.firstPage();
  do 
  {
    display.fillScreen(GxEPD_WHITE);

    u8g2Schriften.setForegroundColor(GxEPD_BLACK);   
    u8g2Schriften.setBackgroundColor(GxEPD_WHITE);
    u8g2Schriften.setFont(u8g2_font_fub35_tf);  

    u8g2Schriften.setCursor(1, 80);
    u8g2Schriften.print(Temperatur + " °C");
    u8g2Schriften.setCursor(1, 180);
    u8g2Schriften.print(Luftfeuchtigkeit + " %");
  } 
  while (display.nextPage());

  // alle 5 Minuten aktualisieren
  delay(300000);
}

Anzei­ge nur Text mit Uhrzeit

// ESP32
// #include "WiFi.h"

// ESP8266
// #include "ESP8266WiFi.h"

#include "time.h"
#include "GxEPD2_3C.h"
#include "U8g2_for_Adafruit_GFX.h"
#include "DHT.h"

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// freien Pin auf dem Board wählen
int SENSOR_DHT = 9;

// Sensortyp festlegen
// DHT22
#define SensorTyp DHT22

// DHT11
// #define SensorTyp DHT11

// Sensor einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

// Schriftart
#include "Fonts/FreeMonoBold24pt7b.h"

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;
WiFiServer Server(80);
WiFiClient Client;

// Display-Parameter
// GxEPD2_154_Z90c: Chip SSD1681 Bildschirm: 200x200
#define GxEPD2_DISPLAY_CLASS GxEPD2_3C
#define GxEPD2_DRIVER_CLASS GxEPD2_154_Z90c  

// Board wählen:
// ESP32-Wroom
// Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC -> 2, RST -> 22, BUSY -> 4
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ 5, /*DC=*/ 2, /*RST=*/ 22, /*BUSY=*/ 4));

// NodeMCU
// CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/D4, /*DC=*/ D6, /*RST=*/ D2, /*BUSY=*/ D1));

// ESP32-C6
// Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC -> 3, RST -> 10, BUSY -> 11
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ 18, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 11));

// Nano ESP32
// Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D8, BUSY -> D9
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ D10, /*DC=*/ D6, /*RST=*/ D7, /*BUSY=*/ D9));

void setup() 
{
  // Schriften von u8g2 display zuordnen
  u8g2Schriften.begin(display); 
  
  // Zeitzone: Parameter für die zu ermittelnde Zeit
  configTzTime(Zeitzone, Zeitserver);

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

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

  // Sensor starten
  dht.begin();

  // Bildschirm starten
  display.init(115200, true, 2, false); 

  // Bildschirm um 90° drehen
  display.setRotation(1);

  // vollständigen Bildschirm nutzen
  display.setFullWindow();

  // weißer Hintergrund
  display.fillScreen(GxEPD_WHITE);
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // Temperatur lesen
  String Temperatur = String(dht.readTemperature());

  // replace -> . durch , ersetzen
  Temperatur.replace(".", ",");

  // Luftfeuchtigkeit lesen
  String Luftfeuchtigkeit = String(dht.readHumidity());

  // replace -> . durch , ersetzen
  Luftfeuchtigkeit.replace(".", ",");

  // Anzeige aufbauen
  display.firstPage();
  do 
  {
    display.fillScreen(GxEPD_WHITE);
    
    u8g2Schriften.setForegroundColor(GxEPD_BLACK);   
    u8g2Schriften.setBackgroundColor(GxEPD_WHITE);
    u8g2Schriften.setFont(u8g2_font_fub35_tf); 
    
    u8g2Schriften.setCursor(1, 50);

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

    // Minuten
    if (Zeit.tm_min < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_min);

    // horizontale Linie
    display.fillRect(1, 62, display.width(), 4, GxEPD_BLACK);

    u8g2Schriften.setCursor(1, 110);

    u8g2Schriften.print(Temperatur + " °C");
    u8g2Schriften.setCursor(1, 170);
    u8g2Schriften.print(Luftfeuchtigkeit + " %");
  } 
  while (display.nextPage());

  // alle 5 Minuten aktualisieren
  delay(300000);
}

Anzei­ge mit Sym­bo­len und Text

// ESP8266
// #include "ESP8266WiFi.h"

// ESP32
// #include "WiFi.h"

#include "time.h"
#include "GxEPD2_3C.h"
#include "U8g2_for_Adafruit_GFX.h"
#include "DHT.h"

// Objekt u8g2Schriften
U8G2_FOR_ADAFRUIT_GFX u8g2Schriften;

// Pin DHT
int SENSOR_DHT = 9;

// Sensortyp festlegen
// DHT22
#define SensorTyp DHT22

// DHT11
// #define SensorTyp DHT11

// Sensor einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

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;
WiFiServer Server(80);
WiFiClient Client;

// Display-Parameter
// GxEPD2_154_Z90c: Chip SSD1681 Bildschirm: 200x200
#define GxEPD2_DISPLAY_CLASS GxEPD2_3C
#define GxEPD2_DRIVER_CLASS GxEPD2_154_Z90c

// ESP32-Wroom
// Anschlüsse: CLK -> 18, DIN -> 23, CS -> 5, DC-> 2, RST -> 22, BUSY -> 4
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/5, /*DC=*/2, /*RST=*/22, /*BUSY=*/4));

// NodeMCU
// CLK - D5, DIN -> D7, CS -> D8, DC -> D6, RST -> D2, BUSY -> D1
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/D4, /*DC=*/D6, /*RST=*/D2, /*BUSY=*/D1));

// ESP32-C6
// Anschlüsse: CLK -> 21, DIN -> 19, CS -> 18, DC-> 3, RST -> 10, BUSY -> 11
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
//  display(GxEPD2_DRIVER_CLASS(/*CS=*/ 18, /*DC=*/ 3, /*RST=*/2, /*BUSY=*/11));

// Nano ESP32
// Anschlüsse: CLK -> D13, DIN -> D11, CS -> D10, DC-> D6, RST -> D8, BUSY -> D9
// GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, 200>
// display(GxEPD2_DRIVER_CLASS(/*CS=*/ D10, /*DC=*/ D6, /*RST=*/ D7, /*BUSY=*/ D9));


const unsigned char Thermometer [] PROGMEM = {
	// 'Thermometer, 34x70px
	0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 
	0x7c, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x07, 0x80, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0x00, 0x00, 0xe0, 
	0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 
	0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 
	0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 
	0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 
	0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 
	0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x0f, 0xc0, 0x01, 
	0xc0, 0x00, 0x0f, 0xc0, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, 0xc3, 0xe1, 0xc0, 
	0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x0f, 0xc3, 0xf1, 0xc0, 0x00, 
	0x0f, 0xc3, 0xf1, 0xc0, 0x00, 0x0f, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 
	0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x00, 0xc3, 
	0xf1, 0xc0, 0x00, 0x00, 0xc3, 0xf1, 0xc0, 0x00, 0x03, 0xc3, 0xf1, 0xf0, 0x00, 0x07, 0xc3, 0xf0, 
	0xf8, 0x00, 0x0f, 0x03, 0xf0, 0x7c, 0x00, 0x0e, 0x03, 0xe0, 0x3c, 0x00, 0x1c, 0x07, 0xf0, 0x1e, 
	0x00, 0x3c, 0x1f, 0xfc, 0x0f, 0x00, 0x38, 0x3f, 0xfe, 0x0f, 0x00, 0x78, 0x7f, 0xff, 0x07, 0x80, 
	0x70, 0x7f, 0xff, 0x87, 0x80, 0x70, 0x7f, 0xff, 0x83, 0x80, 0xf0, 0xff, 0xff, 0x83, 0xc0, 0xf0, 
	0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0xc3, 0xc0, 0xf0, 0xff, 
	0xff, 0xc3, 0xc0, 0xf0, 0xff, 0xff, 0x83, 0xc0, 0x70, 0x7f, 0xff, 0x83, 0x80, 0x70, 0x7f, 0xff, 
	0x87, 0x80, 0x78, 0x3f, 0xff, 0x07, 0x80, 0x38, 0x3f, 0xfe, 0x0f, 0x00, 0x3c, 0x0f, 0xfc, 0x0f, 
	0x00, 0x1e, 0x03, 0xe0, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x00, 0x00, 0x7c, 0x00, 
	0x07, 0xe0, 0x01, 0xf8, 0x00, 0x03, 0xf8, 0x07, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x00, 
	0x7f, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00
};

const unsigned char Regen [] PROGMEM = {
	// 'Regen, 60x49px
	0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x02, 0x08, 0x21, 0x04, 0x10, 0x00, 0x00, 0x00, 0x06, 0x18, 0x63, 0x0c, 0x30, 0x80, 0x00, 
	0x00, 0x06, 0x10, 0x63, 0x0c, 0x31, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x20, 0x84, 0x10, 0x41, 0x08, 0x20, 0x00, 0x00, 0x61, 0x8c, 0x30, 0xc3, 0x18, 0x60, 0x00, 
	0x08, 0xc1, 0x8c, 0x30, 0xc3, 0x18, 0x61, 0x00, 0x00, 0x41, 0x04, 0x20, 0x82, 0x08, 0x40, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30, 0x86, 0x18, 0x43, 0x04, 0x30, 0x80, 
	0x18, 0x71, 0x86, 0x18, 0xc3, 0x0c, 0x31, 0x80, 0x18, 0x21, 0x84, 0x10, 0xc3, 0x0c, 0x21, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x18, 0x21, 0x04, 0x10, 0x42, 0x18, 0x40, 
	0x86, 0x18, 0x63, 0x0c, 0x30, 0xc6, 0x18, 0xc0, 0x86, 0x10, 0x63, 0x0c, 0x30, 0xc6, 0x18, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x18, 0x21, 0x04, 0x10, 0xc2, 0x0c, 0x21, 0x00, 0x30, 0x63, 0x0c, 0x31, 0xc6, 0x0c, 0x63, 0x00, 
	0x30, 0x63, 0x0c, 0x31, 0x86, 0x18, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x06, 0x10, 0x43, 0x08, 0x20, 0x86, 0x10, 0x00, 0x06, 0x30, 0xc3, 0x18, 0x61, 0x86, 0x30, 0x00, 
	0x04, 0x30, 0xc2, 0x18, 0x61, 0x8c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x0c, 0x30, 0xc6, 0x18, 0x61, 0x00, 0x00, 
	0x00, 0x00, 0x61, 0xc6, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x60, 0x86, 0x10, 0x60, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char Uhr [] PROGMEM = {
	// Uhr, 50x50px
	0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x03, 
	0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x01, 
	0xfe, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0, 
	0x00, 0x01, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x03, 0xf0, 0x00, 0xc0, 0x03, 0xf0, 0x00, 0x07, 
	0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x07, 0x80, 0xc0, 0x00, 0x40, 0x78, 0x00, 0x0f, 0x80, 0x00, 
	0x00, 0x00, 0x7c, 0x00, 0x1f, 0x00, 0x00, 0x80, 0x00, 0x3e, 0x00, 0x1e, 0x00, 0x00, 0xc0, 0x00, 
	0x1e, 0x00, 0x3e, 0x00, 0x00, 0xc0, 0x00, 0x1f, 0x00, 0x3c, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0x00, 
	0x38, 0x30, 0x00, 0xc0, 0x01, 0x07, 0x00, 0x78, 0x00, 0x00, 0xc0, 0x00, 0x07, 0x80, 0x78, 0x00, 
	0x00, 0xc0, 0x00, 0x07, 0x80, 0x70, 0x00, 0x00, 0xc0, 0x00, 0x03, 0x80, 0xf0, 0x00, 0x00, 0xc0, 
	0x00, 0x03, 0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 
	0xc0, 0xf0, 0x00, 0x00, 0xc0, 0x00, 0x03, 0xc0, 0xf1, 0x80, 0x00, 0xc0, 0x00, 0x63, 0xc0, 0xf1, 
	0x80, 0x01, 0x80, 0x00, 0x63, 0xc0, 0xf0, 0x00, 0x07, 0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x1c, 
	0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x78, 0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0xe0, 0x00, 0x00, 
	0x03, 0xc0, 0x70, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x78, 0x07, 0x00, 0x00, 0x00, 0x07, 0x80, 
	0x78, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x78, 0x20, 0x00, 0x00, 0x01, 0x07, 0x80, 0x3c, 0x00, 
	0x00, 0x00, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x00, 
	0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x7c, 
	0x00, 0x07, 0x80, 0x80, 0x00, 0xc0, 0x78, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x03, 
	0xf0, 0x00, 0xc0, 0x03, 0xf0, 0x00, 0x01, 0xf8, 0x00, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0xfe, 0x00, 
	0x00, 0x1f, 0xc0, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x1f, 0xe0, 0x01, 0xfe, 
	0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf0, 0x00, 0x00, 
	0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00
};

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

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

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

  // Bildschirm starten
  display.init(115200, true, 2, false);

  // Bildschirm um 90° drehen
  display.setRotation(1);

  // vollständigen Bildschirm nutzen
  display.setFullWindow();
  display.fillScreen(GxEPD_WHITE);

  // Sensor starten
  dht.begin();
}

void loop()
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // Temperatur lesen
  String Temperatur = String(dht.readTemperature());

  // replace -> . durch , ersetzen
  Temperatur.replace(".", ",");

  // Luftfeuchtigkeit lesen
  String Luftfeuchtigkeit = String(dht.readHumidity());

  // replace -> . durch , ersetzen
  Luftfeuchtigkeit.replace(".", ",");

  // Anzeige aufbauen
  display.firstPage();
  do 
  {
    u8g2Schriften.setForegroundColor(GxEPD_BLACK);   
    u8g2Schriften.setBackgroundColor(GxEPD_WHITE);
    u8g2Schriften.setFont(u8g2_font_helvB24_tf);   

    u8g2Schriften.setCursor(70, 40);

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

    // Minuten
    if (Zeit.tm_min < 10) u8g2Schriften.print("0");
    u8g2Schriften.print(Zeit.tm_min);

    // x, y, Bild-Array, Breite, Höhe, Farbe
    display.drawBitmap(5, 5, Uhr, 50, 50, GxEPD_BLACK);
    display.drawBitmap(15, 70, Thermometer, 34, 70, GxEPD_BLACK);
    display.drawBitmap(5, 150, Regen, 60, 49, GxEPD_BLACK);  

    // Messdaten anzeigen
    u8g2Schriften.setCursor(70, 110);
    u8g2Schriften.print(Temperatur + " °C");
    u8g2Schriften.setCursor(70, 180);
    u8g2Schriften.print(Luftfeuchtigkeit + " %");
  } 
  while (display.nextPage());

  // alle 5 Minuten aktualisieren
  delay(300000);
}

Letzte Aktualisierung: Wei­ter lesen ...

Zeit mit time.h auf einem 4-stel­li­gen 7-Segment-Anzeige

ESP32-Wroom

#include "WiFi.h"
#include "time.h"
#include "TM1637.h"

TM1637 Anzeige(5, 17);

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_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  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;
WiFiServer Server(80);

// String für die Anzeige der Zeit
String ZeitAnzeige;

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // 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());
  
  // Anzeige starten
  Anzeige.begin();  

  // Helligkeit
  Anzeige.setBrightness(10);

  Anzeige.clearScreen();
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // : einschalten
  Anzeige.colonOn();

  /*
    es kann bis zu 30 Sekunden dauern
    bis die Zeit ermittelt wird  
    String ZeitAnzeige zusammenbauen
    wenn Stunden/Minuten < 10 → führende 0 ergänzen
  */
  if (Zeit.tm_hour < 10) ZeitAnzeige = "0" + String(Zeit.tm_hour);
  else ZeitAnzeige = String(Zeit.tm_hour);

  if (Zeit.tm_min < 10) ZeitAnzeige += "0" + String(Zeit.tm_min);
  else ZeitAnzeige += String(Zeit.tm_min);

  Anzeige.display(ZeitAnzeige);
  delay(5000);
}

ESP32-C6

#include "WiFi.h"
#include "time.h"
#include "TM1637.h"

TM1637 Anzeige(15, 23);

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_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  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;
WiFiServer Server(80);

// String für die Anzeige der Zeit
String ZeitAnzeige;

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // 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());
  
  // Anzeige starten
  Anzeige.begin();  

  // Helligkeit
  Anzeige.setBrightness(10);

  Anzeige.clearScreen();
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // : einschalten
  Anzeige.colonOn();

  /*
    es kann bis zu 30 Sekunden dauern
    bis die Zeit ermittelt wird  
    String ZeitAnzeige zusammenbauen
    wenn Stunden/Minuten < 10 → führende 0 ergänzen
  */ 
  if (Zeit.tm_hour < 10) ZeitAnzeige = "0" + String(Zeit.tm_hour);
  else ZeitAnzeige = String(Zeit.tm_hour);

  if (Zeit.tm_min < 10) ZeitAnzeige += "0" + String(Zeit.tm_min);
  else ZeitAnzeige += String(Zeit.tm_min);

  Anzeige.display(ZeitAnzeige);
  delay(5000);
}

XIAO-ESP32-C3

#include "WiFi.h"

#include "time.h"
#include "TM1637.h"

TM1637 Anzeige(D3, D4);

// Router/Passwort
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_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  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;
WiFiServer Server(80);

// String für die Anzeige der Zeit
String ZeitAnzeige;

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // 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());
  
  // Anzeige starten
  Anzeige.begin();  

  // Helligkeit
  Anzeige.setBrightness(10);

  Anzeige.clearScreen();
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // : einschalten
  Anzeige.colonOn();

  /*
    es kann bis zu 30 Sekunden dauern
    bis die Zeit ermittelt wird  
    String ZeitAnzeige zusammenbauen
    wenn Stunden/Minuten < 10 → führende 0 ergänzen
  */
  if (Zeit.tm_hour < 10) ZeitAnzeige = "0" + String(Zeit.tm_hour);
  else ZeitAnzeige = String(Zeit.tm_hour);

  if (Zeit.tm_min < 10) ZeitAnzeige += "0" + String(Zeit.tm_min);
  else ZeitAnzeige += String(Zeit.tm_min);

  Anzeige.display(ZeitAnzeige);
  delay(5000);
}

Wemos D1 Mini

#include "ESP8266WiFi.h"

#include "time.h"
#include "TM1637.h"

TM1637 Anzeige(D3, D4);

// Router/Passwort
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_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  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;
WiFiServer Server(80);

// String für die Anzeige der Zeit
String ZeitAnzeige;

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

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // 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());
  
  // Anzeige starten
  Anzeige.begin();  

  // Helligkeit
  Anzeige.setBrightness(10);

  Anzeige.clearScreen();
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

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

  // : einschalten
  Anzeige.colonOn();

  /*
    es kann bis zu 30 Sekunden dauern
    bis die Zeit ermittelt wird  
    String ZeitAnzeige zusammenbauen
    wenn Stunden/Minuten < 10 → führende 0 ergänzen
  */
  if (Zeit.tm_hour < 10) ZeitAnzeige = "0" + String(Zeit.tm_hour);
  else ZeitAnzeige = String(Zeit.tm_hour);

  if (Zeit.tm_min < 10) ZeitAnzeige += "0" + String(Zeit.tm_min);
  else ZeitAnzeige += String(Zeit.tm_min);

  Anzeige.display(ZeitAnzeige);
  delay(5000);
}

Ardui­no UNO R4 WiFi

Zusätz­li­che Biblio­thek instal­lie­ren Wei­ter lesen ...

Mikro­con­trol­ler im AP-Modus vernetzen

Ser­ver

// ESP32
#include "WiFi.h"
#include "WebServer.h"

// ESP8266
// #include "ESP8266WebServer.h"

#include "DHT.h"

// Pin des DHT-Sensors
int SENSOR_DHT = 19;

// Sensortyp festlegen
// DHT22 oder DHT11
#define SensorTyp DHT22

DHT dht(SENSOR_DHT, SensorTyp);

// Netzwerkname und Passwort des ESP
char Router[] = "ESPServer";
char Passwort[] = "espserver";

// ESP32
WebServer Server(80);

// ESP8266
// ESP8266WebServer Server(80);

// farbige Box mit CSS
String Seitenkopf =
  "<head><style>"
  ".farbigeBox {"
  "background-color: ivory;"
  "color: black;"
  "width: 450px;"
  "padding: 20px;"
  "text-align: left;"
  "font-size: 40px;"
  "font-family: arial;"
  "}"
  "</style>"

  // refresh -> Seite automatisch aktualisieren
  "<meta http-equiv=\"refresh\" content=\"30\"></head>";

// Wartezeit für die sichere Übermittlung der Daten
unsigned long Wartezeit = 5000;

// enthält die Daten des 2. ESPs
String Messung;

// IP-Adresse des 2. ESP
const char* host = "192.168.4.2";

// Konfiguration als Server
IPAddress ip(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

void setup() 
{
  Serial.begin(9600);
  
  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // ESP als Access-Point (AP) konfigurieren
  WiFi.softAPConfig(ip, gateway, subnet);

  // Access-Point starten
  WiFi.softAP(Router, Passwort);
   
  // SSID des Routers anzeigen
  Serial.println();
  Serial.print("Verbunden mit ");
  Serial.println(WiFi.softAPSSID());

  Serial.print("IP-Adresse: ");
  Serial.println(WiFi.softAPIP());

  // Webserver starten
  // / -> Aufruf der URL, SeiteBauen -> Aufruf der Funktion
  Server.begin();
  Server.on("/", SeiteBauen);

  dht.begin();
}

void loop() 
{
  static unsigned long Startzeit = millis();

  // auf Anfragen warten
  Server.handleClient();

  // Messdaten einsammeln
  if ((millis() - Startzeit) > Wartezeit)
  {
    // Daten des 2. ESPs einsammeln
    DatenHolen();
    
    Startzeit = millis();
  }
}


void SeiteBauen()
{
  // Seite "zusammenbauen"
  String Seite = "";
  Seite += Seitenkopf;
  Seite += "<h1>Messdaten</h1>";
  Seite += "<hr>";
  
  /*
    Messung enthält die mit / gtrennten Daten
    String Messung mit substring am / trennen
    Temperatur: von Position 0 bis zum / (indexOf))
    Luftfeuchtigkeit von /+1 bis zur Länge des Strings
  */
  String TemperaturKlient = Messung.substring(0, Messung.indexOf("/"));
  String LuftfeuchtigkeitKlient = Messung.substring(Messung.indexOf("/") + 1, Messung.length());
  
  Seite += "<h2>Daten vom Klienten ...</h2>";
  Seite += "<div class=\"farbigeBox\">";
  Seite += "Temperatur: ";
  Seite += TemperaturKlient;
  Seite += "<br>";
  Seite += "Luftfeuchtigkeit: ";
  Seite += LuftfeuchtigkeitKlient;
  Seite += "<br>";
  Seite += "</div>";

  // Messwerte ermitteln
  // . durch , ersetzen
  String TemperaturServer = String(dht.readTemperature());
  TemperaturServer.replace(".", ",");
  
  String LuftfeuchtigkeitServer = String(dht.readHumidity());
  LuftfeuchtigkeitServer.replace(".", ",");
  
  Seite += "<h2>Daten vom Server ...</h2>";
  Seite += "<div class=\"farbigeBox\">";
  Seite += "Temperatur: ";
  Seite += TemperaturServer + "&degC";
  Seite += "<br>";
  Seite += "Luftfeuchtigkeit: ";
  Seite += LuftfeuchtigkeitServer + "%";
  Seite += "</div>";

  // Button aktualisieren
  Seite += "<hr><input style=\"font-size:16pt; font-weight:bold;";
  Seite += "background-color:#55A96B;";
  Seite += "display:block; cursor:pointer;\"type=\"button\"";

  // IP für den Button aktualisieren (location.href)
  // muss mit dem Wert für IPAdress übereinstimmen (. statt ,)
  Seite += " onClick=\"location.href='http://192.168.4.1'\" value=\"aktualisieren\">";
  Seite += "<hr>";

  // Seite anzeigen
  Server.send(200, "text/html", Seite);
}

void DatenHolen()
{
  WiFiClient client;

  // wenn Klient erfolgreich verbunden wurde
  // wenn nicht return -> neuer Versuch
  if (!client.connect(host, 80)) return;
  
  /*
    GET-Anfrage senden
    /Messung -> Adresse (URL) für die zu übermittelnden Werte
    wird von den Klienten festgelegt
    host -> IP-Adresse des 2. ESPs
    HTTP/1.1 -> Abfrageprotokoll
    \r\n -> return mit anschließender neuer Zeile
  */
  client.print(String("GET ") + "/Messung" + " HTTP/1.1\r\n" + host + "\r\n");
  unsigned long LetzteZeit = millis();

  // Wartezeit 
  while (!client.available() && ((millis() - LetzteZeit) < 3000))
  {
    delay(1);
  }  

  // der Klient ist verfügbar
  while (client.available()) 
  {
    // den mit GET erhaltenen String bis zum return (\r) lesen
    String Daten = client.readStringUntil('\r');

    // wenn Daten vorhanden sind
    // Messung enthält die vom 2. ESP übermittelten Daten
    if(Daten != "")
    {
      Messung = Daten;
      Serial.println(Daten);
    }
  }
}

Kli­ent

// ESP32
#include "WiFi.h"
#include "WebServer.h"

// ESP8266
// #include "ESP8266WebServer.h"

#include "DHT.h"

// Pin des DHT-Sensors
int SENSOR_DHT = 19;

#define SensorTyp DHT22

// Sensor DHT einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

// ESP als AP
char Router[] = "ESPServer";
char Passwort[] = "espserver";

// IP des 2. ESPs
IPAddress ip(192, 168, 4, 2);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

// ESP32
WebServer Server(80);

// ESP8266
// ESP8266WebServer Server(80);

void setup() 
{
  // WiFi starten
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(Router, Passwort);

  // Adresse (URL)festlegen (/Messung)
  // SeiteBauen -> zu übermittelnde Daten
  Server.on("/Messung", SeiteBauen);
  Server.begin();
  Serial.begin(9600);
  
  // DHT starten
  dht.begin();
}

void loop() 
{
  // auf Anfragen warten
  Server.handleClient();
}

void SeiteBauen() 
{
  String Seite ="";

  // Messwerte ermitteln
  // . durch , ersetzen
  String Temperatur = String(dht.readTemperature());
  Temperatur.replace(".", ",");
  
  String Luftfeuchtigkeit = String(dht.readHumidity());
  Luftfeuchtigkeit.replace(".", ",");
  
  // Seite zusammenbauen
  // / Trennzeichen
  Seite = Temperatur + "&degC/";
  Seite += Luftfeuchtigkeit + "%";

  // Seite übermitteln
  Server.send(200, "text/html", Seite);
}

Letzte Aktualisierung: Wei­ter lesen ...

LEDs Tran­sis­tor schalten

#define TRANSISTOR 6 

void setup()
{
  pinMode(TRANSISTOR, OUTPUT);
}

void loop()
{
  digitalWrite(TRANSISTOR, HIGH);  
  delay(1000);                             
  digitalWrite(TRANSISTOR, LOW);  
  delay(1000);                              
}

Letzte Aktualisierung: Wei­ter lesen ...

MQTT ESP32

Inhalts­ver­zeich­nis

Sen­der

#include "ArduinoMqttClient.h"

// ESP8266: NodeMCU, Wemos D1 Mini
// #include "ESP8266WiFi.h"

// ESP32
#include "WiFi.h"
#include "DHT.h"

// Pin des DHT-Sensors
int SENSOR_DHT = 4;

// DHT11
// #define SensorTyp DHT11

// DHT22
#define SensorTyp DHT22

// dht-Sensor einen Namen und Typ zuweisen
DHT dht(SENSOR_DHT, SensorTyp);

char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxx";

WiFiClient wifiClient;

// wifiClient MqttClient zuordnen
MqttClient mqttClient(wifiClient);

// RaspberryPi als Broker
// const char broker[] = "192.168.1.222";
int port = 1883;

const char broker[] = "test.mosquitto.org";

/* öffentliche Broker
const char broker[] = "public.mqtthq.com";
int port = 1883;

const char broker[] = "test.mosquitto.org";
int port = 1883;

const char broker[] = "broker.emqx.io";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
int port = 1883;
*/

// Thema für Senden/Empfangen
const char Messdaten[] = "Messdaten";

// Thema für die "will"-Nachricht für den Versuch die Verbindung 
// neu aufzubauen
const char getrennteVerbindung[] = "getrennteVerbindung";

// Intervall zwischen den Messungen
const long Interval = 5000;
unsigned long vorherigeZeit = 0;

void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  delay(1000);

  WiFi.begin(Router, Passwort);

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

  /*
    will-Nachricht:
    wird an den Broker gesendet und versucht eine getrennte Verbindung neu aufzubauen
    Parameter:
    Thema, Länge des gesendeten Strings, Behalten der Anforderung, Qualität der Verbindung
    muss vor dem Aufbau der Verbindung zum Broker festgelegt werden
  */
  String willDaten = "getrennt";
  bool Behalten = true;
  int willQualitaetService= 2;

  // will-Nachricht senden
  mqttClient.beginWill(getrennteVerbindung, willDaten.length(), Behalten, willQualitaetService);
  mqttClient.print(getrennteVerbindung);
  mqttClient.endWill();

  Serial.println("Versuche mit dem Broker " + String(broker) + " zu verbinden ... ");

  delay(1000);

  // Verbindungsversuch
  if (!mqttClient.connect(broker, port)) 
  {
    Serial.print("Verbindung zum Broker gescheitert");

    // Programm anhalten
    while (1);
  }
  Serial.println();

  Serial.println("Mit dem Broker " + String(broker) + " verbunden!");
  Serial.println();

  // dht-Sensor starten
  dht.begin();
}

void loop() 
{
  // Broker abfragen
  mqttClient.poll();

  unsigned long aktuelleZeit = millis();

  // Intervall zwischen den Sendezeiten
  if (aktuelleZeit - vorherigeZeit >= Interval) 
  {
    // letzte Sendezeit sichern
    vorherigeZeit = aktuelleZeit;

    // gemessene Temperatur dht in String umwandeln
    String Temperatur = String(dht.readTemperature(), 1);

    // . durch , ersetzen
    Temperatur.replace(".", ",");

    // gemessene Luftfeuchtigkeit in String umwandeln
    String Luftfeuchtigkeit = String(dht.readHumidity(), 1);

    // . durch , ersetzen
    Luftfeuchtigkeit.replace(".", ",");

    // String Senden zusammenbauen / als Trennzeichen
    String Senden = Temperatur + "/" + Luftfeuchtigkeit;
    Serial.println("Nachricht gesendet:");

    // Anzeige im Seriellen Monitor: String Senden am / trennen
    int Suche = Senden.indexOf("/");

    // String bis zum /
    Temperatur = Senden.substring(0, Suche);

    // String vom ersten Zeichen hinter / bis zum Ende
    Luftfeuchtigkeit = Senden.substring(Suche + 1, Senden.length());

    // Daten im Seriellen Monitor anzeigen
    Serial.println(Temperatur + "°C");
    Serial.println(Luftfeuchtigkeit + "%");
    Serial.println("---------------------");

    // Messdaten senden
    bool Behalten = false;
    int ServiceQualitaet = 2;
    bool Duplikat = false;
    mqttClient.beginMessage(Messdaten, Senden.length(), Behalten, ServiceQualitaet, Duplikat);
    mqttClient.print(Senden);
    mqttClient.endMessage();
  }
}

Emp­fän­ger

#include "ArduinoMqttClient.h"

// ESP32
// #include "WiFi.h"

// ESP8266: NodeMCU, Wemos D1 Mini
#include "ESP8266WiFi.h"

#include "U8g2lib.h"

/*
  Typbezeichnung mit Bildschirmgröße in Pixeln
  1 = page buffer mode, F = full screen buffer mode 
  Hardware I2C/Hardware SPI
  Name des OLEDs
  Rotation R0 (keine)
*/
U8G2_SSD1306_128X64_NONAME_1_HW_I2C oled(U8G2_R0, U8X8_PIN_NONE);

// Router SSID/Passwort
char Router[] = "FRITZ!Box 7590 LB";
char Passwort[] = "anea1246";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

// RaspberryPi als Broker
// const char broker[] = "192.168.1.222";

const char broker[] = "test.mosquitto.org";
int port = 1883;

/* öffentliche Broker
const char broker[] = "public.mqtthq.com";
int port = 1883;

const char broker[] = "test.mosquitto.org";
int port = 1883;

const char broker[] = "broker.emqx.io";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
int port = 1883;
*/

// Thema  für Senden/Empfangen
const char Messdaten[] = "Messdaten";

/*
  Qualität der Verbindung (0 .. 2)
  0 = Nachricht wird einmal versendet
      eine Überprüfung des Empfangs durch den Broker findet nicht statt
  1 = die Nachricht wird solange versendet, bis der Broker den Empfang bestätigt hat
  2 = die Nachricht wird einmal gesendet, es wird sicher gestellt, dass sie
      beim Broker angekommen ist
*/
int subscribeQoS = 2;

void setup() 
{
  Serial.begin(9600);
  while (!Serial);
  delay(1000);

  WiFi.begin(Router, Passwort);

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

  Serial.print("Versuche mit dem Broker " + String(broker) + " zu verbinden ... ");

  // Verbindung zum Broker aufbauen
  if (!mqttClient.connect(broker, port)) 
  {
    Serial.print("Verbindung zum Broker gescheitert");

    // Programm anhalten
    while (1);
  }
  Serial.println();

  Serial.println("Mit dem Broker " + String(broker) + " verbunden!");
  Serial.println();

  // den Rückruf für den Nachrichtenempfang festlegen
  mqttClient.onMessage(empfangeneNachricht);

  // in das Thema Messdaten "einschreiben"
  mqttClient.subscribe(Messdaten, subscribeQoS);

  // OLED starten
  oled.begin();

  // Kontrast maximal 255
  oled.setContrast(200);
  oled.setFont(u8g2_font_helvR24_tf);

  // Zeichenfarbe weiß
  oled.setDrawColor(1);

  // horizontale Schrift
  oled.setFontDirection(0);
}

void loop() 
{
  // Broker abfragen
  mqttClient.poll();
}

void empfangeneNachricht(int NachrichtGroesse) 
{
  Serial.println("Nachricht empfangen: ");

  // Thema der Nachricht empfangen und anzeigen
  String Nachricht = mqttClient.messageTopic();
  Serial.println(Nachricht + " ");

  // Nachricht als String lesen
  String EmpfangeneNachricht = mqttClient.readString();

  // String Anzeige am / trennen
  int Suche = EmpfangeneNachricht.indexOf("/");
  String Temperatur = EmpfangeneNachricht.substring(0, Suche);
  String Luftfeuchtigkeit = EmpfangeneNachricht.substring(Suche + 1, EmpfangeneNachricht.length());

  // Anzeige im Seriellen Monitor
  Serial.println(Temperatur + "°C");
  Serial.println(Luftfeuchtigkeit + "%");
  Serial.println("---------------------");
  Serial.println();

  // Anzeige OLED
  oled.clearDisplay();
  oled.firstPage();

  do 
  {
    oled.setCursor(2, 30);
    oled.print(Temperatur);

    // Grad-Zeichen
    oled.print((char)176);
    oled.print("C");
    oled.setCursor(2, 60);
    oled.print(Luftfeuchtigkeit + "%");

  } 
  while (oled.nextPage());
}
Wei­ter lesen ...

BME680 Dar­stel­lung LCD und Web

Dar­stel­lung auf LCD

#include "bsec.h"
#include "LCDIC2.h"

// 4-zeiliges LCD
LCDIC2 lcd(0x27, 20, 4);

// Objekt (iaqSensor) der Klasse Bsec definieren
Bsec iaqSensor;

void setup() 
{
  Serial.begin(9600);

  // auf Serielle Verbindung warten
  while (!Serial);
  delay(1000);
  
  // LCD starten
  lcd.begin();

  // Cursor "verstecken"
  lcd.setCursor(false);

  // Hex-Adresse des BME680
  // BME68X_I2C_ADDR_HIGH = 0x77 (Standard)
  // BME68X_I2C_ADDR_LOW = 0x76 
  iaqSensor.begin(BME68X_I2C_ADDR_HIGH, Wire);

  // Array der verfügbaren Sensoren
  bsec_virtual_sensor_t sensorList[13] = 
  {
    BSEC_OUTPUT_IAQ,
    BSEC_OUTPUT_STATIC_IAQ,
    BSEC_OUTPUT_CO2_EQUIVALENT,
    BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
    BSEC_OUTPUT_RAW_TEMPERATURE,
    BSEC_OUTPUT_RAW_PRESSURE,
    BSEC_OUTPUT_RAW_HUMIDITY,
    BSEC_OUTPUT_RAW_GAS,
    BSEC_OUTPUT_STABILIZATION_STATUS,
    BSEC_OUTPUT_RUN_IN_STATUS,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
    BSEC_OUTPUT_GAS_PERCENTAGE
  };

  // BSEC_SAMPLE_RATE_ULP: Ultra Low Powermode -> Messung alle 5 Minuten
  // BSEC_SAMPLE_RATE_LP: Low Powermode -> Messung alle 3 Sekunden
  iaqSensor.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
}

void loop() 
{
  // wenn der Sensor arbeitet ...
  if (iaqSensor.run()) 
  {
    // Messwerte ermitteln, in Strings umwandeln, . durch , ersetzen
    String Temperatur = String(iaqSensor.temperature);
    Temperatur.replace(".", ",");

    String Luftfeuchtigkeit = String(iaqSensor.humidity);
    Luftfeuchtigkeit.replace(".", ",");

    String Luftdruck = String(iaqSensor.pressure / 100);
    Luftdruck.replace(".", ",");

    String IAQ = String(iaqSensor.iaq);
    IAQ.replace(".", ",");

    String StatischerIAQ = String(iaqSensor.staticIaq);
    StatischerIAQ.replace(".", ",");
    
    String CO2 = String(iaqSensor.co2Equivalent);
    CO2.replace(".", ",");

    String VOC = String(iaqSensor.breathVocEquivalent);
    VOC.replace(".", ",");

    String GasInProzent = String(iaqSensor.gasPercentage);
    GasInProzent.replace(".", ",");

    String WiderstandMOXSensor = String(iaqSensor.gasResistance / 1000);
    WiderstandMOXSensor.replace(".", ",");

    // Ausgabe Serieller Monitor
    Serial.println("Statusmeldungen:");
    Serial.println("-----------------------------");
    Serial.println("Sensor bereit (0-1): " + String(int(iaqSensor.runInStatus)));
    Serial.println("Genauigkeit IAQ (0-3): " + String(int(iaqSensor.iaqAccuracy)));
    Serial.println("-----------------------------");
    Serial.println("Messwerte:");
    Serial.println("-----------------------------");
    Serial.println("Temperatur: " + Temperatur + " °C");
    Serial.println("Feuchtigkeit: " + Luftfeuchtigkeit + " %");
    Serial.println("Luftdruck: " + Luftdruck + " hPa");
    Serial.println("IAQ: " + IAQ);
    Serial.println("Statischer IAQ: " + StatischerIAQ);
    Serial.println("Schätzung CO2: " + CO2 + " ppm");
    Serial.println("Gas (0-100): " + GasInProzent + " %");
    Serial.println("Widerstandswert MOX-Sensor: " + WiderstandMOXSensor + " kOhm");
    Serial.println("VOC: " + VOC);
    Serial.println("-----------------------------");

    // Ausgabe LCD
    lcd.setCursor(0, 0);
    lcd.print("Temperatur: " + Temperatur + "\337C");
    lcd.setCursor(0, 1);
    lcd.print("Feuchtigkeit: " + Luftfeuchtigkeit + "%");
    lcd.setCursor(0, 2);
    lcd.print("IAQ: " + IAQ);
    lcd.setCursor(0, 3);
    lcd.print("CO2: " + CO2 + " ppm");
  }
}

Dar­stel­lung im Web

#include "bsec.h"
#include "WiFi.h"
#include "WebServer.h"
#include "time.h"

// Objekt (iaqSensor) der Klasse Bsec definieren
Bsec iaqSensor;

char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

// ip und gateway müssen an das lokale Netz angepasst werden
IPAddress ip(192, 168, 1, 100);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

/*
  öffentliche DNS-Server
  -----------------------------------------------
  OpenDNS 208, 67, 222, 222 (USA)
  Google 8, 8, 8, 8 (USA)
  Cloudfare 1, 1, 1, 1 (USA)
  DNSWWatch 84, 200, 69, 80 (Deutschland)
  Quad9 9, 9, 9, 9 (Schweiz)
  Neustar UltraDNS 56, 154, 70, 3 (USA, gefiltert)
  Deutsche Telekom 217, 5,100, 185
  ------------------------------------------------
  oder die im Router eingetragene IP
  im Beispiel: 192, 168, 1, 20
*/
IPAddress primaryDNS(192, 168, 1, 20);
IPAddress secondaryDNS(9, 9, 9, 9);

// 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_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  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;

WebServer server(80);

// benötigte Strings
String Nachricht;
String Temperatur;
String Luftfeuchtigkeit;
String Luftdruck;
String CO2;
String IAQ;
String StatischerIAQ;

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

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

  // auf Serielle Verbindung warten
  while (!Serial);
  delay(1000);

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

  WiFi.config(ip, gateway, subnet, primaryDNS, secondaryDNS);
  Serial.print("Verbunden mit ");
  Serial.println(Router);

  // IP anzeigen
  Serial.print("Statische IP: ");
  Serial.println(ip);

  server.begin();
  server.on("/", handleRoot);

  // Hex-Adresse des BME680
  // BME68X_I2C_ADDR_HIGH = 0x77
  // BME68X_I2C_ADDR_LOW = 0x76
  iaqSensor.begin(BME68X_I2C_ADDR_HIGH, Wire);

  // Array der verfügbaren Sensoren
  bsec_virtual_sensor_t sensorList[13] = 
  {
    BSEC_OUTPUT_IAQ,
    BSEC_OUTPUT_STATIC_IAQ,
    BSEC_OUTPUT_CO2_EQUIVALENT,
    BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
    BSEC_OUTPUT_RAW_TEMPERATURE,
    BSEC_OUTPUT_RAW_PRESSURE,
    BSEC_OUTPUT_RAW_HUMIDITY,
    BSEC_OUTPUT_RAW_GAS,
    BSEC_OUTPUT_STABILIZATION_STATUS,
    BSEC_OUTPUT_RUN_IN_STATUS,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
    BSEC_OUTPUT_GAS_PERCENTAGE
  };

  // BSEC_SAMPLE_RATE_ULP: Ultra Low Powermode -> Messung alle 5 Minuten
  // BSEC_SAMPLE_RATE_LP: Low Powermode -> Messung alle 3 Sekunden
  iaqSensor.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
}

void loop() 
{
  // wenn der Sensor arbeitet ...
  if (iaqSensor.run()) 
  {
    // aktuelle Zeit holen
    time(&aktuelleZeit);

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

    // es kann bis zu 30 Sekunden dauern
    // bis die Zeit ermittelt wird
    // Name des Wochentages 0-6
    switch (Zeit.tm_wday) {
      case 0:
        Serial.print("Sonntag");
        break;
      case 1:
        Serial.print("Montag");
        break;
      case 2:
        Serial.print("Dienstag");
        break;
      case 3:
        Serial.print("Mittwoch");
        break;
      case 4:
        Serial.print("Donnerstag");
        break;
      case 5:
        Serial.print("Freitag");
        break;
      case 6:
        Serial.print("Samstag");
        break;
    }

    Serial.print(",");
    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 < 10) Serial.print("0");

    // Zählung beginnt mit 0 -> + 1
    Serial.print(Zeit.tm_mon + 1);
    Serial.print(".");

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

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

    // Minuten
    if (Zeit.tm_min < 10) Serial.print("0"); 
    Serial.println(Zeit.tm_min);

    server.handleClient();

    // Messwerte ermitteln, in Strings umwandeln, . durch , ersetzen
    Temperatur = String(iaqSensor.temperature);
    Temperatur.replace(".", ",");

    Luftfeuchtigkeit = String(iaqSensor.humidity);
    Luftfeuchtigkeit.replace(".", ",");

    Luftdruck = String(iaqSensor.pressure / 100);
    Luftdruck.replace(".", ",");

    IAQ = String(iaqSensor.iaq);
    IAQ.replace(".", ",");

    StatischerIAQ = String(iaqSensor.staticIaq);
    StatischerIAQ.replace(".", ",");

    CO2 = String(iaqSensor.co2Equivalent);
    CO2.replace(".", ",");

    String VOC = String(iaqSensor.breathVocEquivalent);
    VOC.replace(".", ",");

    String GasInProzent = String(iaqSensor.gasPercentage);
    GasInProzent.replace(".", ",");

    String WiderstandMOXSensor = String(iaqSensor.gasResistance / 1000);
    WiderstandMOXSensor.replace(".", ",");

    // Ausgabe Serieller Monitor
    Serial.println("Statusmeldungen:");
    Serial.println("-----------------------------");
    Serial.println("Sensor bereit (0-1): " + String(int(iaqSensor.runInStatus)));
    Serial.println("Genauigkeit IAQ (0-3): " + String(int(iaqSensor.iaqAccuracy)));
    Serial.println("-----------------------------");
    Serial.println("Messwerte:");
    Serial.println("-----------------------------");
    Serial.println("Temperatur: " + Temperatur + "°C");
    Serial.println("Feuchtigkeit: " + Luftfeuchtigkeit + " %");
    Serial.println("Luftdruck: " + Luftdruck + " hPa");
    Serial.println("IAQ: " + IAQ);
    Serial.println("Statischer IAQ: " + StatischerIAQ);
    Serial.println("Schätzung CO2: " + CO2 + " ppm");
    Serial.println("Gas (0-100): " + GasInProzent + " %");
    Serial.println("Widerstandswert MOX-Sensor: " + WiderstandMOXSensor + " kOhm");
    Serial.println("VOC: " + VOC);
    Serial.println("-----------------------------");
  }
}

void handleRoot() 
{
  // Seite zusammenbauen
  // Kopf der HTML-Seite: aktualisierung alle 60 Sekunden
  // kann angepasst werden
  Nachricht = "<head><meta http-equiv=\"refresh\" content=\"60\"></head>";
  Nachricht += "<h1>Messwerte BME680</h1><hr>";

  // Datum anzeigen
  // formatieren: Schrift 14pt, ohne Serifen, Zeilenhöhe
  Nachricht += "<div style = \"font-size:14pt; font-family:sans-serif; line-height:1.8em\">";
  Nachricht += "Letzte Aktualisierung: ";

  // wenn der Tag < 10
  if (Zeit.tm_mday < 10) Nachricht += "0";
  Nachricht += String(Zeit.tm_mday) + ".";

  // wen der Monat < 10, Zählung beginnt mit 0
  if ((Zeit.tm_mon + 1) < 10) Nachricht += "0";
  Nachricht += String(Zeit.tm_mon + 1) + ". ";

  // Zeit anzeigen
  // wenn die Stunde < 10
  if (Zeit.tm_hour < 10) Nachricht += "0";
  Nachricht += String(Zeit.tm_hour) + ":";

  // wenn die Minute < 10
  if (Zeit.tm_min < 10) Nachricht += "0";
  Nachricht+= String(Zeit.tm_min) + " Uhr<br><hr>";
  
  Nachricht += "Temperatur: " + Temperatur + " &degC<br>";
  Nachricht += "Luftfeuchtigkeit: " + Luftfeuchtigkeit + " %<br>";
  Nachricht += "Luftdruck: " + Luftdruck + " hPa<br>";
  Nachricht += "IAQ: " + IAQ + "<br>";
  Nachricht += "Statischer IAQ: " + StatischerIAQ + "<br>";
  Nachricht += "Sch&auml;tzung CO2: " + CO2 + " ppm<br>";
  Nachricht += "Genauigkeit IAQ (0-3): " + String(int(iaqSensor.iaqAccuracy)) + "</div>";

  // Button aktualisieren
  Nachricht += "<hr><input style=\"font-size:16pt; font-weight:bold;";
  Nachricht += "background-color:#55A96B;";
  Nachricht += "display:block; cursor:pointer;\"type=\"button\"";

  // IP für den Button aktualisieren (location.href)
  // muss mit dem Wert für IPAdress übereinstimmen (. statt ,)
  Nachricht += " onClick=\"location.href='http://192.168.1.100'\" value=\"aktualisieren\">";
  Nachricht += "<hr>";

  // Nachricht senden -> Seite anzeigen
  server.send(200, "text/html", Nachricht);
}

Letzte Aktualisierung: Wei­ter lesen ...