Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:schlafphasenwecker:programmversion_0.7

Schlafphasenwecker Programmversion 0.7

Nachdem in Programmversion 0.6 vor allem das Teensy Audio Adaptor Board eingebunden wurde, werden in Programmversion 0.7 der Temperatur- und Luftfeuchtigkeitssensor DHT22 und die NeoPixel für das Ziffernblatt integriert.

Weitere Änderungen:

  • Die Uhrzeit wird auf dem NeoPixel-Ring angezeigt.
  • Die Helligkeit des Ziffernblatts wird abhängig von der Umgebungsbeleuchtung geregelt.
  • Die Lautstärke des akustischen Weckalarms kann eingestellt werden.
  • Im Snoozle-Modus nach Ablauf der vorausgewählten Zeit die Lautstärke langsam reduziert.
  • Jeder Alarm kann abgebrochen oder in einen Schlummermodus überführt werden. Im Schlummermodus wird nach einer vorausgewählten Schlummerzeit der akustische Alarm aktiviert.
  • Das Menü wurde an verschiedenen Stellen aufgehübst und erweitert.
  • Es kann ein visueller Weckalarm ausgewählt werden.
  • kleinere Optimierungen des Programmcodes
  • Fehlerbeseitigungen
    • Der Snoozle-Modus behält jetzt die zuletzt eingestellte Lautstärke korrekt.
    • Die Rate erfolgreich empfangener Zeitsignale wird jetzt korrekt berechnet.

ToDos:

  • Die Helligkeit des Ziffernblatts muss in dunklen Lichtsituationen stärker reduziert werden.
  • Die Menüs müssen aufgehübscht werden.
  • Die Funktion zum Einstellen der Alarmzeit berechnet unter bestimmten Bedingungen die Startzeit für den Vorlauf falsch.
  • Der Verstärker macht bei den Dateien „VOEGEL01.WVA“ und „RELAX02.WVA“ eigenartige Knattergeräusche.
  • DIE Datei „REGEN03.WAV“ wird nicht abgespielt.
  • Die Farbtemperatur des Ziffernblatts sollte abhängig von Sonnenauf- und Untergangszeit sein.

Hilfreiche Links:

// Schlafphasenwecker Version 0.7.3

// Bibliotheken einbinden
#include <TimeLib.h>               // Stellt verschiedene Zeitfunktionen zur Verfügung
#include <EEPROM.h>                // Ermöglicht den Zugriff auf den EEPROM
#include <DCF77.h>                 // Bibliothek für das DCF77-Modul
#include <Audio.h>
#include <Wire.h>                  // 
#include <SPI.h>                   // this is needed for display
#include <SD.h>
#include <SerialFlash.h>
#include <ILI9341_t3.h>            // Teensy-optimierte Bibliothek für das TFT-Display
#include <Adafruit_FT6206.h>       // Kapazitiver Touchsensor
#include <Adafruit_TPA2016.h>      // Stereo 2.8W Class D Audio Amplifier TPA2016 
#include <Adafruit_Sensor.h>       // Adafruit Unified Sensor Driver
#include <Adafruit_TSL2591.h>      // Bibliothek für den Lichtsensor TSL2591
#include <Adafruit_LSM303_U.h>     // Bibliothek für den Beschleunigungssensor LSM303
#include <Adafruit_Simple_AHRS.h>
#include <Adafruit_NeoPixel.h>     // NeoPixel
#include <DHT.h>                   // DHT22-Sensor
#include <Kalman.h>

// Fonts einbinden
#include "font_DroidSans.h"        // Droid Sans Regular
#include "font_DroidSans_Bold.h"   // Droid Sans Bold
#include "font_AwesomeF000.h"      // AwesomeF000 (Symbole)
#include "font_AwesomeF080.h"      // AwesomeF080 (Symbole)
#include "font_AwesomeF100.h"      // AwesomeF100 (Symbole)
#include "font_AwesomeF180.h"      // AwesomeF180 (Symbole)
#include "font_AwesomeF200.h"      // AwesomeF200 (Symbole)

// Definiert Adressen im EEPROM
int addrAlarmHour = 0;
int addrAlarmMinute = 1;
int addrAlarmMode = 2;
int addrDisplayedAlarmHour = 3;
int addrDisplayedAlarmMinute = 4;
int addrAlarmAdvancetime = 5;      // Vorlauf für die Alarmfunktion
int addrAlarmFile = 6;             // Musikdatei für die Alarmfunktion
int addrSnoozleFile = 7;           // Musikdatei für die Einschalffunktion (Snoozle)
int addrSnoozleGain = 8;           // Lautstärke der Einschlaffunkion (Snoozle)
int addrAlarmGain = 9;             // Lautstärke der Alarmfunktion

// Definiert die Pins
#define DCF_PIN 2                  // DCF77-Modul
#define DCF_INTERRUPT 2            // Interrupt number associated with pin
#define DHTPIN 3
#define TFTbacklightPin 4          // PWM Backlight TFT
#define NEOPIXELPIN 33             // NeoPixel

// Definiert die DCF77-Bibliothek
DCF77 DCF = DCF77(DCF_PIN, DCF_INTERRUPT, false); 

// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ctp = Adafruit_FT6206();

// The display also uses hardware SPI
#define TFT_DC 20
#define TFT_CS 21
#define TFT_RST 255 // Set to 255 when reset is not used
#define TFT_MOSI 7
#define TFT_SCLK 14
#define TFT_MISO 12

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

//  pass in a number for the sensor identifier (for your use later)
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);

// Assign a unique ID to this sensor at the same time
Adafruit_LSM303_Accel_Unified accel(30301);
Adafruit_LSM303_Mag_Unified   mag(30302);

// Create simple AHRS algorithm using the above sensors.
Adafruit_Simple_AHRS          ahrs(&accel, &mag);

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, NEOPIXELPIN, NEO_GRBW + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

int numPixels = 60;                      // Anzahl der NeoPixel

// Konfiguriert die Audio-Funktionen
AudioPlaySdWav           playSdWav1;     //xy=154,239
AudioPlaySdWav           playSdWav2;     //xy=171,302
AudioMixer4              mixer2;         //xy=389,332
AudioMixer4              mixer1;         //xy=391,236
AudioOutputI2S           i2s1;           //xy=532,299
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection          patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection          patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection          patchCord5(mixer2, 0, i2s1, 1);
AudioConnection          patchCord6(mixer1, 0, i2s1, 0);
AudioControlSGTL5000     sgtl5000_1;     //xy=381,690

// Stereo 2.8W Class D Audio Amplifier TPA2016
Adafruit_TPA2016 audioamp = Adafruit_TPA2016();

// Initialisiert den DHT22-Sensor
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// Definiert die Variablen
int flankUp = 0;
int flankDown = 0;
int PreviousflankUp;
bool Up = false;

boolean IMUconnected = false;             // Wird wahr, wenn die IMU gefunden wurde.
boolean DCFtimesignalFound = false;       // Wird wahr, sobald ein DCF77-Zeitzeichen erfolgreich empfangen wurde.

time_t DCFtime = 0;                       // Das aktuelleste erfolgreich empfangene Zeitzeichen im Variablenformat time_t (Sekunden seit dem 1.1.1970)
time_t t = 0;                             // Die Zeit der Real Time Clock im Variablenformat time_t (Sekunden seit dem 1.1.1970)
time_t DefaultTime = 1477958400;          // Die bis zum 1.11.2016 verstrichene Zeit in Sekunden seit dem 1.1.1970.
//time_t startTime;                         // Zeit, zu der die Uhr zuletzt gestartet wurde
unsigned long timesinceDCFsignal;         // Zeit im Format time_t, die seit dem letzten vollstänig empfangenen DCF77-Zeitzeichen vergangen ist.
unsigned long noDCFsignal;                // Zeit in Sekunden, die seit dem Systemstart bis zum ersten erfolgreich empfangenen DCF-Zeitzeichen vergangen ist. (Läuft nach ca. 52 Tagen über.)
time_t timestampDCFsignal;                // Zeitstempel im Format time_t, für das zuletzt vollständig empfangene Zeitsignal.
unsigned long receivedDCFsignals = 0;     // Zählt die Anzahl der erfolgreich empfangenen DCF77-Zeitzeichen seit dem Systemstart.
float DCFsuccessRate = 0;                 // Wert für die Quote der erfolgreich empfangenen DCF77-Zeitzeichen seit dem Systemstart.

boolean clockfaceOn = true;               // Kann auf falsch gesetzt werden, om das Ziffernblatt zugunsten anderer Effekte zu deaktivieren.
int8_t intensity = 1;                     // Wert für die Helligkeit des Ziffernblatts

float x = 4.712388980;        // Start- und Zählwert für verschiedene Beleuchtungseffekte 

int i;                        // Zählwert für verschiedene Beleuchtungseffekte
int j;                        // Zählwert für verschiedene Beleuchtungseffekte
int k;                        // Zählwert für verschiedene Beleuchtungseffekte
int l;                        // Zählwert für verschiedene Beleuchtungseffekte

// Definiert die globalen RGBW-Werte für das NeoPixel-Ziffernblatt
byte r = 0;
byte g = 0;
byte b = 0;
byte w = 0;



int displayedAlarmHour = 6;               // Stunde, die auf dem TFT als Alarmzeit angezeigt wird. Wird als Integer definiert, damit die Variable theoretisch negativ werden kann. (Das ist für den Rollover von 0 auf 23 nötig.)
int displayedAlarmMinute = 0;             // Minute, die auf dem TFT als Alarmzeit angezeigt wird. Wird als Integer definiert, damit die Variable theoretisch negativ werden kann. (Das ist für den Rollover von 0 auf 45 nötig.)
int alarmHour = 5;                        // Stunde, zu der ein schlafphasensensibler Alarm frühestens ausgelöst werden soll. Wird als Integer definiert, damit die Variable theoretisch negativ werden kann. (Das ist für den Rollover von 0 auf 23 nötig.)
int alarmMinute = 30;                     // Minute, zu der ein schlafphasensensibler Alarm frühestens ausgelöst werden soll. Wird als Integer definiert, damit die Variable theoretisch negativ werden kann. (Das ist für den Rollover von 0 auf 45 nötig.)
int alarmAdvancetime = 30;                // Größe des Zeitfensters in Minuten, in der der schlafphasensensible Alarm ausgelöst werden kann. 
byte alarmMode = 0;                       // Alarmmodus (0 = Alarm aus)
byte alarmFile = 1;                       // Legt die WAV-Datei fest, die bei einem Alarm abgespielt wird
int16_t alarmGain = 30;                   // Lautstärke der Alarmfunktion (wird mit 0.004 multipliziert). Wird als Integer definiert, damit sie theoretisch negativ weden kann.
boolean alarmOn = false;                  // Wird wahr, sobald ein Schlafphasenalarm aktiviert wird

boolean snoozeOn = false;                 // Wird wahr, wenn derSchlummeralarm aktiv ist
int snoozeDelay = 600;                    // Schlummerzeit in Sekunden
int snoozeTime = 1477958400;              // Die Zeit, zu der ein neuer Alarm ausgelöst werden soll

boolean snoozleOn = false;                // Wird wahr, wenn die Snoozle-Funktion aktiv ist
byte snoozleFile = 1;                     // Legt die WAV-Datei fest, die zum Snoozlen abgespielt wird
time_t snoozleTime = 1477958400;          // Die Zeit, bis zu der Snoozle-Musik abgespielt werden soll
int16_t snoozleGain = 70;                 // Lautstärke der Einschlaffunktion (wird mit 0.004 multipliziert). Wird als Integer definiert, damit sie theoretisch negativ weden kann.
int16_t sg;                               // Variable für das Fade out der Snoozle-Musik

uint16_t ir;                              // Helligkeitswert für den Infrarotanteil des Lichts
uint16_t full;                            // Helligkeitswert für das Infrarotanteil und das sichtbare Licht
uint32_t lum;
uint16_t lux;
uint16_t filteredLux;

float accelX;
float accelY;
double accelZ, filteredAccelZ;

double roll, filteredRoll;
double pitch, filteredPitch;
float heading;

Kalman accelZFilter(0.25,8,1023,0);       //suggested initial values for high noise filtering (q [process noise covariance], r [measurement noise covariance], p [estimation error covariance], x [value])
Kalman rollFilter(0.25,8,1023,0);         //suggested initial values for high noise filtering
Kalman pitchFilter(0.25,8,1023,0);        //suggested initial values for high noise filtering
Kalman luxFilter(0.25,8,1023,0);          //suggested initial values for high noise filtering


int eventAccelZ = 0;                      // Zählt Ereignisse auf der Beschleunigungsachse Z
int eventRoll = 0;                        // Zählt Ereignisse auf der Rollachse
int eventPitch = 0;                       // Zählt Ereignisse auf der Pitchachse
int eventTotal = 0;

float h;                                  // Wert für die Luftfeuchtigkeit
float c;                                  // Wert für Temperatur in Grad Celsius
float f;                                  // Wert für Temperatur in Fahrenheit
float taupunkt;                           // Wert für den Taupunkt

boolean touch = false;
boolean prevtouch = false;
boolean touch2 = false;
boolean prevtouch2 = false;

boolean TFTbacklightOn = false;           // Wird wahr, sobald das TFT Backlight an ist
byte TFTbrightness = 0;                   // Wert für die aktuelle Helligkeit des TFT Backlights
//byte TFTmaxbrightness = 255;            // Wert für die maximale Helligkeit des TFT backlights
//byte TFTminbrightness = 0;              // Wert für die minimale Helligkeit des TFT backlights
const unsigned long TFTbacklightDelay = 60000; // Zeit in Millisekunden, nach der das TFT Backlight abgeschaltet wird.
unsigned long TFTbacklightTime = 0;   
boolean TFTrefresh = false;               // Wird true, wenn ein Menü aktualisiert werden soll


byte menuPage = 0;                        // Wert für das aktuell auf dem TFT angezeigten Menü. Gestartet wird mit Menü Nr. 0.
byte previousmenuPage = 1;                // Wert für die Menüseite, die in dem vormaligen Durchlauf aktuell war.
int tx;                                   // Auf dem Touchscreen gedrücktes Pixel auf der x-Achse. Pixelspalte Nr. 0 ist links.
int ty;                                   // Auf dem Touchscreen gedrücktes Pixel auf der y-Achse. Pixelzeile Nr. 0 ist oben.


// Definiert die Tracking-Variablen für die IF-Abfragen
unsigned long previousMillisSetRTC = 0;          // Real time Clock
unsigned long previousMillisAlarmClock = 0;      // Alarm-Funktion
unsigned long previousMillisSnoozleTime = 0;     // Einschlaf-Funktion
unsigned long previousMillisClockFace = 0;       // Ziffernblatt
unsigned long previousMillisTFTScreen = 0;       // TFT-Screen
unsigned long previousMillisTouchScreen = 0;     // Touch-Sensor
unsigned long previousMillisSensorData = 0;      // IMU und TSL2591
unsigned long previousMillisDHTSensor = 0;       // DHT22
unsigned long previousMillisSerialPrint = 0;     // Serielle Ausgabe
unsigned long previousMillisDCFPulseLength = 0;  // Pulsweitenmessung

// Definiert die Intervalle für die IF-Abfragen in Millisekunden
const unsigned long intervalSetRTC = 1000;        // konstanter Delay für Holen der Zeit
const unsigned long intervalAlarmClock = 1000;    // konstanter Delay für die Weckfunktionen
const unsigned long intervalSnoozleTime = 1000;   // konstanter Delay für die Snoozlefunktion
const unsigned long intervalClockFace = 20;       // konstanter Delay für das Ziffernblatt
unsigned long intervalTFTScreen = 100;            // variabler Delay für Anteuerung des TFT-Screens
const unsigned long intervalTouchScreen = 50;     // konstanter Delay für Anteuerung des kapazitiven Touchsreens
const unsigned long intervalSensorData = 100;     // konstanter Delay für Auslesen der Sensoren
const unsigned long intervalDHTSensor = 60000;    // konstanter Delay für Auslesen ded Temperatursensors
const unsigned long intervalSerialPrint = 100;    // konstanter Delay für serielle Ausgabe
const unsigned long intervalDCFPulseLength = 1;   // konstanter Delay für die Messung der Periode und Pulsweite des Zeitsignals


void setup()  {
  // Initalisiert die Pins
  pinMode(DCF_PIN, INPUT_PULLUP);                 // DFC77-Modul
  pinMode(DHTPIN, INPUT_PULLUP);                  // DHT22-Sensor
  pinMode(TFTbacklightPin, OUTPUT);               // PWM für TFT Backlight

  // Initialisiert die serielle Schnittstelle
  Serial.begin(115200);
  
  // set the Time library to use Teensy 3.0's RTC to keep time
  setSyncProvider(getTeensy3Time);

  delay(2000);                                   // 2000 Millisekunden Pause, damit der serielle Monitor verfügbar ist, das Programm aber auch ohne läuft
  if (timeStatus()!= timeSet) {
    Serial.println("Unable to sync with the RTC");
  } else {
    Serial.println("RTC has set the system time");
  }

  //Initialisiert den Touchscrenn
  if (! ctp.begin(40)) {                               // Stellt u.a. die Sensitivität des Touchscreens ein
    Serial.println("Couldn't start FT6206 touchscreen controller");
    //while (1);
  } else {
    Serial.println("Capacitive touchscreen started");
  }

  //Initialisiert den Beschleunigungssensor LSM303
  if(!accel.begin()) {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
    //while(1);
  } else {
    IMUconnected = true;
  }
  if(!mag.begin()) {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
    //while(1);
  }
  
  // Initialisiert den TFT-Bildschirm
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  
  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 

  // Konfiguration des TSL2591
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  // tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  // tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  //tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  // Initialisiert den TSL2591
  tsl.begin(); //Lichtsensor

  // Intitialisiert den DHT22
  dht.begin();

  // Displays some basic information on this sensor from the unified sensor API sensor_t type
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux");  
  Serial.println("------------------------------------");
  Serial.println("");
  
  // Startet die Abfrage des DCF77-Moduls
  DCF.Start();
  Serial.println("Waiting for DCF77 time ... ");
  Serial.println("It will take at least 2 minutes until a first update can be processed."); 
  
  // Initialisiert das Audio Board und die SD-Karte
  AudioMemory(12);
  sgtl5000_1.enable();
  sgtl5000_1.muteHeadphone();
  sgtl5000_1.volume(0.8);
  sgtl5000_1.audioPostProcessorEnable();
  sgtl5000_1.enhanceBassEnable();
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    Serial.println("Unable to access the SD card");
  }
  Serial.println("Teensy Audio Adaptor initialisiert");
  
  // Initialisiert den Class D Amplifier
  audioamp.begin();
  audioamp.setAGCCompression(TPA2016_AGC_OFF); // Turn off AGC
  // audioamp.setAGCCompression(TPA2016_AGC_2);      // Set compression to 1:2
  audioamp.setLimitLevelOn();
  audioamp.setLimitLevel(10);

  // Initialisiert den NeoPixel-Teststrip
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  
  // Lese die abgespeicherten Werte für die angezeigte Alarmzeit, die schlafphasenabhängige Alarmzeit und den Alarmmmodus
  alarmHour = EEPROM.read(addrAlarmHour);                       // die aus der angezeigten Alarmwit und der Vorlaufzeit berechnete Alarmzeit (Stunde)
  alarmMinute = EEPROM.read(addrAlarmMinute);                   // die aus der angezeigten Alarmwit und der Vorlaufzeit berechnete Alarmzeit (Minute)
  alarmMode = EEPROM.read(addrAlarmMode);                       // der ausgewählte Alarmmodus
  displayedAlarmMinute = EEPROM.read(addrDisplayedAlarmMinute); // die angezeigte Alarmzeit (Minute)
  displayedAlarmHour = EEPROM.read(addrDisplayedAlarmHour);     // die angezeigte Alarmzeit (Stunde)
  alarmAdvancetime = EEPROM.read(addrAlarmAdvancetime);         // die ausgewählte Vorlaufzeit für den Alarm (in Minuten)
  alarmFile = EEPROM.read(addrAlarmFile);                       // die ausgewählte WAV-Datei
  alarmGain = EEPROM.read(addrAlarmGain);                       // die Lautstärke für die Alarmfunktion
  snoozleFile = EEPROM.read(addrSnoozleFile);                   // die ausgewählte WAV-Datei
  snoozleGain = EEPROM.read(addrSnoozleGain);                   // die Lautstärke für die Einschlaffunktion (Snoozle)

  Serial.println("Werte werden aus dem EEPROM ausgelesen:");
  Serial.print("alarmAdvancetime: "); Serial.println(alarmAdvancetime);
  Serial.print("alarmFile: "); Serial.println(alarmFile);
  Serial.print("alarmGain: "); Serial.println(alarmGain);
  Serial.print("snoozleFile: "); Serial.println(snoozleFile);
  Serial.print("snoozleGain: "); Serial.println(snoozleGain);

  // Es wird einmalig die Funktion zur Berechnung des Sonnenauf- und untergangs aufgerufen.
  sunrise();
}


void loop() {
// Aktuelle Zeit abfragen
  unsigned long currentMillis = millis();


// Stelle die Real Time Clock (RTC) auf die aktuelle Zeit
 if ((unsigned long)(currentMillis - previousMillisSetRTC) >= intervalSetRTC) {

  DCFtime = DCF.getTime();              // Check if new DCF77 time is available

  // Wenn die serielle Schnittstelle verfügbar ist, setze die RTC auf diese Zeit
  if (Serial.available()) {
    t = processSyncMessage();
    if (t != 0) {
      Teensy3Clock.set(t);             // set the RTC
      setTime(t);
    }
  }

  // Wenn ein Zeitsignal vom DCF77-Modul verfügbar ist, setze die RTC auf diese Zeit
  if (DCFtime > DefaultTime) {
    t = DCFtime;
    Serial.println("RTC has been updated to DCF77 time");
    Teensy3Clock.set(t);               // set the RTC
    setTime(t);
    DCFtimesignalFound = true;         // die Variable wird wahr
    receivedDCFsignals = receivedDCFsignals + 1;
    timestampDCFsignal = now();
  }

  // Berechne die Zeit die seit dem Empfang des letzten vollständig empfangenen Zeitsignals vergangen ist
  if (DCFtimesignalFound == false) {
    noDCFsignal = currentMillis / 1000;         // in Sekunden
  }
  else {
    timesinceDCFsignal = now() - timestampDCFsignal;   // im Format time_t
  }
 
  // Berechnet die Quote erfolgreich empfangener DCF77-Signale seit dem letzten Systemstart
  DCFsuccessRate = (float(receivedDCFsignals) / ((millis() / 60000))) * 100;
  
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisSetRTC = currentMillis;
  }


// Ziffernblatt
  if ((unsigned long)(currentMillis - previousMillisClockFace) >= intervalClockFace) {

    // Berechnung der Helligkeit des Ziffernblatts
    /*
    if (filteredLux <= 20) {intensity = 10;}
    else if (filteredLux > 20 && filteredLux <= 100) {intensity = 5;}
    else if (filteredLux > 100 && filteredLux <= 10000) {intensity = 4;}
    else if (filteredLux > 10000 && filteredLux <= 20000) {intensity = 3;}
    else if (filteredLux > 20000 && filteredLux <= 40000) {intensity = 2;}
    else if (filteredLux > 40000) {intensity = 1;}

    Serial.print("Intensitaet: "); Serial.println(intensity);
    */
    intensity = round(10 - (log(filteredLux/5)));
    Serial.print("Intensitaet: "); Serial.println(intensity);
    if (intensity > 10) {
      intensity = 10;
    }
    if (intensity < 0) {
      intensity = 0;
    }


    // Anmerkung:
    // Wenn bei 7 NeoPixelen eine Farbe mit einem Wert von 32 (1/8 der max. Intensität) angesteuert wird, ist das für einen dunklen Raum zu hell.
    // Je mehr NeoPixel von einem Ziffernblatteffekt verwendet werden, desto besser muss die Anzahl der aktiven NeoPixel berücksichtigt werden.
  
    if (clockfaceOn == true) {            // Das Ziffernblatt wird angezeit, wenn die Variable wahr ist
      strip.clear();
      /*
      // Stundenskaka
      for (int i = 0; i < 60; i = i + 5) {
        strip.setPixelColor(i, r, g, b, 32);
      }
      */
      // Stundenanzeige
      if (hour() < 12) {
        for (int j = (hour() * 5); j < ((hour() * 5) + 6); j++) {
          strip.setPixelColor(j, r, g, (250 / (intensity *2)), (250 / intensity));
        }
      } 
      else if (hour() >= 12) {
        for (int j = ((hour() - 12) * 5); j < (((hour() - 12) * 5) + 6); j++) {
          strip.setPixelColor(j, r, g, (250 / (intensity *2)), (250 / intensity));
        }
      }
      // Minutenanzeige
      k = minute();
      strip.setPixelColor(k, r, g, (250 / intensity), (250 / (intensity *4)));
     
      // Sekundenanzeige
      l = second();
      strip.setPixelColor(l, r, g, (250 / intensity), (250 / (intensity *4)));

      strip.show();
    }
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisClockFace = currentMillis;
  }
  

// Snoozle-Funktion
  if ((unsigned long)(currentMillis - previousMillisSnoozleTime) >= intervalSnoozleTime) {

    /*
    // Ausgabe an serielle Schnittstelle für Debugging
    Serial.print("current time: ");
    Serial.print(now());
    Serial.print("; snoozleTime: ");
    Serial.print(snoozleTime);
    Serial.print("; snoozleOn: ");
    Serial.print(snoozleOn);
    Serial.print("; snoozleFile: ");
    Serial.println(snoozleFile);
    */
    
    // Wenn die aktuelle Zeit kleiner ist als die eingestellte Snoozle-Zeit, dann ...
    if (snoozleOn == true) {
      
      if (now() < snoozleTime) {
        audioamp.enableChannel(true, true);          // Schaltet beide Ausgänge des Verstärkers online
        snoozleGain = EEPROM.read(addrSnoozleGain);  // Ließt die Lautstärke für die Einschlaffunktion aus dem EEPROM
        mixer1.gain(0, (snoozleGain * 0.005));       // Stellt die Lautstärke ein
        mixer2.gain(0, (snoozleGain * 0.005));
      }
      
      if (playSdWav1.isPlaying() == false) {
        Serial.println("Start playing");
        if (snoozleFile == 1) {
          playSdWav1.play("MEER01.WAV");
        } 
        else if (snoozleFile == 2) {
          playSdWav1.play("REGEN01.WAV");
        } 
        else if (snoozleFile == 3) {
          playSdWav1.play("REGEN02.WAV");
        }
        else if (snoozleFile == 4) {
          playSdWav1.play("REGEN03.WAV");
        }
         if (snoozleFile == 5) {
          playSdWav1.play("REGEN04.WAV");
        } 
        else if (snoozleFile == 6) {
          playSdWav1.play("REGEN05.WAV");
        } 
        else if (snoozleFile == 7) {
          playSdWav1.play("VOEGEL01.WAV");
        }
        else if (snoozleFile == 8) {
          playSdWav1.play("RELAX02.WAV");
        }       
      }
      
      if (menuPage != 8) {                   // Das Menü "Snoozle aus/Lautstärke" soll nur einmal aufgerufen werden.
        menuPage = 8;
        TFTrefresh = true;      
      }
    }  
     if (now() >= snoozleTime && snoozleOn == true) {
       Serial.println("Snoozletime expired");
       
       // Reduziere langsam die Lautstärke
       snoozleGain = snoozleGain - 1;               // Verringert die Lautstärke
       mixer1.gain(0, (snoozleGain * 0.005));       // Stellt die Lautstärke ein
       mixer2.gain(0, (snoozleGain * 0.005));
       Serial.print("Reducing volume"); Serial.print(", snoozleGain: "); Serial.println(snoozleGain); 
       
       // Wenn die Lautstärke null ist, wird die Wiedergabe gestoppt und in das Hauptmenü gewechselt
       if (snoozleGain <= 0) {
         snoozleOn = false;
         playSdWav1.stop();
         Serial.println("Stop playing");
         audioamp.enableChannel(false, false);    // Schaltet den Verstärker aus
         if (menuPage == 8) {                     // Wenn Menü "8" angezeigt wird ...
           menuPage = 0;                          // ... rufe das Hauptmenü auf.
           TFTrefresh = true;
         }      
       }
    }
       
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisSnoozleTime = currentMillis;
  }


// Alarm-Funktionen (alarm und Snooze)
  if ((unsigned long)(currentMillis - previousMillisAlarmClock) >= intervalAlarmClock) {
    
    // Die Schleife wird durchlaufen, a) wenn ein Alarm eingestellt und die Zeit dafür gekommen ist oder b) eine Alarmfunktion läuft.
    if (alarmMode != 0 && hour() == alarmHour && minute() == alarmMinute && second() == 0 || alarmOn == true) {
      
      // Die Eventzähler müssen zu beginn einer Alarmphase einmalig zurückgesetzt werden
      if (alarmOn == false) {
        eventAccelZ = 0;
        eventRoll = 0;
        eventPitch = 0;
        eventTotal = 0;
      }

      // Wecken mit Licht
      if (alarmMode == 1) {
        Serial.println("Alarmphase 1 aktiv!");
        if (eventTotal >= 10) {                   // Weil dieser Alarm sehr schonend ist, kann er früh gestartet werden
          clockfaceOn = false;
          Serial.print("ALARM 1!!!!");

          // Ansteuerung der NeoPixel
          if (r < 255) {
            r = r + 1;                            // r wird in jeder Schleife etwas erhöht
          }
          if (r == 255 && g < 120) {
            g = g + 1;
          }
          //if (g == 255 && b < 255) {
          //  b = b + 1;
          //}
          if (g == 120 && w < 255) {  
            w = w + 1;
          }
 

          Serial.print("; r = ");
          Serial.print(r);
          Serial.print("; g = ");
          Serial.print(g);
          Serial.print("; b = ");
          Serial.print(b);
          Serial.print("; w = ");
          Serial.println(w);     
              
          for (int i = 0; i < numPixels; i++) {
            strip.setPixelColor(i, r, g, b, w);
          }
          strip.show();
        }
      }
      
      // Wecken mit Musik
      else if (alarmMode == 2) {
        Serial.println("Alarmphase 2 aktiv!");
        if (eventTotal >= 100) {
          audioamp.enableChannel(true, true);          // Schaltet beide Ausgänge des Verstärkers online
          alarmGain = EEPROM.read(addrAlarmGain);      // Ließt die Lautstärke für die Alarmfunktion aus dem EEPROM
          mixer1.gain(1, (alarmGain * 0.005));         // Stellt die Lautstärke ein
          mixer2.gain(1, (alarmGain * 0.005));
          Serial.print("ALARM 2!!!!");
          if (playSdWav2.isPlaying() == false) {
            Serial.println("Start playing");
            if (alarmFile == 1) {
              playSdWav2.play("MEER01.WAV");
            } 
            else if (alarmFile == 2) {
              playSdWav2.play("MEER02.WAV");
            } 
            else if (alarmFile == 3) {
              playSdWav2.play("REGEN01.WAV");
            }
            else if (alarmFile == 4) {
              playSdWav2.play("REGEN02.WAV");
            }
          }
        }
      }
      
      // Wecken mit Licht und Musik
      else if (alarmMode == 3) {
        Serial.println("Alarmphase 3 aktiv!");
        if (eventTotal >= 100) {
          audioamp.enableChannel(true, true);          // Schaltet beide Ausgänge des Verstärkers online
          alarmGain = EEPROM.read(addrAlarmGain);      // Ließt die Lautstärke für die Alarmfunktion aus dem EEPROM
          mixer1.gain(1, (alarmGain * 0.005));         // Stellt die Lautstärke ein
          mixer2.gain(1, (alarmGain * 0.005));
          Serial.print("ALARM 3!!!!");
        }
      }
    


      // Anzeige des Menüs "Wecker aus"/"Schlummern"
      TFTbrightness = 255;
      analogWrite(TFTbacklightPin, TFTbrightness);
      TFTbacklightOn = true;             // Das Backlight bleibt eingeschaltet, so lange die Alarm-Funktion aktiv ist
      alarmOn = true;
      
      if (menuPage != 7) {               // Das Menü "Alarm aus/Snooze" soll nur einmal aufgerufen werden.
        menuPage = 7;
        TFTrefresh = true;
      }
    }
      
      
      // Schlummeralarm
      if (snoozeOn == true && now() >= snoozeTime) {
        Serial.println("Schlummerlarm!");
        if (playSdWav2.isPlaying() == false) {
          audioamp.enableChannel(true, true);          // Schaltet beide Ausgänge des Verstärkers online
          alarmGain = EEPROM.read(addrAlarmGain);      // Ließt die Lautstärke für die Alarmfunktion aus dem EEPROM
          mixer1.gain(1, (alarmGain * 0.005));         // Stellt die Lautstärke ein
          mixer2.gain(1, (alarmGain * 0.005));
          Serial.println("Start playing");
          if (alarmFile == 1) {
            playSdWav2.play("MEER01.WAV");
          } 
          else if (alarmFile == 2) {
            playSdWav2.play("MEER02.WAV");
          } 
          else if (alarmFile == 3) {
            playSdWav2.play("REGEN01.WAV");
          }
          else if (alarmFile == 4) {
            playSdWav2.play("REGEN02.WAV");
          }
        }        
        // Anzeige des Menüs "Wecker aus"/"Schlummern"
        TFTbrightness = 255;
        analogWrite(TFTbacklightPin, TFTbrightness);
        TFTbacklightOn = true;             // Das Backlight bleibt eingeschaltet, so lange die Snooze-Funktion aktiv ist
        snoozeOn = true;
        
        if (menuPage != 7) {               // Das Menü "Alarm aus/Snooze" soll nur einmal aufgerufen werden.
          menuPage = 7;
          TFTrefresh = true;
        }
      }  
  
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisAlarmClock = currentMillis;
  }


// Abfrage verschiedener Sensoren
  if ((unsigned long)(currentMillis - previousMillisSensorData) >= intervalSensorData) {

    if (IMUconnected == true) {
      // Auslesen des Beschleunigungs- / Lagesensors und Magnetometers LSM303
      sensors_event_t event;
      accel.getEvent(&event);
      sensors_vec_t   orientation;
      ahrs.getOrientation(&orientation);

      accelX = event.acceleration.x;
      accelY = event.acceleration.y;
      accelZ = event.acceleration.z;

      pitch = orientation.roll;                 // Pitch und Roll müssen vertauscht werden, damit die Orientierung zur Einbaulage des Sensors passt
      roll = orientation.pitch;
      heading = orientation.heading;
    }
    
    // Die Werte für accelZ, pitch und roll werden mit einem Kalman-Filter geglättet
    filteredAccelZ = accelZFilter.getFilteredValue(accelZ);
    filteredRoll = rollFilter.getFilteredValue(roll);
    filteredPitch = pitchFilter.getFilteredValue(pitch);

    // Relativ schnelle Änderungen der Sensordaten lösen Ereignisse aus 
    if (filteredAccelZ - accelZ > 1 || filteredAccelZ - accelZ < -1) {
      eventAccelZ = eventAccelZ + 1;
      logSDcard();
    }
    if (filteredRoll - roll > 5 || filteredRoll - roll < -5) {
      eventRoll = eventRoll + 1;
    }
    if (filteredPitch - pitch > 5 || filteredPitch - pitch < -5) {
      eventPitch = eventPitch + 1;
    }

    // Berechne die Summe aller Ereignisse
    eventTotal = eventAccelZ + eventRoll + eventPitch;
    
    //Auslesen des Helligkeitssensors TSL2591
    lum = tsl.getFullLuminosity();
    ir = lum >> 16;
    full = lum & 0xFFFF;
    lux = tsl.calculateLux(full, ir);

    // Der Wert für Lux wird geglättet, weil er bei schnellen Änderungen des Umgebungslichts über das Ziel hinausschießt
    filteredLux = luxFilter.getFilteredValue(lux);

    Serial.print("lum: "); Serial.print(lum);
    Serial.print(", ir: "); Serial.print(ir);
    Serial.print(", full: "); Serial.print(full);
    Serial.print(", lux: "); Serial.print(lux);
    Serial.print(", filtered lux: "); Serial.println(filteredLux);
  
  /*
  // Daten auf SD-Karte loggen
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.print(currentMillis);
    dataFile.print(",");
    dataFile.println(lux);
    dataFile.close();
    // print to the serial port too:
    Serial.print(currentMillis);
    Serial.print(",");
    Serial.print(lux);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
  */  
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisSensorData = currentMillis;
  }


// Abfrage des Temperatur- und Luftfeuchtigkeitssensors DHT22
  if ((unsigned long)(currentMillis - previousMillisDHTSensor) >= intervalDHTSensor) {

    // Auslesen des Temperatursensors DHT22
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    c = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    f = dht.readTemperature(true);

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(c) || isnan(f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }

    // Compute heat index in Fahrenheit (the default)
    float hif = dht.computeHeatIndex(f, h);
    // Compute heat index in Celsius (isFahreheit = false)
    float hic = dht.computeHeatIndex(c, h, false);

    // Taupunkt berechnen
    float a = 17.271; 
    float b = 237.7; 
    float taupunktTmp = (a * c) / (b + c) + log(h/100); 
    taupunkt = (b * taupunktTmp) / (a - taupunktTmp); 
  
    Serial.print("Relative Luftfeuchtigkeit: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperatur: ");
    Serial.print(c);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t");
    Serial.print("Hitzeindex: ");
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(hif);
    Serial.print(" *F\t");
    Serial.print("Taupunkt: ");
    Serial.print(taupunkt);
    Serial.println(" *C");
    
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisDHTSensor = currentMillis;
  }


// TFT- imd Touchscreen
  if ((unsigned long)(currentMillis - previousMillisTouchScreen) >= intervalTouchScreen) {

    // Auslesen des kapazitiven Touchsensors
    if (ctp.touched()) {
      // Retrieve a point  
      TS_Point p = ctp.getPoint();
      // Damit der Wert 0, 0 des Touchsensors mit dem Pixel 0, 0 des TFT-Screens übereinstimmt, müssen p.x und p.y rekodiert werden
      tx = map(p.y, 0, 320, 320, 0);
      ty = p.x;

      // Variablen für die Steuerung des Backlights
      touch = true;                              // Wird wahr, so lange der Touchsensor berührt wird (d.h. wird am Ende der TouchScreen-Schleife false).
      prevtouch = touch;                         
      TFTbacklightTime = currentMillis;               // Wird auf die aktuelle Systemzeit gesetzt, soblad der Touchsensor berührt wird.

      // Variablen für die Steurung des Menüs
      if (TFTbacklightOn == true) {
        touch2 = true;
        prevtouch2 = touch2;
      }
    }

    // Das Backlight wird eingeschaltet, nachdem der Touchsensor losgelassen wird.
    if (touch == false && prevtouch == true) {
      TFTbrightness = 255;
      analogWrite(TFTbacklightPin, TFTbrightness);
      TFTbacklightOn = true;
      TFTrefresh = true;                       // Wenn das Backlight eingeschaltet wird, muss einmal das alte Menü aufgebaut werden
      prevtouch = false;
    }

    // Wenn das Backlight an ist, soll es nach einer bestimmten Zeit wieder ausgeschaltet werden.
    // Allerdings nur dann, wenn a) keine Alarmfunktion, b) keine Schlummerfunktion oder c) keine Snoozlemusik läuft.
    if (alarmOn == false && snoozeOn == false && snoozleOn == false) {
      if (TFTbacklightOn == true && (millis() > TFTbacklightTime + TFTbacklightDelay)) {
        TFTbrightness = TFTbrightness - 1;
        if (TFTbrightness == 0) {
          TFTbacklightOn = false;
          tft.fillScreen(ILI9341_BLACK);
        }
        analogWrite(TFTbacklightPin, TFTbrightness);
      }
    }

    // Wenn das Backlight an ist, kann das Menü mit dem Touchsensor bedient werden        
    // Es folgen für jedes einzelne Menü die Definitionen der jeweils sensiblen Bereiche einschließlich der Befehle, die jeweils ausgelöst werden sollen. 
    if (menuPage == 0 && touch2 == false && prevtouch2 == true) {           // Wenn der Touchscreen losgelassen wurd und Menüseite 0 ausgewählt ist ...
      if ((tx >= 0) && (tx <= 120) && (ty >= 0) && (ty <= 59)) {            // ... und der TouchScreen in dem angegebenen Bereich berührt wird ... 
        menuPage = 1;                                                       // ... dann rufe Menüseite 1 auf.
      } 
      else if ((tx >= 0) && (tx <= 120) && (ty >= 60) && (ty <= 120)) {
        menuPage = 2;
      }
      else if ((tx >= 0) && (tx <= 120) && (ty >= 121) && (ty <= 180)) {
        menuPage = 3;
      }
      else if ((tx >= 0) && (tx <= 120) && (ty >= 181) && (ty <= 240)) {
        menuPage = 4;
      } 
      else if ((tx >= 121) && (tx <= 320) && (ty >= 1) && (ty <= 240)) {
        menuPage = 5;
      }
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;                                                    // Aktualisiere den Inhalt des TFT-Screens
      prevtouch2 = false;                                                   // Wird unwahr, damit die folgenden Schleifen übersprungen werden.
    }

    // Menü Snoozle
    if (menuPage == 1 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Hauptmenü
      if ((tx >= 0) && (tx <= 49) && (ty >= 0) && (ty <= 240)) {
        menuPage = 0;
      } 
      // Snoozle 15 Minuten
      else if ((tx >= 50) && (tx <= 268) && (ty >= 0) && (ty <= 59)) {
        snoozleOn = true;
        snoozleTime = now() + 900;
      }
      // Snoozle 30 Minuten
      else if ((tx >= 50) && (tx <= 268) && (ty >= 60) && (ty <= 119)) {
        snoozleOn = true;
        snoozleTime = now() + 1800;
      }
      // Snoozle 45 Minuten
      else if ((tx >= 50) && (tx <= 268) && (ty >= 120) && (ty <= 179)) {
        snoozleOn = true;
        snoozleTime = now() + 2700;
      }    
      // Snoozle 60 Minuten
      else if ((tx >= 50) && (tx <= 268) && (ty >= 180) && (ty <= 239)) {
        snoozleOn = true;
        snoozleTime = now() + 3600;
      }
      // Zum Unteruntermenü Snoozle-Musik auswählen
      else if ((tx >= 269) && (tx <= 319) && (ty >= 0) && (ty <= 239)) {
        menuPage = 11;
      }
      // Debugging
      Serial.print("Aktueller Zeitindex: "); Serial.print(now());
      Serial.print(", berechnete SnoozleTime: "); Serial.println(snoozleTime);
      
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;  
    }

    // Unteruntermenü Auswahl Snoozlemusik
    if (menuPage == 11 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Snoozle
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 1;
        tft.fillScreen(ILI9341_BLACK);
      } 
      // Auswahl Musik 1
      else if ((tx >= 51) && (tx <= 184) && (ty >= 0) && (ty <= 59)) {
        snoozleFile = 1;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      } 
      // Auswahl Musik 2
      else if ((tx >= 51) && (tx <= 184) && (ty >= 60) && (ty <= 120)) {
        snoozleFile = 2;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      }
      // Auswahl Musik 3
      else if ((tx >= 51) && (tx <= 184) && (ty >= 121) && (ty <= 180)) {
        snoozleFile = 3;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      }
      // Auswahl Musik 4
      else if ((tx >= 51) && (tx <= 184) && (ty >= 181) && (ty <= 240)) {
        snoozleFile = 4;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      } 
      // Auswahl Musik 5
      else if ((tx >= 186) && (tx <= 319) && (ty >= 0) && (ty <= 59)) { 
        snoozleFile = 5;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      } 
      // Auswahl Musik 6
      else if ((tx >= 186) && (tx <= 319) && (ty >= 60) && (ty <= 120)) {
        snoozleFile = 6;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      }
      // Auswahl Musik 7
      else if ((tx >= 186) && (tx <= 319) && (ty >= 121) && (ty <= 180)) {
        snoozleFile = 7;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      }
      // Auswahl Musik 8
      else if ((tx >= 186) && (tx <= 319) && (ty >= 181) && (ty <= 240)) {
        snoozleFile = 8;
        EEPROM.update(addrSnoozleFile, snoozleFile);
      } 
      
      TFTrefresh = true;
      prevtouch2 = false;
    }

    // Menü Ziffernblatt
    if (menuPage == 2 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Hauptmenü
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 0;
      } 
      else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
        menuPage = 0;
      }
      TFTrefresh = true;
      prevtouch2 = false;
    }

    // Menü Einstellungen
    if (menuPage == 3 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Hauptmenü
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 0;
      } 
      // Zum Untermenü Weckzeitvorlauf
      else if ((tx >= 51) && (tx <= 184) && (ty >= 0) && (ty <= 59)) {
        menuPage = 31;
      } 
      // Zum Untermenü Weckmusik
      else if ((tx >= 51) && (tx <= 184) && (ty >= 60) && (ty <= 120)) {
        menuPage = 32;
      }
      // Zum Untermenü Wecklautstärke
      else if ((tx >= 51) && (tx <= 184) && (ty >= 121) && (ty <= 180)) {
        menuPage = 33;
      }
      /*
      // Zum Untermenü "frei"
      else if ((tx >= 51) && (tx <= 184) && (ty >= 181) && (ty <= 240)) {
        menuPage = 34;
      } 
      // Zum Untermenü "frei" 
      else if ((tx >= 186) && (tx <= 319) && (ty >= 0) && (ty <= 59)) { 
        menuPage = 35;
      } 
      // Zum Untermenü "frei"
      else if ((tx >= 186) && (tx <= 319) && (ty >= 60) && (ty <= 120)) {
        menuPage = 36;
      }
      // Zum Untermenü "frei"
      else if ((tx >= 186) && (tx <= 319) && (ty >= 121) && (ty <= 180)) {
        menuPage = 37;
      }
      // Zum Untermenü "frei"
      else if ((tx >= 186) && (tx <= 319) && (ty >= 181) && (ty <= 240)) {
        menuPage = 38;
      } 
      */
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }

    // Untermenü Weckzeitvorlauf einstellen
    if (menuPage == 31 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Einstellungen
      if ((tx >= 0) && (tx <= 49) && (ty >= 0) && (ty <= 240)) {
        menuPage = 3;
      } 
      else if ((tx >= 50) && (tx <= 320) && (ty >= 0) && (ty <= 79)) {
        alarmAdvancetime = 15;
        EEPROM.update(addrAlarmAdvancetime, alarmAdvancetime);
      }
      else if ((tx >= 50) && (tx <= 320) && (ty >= 80) && (ty <= 159)) {
        alarmAdvancetime = 30;
        EEPROM.update(addrAlarmAdvancetime, alarmAdvancetime);
      }
      else if ((tx >= 50) && (tx <= 320) && (ty >= 160) && (ty <= 239)) {
        alarmAdvancetime = 45;
        EEPROM.update(addrAlarmAdvancetime, alarmAdvancetime);
      } 
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;  
    }

    // Untermenü Weckmusikauswahl
    if (menuPage == 32 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Einstellungen
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 3;
      } 
      // Auswahl Musik 1
      else if ((tx >= 51) && (tx <= 184) && (ty >= 0) && (ty <= 59)) {
        alarmFile = 1;
        EEPROM.update(addrAlarmFile, alarmFile);
      } 
      // Auswahl Musik 2
      else if ((tx >= 51) && (tx <= 184) && (ty >= 60) && (ty <= 120)) {
        alarmFile = 2;
        EEPROM.update(addrAlarmFile, alarmFile);
      }
      // Auswahl Musik 3
      else if ((tx >= 51) && (tx <= 184) && (ty >= 121) && (ty <= 180)) {
        alarmFile = 3;
        EEPROM.update(addrAlarmFile, alarmFile);
      }
      // Auswahl Musik 4
      else if ((tx >= 51) && (tx <= 184) && (ty >= 181) && (ty <= 240)) {
        alarmFile = 4;
        EEPROM.update(addrAlarmFile, alarmFile);
      } 
      /*
      // Auswahl Musik 5
      else if ((tx >= 186) && (tx <= 319) && (ty >= 0) && (ty <= 59)) { 
        alarmFile = 5;
        EEPROM.update(addrAlarmFile, alarmFile);
      } 
      // Auswahl Musik 6
      else if ((tx >= 186) && (tx <= 319) && (ty >= 60) && (ty <= 120)) {
        alarmFile = 6;
        EEPROM.update(addrAlarmFile, alarmFile);
      }
      // Auswahl Musik 7
      else if ((tx >= 186) && (tx <= 319) && (ty >= 121) && (ty <= 180)) {
        alarmFile = 7;
        EEPROM.update(addrAlarmFile, alarmFile);
      }
      // Auswahl Musik 8
      else if ((tx >= 186) && (tx <= 319) && (ty >= 181) && (ty <= 240)) {
        alarmFile = 8;
        EEPROM.update(addrAlarmFile, alarmFile);
      } 
      */
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }
    
    // Menü Informationen
    if (menuPage == 4 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Hauptmenü
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 0;
      } 
      // Zum Unteruntermenü DCF Zeitsignal
      else if ((tx >= 51) && (tx <= 184) && (ty >= 0) && (ty <= 59)) { 
        menuPage = 41;
      } 
      // Zum Unteruntermenü LSM303
      else if ((tx >= 51) && (tx <= 184) && (ty >= 60) && (ty <= 120)) {
        menuPage = 42;
      }
      /*
      // Zum Unteruntermenü "frei"
      else if ((tx >= 51) && (tx <= 184) && (ty >= 121) && (ty <= 180)) {
        menuPage = 43;
      }
      // Zum Unteruntermenü "frei"
      else if ((tx >= 51) && (tx <= 184) && (ty >= 181) && (ty <= 240)) {
        menuPage = 44;
      } 
      */
      // Zum Unteruntermenü TSL2591-Sensor
      else if ((tx >= 186) && (tx <= 319) && (ty >= 0) && (ty <= 59)) { 
        menuPage = 45;
      }
      // Zum Unteruntermenü DHT22 Sensor
      else if ((tx >= 186) && (tx <= 319) && (ty >= 60) && (ty <= 120)) {
        menuPage = 46;
      }
      /*
      // Zum Unteruntermenü "frei"
      else if ((tx >= 186) && (tx <= 319) && (ty >= 121) && (ty <= 180)) {
        menuPage = 47;
      }
      // Zum Unteruntermenü "frei"
      else if ((tx >= 186) && (tx <= 319) && (ty >= 181) && (ty <= 240)) {
        menuPage = 48;
      } 
      */
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }

    // Unteruntermenü DCF77 Zeitsignal
    if (menuPage == 41 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      } 
      else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      }
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }
    
    // Unteruntermenü TSL303 Sensor
    if (menuPage == 42 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      } 
      else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      }
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }  
    
    // Unteruntermenü TSL2591 Sensor
    if (menuPage == 45 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      } 
      else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      }
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }
   
    // Unteruntermenü DHT22 Sensor
    if (menuPage == 46 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 40) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      } 
      else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
        menuPage = 4;
      }
      tft.fillScreen(ILI9341_BLACK);
      TFTrefresh = true;
      prevtouch2 = false;
    }
   
    // Menü Alarmzeit stellen. Vor dem Speichern werden von der eingestellten Zeit 30 Minuten abgezogen.
    if (menuPage == 5 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Hauptmenü
      if ((tx >= 0) && (tx <= 49) && (ty >= 0) && (ty <= 239)) {
        menuPage = 0;
        tft.fillScreen(ILI9341_BLACK);

        // Vor dem Speichern der Alarmzeit ins EEPROM wird die angezeigte Alarmzeit in die schlafphasensensible Alarmzeit umgerechnet
        alarmMinute = displayedAlarmMinute;        // Damit es bei leerem EEPROM nicht zu Chaos kommt
        alarmHour = displayedAlarmHour;            // Damit es bei leerem EEPROM nicht zu Chaos kommt
        
        if (alarmAdvancetime == 15) {
          if (displayedAlarmMinute == 0) {
            alarmMinute = displayedAlarmMinute - 15;
            alarmHour = displayedAlarmHour - 1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 15) {
            alarmMinute = displayedAlarmMinute - 15;
          }
          else if (displayedAlarmMinute == 30) {
            alarmMinute = displayedAlarmMinute - 15;
          }
          else if (displayedAlarmMinute == 45) {
            alarmMinute = displayedAlarmMinute - 15;
          }
        }
        else if (alarmAdvancetime == 30) {
          if (displayedAlarmMinute == 0) {
            alarmMinute = 30;
            alarmHour = displayedAlarmHour - 1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 15) {
            alarmMinute = 45;
            alarmHour = displayedAlarmHour - 1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 30) {
            alarmMinute = 0;
          }
          else if (displayedAlarmMinute == 45) {
            alarmMinute = 15;
          }
        }
        else if (alarmAdvancetime == 45) {
          if (displayedAlarmMinute == 0) {
            alarmMinute = displayedAlarmMinute - 45;
            alarmHour = displayedAlarmHour -1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 15) {
            alarmMinute = displayedAlarmMinute - 45;
            alarmHour = displayedAlarmHour -1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 30) {
            alarmMinute = displayedAlarmMinute - 45;
            alarmHour = displayedAlarmHour -1;
            if (alarmHour < 0) {
              alarmHour = 23;
            }
          }
          else if (displayedAlarmMinute == 45) {
            alarmMinute = displayedAlarmMinute - 45;
          }
        }
      
        // Um das EEPROM zu schonen, werden die Alarmzeit und der Alarmmodus erst gespeichert, wenn das Hauptmenü aufgerufen wird.
        // Um Speicherplatz im EEPROM zu sparen, werden die Integervariablen alarmHour, alarmMinute etc. als Byte gespeichert.
        EEPROM.update(addrDisplayedAlarmHour, int8_t(displayedAlarmHour));
        EEPROM.update(addrDisplayedAlarmMinute, int8_t(displayedAlarmMinute));        
        EEPROM.update(addrAlarmHour, int8_t(alarmHour));
        EEPROM.update(addrAlarmMinute, int8_t(alarmMinute));
        EEPROM.update(addrAlarmMode, alarmMode);

        // Ausgabe an die serielle Schnittstelle 
        Serial.print("Angezeigte Alarmzeit: "); Serial.print(displayedAlarmHour);
        Serial.print(":"); Serial.print(displayedAlarmMinute); Serial.println(" Uhr");
        Serial.print("Startzeit der Weckphase: "); Serial.print(alarmHour);
        Serial.print(":"); Serial.print(alarmMinute); Serial.println(" Uhr");
      } 
      // Stunden auf
      else if ((tx >= 50) && (tx <= 159) && (ty >= 0) && (ty <= 119)) {
        displayedAlarmHour = displayedAlarmHour + 1;
        if (displayedAlarmHour >= 24) {
          displayedAlarmHour = 0;
        }
      } 
      // Minuten auf
      else if ((tx >= 160) && (tx <= 268) && (ty >= 0) && (ty <= 119)) {
        displayedAlarmMinute = displayedAlarmMinute + 15;
        if (displayedAlarmMinute >= 60) {
          displayedAlarmMinute = 0;
          displayedAlarmHour = displayedAlarmHour + 1;
        }
      } 
      // Stunden ab
      else if ((tx >= 50) && (tx <= 159) && (ty >= 120) && (ty <= 239)) {
        displayedAlarmHour = displayedAlarmHour - 1;
        if (displayedAlarmHour < 0) {
          displayedAlarmHour = 23;
        }
      } 
      // Minuten ab
      else if ((tx >= 160) && (tx <= 268) && (ty >= 120) && (ty <= 239)) {
        displayedAlarmMinute = displayedAlarmMinute - 15;
        if (displayedAlarmMinute < 0) {
          displayedAlarmMinute = 45;
          displayedAlarmHour = displayedAlarmHour - 1;
        }
      } 
      // Zum Menü Weckmodus stellen
      else if ((tx >= 269) && (tx <= 319) && (ty >= 0) && (ty <= 239)) {
        menuPage = 51;
        tft.fillScreen(ILI9341_BLACK);
      }
      TFTrefresh = true;
      prevtouch2 = false;
    }

    // Untermenü Weckmodus stellen
    if (menuPage == 51 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 49) && (ty >= 0) && (ty <= 240)) {
        menuPage = 5;
        tft.fillScreen(ILI9341_BLACK);
      } 
      else if ((tx >= 50) && (tx <= 268) && (ty >= 0) && (ty <= 59)) {
        alarmMode = 0;
      }
      else if ((tx >= 50) && (tx <= 268) && (ty >= 60) && (ty <= 119)) {
        alarmMode = 1;
      }
      else if ((tx >= 50) && (tx <= 268) && (ty >= 120) && (ty <= 179)) {
        alarmMode = 2;
      }    
      else if ((tx >= 50) && (tx <= 268) && (ty >= 180) && (ty <= 239)) {
        alarmMode = 3;
      }
      // Zum Menü Wecklautstärke stellen
      else if ((tx >= 269) && (tx <= 319) && (ty >= 0) && (ty <= 239)) {
        menuPage = 52;
        tft.fillScreen(ILI9341_BLACK);
        // Um die Wecklautstärke einstellen zu können, muss die in den EInstellungen ausgewählte Datei mit der eingestellten Lautstärke abgespielt werden
        audioamp.enableChannel(true, true);          // Schaltet beide Ausgänge des Verstärkers online
        alarmGain = EEPROM.read(addrAlarmGain);      // Ließt die Lautstärke für die Alarmfunktion aus dem EEPROM
        mixer1.gain(1, (alarmGain * 0.005));         // Stellt die Lautstärke ein
        mixer2.gain(1, (alarmGain * 0.005));
        if (playSdWav2.isPlaying() == false) {
          Serial.println("Start playing");
          if (alarmFile == 1) {
            playSdWav2.play("MEER01.WAV");
          } 
          else if (alarmFile == 2) {
            playSdWav2.play("MEER02.WAV");
          } 
          else if (alarmFile == 3) {
            playSdWav2.play("REGEN01.WAV");
          }
          else if (alarmFile == 4) {
            playSdWav2.play("REGEN02.WAV");
          }
        } 
      }
      TFTrefresh = true;
      prevtouch2 = false;  
    }

    // Untermenü Wecklautstärke stellen
    if (menuPage == 52 && touch2 == false && prevtouch2 == true) {
     
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 49) && (ty >= 0) && (ty <= 240)) {
        menuPage = 51;
        tft.fillScreen(ILI9341_BLACK);
        playSdWav2.stop();                         // Die Wiedergabe der Musik wird gestoppt
        Serial.println("Stop playing");
        audioamp.enableChannel(false, false);      // Der Verstärker wird deaktiviert
      }
        
      // Lautstärke einstellen
      else if ((tx >= 214) && (tx <= 319) && (ty >= 0) && (ty <= 119)) {
        // Lautstärke erhöhen
        alarmGain = alarmGain + 10;
        if (alarmGain >= 200) {
          alarmGain = 200;
        }
        EEPROM.update(addrAlarmGain, int8_t(alarmGain));  // schreibt den Wert in das EEPROM
        mixer1.gain(1, (alarmGain * 0.005));
        mixer2.gain(1, (alarmGain * 0.005));  
      }
      else if ((tx >= 214) && (tx <= 319) && (ty >= 120) && (ty <= 239)) {
        // Lautstärke verringern
        alarmGain = alarmGain - 10;
        if (alarmGain <= 0) {
          alarmGain = 0;
        }
        EEPROM.update(addrAlarmGain, int8_t(alarmGain));  // schreibt den Wert in das EEPROM
        mixer1.gain(1, (alarmGain * 0.005));
        mixer2.gain(1, (alarmGain * 0.005));  
      }
       Serial.print("Gain = "); Serial.println(alarmGain); 

      TFTrefresh = true;
      prevtouch2 = false;  
    }
        
    // Untermenü "Wecker aus"/"Schlummern"
    if (menuPage == 7 && touch2 == false && prevtouch2 == true) {
      // Wecker aus
      if ((tx >= 0) && (tx <= 213) && (ty >= 0) && (ty <= 239)) {
        menuPage = 0;                             // Das Hauptmenü wird aufgerufen.
        alarmOn = false;                          // Der Alarm wird ggf. beendet.
        snoozeOn = false;                         // Der Schlummeralarm wird ggf. beendet.
        clockfaceOn = true;                       // Das Ziffernblatt wirg ggf. aktiviert.
        playSdWav2.stop();                        // Die Musikwiedergabe wird ggf. gestoppt.
        Serial.println("Stop playing");
        audioamp.enableChannel(false, false);     // Der Verstärker wird ausgeschaltet
        r = 0;                                    // setzt den globalen Farbwert zurück
        g = 0;                                    // setzt den globalen Farbwert zurück
        b = 0;                                    // setzt den globalen Farbwert zurück
        w = 0;                                    // setzt den globalen Farbwert zurück
        for (int i = 0; i < numPixels; i++) {
          strip.setPixelColor(i, r, g, b, w);
        }
        strip.show();
      } 
      // Schlummern
      else if ((tx >= 214) && (tx <= 319) && (ty >= 0) && (ty <= 239)) {
        alarmOn = false;                          // Der Alarm wird ggf. beendet.
        snoozeOn = true;                          // Der Schlummerlarm wird aktiviert.
        clockfaceOn = true;                       // Das Ziffernblatt wirg ggf. aktiviert.
        playSdWav2.stop();                        // Die Musikwiedergabe wird ggf. gestoppt.
        Serial.println("Stop playing");
        audioamp.enableChannel(false, false);     // Der Verstärker wird ausgeschaltet
        r = 0;                                    // setzt den globalen Farbwert zurück
        g = 0;                                    // setzt den globalen Farbwert zurück
        b = 0;                                    // setzt den globalen Farbwert zurück
        w = 0;                                    // setzt den globalen Farbwert zurück
        for (int i = 0; i < numPixels; i++) {
          strip.setPixelColor(i, r, g, b, w);
        }
        strip.show();
        snoozeTime = now() + snoozeDelay;         // Der Countdown für den Schlummeralarm wird berechnet.

        // Debugging
        Serial.print("Zeitstempel: "); Serial.print(now());
        Serial.print(", snoozeTime: "); Serial.println(snoozeTime);
      }
      TFTrefresh = true;
      prevtouch2 = false;
    }
  
    // Untermenü "Snoozle aus"/"Lautstärke"
    if (menuPage == 8 && touch2 == false && prevtouch2 == true) {
      // Zurück zum Untermenü Informationen
      if ((tx >= 0) && (tx <= 213) && (ty >= 0) && (ty <= 239)) {
        menuPage = 0;
        snoozleOn = false;
        playSdWav1.stop();
        Serial.println("Stop playing");
        audioamp.enableChannel(false, false);
      } 
      else if ((tx >= 214) && (tx <= 319) && (ty >= 0) && (ty <= 119)) {
        // Lautstärke erhöhen
        snoozleGain = snoozleGain + 10;
        if (snoozleGain >= 200) {
          snoozleGain = 200;
        }
        EEPROM.update(addrSnoozleGain, int8_t(snoozleGain));  // schreibt den Wert in das EEPROM
        mixer1.gain(0, (snoozleGain * 0.005));
        mixer2.gain(0, (snoozleGain * 0.005));  
      }
      else if ((tx >= 214) && (tx <= 319) && (ty >= 120) && (ty <= 239)) {
        // Lautstärke verringern
        snoozleGain = snoozleGain - 10;
        if (snoozleGain <= 0) {
          snoozleGain = 0;
        }
        EEPROM.update(addrSnoozleGain, int8_t(snoozleGain));  // schreibt den Wert in das EEPROM
        mixer1.gain(0, (snoozleGain * 0.005));
        mixer2.gain(0, (snoozleGain * 0.005));  
      }
       Serial.print("Gain = "); Serial.println(snoozleGain); 
      TFTrefresh = true;
      prevtouch2 = false;
    }


    // Der Inhalt des Bildschirms wird nur dann neu aufgebaut, wenn a) das Backlight an ist und b) ein Refresh angewiesen wurde.
    if (TFTbacklightOn == true) {
      // Die Nummerierung der Menüseiten erfolgt nach dem folgendendem Muster:
      // Hauptmenü = 0; von dort Verzweigungen zu den Untermenüs 1 bis 5

      // Hauptmenü
      if (menuPage == 0 && TFTrefresh == true) {
        tft.fillScreen(ILI9341_BLACK);
    
        // Linke Spalte des Menüs
        tft.drawRoundRect(1, 17, 120, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(1, 73, 120, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(1, 129, 120, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(1, 185, 120, 40, 20, ILI9341_WHITE);

        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(15, 31);
        tft.print("Snoozle");
        tft.setCursor(15, 87);
        tft.print("Ziffernblatt");
        tft.setCursor(15, 143);
        tft.print("Einstellung");
        tft.setCursor(15, 199);
        tft.print("Information");

        // Anzeige Uhrzeit
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_13);
        tft.setCursor(190, 15);
        tft.print("Uhrzeit");
        if (DCFtimesignalFound == true) {
          tft.setCursor(300, 5);
          tft.setFont(AwesomeF180_10);
          if (timesinceDCFsignal >= 86400) {                           // Die Farbe des Symbols hängt vom Alter des zuletzt erfolgreich empfangenen Zeitsignals ab
            tft.setTextColor(ILI9341_BLACK);
          }
          else if (timesinceDCFsignal < 86400 && timesinceDCFsignal >= 43200) {
            tft.setTextColor(ILI9341_DARKGREY);
          } 
          else if (timesinceDCFsignal < 43200 && timesinceDCFsignal >= 3600) {
            tft.setTextColor(ILI9341_LIGHTGREY);
          } 
          else if (timesinceDCFsignal < 3600) {
            tft.setTextColor(ILI9341_WHITE);
          }
          tft.print((char)107);
          tft.setTextColor(ILI9341_WHITE);
        }

/*
        // Anzeige Sonnenaufgang und Sonnenuntergang
        tft.setTextColor(ILI9341_YELLOW);
        tft.setFont(AwesomeF180_13);
        tft.setCursor(140, 95);
        tft.print((char)5);
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_13);
        tft.print(AufgangStunden);
        tft.print(":");
        if (AufgangMinuten<10.0) tft.print("0");
        tft.print(AufgangMinuten);
        
        tft.setTextColor(ILI9341_BLUE);
        tft.setFont(AwesomeF180_13);
        tft.setCursor(140, 95);
        tft.print((char)6);
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_13);       
        tft.print(UntergangStunden);
        tft.print(":");
        if (UntergangMinuten<10.0) tft.print("0");
        tft.print(UntergangMinuten);
*/        
        // Die Uhrzeit wird unabhängig davon einmal pro Sekunde aktualisiert
    
        tft.fillRect(130, 119, 180, 2, ILI9341_WHITE);
    
        //Anzeige Alarmzeit
        tft.setTextColor(ILI9341_WHITE);
        if (alarmMode == 0) {
          tft.setFont(DroidSans_24);
          tft.setCursor(140, 170);
          tft.print("Alarm aus");
        }
        else {
          tft.setFont(DroidSans_13);
          tft.setCursor(180, 135);
          tft.print("Alarmzeit");

          tft.setFont(DroidSans_24);
          tft.setCursor(165, 170);
            if(alarmHour < 10) {
              tft.print('0');
            } 
          tft.print(displayedAlarmHour);
          tft.print(" : ");
            if(displayedAlarmMinute < 10) {
              tft.print('0');
            }
          tft.print(displayedAlarmMinute);
          tft.setFont(DroidSans_13);
          tft.setCursor(155, 220);
          tft.print("Modus: ");
          if (alarmMode == 1) {
            tft.setFont(AwesomeF080_14);
            tft.print((char)35);   
          }
          else if (alarmMode == 2) {
            tft.setFont(AwesomeF000_14);
            tft.print((char)38);
          }
          else if (alarmMode == 3) {
            tft.setFont(AwesomeF000_14);
            tft.print((char)38);
            tft.setFont(DroidSans_13);
            tft.print(" & ");
            tft.setFont(AwesomeF080_14);
            tft.print((char)35);
          }  
        }
        TFTrefresh = false;
      }

      if (menuPage == 0 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
        intervalTFTScreen = 1000;

        tft.fillRect(140,40, 160, 40, ILI9341_BLACK);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(150, 50);
        tft.setFont(DroidSans_24);    
        if(hour() < 10) {
          tft.print('0');
        }
        tft.print(hour());
        tftprintDigits(minute());
        tftprintDigits(second());
        tft.setFont(DroidSans_13);    
        tft.setCursor(180, 95);
        tft.print(day());
        tft.print(".");
        tft.print(month());
        tft.print(".");
        tft.print(year());

        previousMillisTFTScreen = currentMillis;
      }

      // Untermenü "Snoozle"
      if (menuPage == 1 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
    
        // Optionen
        tft.drawRoundRect(69, 17, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(69, 73, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(69, 129, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(69, 185, 130, 40, 20, ILI9341_WHITE);
        
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(84, 31);
        tft.print("15 Minuten");
        tft.setCursor(84, 87); 
        tft.print("30 Minuten");
        tft.setCursor(84, 143);  
        tft.print("45 Minuten");
        tft.setCursor(84, 199); 
        tft.print("60 Minuten");

        // Weiter zur Auswahl der WAV-Datei
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(290, 100);
        tft.print((char)1);
        
        TFTrefresh = false;
      }

      // Unteruntermenü "Snoozlemusik auswählen"
      if (menuPage == 11 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Snoozlemenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Optionen
        tft.setFont(DroidSans_9_Bold);
        if (snoozleFile == 1) {
          tft.fillRect(49, 17, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(49, 17, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(64, 32);
          tft.print("Meeresbrandung");   
        }
        else {
          tft.fillRect(49, 17, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(49, 17, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(64, 32);
          tft.print("Meeresbrandung"); 
        }
    
        if (snoozleFile == 2) {
          tft.fillRect(49, 73, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(49, 73, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(64, 88);
          tft.print("Regenschauer");
        }
        else {
          tft.fillRect(49, 73, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(49, 73, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(64, 88);
          tft.print("Regenschauer");
        } 
    
        if (snoozleFile == 3) {
          tft.fillRect(49, 129, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(49, 129, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(64, 144);
          tft.print("Gewitterschauer");
        }
        else {
          tft.fillRect(49, 129, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(49, 129, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(64, 144);
          tft.print("Gewitterschauer");
        }    

        if (snoozleFile == 4) {
          tft.fillRect(49, 185, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(49, 185, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(64, 200);
          tft.print("geschl. Fenster");
        }
        else {
          tft.fillRect(49, 185, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(49, 185, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(64, 200);
          tft.print("geschl. Fenster");
        } 

        if (snoozleFile == 5) {
          tft.fillRect(184, 17, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(184, 17, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(199, 32);
          tft.print("offenes Fenster");   
        }
        else {
          tft.fillRect(184, 17, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(184, 17, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(199, 32);
          tft.print("offenes Fenster"); 
        }
    
        if (snoozleFile == 6) {
          tft.fillRect(184, 73, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(184, 73, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(199, 88);
          tft.print("leichter Regen");
        }
        else {
          tft.fillRect(184, 73, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(184, 73, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(199, 88);
          tft.print("leichter Regen");
        } 
    
        if (snoozleFile == 7) {
          tft.fillRect(184, 129, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(184, 129, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(199, 144);
          tft.print("Voegel im Wald");
        }
        else {
          tft.fillRect(184, 129, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(184, 129, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(199, 144);
          tft.print("Voegel im Wald");
        }    

        if (snoozleFile == 8) {
          tft.fillRect(184, 185, 130, 40, ILI9341_BLACK);
          tft.fillRoundRect(184, 185, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_BLACK);
          tft.setCursor(199, 200);
          tft.print("Entspannung");
        }
        else {
          tft.fillRect(184, 185, 130, 40, ILI9341_BLACK);
          tft.drawRoundRect(184, 185, 130, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_WHITE);
          tft.setCursor(199, 200);
          tft.print("Entspannung");
        } 
        
        TFTrefresh = false;
      }
      
      // Untermenü "Ziffernblatteffekte"
      if (menuPage == 2 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Effekte einstellen
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_8);
        tft.setCursor(50, 120);
        tft.print("Menue Effekte einstellen");

        TFTrefresh = false;
        }

      // Untermenü "Einstellungen"
      if (menuPage == 3 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Optionen
        tft.setFont(DroidSans_9_Bold);
        // Linke Spalte
        tft.drawRoundRect(49, 17, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 73, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 129, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 185, 130, 40, 20, ILI9341_WHITE);

        
        tft.setTextColor(ILI9341_WHITE);
        
        tft.setCursor(64, 32);
        tft.print("Weckzeitvorlauf");
        tft.setCursor(64, 88);
        tft.print("Weckmusik");
        tft.setCursor(64, 144);
        tft.print("Wecklautstaerke");
        tft.setCursor(64, 200);
        tft.print("frei");

       // Rechte Spalte
        tft.drawRoundRect(184, 17, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 73, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 129, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 185, 130, 40, 20, ILI9341_WHITE);
        
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(199, 32);
        tft.print("frei");
        tft.setCursor(199, 88);
        tft.print("frei");
        tft.setCursor(199, 144);
        tft.print("frei");
        tft.setCursor(199, 200);
        tft.print("frei");

        TFTrefresh = false;
        }

      // Unteruntermenü "Weckzeitvorlauf"
      if (menuPage == 31 && TFTrefresh == true) {
         //tft.fillScreen(ILI9341_BLACK);
        
        // Zurück zum "Einstellungen"
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
    
        // Optionen
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(84, 34);
        if (alarmAdvancetime == 15) {
          tft.fillCircle(89, 40, 20, ILI9341_RED);
          tft.setTextColor(ILI9341_WHITE);
        }
        else {
          tft.fillCircle(89, 40, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_RED);
        }
        tft.print("15 Minuten Vorlauf");
    
        tft.setCursor(84, 114);
        if (alarmAdvancetime == 30) {
          tft.fillCircle(89, 120, 20, ILI9341_RED);
          tft.setTextColor(ILI9341_WHITE);
        }
        else {
          tft.fillCircle(89, 120, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_RED);
        }    
        tft.print("30 Minuten Vorlauf");
    
        tft.setCursor(84, 194);
        if (alarmAdvancetime == 45) {
          tft.fillCircle(89, 200, 20, ILI9341_RED);
          tft.setTextColor(ILI9341_WHITE);
        }
        else {
          tft.fillCircle(89, 200, 20, ILI9341_WHITE);
          tft.setTextColor(ILI9341_RED);
        }    
        tft.print("45 Minuten Vorlauf");

        TFTrefresh = false;
      }
      
      // Unteruntermenü "Weckmusik auswählen"
      if (menuPage == 32 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Linke Spalte
        tft.fillCircle(69, 35, 20, ILI9341_RED);
        tft.fillCircle(69, 91, 20, ILI9341_RED);
        tft.fillCircle(69, 147, 20, ILI9341_RED);
        tft.fillCircle(69, 204, 20, ILI9341_RED);
    
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(64, 31);
        tft.print("Meeresrauschen 1");
        tft.setCursor(64, 87);
        tft.print("Meeresrauschen 2");
        tft.setCursor(64, 143);
        tft.print("Regen");
        tft.setCursor(64, 199);
        tft.print("Regen mit Donner");

       // Rechte Spalte
        tft.fillCircle(199, 35, 20, ILI9341_RED);
        tft.fillCircle(199, 91, 20, ILI9341_RED);
        tft.fillCircle(199, 147, 20, ILI9341_RED);
        tft.fillCircle(199, 204, 20, ILI9341_RED);

        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(194, 31);
        tft.print("frei");
        tft.setCursor(194, 87);
        tft.print("frei");
        tft.setCursor(194, 143);
        tft.print("frei");
        tft.setCursor(194, 199);
        tft.print("frei");

        TFTrefresh = false;
        }

      // Untermenü "Informationen"
      if (menuPage == 4 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Linke Spalte
        tft.drawRoundRect(49, 17, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 73, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 129, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(49, 185, 130, 40, 20, ILI9341_WHITE);
    
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(64, 31);
        tft.print("Zeitsignal");
        tft.setCursor(64, 87);
        tft.print("LSM303");
        tft.setCursor(64, 143);
        tft.print("frei");
        tft.setCursor(64, 199);
        tft.print("frei");

       // Rechte Spalte
        tft.drawRoundRect(184, 17, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 73, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 129, 130, 40, 20, ILI9341_WHITE);
        tft.drawRoundRect(184, 185, 130, 40, 20, ILI9341_WHITE);

        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_12_Bold);
        tft.setCursor(194, 31);
        tft.print("TSL2591");
        tft.setCursor(194, 87);
        tft.print("DHT22");
        tft.setCursor(194, 143);
        tft.print("frei");
        tft.setCursor(194, 199);
        tft.print("frei");

        TFTrefresh = false;
        }

      // Unteruntermenü "DCF-Empfang"
      if (menuPage == 41 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Untermenü Informationen
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        TFTrefresh = false;
      }
    
       if (menuPage == 41 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
        intervalTFTScreen = 50;
      
        tft.setFontAdafruit();
        tft.setTextSize(1);

        // Datenausgabe
        tft.setFontAdafruit();
        tft.setTextSize(1);
    
        if (DCFtimesignalFound == false){
          tft.setCursor(60, 10);
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
          tft.print("Kein Zeitzeichen erfolgreich empfangen");
          tft.setCursor(60, 20);
          tft.print("seit: ");
          tft.setTextColor(ILI9341_RED, ILI9341_BLACK);

          int seconds = noDCFsignal % 60;
          int minutes = (noDCFsignal  /60) % 60;
          int hours = (noDCFsignal / 3600) % 24;
          int days = (noDCFsignal / 86400) % 1;

          tft.print(days); tft.print(":");
          tft.print(hours); tft.print(":");
          tft.print(minutes); tft.print(":");
          tft.print(seconds);
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
          tft.print(" (d:h:m:s)   ");
        }
        else {
          tft.setCursor(60, 10);
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
          tft.println("Letztes Zeitsignal erfolgreich empfangen");
          tft.setCursor(60, 20);
          tft.print("vor: ");
          tft.setTextColor(ILI9341_RED, ILI9341_BLACK);

          int seconds = timesinceDCFsignal % 60;
          int minutes = (timesinceDCFsignal  /60) % 60;
          int hours = (timesinceDCFsignal / 3600) % 24;
          int days = (timesinceDCFsignal / 86400) % 1;
  
          tft.print(days); tft.print(":");
          tft.print(hours); tft.print(":");
          tft.print(minutes); tft.print(":");
          tft.print(seconds);
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
          tft.print(" (d:h:m:s)   ");         
        }

        tft.setCursor(60, 40);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("Anzahl erfolgreich empfangener Zeitzeichen");
        tft.setCursor(60, 50);
        tft.print("seit dem letzten Systemstart: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(receivedDCFsignals);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(".");

        tft.setCursor(60, 70);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("Anteil erfolgreich empfangener Zeitzeichen");
        tft.setCursor(60, 80);
        tft.print("seit dem letzten Systemstart: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(DCFsuccessRate);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" %");

        tft.setCursor(60, 100);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("(System ist seit ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(millis()/60000);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" Minuten in Betrieb.)");

        tft.fillRect(60,120, 250, 50, ILI9341_BLACK);
        tft.setCursor(60, 130);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("Periode: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(flankUp-PreviousflankUp);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" Pulsweite :");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(flankDown - flankUp);

        previousMillisTFTScreen = currentMillis;
      }

      // Unteruntermenü "LSM303"
      if (menuPage == 42 && TFTrefresh == true) { 
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Untermenü Informationen
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        TFTrefresh = false;
      }
    
      if (menuPage == 42 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
        intervalTFTScreen = 50;    
    
        // Datenausgabe
        tft.setFontAdafruit();
        tft.setTextSize(1);

        tft.setCursor(60, 10);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("Beschleunigungswerte: ");
        tft.setCursor(60, 20);
        tft.print("X: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(accelX);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" Y: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(accelY);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" Z: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(accelZ);

        tft.setCursor(60, 40);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print("Orientierung: ");
        tft.setCursor(60, 50);
        tft.print("Roll: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(roll);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.print(" Pitch: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(pitch);
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);            
        tft.print(" Heading: ");
        tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
        tft.print(heading);

        previousMillisTFTScreen = currentMillis;
      }
    
      // Unteruntermenü "TSL2591"
      if (menuPage == 45 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Untermenü Informationen
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
        
        TFTrefresh = false;
      }
  
      if (menuPage == 45 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
        intervalTFTScreen = 500;
    
        // Datenausgabe
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_9);
    
        tft.setCursor(60, 10);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Infrarot: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(ir); tft.print("    ");
        tft.setCursor(60, 30);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Full: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(full); tft.print("    ");
        tft.setCursor(60, 50);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Visible: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(full - ir); tft.print("    ");
        tft.setCursor(60, 70);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Lux: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(lux); tft.print("    ");
        tft.setCursor(60, 90);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Lux, geglaettet: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(filteredLux); tft.print("    ");        
    
        previousMillisTFTScreen = currentMillis;
      }

      // Unteruntermenü "DHT22"
      if (menuPage == 46 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);

        // Zurück zum Untermenü Informationen
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
        
        // Datenausgabe
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_9);

        tft.setCursor(60, 10);
        tft.print("Temperatur: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(c); tft.print(" "); tft.print(char(247)); tft.print("C; ");
        tft.print(f); tft.print(" "); tft.print(char(247)); tft.print("F   ");      
        tft.setCursor(60, 30);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Relative Luftfeuchtigkeit: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(h);
        tft.print(" %  ");
        tft.setCursor(60, 50);
        tft.setTextColor(ILI9341_WHITE);
        tft.print("Taupunkt: ");
        tft.setTextColor(ILI9341_RED);
        tft.print(taupunkt); tft.print(" "); tft.print(char(247)); tft.print("C  ");

        TFTrefresh = false;
      }

      // Unteruntermenü "Systeminformationen"
      if (menuPage == 48 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Untermenü Informationen
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

        // Obere Reihe des Menüs
        tft.setTextSize(1);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(35, 12);
        tft.print("Hauptmenü");
        tft.setCursor(145, 12);
        tft.print("Informationen");
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
        tft.setCursor(255, 7);
        tft.print("System-");
        tft.setCursor(245, 18);
        tft.print("informationen");

        // Bereich der Datenausgabe
        tft.print("Das System ist seit ");
        tft.print(millis() / 60000);
        tft.print(" Minuten in Betrieb");

        TFTrefresh = false;
      }

      // Untermenü "Alarmzeit einstellen"
      if (menuPage == 5 && TFTrefresh == true) {
        //tft.fillScreen(ILI9341_BLACK);
    
        // Zurück zum Hauptmenü
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);

   
        // Wecker stellen
        tft.setFont(DroidSans_13);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(75, 15);
        tft.print("Angestrebte Weckzeit");

        // Stunden auf
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(100, 50);
        tft.print((char)6);

        // Stunde anzeigen
        tft.fillRect(90, 95, 50, 50, ILI9341_BLACK);
        tft.setFont(DroidSans_24);
        tft.setCursor(95, 108);
        if(displayedAlarmHour < 10) {
          tft.print('0');
        } 
        tft.print(displayedAlarmHour);
 
        // Stunde ab
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(100, 150);
        tft.print((char)7);

        // Doppelpunkt
        tft.setCursor(159, 108);
        tft.setFont(DroidSans_24);
        tft.print(":");

        // Minuten auf
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(195, 50);
        tft.print((char)6);

        // Minuten anzeigen
        tft.fillRect(185, 95, 50, 50, ILI9341_BLACK);
        tft.setFont(DroidSans_24);
        tft.setCursor(192, 108);
        if(displayedAlarmMinute < 10) {
          tft.print('0');
        }
        tft.print(displayedAlarmMinute);

        // Minuten ab
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(195, 150);
        tft.print((char)7);
        
        // Alarmmodus anzeigen
        tft.setFont(DroidSans_13);
        tft.setTextColor(ILI9341_WHITE);
        if (alarmMode == 0) {
          tft.setCursor(125, 215);
          tft.print("Alarm aus");    
        }
        else if (alarmMode == 1) {
          tft.setCursor(95, 215);
          tft.print("visueller Modus");
        }
        else if (alarmMode == 2) {
          tft.setCursor(95, 215);
          tft.print("auditiver Modus");
        }
        else if (alarmMode == 3) {
          tft.setCursor(75, 215);
          tft.print("audiovisueller Modus");
        }
        
        // Weiter zur Auswahl des Programmmodus
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(290, 100);
        tft.print((char)1);
    
        TFTrefresh = false;
      }

      // Unteruntermenü "Alarmmodus einstellen"
      if (menuPage == 51 && TFTrefresh == true) {
        
        // Zurück zum "Alarmzeit einstellen"
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
    
        // Optionen
        if (alarmMode == 0) {
          tft.fillRect(60, 17, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 15);
          tft.print((char)88);    
        }
        else {
          tft.fillRect(60, 17, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 15);
          tft.print((char)87); 
        }
          tft.setFont(DroidSans_13);
          tft.setCursor(100, 25);
          tft.print("Alarm aus");
    
        if (alarmMode == 1) {
          tft.fillRect(60, 73, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 71);
          tft.print((char)88);
        }
        else {
          tft.fillRect(60, 73, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 71);
          tft.print((char)87); 
        }    
        tft.setFont(DroidSans_13);
        tft.setCursor(100, 81);
        tft.print("visueller Modus");
    
        if (alarmMode == 2) {
          tft.fillRect(60, 135, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 133);
          tft.print((char)88); 
        }
        else {
          tft.fillRect(60, 135, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 133);
          tft.print((char)87); 
        }    
        tft.setFont(DroidSans_13);
        tft.setCursor(100, 143);
        tft.print("auditiver Modus");
    
        if (alarmMode == 3) {
          tft.fillRect(60, 196, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 194);
          tft.print((char)88); 
        }
        else {
          tft.fillRect(60, 196, 30, 29, ILI9341_BLACK);
          tft.setFont(AwesomeF000_24);
          tft.setCursor(60, 194);
          tft.print((char)87); 
        }  
        tft.setFont(DroidSans_13);
        tft.setCursor(100, 204);
        tft.print("audiovisueller Modus");

        // Weiter zur Auswahl der Wecklautstärke
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(290, 100);
        tft.print((char)1);
        
        TFTrefresh = false;
      }


      // Untermenü "Wecklautstärke einstellen"
      if (menuPage == 52 && TFTrefresh == true) {
    
        // Zurück zu "Alarmmodus einstelle"
        tft.setFont(AwesomeF100_32);
        tft.setTextColor(ILI9341_WHITE);
        tft.setCursor(6, 100);
        tft.print((char)0);
    
        // Lautstärke
        tft.fillRect(213, 20, 2, 200, ILI9341_WHITE);
        
        tft.setFont(AwesomeF000_28);
        tft.setCursor(250, 40);
        tft.print((char)40);
        
        tft.setFont(DroidSans_10);
        tft.setCursor(225, 120);
        tft.print("lauter / leiser");
        
        tft.setFont(AwesomeF000_28);
        tft.setCursor(255, 160);
        tft.print((char)39);

        TFTrefresh = false;
      }

      // Untermenü "Wecker aus/Schlummern"
      if (menuPage == 7 && TFTrefresh == true) {
        tft.fillScreen(ILI9341_BLACK);            // Dieses Menü wird automatisch aufgerufen. Daher muss der Bildschirm an dieser Stelle gelöscht werden.
    
        // Wecker/Schlummern aus
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_18_Bold);
        if (snoozeOn == false) {
          tft.setCursor(60, 95);
          tft.print("Wecker");
        }
        else if (snoozeOn == true) {
          tft.setCursor(30, 95);
          tft.print("Schlummern");
        }
        tft.setCursor(85, 135);
        tft.print("aus");

        tft.fillRect(213, 20, 2, 200, ILI9341_WHITE);

        // Schlummern
        tft.setFont(DroidSans_10);
        tft.setCursor(225, 120);
        tft.print("Schlummern");

        TFTrefresh = false;
      }

      // Untermenü "Snoozle aus/Lautstärke"
      if (menuPage == 8 && TFTrefresh == true) {
        tft.fillScreen(ILI9341_BLACK);            // Dieses Menü wird automatisch aufgerufen. Daher muss der Bildschirm an dieser Stelle gelöscht werden.
    
        // Snoozle aus
        tft.setTextColor(ILI9341_WHITE);
        tft.setFont(DroidSans_18_Bold);
        tft.setCursor(60, 95);
        tft.print("Snoozle");
        tft.setCursor(85, 135);
        tft.print("aus");
    
        // Lautstärke
        tft.fillRect(213, 20, 2, 200, ILI9341_WHITE);
        
        tft.setFont(AwesomeF000_28);
        tft.setCursor(250, 40);
        tft.print((char)40);
        
        tft.setFont(DroidSans_10);
        tft.setCursor(225, 120);
        tft.print("Volume: "); tft.print(snoozleGain / 2); tft.print("%");
        
        tft.setFont(AwesomeF000_28);
        tft.setCursor(255, 160);
        tft.print((char)39);

        TFTrefresh = false;
      }
    }

  touch = false;                         // Die Variable wird unwahr
  touch2 = false;                        // Die Variable wird unwahr
  
  //Speichere die aktuelle Zeit in die zughörige Variable
   previousMillisTouchScreen = currentMillis;
  }

// Ausgabe an die serielle Schnittstelle
  if ((unsigned long)(currentMillis - previousMillisSerialPrint) >= intervalSerialPrint) {
/*    
    // Gibt die aktuelle Zeit aus
    Serial.print(hour());
    printDigits(minute());
    printDigits(second());
    Serial.print(" ");
    Serial.print(day());
    Serial.print(".");
    Serial.print(month());
    Serial.print(".");
    Serial.print(year());
    Serial.print(" ");
    Serial.print(weekday());
    printDCFsyncTime();
    
    Serial.print(" MenuPage: ");
    Serial.print(menuPage);
    Serial.print("; TFT Helligkeit: ");
    Serial.print(TFTbrightness);

    Serial.print("; empf. DCF-Sig.: ");
    Serial.print(receivedDCFsignals);
*/
    // Display the results (acceleration is measured in m/s^2)
    /*
    Serial.print("; X: "); Serial.print(accelX); Serial.print("  ");
    Serial.print("Y: "); Serial.print(accelY); Serial.print("  ");
    Serial.print("Z: "); Serial.print(accelZ); Serial.print("  ");Serial.print("m/s^2 ");

    // 'orientation' should have valid .roll and .pitch fields
    Serial.print(F("; Orientation: "));
    Serial.print(roll);
    Serial.print(F(" "));
    Serial.print(pitch);
    Serial.print(F(" "));
    Serial.print(heading);
    Serial.print(F(""));    

    Serial.print("; filtered AccelZ: ");
    Serial.print(filteredAccelZ);
    Serial.print("; filtered Roll: ");
    Serial.print(filteredRoll);
    Serial.print("; filtered Pitch: ");
    Serial.print(filteredPitch);
        
    Serial.print("; EventAccelZ: ");
    Serial.print(eventAccelZ);
     Serial.print("; EventRoll: ");
    Serial.print(eventRoll);
        Serial.print("; EventPitch: ");
    Serial.print(eventPitch);   
    */
    Serial.println();
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisSerialPrint = currentMillis;
  }

// Misst die Periode und Pusweite des vom DCF77-Modul empfangenen Signals in Millisekunden
  if ((unsigned long)(currentMillis - previousMillisDCFPulseLength) >= intervalDCFPulseLength) {

    int sensorValue = !digitalRead(DCF_PIN);  // Bei dem DCF77-Modul von ELV muss das Signal invertiert werden
      if (sensorValue) {
        if (!Up) {
          flankUp=millis();
          Up = true;
        }
      } else {
        if (Up) {
          flankDown=millis();
          Serial.print("Periode: ");
          Serial.print(flankUp-PreviousflankUp);
          Serial.print(" Pulsweite :");
          Serial.println(flankDown - flankUp);
          PreviousflankUp = flankUp;
          Up = false;
        }              
      }
  
  //Speichere die aktuelle Zeit in die zughörige Variable
  previousMillisDCFPulseLength = currentMillis;
  }



}


time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}


/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  time_t pctime = 0L;
  //unsigned long pctime = 0L;

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     return pctime;
     if( pctime < DefaultTime) { // check the value is a valid time (greater than Nov 1 2016)
       pctime = 0L; // return 0 to indicate that the time is not valid
     }
  }
  return pctime;
          Serial.print("pctime: ");
    Serial.print(pctime);
}


void tftprintDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  tft.print(":");
  if(digits < 10)
    tft.print('0');
  tft.print(digits);
}


void printDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}


void tftprintDCFsyncTime() {
  if (DCFtimesignalFound == false){
    tft.println("Kein Zeitsignal empfangen seit ");
    tft.print(noDCFsignal);
    tft.print(" Sek.");
  }
  else {
    tft.println("Zeitsignal empfangen vor ");
    tft.print(timesinceDCFsignal);
    tft.print(" Sek.");
  }
}


void printDCFsyncTime() {
  if (DCFtimesignalFound == false){
    Serial.print(" no DCF77 sync since ");
    Serial.print(noDCFsignal);
    Serial.print(" sec.");
  }
  else {
    Serial.print(" last DCF77 sync ");
    Serial.print(timesinceDCFsignal);
    Serial.print(" sec. ago");
  }
}


void tftprintDCFsyncCycle() {
  if (DCFtimesignalFound == false){
    tft.println("Kein Zeitsignal empfangen seit ");
    tft.print(noDCFsignal / 60);
    tft.print(" Zyklen");
  }
  else {
    tft.println("Zeitsignal empfangen vor ");
    tft.print(timesinceDCFsignal /60);
    tft.print(" Zyklen");
  }
}


void logSDcard() {
  
  // Daten auf SD-Karte loggen
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.print(millis());
    dataFile.print(",");
    dataFile.println(accelZ);
    dataFile.close();
    // print to the serial port too:
    Serial.print(millis());
    Serial.print(",");
    Serial.println(lux);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

Der Sketch verwendet 170.088 Bytes (16%) des Programmspeicherplatzes. Das Maximum sind 1.048.576 Bytes. Globale Variablen verwenden 13.180 Bytes (5%) des dynamischen Speichers, 248.964 Bytes für lokale Variablen verbleiben. Das Maximum sind 262.144 Bytes.

arduino/schlafphasenwecker/programmversion_0.7.txt · Zuletzt geändert: 18.05.2023 12:34 von 127.0.0.1