Schlafphasenwecker Programmversion 0.4
Achtung
Das Backlight wird nach einer definierten Zeit deaktiviert. Bei der ersten Berührung wird das Backlight wieder aktiviert, das Menü reagiert erst danach auf Berührungen. (Der Programmcode, der das möglich macht, wurde im Vergleich zur Programmversion 0.3 optimiert.) Es kann nun eine Weckzeit eingestellt werden, zu der eine spezifische Weckfunktionen aktiviert wird. Die Alarmzeit und die gewählte Weckfunktion werden im EEPROM gespeichert und nach einem Systemstart (zum Beispiel nach einem Stromausfall) aus dem EEPROM gelesen. Bei aktivem Alarm zeigt der TFT-Screen das „Alarm aus“/„Snooze“-Menü. Das Backlight bleibt aktiv, bis der Alarm deaktiviert wird.
Die gesamte Menüstruktur wurde aufgehübscht. Das neue Design zitiert Grundformen des Schlafphasenweckers.
Der Wecker ist nun außerdem in der Lage, die Sonnenauf- und -untergangszeiten zu berechnen.
Hilfreiche Links:
- Übersicht über die Funktionen der Time-Library: http://www.86duino.com/?p=5765
- Berechnung von Sonnenauf- und untergang: https://forum.arduino.cc/index.php?topic=218280.0
- Aufteilen von Projekten auf mehrere Dateien: http://www.visualmicro.com/page/User-Guide.aspx?doc=INOs-and-CPPs.html
ToDos:
- Der Sketch würde übersichtlicher, wenn er auf verschiedene Dateien aufgeteilt werden würde.
// Schlafphasenwecker Version 0.4
// 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 <Adafruit_GFX.h> // Core graphics library
#include <SPI.h> // this is needed for display
#include <Adafruit_ILI9341.h> // TFT-Display
#include <Wire.h> // this is needed for FT6206
#include <Adafruit_FT6206.h> // Kapazitiver Touchsensor
#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 "SdFat.h" // The Arduino SdFat library provides read/write access to FAT16/FAT32 file systems on SD/SDHC flash cards
#include <Fonts/FreeSans9pt7b.h> // Font
#include <Fonts/FreeSans12pt7b.h> // Font
#include <Fonts/FreeSans18pt7b.h> // Font
//#include <Fonts/FreeSans24pt7b.h>// Font
// Definiert Adressen im EEPROM
int addrAlarmHour = 0;
int addrAlarmMinute = 1;
int addrAlarmMode = 2;
// Definiert die Pins
#define DCF_PIN 2 // Connection pin to DCF 77 device
#define DCF_INTERRUPT 2 // Interrupt number associated with pin
#define TFTbacklightPin 7 // PWM Backlight TFT
// Definiert die Farben für das Menü (im RGB585-Format)
#define white 0xFFFF // weiß
#define black 0x0000 // schwarz
#define red 0xF800 // rot
#define orange 0xFB20 // orange
// 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, plus #9 & #10
#define TFT_CS 10 // ChipSelect-Signal an Teensy-Pin 10
#define TFT_DC 9 // Data/Command-Signal an Teensy-Pin 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// 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);
// Definiert die Variablen
//int sensorValue;
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.
unsigned long lastDCFsignal; // Zeit in Millisekunden, sie seit dem letzten erfolgrich empfangenen DCF77-Zeitzeichen vergangen ist.
unsigned long noDCFsignal; // Zeit in Millisekunden, die seit dem Systemstart bis zum ersten erfolgreich empfangenen DCF-Zeitzeichen vergangen ist.
unsigned long currentDCFsignal;
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.
int alarmHour = 6; // Stunde, zu der ein Alarm 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 = 0; // Minute, zu der ein Alarm 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.)
byte alarmMode = 0; // Alarmmodus (0 = Alarm aus)
boolean alarmOn = false; // Wird wahr, so lange ein Alarm läuft
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;
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 touchtouched2 = false; // Wird true, wenn der Touchscreen berührt wird
boolean TFTrefresh = false; // Wird true, wenn ein Menü aktualisiert werden soll
//int i; // Zählwert für Fadein und Fadeout des TFT Backlights
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.
//boolean touchtouched = false; // Wird true, wenn der Touchscreen berührt wird
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.
//const unsigned long debouncetime = 5; // Zeit für "Entprellung" der Eingaben auf dem Touchscreen.
//unsigned long touchtime = 0; // Speichert die Zeit, zu der der Touchscreen berührt wird.
float accelX;
float accelY;
float accelZ;
float roll;
float pitch;
float heading;
// Definiert die Tracking-Variablen für die IF-Abfragen
unsigned long previousMillisSetRTC = 0;
unsigned long previousMillisAlarmClock = 0;
unsigned long previousMillisTFTScreen = 0;
unsigned long previousMillisTouchScreen = 0;
unsigned long previousMillisSensorData = 0;
unsigned long previousMillisSerialPrint = 0;
unsigned long previousMillisDCFPulseLength = 0;
// 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
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 = 500; // konstanter Delay für Auslesen der Sensoren
const unsigned long intervalSerialPrint = 1000; // 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(TFTbacklightPin, OUTPUT); // PWM für TFT Backlight
// set the Time library to use Teensy 3.0's RTC to keep time
setSyncProvider(getTeensy3Time);
// Initialisiert den TFT-Bildschirm
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
// Initialisiert die serielle Schnittstelle
Serial.begin(115200);
// Zeigt auf dem TFT einen Startbildschirm an
//StartupScreen();
delay(100);
if (timeStatus()!= timeSet) {
Serial.println("Unable to sync with the RTC");
} else {
Serial.println("RTC has set the system time");
}
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");
}
/* Initiolisiere 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);
}
// 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
// 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.");
// Lese die abgespeicherten Werte für die Alarmzeit und -modus
alarmHour = EEPROM.read(addrAlarmHour);
alarmMinute = EEPROM.read(addrAlarmMinute);
alarmMode = EEPROM.read(addrAlarmMode);
// 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() && DCFtime < DefaultTime) {
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;
receivedDCFsignals = receivedDCFsignals + 1;
currentDCFsignal = millis();
}
// Berechne die Zeit (in Sekunden) die seit dem Empfang des letzten gültigen DCF-Signals vergangen ist
if (DCFtimesignalFound == false) {
noDCFsignal = millis() /1000;
}
else {
lastDCFsignal = (millis() - currentDCFsignal) / 1000;
}
// Berechnet die Quote erfolgreich empfangener DCF77-Signale seit dem letzten Systemstart
DCFsuccessRate = (receivedDCFsignals / ((millis() / 60000))) * 100;
//Speichere die aktuelle Zeit in die zughörige Variable
previousMillisSetRTC = currentMillis;
}
// Alarm-Funktionen
if ((unsigned long)(currentMillis - previousMillisAlarmClock) >= intervalAlarmClock) {
if (alarmMode != 0 && hour() == alarmHour && minute() == alarmMinute && second() == 0 || alarmOn == true) {
if (alarmMode == 1) {
Serial.print("ALARM 1!!!!");
}
else if (alarmMode == 2) {
Serial.print("ALARM 2!!!!");
}
else if (alarmMode == 3) {
Serial.print("ALARM 3!!!!");
}
TFTbrightness = 255;
analogWrite(TFTbacklightPin, TFTbrightness);
TFTbacklightOn = true;
alarmOn = 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;
roll = orientation.roll;
pitch = orientation.pitch;
heading = orientation.heading;
}
//Auslesen des Helligkeitssensors TSL2591
lum = tsl.getFullLuminosity();
ir = lum >> 16;
full = lum & 0xFFFF;
lux = tsl.calculateLux(full, ir);
//Speichere die aktuelle Zeit in die zughörige Variable
previousMillisSensorData = 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 keine Alarmfunktion läuft.
if (alarmOn == 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;
}
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 <= 40) && (ty >= 0) && (ty <= 240)) {
menuPage = 0;
}
else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
menuPage = 0;
}
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;
}
else if ((tx >= 41) && (tx <= 320) && (ty >= 0) && (ty <= 240)) {
menuPage = 0;
}
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 Uhntermenü DCF Zeitsignal
else if ((tx >= 51) && (tx <= 184) && (ty >= 0) && (ty <= 59)) { // ... und der TouchScreen in dem angegebenen Bereich berührt wird ...
menuPage = 41; // ... dann rufe Menüseite 1 auf.
}
// Zum Untermenü LSM303
else if ((tx >= 51) && (tx <= 184) && (ty >= 60) && (ty <= 120)) {
menuPage = 42;
}
/*
// Zum Menü "frei"
else if ((tx >= 51) && (tx <= 184) && (ty >= 121) && (ty <= 180)) {
menuPage = 43;
}
// Zum Menü "frei"
else if ((tx >= 51) && (tx <= 184) && (ty >= 181) && (ty <= 240)) {
menuPage = 44;
}
*/
// Zum Menü TSL2591-Sensor
else if ((tx >= 186) && (tx <= 319) && (ty >= 0) && (ty <= 59)) { // ... und der TouchScreen in dem angegebenen Bereich berührt wird ...
menuPage = 45; // ... dann rufe Menüseite 1 auf.
}
/*
// Zum Menü "frei"
else if ((tx >= 186) && (tx <= 319) && (ty >= 60) && (ty <= 120)) {
menuPage = 46;
}
// Zum Menü "frei"
else if ((tx >= 186) && (tx <= 319) && (ty >= 121) && (ty <= 180)) {
menuPage = 47;
}
// Zum Menü "frei"
else if ((tx >= 186) && (tx <= 319) && (ty >= 181) && (ty <= 240)) {
menuPage = 48;
}
*/
TFTrefresh = true;
prevtouch2 = false;
}
// Untermenü 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;
}
TFTrefresh = true;
prevtouch2 = false;
}
// Untermenü 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;
}
TFTrefresh = true;
prevtouch2 = false;
}
// Untermenü 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;
}
TFTrefresh = true;
prevtouch2 = false;
}
// Menü Alarmzeit stellen
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);
// 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 und alarmMinute als Byte gespeichert.
EEPROM.write(addrAlarmHour, byte(alarmHour));
EEPROM.write(addrAlarmMinute, byte(alarmMinute));
EEPROM.write(addrAlarmMode, alarmMode);
}
// Stunden auf
else if ((tx >= 50) && (tx <= 159) && (ty >= 0) && (ty <= 119)) {
alarmHour = alarmHour + 1;
if (alarmHour >= 24) {
alarmHour = 0;
}
}
// Minuten auf
else if ((tx >= 160) && (tx <= 268) && (ty >= 0) && (ty <= 119)) {
alarmMinute = alarmMinute + 5;
if (alarmMinute >= 60) {
alarmMinute = 0;
}
}
// Stunden ab
else if ((tx >= 50) && (tx <= 159) && (ty >= 120) && (ty <= 239)) {
alarmHour = alarmHour - 1;
if (alarmHour < 0) {
alarmHour = 23;
}
}
// Minuten ab
else if ((tx >= 160) && (tx <= 268) && (ty >= 120) && (ty <= 239)) {
alarmMinute = alarmMinute - 5;
if (alarmMinute < 0) {
alarmMinute = 45;
}
}
// 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;
}
else if ((tx >= 50) && (tx <= 320) && (ty >= 0) && (ty <= 59)) {
alarmMode = 0;
}
else if ((tx >= 50) && (tx <= 320) && (ty >= 60) && (ty <= 119)) {
alarmMode = 1;
}
else if ((tx >= 50) && (tx <= 320) && (ty >= 120) && (ty <= 179)) {
alarmMode = 2;
}
else if ((tx >= 50) && (tx <= 320) && (ty >= 180) && (ty <= 239)) {
alarmMode = 3;
}
TFTrefresh = true;
prevtouch2 = false;
}
// Untermenü "Wecker aus"/"Schlummern"
if (menuPage == 7 && touch2 == false && prevtouch2 == true) {
// Zurück zum Untermenü Informationen
if ((tx >= 0) && (tx <= 213) && (ty >= 0) && (ty <= 239)) {
menuPage = 0;
alarmOn = false;
}
else if ((tx >= 214) && (tx <= 319) && (ty >= 0) && (ty <= 239)) {
menuPage = 0;
alarmOn = false;
}
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.fillCircle(20, 35, 20, red);
tft.fillCircle(20, 91, 20, red);
tft.fillCircle(20, 147, 20, red);
tft.fillCircle(20, 204, 20, red);
tft.setTextColor(white);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(15, 41);
tft.print("Snoozle");
tft.setCursor(15, 97);
tft.print("Ziffernblatt");
tft.setCursor(15, 153);
tft.print("Einstellung");
tft.setCursor(15, 209);
tft.print("Information");
// Anzeige Uhrzeit
tft.setTextColor(white, black);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(190, 25);
tft.print("Uhrzeit");
if (DCFtimesignalFound == true) {
tft.setTextColor(red, black);
tft.print(" DCF77");
tft.setTextColor(white, black);
}
// Die Uhrzeit wird unabhängig davon einmal pro Sekunde aktualisiert
tft.fillRect(130, 119, 180, 2, white);
//Anzeige Alarmzeit
tft.setTextColor(white, black);
if (alarmMode == 0) {
tft.setFont(&FreeSans18pt7b);
tft.setCursor(140, 190);
tft.print("Alarm aus");
}
else {
tft.setFont(&FreeSans9pt7b);
tft.setCursor(180, 140);
tft.print("Alarmzeit");
tft.setFont(&FreeSans18pt7b);
tft.setCursor(165, 190);
if(alarmHour < 10) {
tft.print('0');
}
tft.print(alarmHour);
tft.print(" : ");
if(alarmMinute < 10) {
tft.print('0');
}
tft.print(alarmMinute);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(155, 225);
tft.print("Alarmmodus: ");
tft.print(alarmMode);
}
TFTrefresh = false;
}
if (menuPage == 0 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
intervalTFTScreen = 1000;
tft.fillRect(140,40, 160, 40, black);
tft.setTextColor(white, black);
tft.setCursor(150, 70);
tft.setFont(&FreeSans18pt7b);
if(hour() < 10) {
tft.print('0');
}
tft.print(hour());
tftprintDigits(minute());
tftprintDigits(second());
tft.setFont(&FreeSans9pt7b);
tft.setCursor(170, 100);
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.fillCircle(20, 120, 20, white);
// Snoozle stellen
tft.setTextColor(white, black);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(50, 120);
tft.print("Menue Snoozle stellen");
TFTrefresh = false;
}
// Untermenü "Ziffernblatteffekte"
if (menuPage == 2 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Hauptmenü
tft.fillCircle(20, 120, 20, white);
// Effekte einstellen
tft.setTextColor(white, black);
tft.setFont(&FreeSans9pt7b);
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.fillCircle(20, 120, 20, white);
// Einstellungen stellen
tft.setTextColor(white, black);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(50, 120);
tft.print("Menue Einstellungen");
TFTrefresh = false;
}
// Untermenü "Informationen"
if (menuPage == 4 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Hauptmenü
tft.fillCircle(20, 120, 20, white);
// Linke Spalte
tft.fillCircle(69, 35, 20, red);
tft.fillCircle(69, 91, 20, red);
tft.fillCircle(69, 147, 20, red);
tft.fillCircle(69, 204, 20, red);
tft.setTextColor(white);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(64, 41);
tft.print("Zeitsignal");
tft.setCursor(64, 97);
tft.print("LSM303");
tft.setCursor(64, 153);
tft.print("frei");
tft.setCursor(64, 209);
tft.print("frei");
// Rechte Spalte
tft.fillCircle(199, 35, 20, red);
tft.fillCircle(199, 91, 20, red);
tft.fillCircle(199, 147, 20, red);
tft.fillCircle(199, 204, 20, red);
tft.setTextColor(white);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(194, 41);
tft.print("TSL2591");
tft.setCursor(194, 97);
tft.print("frei");
tft.setCursor(194, 153);
tft.print("frei");
tft.setCursor(194, 209);
tft.print("frei");
TFTrefresh = false;
}
// Unteruntermenü "DCF-Empfang"
if (menuPage == 41 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Untermenü Informationen
tft.fillCircle(20, 120, 20, white);
TFTrefresh = false;
}
if (menuPage == 41 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
intervalTFTScreen = 50;
tft.setFont();
tft.setTextSize(1);
// Datenausgabe
tft.setFont();
tft.setTextSize(1);
if (DCFtimesignalFound == false){
tft.setCursor(60, 10);
tft.setTextColor(white, black);
tft.print("Kein Zeitzeichen erfolgreich empfangen");
tft.setCursor(60, 20);
tft.print("seit ");
tft.setTextColor(red, black);
tft.print(noDCFsignal);
tft.setTextColor(white, black);
tft.print(" Sekunden.");
}
else {
tft.setCursor(60, 10);
tft.setTextColor(white, black);
tft.println("Letztes Zeitsignal erfolgreich empfangen");
tft.setCursor(60, 20);
tft.print("vor ");
tft.setTextColor(red, black);
tft.print(lastDCFsignal);
tft.setTextColor(white, black);
tft.print(" Sekunden.");
}
tft.setCursor(60, 40);
tft.setTextColor(white, black);
tft.print("Anzahl erfolgreich empfangener Zeitzeichen");
tft.setCursor(60, 50);
tft.print("seit dem letzten Systemstart: ");
tft.setTextColor(red, black);
tft.print(receivedDCFsignals);
tft.setTextColor(white, black);
tft.print(".");
tft.setCursor(60, 70);
tft.setTextColor(white, black);
tft.print("Anteil erfolgreich empfangener Zeitzeichen");
tft.setCursor(60, 80);
tft.print("seit dem letzten Systemstart: ");
tft.setTextColor(red, black);
tft.print(DCFsuccessRate);
tft.setTextColor(white, black);
tft.print(" %");
tft.setCursor(60, 100);
tft.setTextColor(white, black);
tft.print("(System ist seit ");
tft.setTextColor(red, black);
tft.print(millis()/60000);
tft.setTextColor(white, black);
tft.print(" Minuten in Betrieb.)");
tft.fillRect(60,120, 250, 50, black);
tft.setCursor(60, 130);
tft.setTextColor(white, black);
tft.print("Periode: ");
tft.setTextColor(red, black);
tft.print(flankUp-PreviousflankUp);
tft.setTextColor(white, black);
tft.print(" Pulsweite :");
tft.setTextColor(red, black);
tft.print(flankDown - flankUp);
previousMillisTFTScreen = currentMillis;
}
// Unteruntermenü "LSM303"
if (menuPage == 42 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Untermenü Informationen
tft.fillCircle(20, 120, 20, white);
TFTrefresh = false;
}
if (menuPage == 42 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
intervalTFTScreen = 50;
// Datenausgabe
tft.setFont();
tft.setTextSize(1);
tft.setCursor(60, 10);
tft.setTextColor(white, black);
tft.print("Beschleunigungswerte: ");
tft.setCursor(60, 20);
tft.print("X: ");
tft.setTextColor(red, black);
tft.print(accelX);
tft.setTextColor(white, black);
tft.print(" Y: ");
tft.setTextColor(red, black);
tft.print(accelY);
tft.setTextColor(white, black);
tft.print(" Z: ");
tft.setTextColor(red, black);
tft.print(accelZ);
tft.setCursor(60, 40);
tft.setTextColor(white, black);
tft.print("Orientierung: ");
tft.setCursor(60, 50);
tft.print("Roll: ");
tft.setTextColor(red, black);
tft.print(roll);
tft.setTextColor(white, black);
tft.print("Pitch: ");
tft.setTextColor(red, black);
tft.print(pitch);
tft.setTextColor(white, black);
tft.print("Heading: ");
tft.setTextColor(red, black);
tft.print(heading);
previousMillisTFTScreen = currentMillis;
}
// Unteruntermenü "TSL2591"
if (menuPage == 45 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Untermenü Informationen
tft.fillCircle(20, 120, 20, white);
TFTrefresh = false;
}
if (menuPage == 45 && ((unsigned long)(currentMillis - previousMillisTFTScreen) >= intervalTFTScreen)) {
intervalTFTScreen = 500;
// Datenausgabe
tft.setFont();
tft.setTextSize(1);
tft.setCursor(60, 10);
tft.setTextColor(white, black);
tft.print("Infrarot: ");
tft.setTextColor(red, black);
tft.println(ir);
tft.setCursor(60, 30);
tft.setTextColor(white, black);
tft.print("Full: ");
tft.setTextColor(red, black);
tft.println(full);
tft.setCursor(60, 50);
tft.setTextColor(white, black);
tft.print("Visible: ");
tft.setTextColor(red, black);
tft.println(full - ir);
tft.setCursor(60, 70);
tft.setTextColor(white, black);
tft.print("Lux: ");
tft.setTextColor(red, black);
tft.println(lux);
previousMillisTFTScreen = currentMillis;
}
// Unteruntermenü "DHT22"
if (menuPage == 46 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Untermenü Informationen
tft.fillCircle(20, 120, 20, white);
// Obere Reihe des Menüs
tft.setTextSize(1);
tft.setTextColor(black, white);
tft.setCursor(35, 12);
tft.print("Hauptmenü");
tft.setCursor(145, 12);
tft.print("Informationen DHT22");
// Bereich der Datenausgabe
tft.print("Der Sensor ist noch nicht in das System eingebunden");
TFTrefresh = false;
}
// Unteruntermenü "Systeminformationen"
if (menuPage == 48 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Zurück zum Untermenü Informationen
tft.fillCircle(20, 120, 20, white);
// Obere Reihe des Menüs
tft.setTextSize(1);
tft.setTextColor(black, white);
tft.setCursor(35, 12);
tft.print("Hauptmenü");
tft.setCursor(145, 12);
tft.print("Informationen");
tft.setTextColor(white, 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.fillCircle(20, 120, 20, white);
// Wecker stellen
tft.fillCircle(105, 69, 20, red); // Stunden auf
tft.fillCircle(214, 69, 20, red); // Minuten auf
tft.fillCircle(105, 169, 20, red); // Stunden ab
tft.fillCircle(214, 169, 20, red); // Minuten ab
tft.setFont(&FreeSans9pt7b);
tft.setTextColor(white, black);
tft.setCursor(125, 20);
tft.print("Weckzeit");
tft.fillRect(80,90, 50, 50, black);
tft.setFont(&FreeSans18pt7b);
tft.setTextColor(red, black);
tft.setCursor(90, 130);
if(alarmHour < 10) {
tft.print('0');
}
tft.print(alarmHour);
tft.setCursor(159, 130);
tft.print(":");
tft.fillRect(185,90, 50, 50, black);
tft.setCursor(195, 130);
if(alarmMinute < 10) {
tft.print('0');
}
tft.print(alarmMinute);
tft.setFont(&FreeSans9pt7b);
tft.setTextColor(white, black);
tft.setCursor(120, 230);
if (alarmMode == 0) {
tft.print("Alarm aus");
}
else if (alarmMode == 1) {
tft.print("Alarm an");
}
// Weiter zur Auswahl des Programmmodus
tft.fillCircle(299, 120, 20, white);
tft.setTextSize(0);
TFTrefresh = false;
}
// Unteruntermenü "Alarmmodus einstellen"
if (menuPage == 51 && TFTrefresh == true) {
// Zurück zum "Alarmzeit einstellen"
tft.fillCircle(20, 120, 20, white);
// Optionen
tft.setFont(&FreeSans9pt7b);
tft.setCursor(84, 41);
if (alarmMode == 0) {
tft.fillCircle(89, 35, 20, red);
tft.setTextColor(white);
}
else {
tft.fillCircle(89, 35, 20, white);
tft.setTextColor(red);
}
tft.print("Alarm aus");
tft.setCursor(84, 97);
if (alarmMode == 1) {
tft.fillCircle(89, 91, 20, red);
tft.setTextColor(white);
}
else {
tft.fillCircle(89, 91, 20, white);
tft.setTextColor(red);
}
tft.print("Alarmmodus 1");
tft.setCursor(84, 153);
if (alarmMode == 2) {
tft.fillCircle(89, 147, 20, red);
tft.setTextColor(white);
}
else {
tft.fillCircle(89, 147, 20, white);
tft.setTextColor(red);
}
tft.print("Alarmmodus 2");
tft.setCursor(84, 209);
if (alarmMode == 3) {
tft.fillCircle(89, 204, 20, red);
tft.setTextColor(white);
}
else {
tft.fillCircle(89, 204, 20, white);
tft.setTextColor(red);
}
tft.print("Alarmmodus 3");
TFTrefresh = false;
}
// Untermenü "Wecker aus/Schlummern"
if (menuPage == 7 && TFTrefresh == true) {
tft.fillScreen(ILI9341_BLACK);
// Wecker aus
tft.fillRect(0, 0, 213, 240, red);
tft.setTextColor(black, red);
tft.setFont(&FreeSans18pt7b);
tft.setCursor(85, 125);
tft.print("aus");
// Schlummern
tft.fillRect(214, 0, 106, 240, orange);
tft.setTextColor(black, orange);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(220, 120);
tft.print("snooze");
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.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;
}
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(lastDCFsignal);
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(lastDCFsignal);
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(lastDCFsignal /60);
tft.print(" Zyklen");
}
}
/*
// Die Funktion alarmFunktion aktiviert einen Weckalarm, wenn der alarmMode ungleich "0" (Alarm aus) ist
void alarmFunction() {
if (alarmMode != 0) {
alarmRunning = true;
}
}
*/
void StartupScreen() {
// Zeigt einen Startup-Screen
tft.println("Schlafphasenwecker");
tft.println("Version 0.2 alpha");
}
Der Sketch verwendet 77.364 Bytes (7%) des Programmspeicherplatzes. Das Maximum sind 1.048.576 Bytes. Globale Variablen verwenden 6.376 Bytes (2%) des dynamischen Speichers, 255.768 Bytes für lokale Variablen verbleiben. Das Maximum sind 262.144 Bytes.