Zeitschaltuhr Problem : Uhrzeit auf Display ausgeben mit Menüfunktion

bananenmilch:
Und genau deswegen möchte ich lieber meine eigenen Probleme erstmal Lösen bevor ich mich auf ganz andere Sachen stürze..

Und ich hab es geschafft... :art: Ich war schlicht und einfach zu dumm die Millis()/1000 zu berechnen um auf Sekunden zu kommen um diese dann abzuziehen.
Bezüglich der Ungenauigkeit messe ich einfach mal den Zeitunterschied in 24h und korrigiere diesen dann beim Umschalten der Stunden auf den neuen Tag. Ist zwar nicht schön aber besser als jetzt schon wieder alles von vorne zu Programmieren.

Ja, ok das versteh ich. Dagegen ist auch nichts einzuwenden.

Auf Ebay findet man auch Arduinos mit Quarz für wenige Euro. Nimmt man so einen, dann sollte der recht genau gehen, im Zweifelsfall genauer als eine DS1307-RTC. Der große Vorteil einer RTC ist, dass sie auch bei Stromausfällen weiter läuft.

Die Arduinos haben keine Temperatukompensation für die Quarze wie z.b. einen DS3232/3231....

Nach meiner Erfahrung ist die aktuelle Abweichung bei konstanter Temperatur und ordentlicher Stromversorgung relativ konstant, so dass man ein bisschen kalibrieren könnte

( Und 2 Minuten / Tag sind auch > 1 Minute Abweichung :wink: )

Die aktuellen Probleme sind ja ganz andere als die Genauigkeit.

Du hast 3 Zeiten: Aktuell, Start, Stop
jeweils 3 Zahlen hour, min, sek im Bereich 0 .. 59, also bequem als [b]byte[/b] zu definieren.

Das mit den 4 Modi ist ja schonmal ziemlich gut. ( Wenn man weiss was 1 bis 4 bedeutet :wink: )
Durch die Taste 'S' kommst du ins eigentliche Zeit-Stellen über initialHour(taste)
Wobei mit 'U' 'D' dann die Stunden verstellt werden und mit 'R' min1=initialmin(taste) aufgerufen wird, also immer, egal ob Start oder Stop-Stunde, die aktuelle Minute verstellt wird ?

Soll man dir das um die Ohren hauen oder selber schreiben? Ich hab zu beidem keine wirkliche Lust (was praktisch auf das erste hinausläuft, sorry).

Als Aufrufparameter für die Minuten- und Stunden-Stell Funktion, die ja selber das keypad lesen, würde ich eher eine Referenz auf die zu stellende Zeit mitgeben als die unnötige zuletzt gedrückte Taste.

z.B.

void stelleZeit( byte& hour, byte& min )
{
     // Exit via S, L
     // U D stellt Stunden
     // R ruft stelleMin für die Minuten auf und beendet danach auch 
     while (true) {
       displayTime (hour, min, 0 );
       char key = ReadKeyPad();
       waitbutton(); 
       switch () {
       case 'U': hour++; if ( hour > 23 ) hour =0; break;  // Überlauf 23->24 = 0
       case 'D': hour--; if ( hour > 23 ) hour =23; break;  // Unterlauf 0->255 = 23
       case 'S':
       case 'L': return;
       case 'R' stelleMin(min); return;
       }
     }
}
void stelleMin(byte& min) { 
  // ... für dich
}

Oh der Fehler ist mir noch gar nicht aufgefallen.( dass ich jedesmal die Zeit der Momentanen Uhrzeit überschreibe :o ).War gestern zu sehr auf die Problematik mit dem Weiterlaufen der Zeit konzentriert.. Schonmal danke für den Tipp.
Ihr sollt mir ja keinen Code hinklatschen.Muss das ja selber lernen, aber manche Sachen sieht man halt als Anfänger erst wenn man es vergeigt hat und von daher sind ein paar Profitipps und Hinweise immer gut. :slight_smile: :slight_smile:

Habe das Problem was du angesprochen hast mit ner Switch-Case Anweisung gelöst, indem ich einfach je nach Modus(also gewähltem Menü) die Variable geändert habe in die es gespeichert wird.

Hallo Leute,

ich habe mal wieder ein kleines Logikproblem..... und zwar möchte ich nun mit den von mir eingestellten Zeiten die Zeitschaltuhr Steuern jedoch klappt das Umschalten zwischen der Einschalt bzw. Auschaltzeit nicht richtig.Es gibt 6 Zeitvariablen die miteinander verglichen werden.

Hour1, Min1 aktuelle Stunden und Minuten ( je nach Einstellung)
Hour2, Min2 Startstunden und Startminuten.
Hour3, Min3 Endstunden und Endminuten.

ich stell den Code mal hier rein vielleicht erkennt ja jemand meinen Fehler.

Das Problem ist , dass das Umschalten auf zwischen den zwei Zuständen Senden und nicht Senden nicht funktioniert.

      if (hour1 >= hour2 && min1 >= min2 && hour1 <= hour3 && min1 <= min3) {
        lcd.setCursor(15, 0);
        lcd.print("!!!");//testausgabe
       
          lcd.setCursor(15, 0);
          lcd.write(byte(0));
          mySwitch.sendTriState("00000FFF0F0F");
        }
      }
      if (hour1 >= hour3 && min1 >= min3)  {
        lcd.setCursor(15, 0);
        lcd.write(byte(1));
        mySwitch.sendTriState("00000FFF0FF0");
      }

if (hour1 <= hour3 && min1 <= min3)

Das funktioniert so nicht, wenn die Zeiten in unterschiedlichen Stunden liegen.

Beispiel:

Zeit3 = 2:30
----------------
Zeit1 = 1:00  true  (ok )
Zeit1 = 1:45  false (falsch)
Zeit1 = 2:10  true  (ok)
Zeit1 = 2:31  false (ok)

Am besten Stunden und Minuten zusammenrechnen if (hour1*60 + min1) <= (hour3*60 + min3)

Wenn das ganze über einen Tageswechsel gehen soll, wird es wieder komplizierter...

Mhh ich hab den code eben nochmal abgeändert. Hab gedacht durch die AND Verknüpfung kann ich diese Probleme vielleicht umgehen. Aber ich hab da mittlerweile so nen Knoten im Kopf. Ich mach jetzt erstmal 20 Minuten Pause.... :slight_smile:

kann man das denn überhaupt mit if- Verzweigungen und vergleichen lösen ?? :confused: oder bin ich da aufm Holzweg?

kann man das denn überhaupt mit if- Verzweigungen und vergleichen lösen ??

Klar, kann man.

Du meinst: Zeit1 < Zeit3

if ( (hour1 < hour3) || ( (hour1 == hour3) && (min1 < min3)) )

Entweder die Stunden sind unterschiedlich oder in der gleichen Stunde die Minuten

Also ich hab jetzt die letzten zwei Stunden schon ungefähr alle mir möglichen Kombinationen ausprobiert. Ich hab mir sogar Skizzen und Ablaufpläne erstellt um den Wust in meinem Kopf zu beheben aber nichts funktioniert. Ich will eig. mal ganz simpel gesagt nur ein Signal pro if-Bedingung senden , eins wenn die Zeit2 überschritten wird und noch eins wenn zeit3 überschritten wird. Also im Prinzip :

if(hour160+min1>= hour260+min2){sende einschaltsignal};

und dann wenn die zweite zeit überschritten wird :

if(hour160+min1>= hour360+min3){sende ausschaltsignal};

Da ja die Stunden am nächsten Tag eh wieder von vorne anfangen würde das komplett ausreichen..... aber irgendwie zieht die zweite if-Bedingung nicht. :neutral_face:

^^ ich hoffe ich langweile euch nicht mit meinen Newbie-Problemen.

Da wir nur in Codeschnipseln reden statt kompletten Sketchen, solltest du mit solchen Aktions-Begriffen wie "sende Einschaltsignal" vorsichtig sein.

loop dauert keine Zeit und kommt daher unendlich oft dran.
Mit 2 ifs hast du in jedem der unendlich vielen Durchläufe einen von 4 Zuständen.

Wie oft willst du dein lcd aktualisieren und womit,
und wie oft soll das merkwürdige mySwitch.sendTriState("seltsamertText"); drankommen ?

Also der plan ist dass sobald die Zeit1 überschritten wird, soll genau einmal mySwitch.(komischer Text) ausgeführt werden(eben zum einschalten von ner Funksteckdose). Beim Überschreiten der zweiten Zeit soll das mySwitch.(komischerText2) auch einmal ausgeführt werden ( zum abschalten der Funksteckdose). Dazu soll ein kleines Symbol am Displayrand geändert werden, dass den anzeigt ob gerade ein oder abgeschaltet ist.

Ich hoffe das war verständlich ansonsten mach ich einfach mal ein bild von dem ganzen Gebilde mit roten Kästen zur Erklärung oder so.

Ich muss das jdoch eigentlich in der Endlosloop laufen lassen, da ja ständig die Zeiten verglichen werden müssen.Oder sehe ich das Falsch?

Gruß Bananenmilch

Alles läuft immer in der Endlosschleife loop()
Brauchst du also einen Merker, was als letztes gesendet wurde.

Entweder dauernd oder einmal ja Minute rechnest du aus wo die aktuelle Zeit ist, und bei Unterschied zum Merker sendest du und setzt den Merker.

Statt der zwei if würde ich zur leichteren Lesbarkeit zwei Variable nehmen:

void schalten() {
 bool nacheinschalt = ( (hour1 > hour2) || ( (hour1 == hour2) && (min1 >= min2)) );
 bool vorausschalt = ( (hour1 < hour3) || ( (hour1 == hour3) && (min1 < min3)) );

 static enum {UNDEF, AUS, EIN} AlterZustand = UNDEF;
 if (nacheinschalt && vorausschalt)   { // jetzt sollte EIN sein
   if (AlterZustand != EIN) {
      mySwitch.sendTriState(EINSCHALTTEXT);
      AlterZustand = EIN;
      ShowStateLcd(1);
   }
 } else {
   if (AlterZustand != AUS) {
      mySwitch.sendTriState(AUSSCHALTTEXT);
      AlterZustand = AUS;
      ShowStateLcd( 0);
   }
 }
}

void ShowStateLcd(byte z) {
  lcd.setCursor(15, 0);
  lcd.write(z);
}

Der Merker AlterZustand kann auch global definiert werden, statt static innerhalb der Funktion

Okay ich glaub ich habs gerafft, danke dir vielmals. Darf ich mal fragen wie lange du schon Programmierst ? Ich musste mir eben erstmal durchlesen was genau dieses Enum macht :stuck_out_tongue:

Ich habe jetzt mal deinen Lösungsansatz implementiert und muss leider feststellen ,dass es trotzdem nicht Funktioniert.:frowning: Naja zurück ans Reißbrett..... irgendwie bekommt er den Übergang nicht ausgewertet. Ich probiers mal weiter trotzdem danke für die Hilfe. Das mit dem enum ist ziemlich hilfreich, dann muss man nich so viele Variablen definieren.:stuck_out_tongue:

Edit: Ich habs..... das mit den Flags war klug gedacht, aber ohne die Merker funktionierts. Nur noch das Problem lösen, wenn die Einschaltzeit > der Ausschaltzeit ist.Dann ist das Projekt bis auf kleine Schönheitsfehler fertig.:D:D Ich danke dir nochmal für die großartige Unterstützung.Hut zieh

Nur noch das Problem lösen, wenn die Einschaltzeit > der Ausschaltzeit ist.Dann ist das Projekt bis auf kleine Schönheitsfehler fertig

Eigentlich bedeutet das, dass du vor Mitternacht einschaltest und am nächsten Tag ausschaltest.
Wenn das so gewollt ist, kannst du es auch so programmieren.
Aber was bedeutet es , wenn beide Zeiten gleich sind? Immer an oder immer aus ?

Alternativ kannst du auch Fehleingaben definieren und abfangen.

Kannst gerne dein "End"-Ergebnis hier posten, auch ohne Frage :wink:


Programmieren tu ich übrigens seit gefühlt *) hundert Jahren, den Arduino (Back to The Roots) hab ich vor drei Jahren entdeckt.

*) Brian Kernighan und Dennis Ritchie sind etwas älter, zugegeben. :wink:

Hallo Leute, also folgendes: Ich habe nun endlich alles geschafft was ich erreichen wollte, sprich die Zeitschaltuhr funktioniert und ich kann auch die Funksteckdosen dementsprechend einschalten :). Nun hab ich mit einem Kollegen versucht über ein GSM-Shield noch ne kleine SMS Steuerung einzubauen und wir Stoßen auf einige kleine Fehler, die ich jetzt mal rotzfrech hier Posten werde. Da das Gesamtergebnis ja auch gewünscht wurde kann man einfach alle funktionen die was mit der SMS Steuerung zu tun haben auskommentieren.

Fehlerbeschreibung:

1.Beim Booten funktioniert die SMS Steuerung ohne Probleme.

2.Sobald eine Uhrzeit eingestellt wurde (egal ob Momentane Zeit, Einschalte- bzw. Ausschaltzeit), werden wird nichts angezeigt (leerer LCD) und erst ab einem Durchlauf von 10 Sekunden die ‚Einerstellen‘ der Sekunden nicht mehr ausgegeben, sondern nur die ‚Zehner‘. Beispiel: Vorher: 00:00:01 … 00:00:02 … 00:00:03 …. Und nun: 00:00:01 … 10 Sekunden später 00:00:11 ohne die ‚Einerstellen‘.  Kurz: Beliebige Uhrzeit einstellen - > 10 Sekunden blanco - > Nur noch Zehner Sekunden. Minuten werden normal angezeigt.

3.Nachdem wie in 2 beschrieben das Verhalten zu beobachten ist, werden keine SMS mehr verarbeitet.

Außerdem wurde vorher die GSM Library aus der IDE 1.4.? genutzt und beim Update auf 1.6.8 tauchten lauter Warnings auf (siehe Liste). Diese Warnings waren jedoch auch in der autonomen Lösung schon da und hatten bisher keinerlei Einfluss auf das Verhalten. Schließlich klappt es ja wie in Punkt 1 beschrieben tadellos.

Weiterhin:

Beim Auskommentieren von Zeile 157 - 160:
if (sms.available())
{
SMS_VERARBEITEN(); // Wertet die SMS aus und sendet Steuerbefehle an die Funksteckdose
}
funktioniert die Zeit wieder problemlos. Scheinbar ist die Funktion sms.available() der Grund für den „Hänger“. SMS_VERARBEITEN() schließen wir aus, da das Problem mit der Zeit auch auftritt wenn keine SMS vorhanden ist.

Im nächsten Post kommt dann der Code. Wer ihn mal testen will viel Spaß damit.Falls jemand etwas bezüglich der genannten SMS Probleme beitragen kann schonmal Danke im Vorhinein.:slight_smile:
Wenn jemand Tipps und Tricks zum besseren Programmieren teilen möchte danke ich auch dafür.

Code Teil 1:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Ersteller: Bananenmilch                                                                                                                                         //
//letzes Datum:11.04.2016                                                                                                                                         //
//Name: Zeitschaltuhr mit Display                                                                                                                                 //  
//Details: Es ist Ratsam erst die Start und die Stopzeit einzustellen, da sich die momentane Zeit "resettet"                                                     //
//         1. Dieses Programm steuert eine Funksteckdose mittels eines angeschlossenen RC-Sender                                                                  //
//         Es bietet weiterhin die möglichkeit Zeiten via Displayshield einzugeben.                                                                               //
//         Um die Momentane Uhrzeit einzustellen muss mitells "Up" oder "Down" das Menü "Momentane Zeitausgewählt" werden.Dazu muss"Select" betätigt werden.      //
//         Durch Drücken der "Up" Taste können die Stunden +1 gezählt werden. Mit betätigung der "Right Taste" kann auf Minuten umgeschaltet werden.              //
//         Mit erneutem Drücken der "Right" taste wird  das einstellungsmenü beendet.                                                                             //
//         Mit "Left" kann das Menü abgebrochen werden.                                                                                                           //
//         2.Um Start und Stop- Zeit einzustellen muss wie in 1. vorgegangen werden.                                                                              //
//         3.Um alle Funktionen Nutzen zu können muss ledigleich ein RC-Funkmodul angeschlossen werden.Datenpin ist hierbei pin 6.                                //
//         4.Zusätzlich wird ein Displayshield benötigt um die eingaben zu tätigen.                                                                               //
//                                                                                                                                                                //
//                                                                                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



#include <GSM.h> 
#include <RCSwitch.h>     //RC Modul Library
#include <Time.h>         //Time Library
#include <TimeLib.h>      //  -/-
#include <LiquidCrystal.h>//Library für LCD Display
#include <sainsmartkeypad.h>//library für Displayshield ( PWM)
////// ######################## DEFINITION GLOBALER VARIABLEN ##############///////////////////////////////

#define PIN ""
#define LED_GRUEN 15  //PIN 15 --> PIN A1 Steuert die GRUENE LED bei SMS und steuert das Funkmodul an --> Einschaltbefehl
#define LED_ORANGE 16     //PIN 16 --> PIN A2 Steuert die Orangene LED bei SMS und symbolisiert Fehlerhaft gesendete Symbole
#define LED_ROT 17        //PIN 17 --> PIN A3 Steuert die ROTE LED bei SMS und steuert das Funkmodul an --> Ausschaltbefehl 
///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////Custom Chars um Sendeaktivität zu indizieren
byte customCharsend[8] = {
  0b00000,
  0b01110,
  0b10001,
  0b00100,
  0b01010,
  0b00000,
  0b00100,
  0b00000
};
byte customCharnosend[8] = {
  0b00000,
  0b01110,
  0b10011,
  0b10101,
  0b11001,
  0b01110,
  0b00000,
  0b00000
};
byte customCharCursor[8] = {
  0b11111,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
//######################INSTANZEN DER BIBLIOTHEKEN INITIALISIEREN#######
RCSwitch mySwitch = RCSwitch();//Sendemodul initialisieren
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);//LCD initialisieren
SainsmartKeypad keypad(0);//Keypad initialisieren
GSM gsmAccess;
GSM_SMS sms; 

// ############ GLOBALE VARIABLEN #################

// ----------- Variablen Funksteuerung & Zeitschaltuhr --------------
unsigned long anzeige2;  // Variable um Stunden in den untermenüs auszugeben
unsigned long hour1=0;   //Variablen zum Speichern der momentanen Uhrzeit
unsigned long min1;
unsigned long sek1;
 int hourvergleich=0;
 int minvergleich=0;
//Startzeit
unsigned long anzeige3;// Variable um Stunden in den untermenüs auszugeben
unsigned long hour2;   //Variablen zum Speichern der momentanen Uhrzeit
unsigned long min2;
unsigned long sek2;

//endzeit
unsigned long anzeige4;// Variable um Stunden in den untermenüs auszugeben
unsigned long hour3;   //Variablen zum Speichern der momentanen Uhrzeit
unsigned long min3;
unsigned long sek3;

//Abzug millis()
unsigned long prev_millis = 0;// wird benötigt um die im Menü verbrachte zeit zu neutralisieren.

unsigned long sek = 0; // Speichert die seit Systemstart vergangenen Sekunden
////Vars Menü und Tastenabfrage
char taste;          //Speichert die gedrückte Taste zwischen.(String)
int modus = 1;       //Auswahlvariable für Hauptmenü
int modus2 = 0;      //Auswahlvariable für Untermenüs
int keypad_pin = A0; //Variable um den Analog wert des Displays abzuspeichern
static enum {UNDEF,AUS,EIN}  flag_old=UNDEF;

// ----------- Variablen GSM --------------

char SENDERNUMMER[20]; // Dient zum Ausgeben/ Speichern der Sendernummer
unsigned long TIME_BEFORE = 0; // Steuert die Leuchtzeit der LED. Speichert die vorherige Zeit.
const long LED_INTERVAL = 5000;  // Leuchtdauer der LED in 

// #################### VOID SETUP #########################
void setup() {
      // -- Variavlendeklaration innerhalb Void Setup --
      lcd.begin(16, 2); // Bekanntgabe um welche Art Display es sich handelt 2Zeilen 16 Zeichen
      lcd.clear();      //Löscht Bildschirm ausgaben
      lcd.createChar(0, customCharsend);// Zuordnung der erstellten Spezialzeiche (senden)
      lcd.createChar(1, customCharnosend);//Zuordnung der erstellten Spezialzeichen(nicht senden)
      lcd.createChar(2, customCharCursor);//Cursor
      mySwitch.enableTransmit(6);//Festlegen des Datenpin für RC Funkmodul
      
      //Initialisiert die GPIOs
      pinMode(LED_GRUEN, OUTPUT);
      pinMode(LED_ORANGE, OUTPUT);
      pinMode(LED_ROT, OUTPUT);
        
      // Initialisiert die Serielle Schnittstelle
      LOAD_SERIAL_INT(); // Lädt die Serielle Schnittstelle für Kontrollausgaben -- bei Fertigstellung nicht mehr relevant
      Serial.println("Serielle Schnittstelle geladen"); //Kontrollausgabe

      // Prüfen des SIM-Karten Status
      // PIN_CHECK_FKT(); --Library fehlerhaft, deshalb vorerst nicht verwendet

      LOAD_GSM_INT(); // -- Lädt die GSM Schnittstelle und prüft die Verbindung
      Serial.println("GSM: Verbindung hergestellt."); // Kontrollausgabe
 
      // Arduino Bereit
      ARDUINO_RDY(); // Lässt alle LEDs einmal aufblinken als Zeichen, dass nun empfangen wird 
 
      Serial.println("Warte auf SMS"); // Kontrollausgabe 
 sms.flush();
}


// #################### VOID LOOP #########################
void loop() {
    // Variablendeklaration
    unsigned long TIME_NOW=0;hor2
    sek = seconds(hour1, min1, sek1);//Umwandeln der Momanten eingestellten Zeit in Sekunden
    taste = ReadKeypad();//Lesen der gedrückten taste
    waitbutton();//Warten auf loslassen der Taste( gepfuschtes entprellen)
  
    //Auswahl des Menüs zum einstellen von "mom. Stunden Start & Stopzeit"
    modus=FKT_MENU(taste,modus); // Mit den Tasten Down,Up, Left, Right wird im Menü geblättert.
    
    FKT_MODUS(sek,modus,TIME_NOW); // Menüeinstellung, Ein- & Ausschaltzeit einstellen

    //Verarbeiten einer empfangenen SMS
    if (sms.available()) 
    {
      SMS_VERARBEITEN(); // Wertet die SMS aus und sendet Steuerbefehle an die Funksteckdose
    }
      

    // Steuerung Orangene LED, um falsch gesendete Zeichen zu melden (Bestandteil der Anweisungen zu 'Verarbeiten einer gesendeten SMS')
    TIME_NOW=millis();
    if(TIME_NOW<(TIME_BEFORE+LED_INTERVAL))
    digitalWrite(LED_ORANGE, HIGH);
    else
    digitalWrite(LED_ORANGE, LOW);

}

code Teil 2:

// ##################################################################################################
// ###################Funktionen ##########################
// ##################################################################################################

void FKT_MODUS(int sek, int modus, unsigned long TIME_NOW)/////////////////////////////////////Aufruf der verscheidenen Funktionen zum Zeiteinstellen je nach Auswahl
{
    switch (modus) {

    case 1://Hauptbildschirm mit Anzeige von eingestellter Zeit, Start, und Endezeit
            //DEFAULT Menü
      lcd.setCursor(0, 0);// auf 1 spalte 1 zeichen cursor setzten
      displaytime(hours(sek - prev_millis), mins(sek - prev_millis), secs(sek - prev_millis));//aufruf Funktion zum anzeigen der "tickenden" Zeit - abzug der in den Münüs verbrachten Zeit
      hourvergleich=hours(sek - prev_millis);
      minvergleich=mins(sek - prev_millis);
      
      ////////////////////////////////////Printen Einschaltzeit
      lcd.setCursor(0, 1);
      lcd.print("E");
      lcd.print(")");
      printDigits(hour2);
      lcd.print(":");
      printDigits(min2);
      //////////////////////////////////////Printen Auschaltzeit
      lcd.setCursor(8, 1);
      lcd.print("A");
      lcd.print(")");
      printDigits(hour3);
      lcd.print(":");
      printDigits(min3);
    
      //--Vergleichen der Zeiten zum senden des Funksignals((klappt so nicht))
     
      schalte_funk();//was genau macht Time NOW??
      break;

    case 4://Menü zum Einstellen der Momentanen Uhrzeit auswahl durch Select button
      lcd.setCursor(0, 0);
      lcd.print("Mom. Uhrzeit");
      if (taste == 'S') {
        // min1=initialmin(taste);
        modus2 = 2; //Variable zum schalten der untermenüs
      
        min1 = 0;
        sek1 = 0;
        hour1 = initialHour(taste);
        lcd.clear();
      }
      break;//break sonst springt es nicht wieder Raus

    case 2:// Menü zum Stellen der Start Uhrzeit
      lcd.setCursor(0, 0);
      lcd.print("Start Uhrzeit");
      if (taste == 'S') {
        // min1=initialmin(taste);
        modus2 = 3; //Variable zum schalten der untermenüs
        hour2 = 0;
        min2 = 0;
        sek2 = 0;
        hour2 = initialHour(taste);

        lcd.clear();
      }
      break;

    case 3://Menü zum sTellen der gewünschten Abschaltzeit
      lcd.setCursor(0, 0);
      lcd.print("End Uhrzeit");
      if (taste == 'S') {
        modus2 = 4; //Variable zum schalten der untermenüs
        hour3 = 0;
        min3 = 0;
        sek3 = 0;
        hour3 = initialHour(taste);
        lcd.clear();
      }
      break;
  }
}


char ReadKeypad() { //Liest die Analog werte der Taster us und gibt Chars zurück
  /* no button pressed 1023
    select  741
    left    503
    down    326
    up      142
    right   0
  */
  int keypad_value = analogRead(keypad_pin);
  if (keypad_value < 100)
    return 'R';
  else if (keypad_value < 200)
    return 'U';
  else if (keypad_value < 400)
    return 'D';
  else if (keypad_value < 600)
    return 'L';
  else if (keypad_value < 800)
    return 'S';
  else
    return 'N';
}

unsigned long seconds(unsigned long initialHours, unsigned long initialMins, unsigned long initialSecs ) {
  unsigned long s = 0;
  s = initialHours * 3600;    //Berechnet aus Stunden die sekunden
  s = s + (initialMins * 60); //Berechnet aus Minuten die Sekunden und addiert auf
  s = s + initialSecs;        //Addiert die Sekunden hinzu
  s = s + (millis() / 1000);  // alle 1000 ms wird 1 sekunde aufaddiert
  return s;
}

unsigned long hours(unsigned long sekunden) {
  unsigned long hrs = 0;
  hrs = sekunden;
  hrs = hrs / 3600;//Umrechung Sekunden in Stunden
  hrs = hrs % 24; // Modulo zur ausgabe der Stunden
  return hrs;
}

unsigned long mins(unsigned long sekunden) {
  unsigned long minutes;
  minutes = sekunden;    // siehe hours()
  minutes = minutes / 60;
  minutes = minutes % 60;
  return minutes;
}

unsigned long secs(unsigned long sekunden) {
  unsigned long sec;
  sec = sekunden;        //siehe hours()
  sec = sec % 60;
  return sec;
}

char sep() {// Doppelpunkte zum Trennen von HH:MM:SS(blinkend)
  unsigned long s = millis() / 1000;     //alle 1000 ms bei geraden zahlen ":" printen
  if (s % 2 == 0)
  {
    lcd.print(":");
  }
  else {
    lcd.print(" ");     // bei ungeraden zahlen " " printen
  }
}

void printDigits(byte digits) { // wenn digits < 10 führenden Null einfügen
  if (digits < 10)
    lcd.print('0');  
  lcd.print(digits);
}

void displaytime(unsigned long stunden, unsigned long minuten, unsigned long sekunden) {//Auftrennen der  Zeit in 24:60:60 format mit trennzeichen
  lcd.setCursor(0, 0);
  printDigits( stunden % 24);
  lcd.setCursor(2, 0);
  sep();
  lcd.setCursor(3, 0);
  printDigits(minuten);
  lcd.setCursor(5, 0);
  sep();
  lcd.setCursor(6, 0);
  printDigits(sekunden);
}

void waitbutton() {//Dient zum warten auf loslassen des Tasters

  while (analogRead(keypad_pin) < 800) {}

}
unsigned long initialHour(char taste) {//Per Modulo einzelne stellen errechnen und per taster hochzählen
 int initialHours = 0;
  unsigned long stunden10 = 0;
  unsigned long stunden1 = 0;
  lcd.clear();
  while (taste != 'L') {    //So lange die "left" Taste nciht gedrückt ist im Menü bleiben
    taste = ReadKeypad();   //lesende der Eingabe

    stunden10 = (initialHours / 10) % 10;   //10er stellen der Zahl berechnen
    stunden1 = initialHours % 10;           //1er stellen der Zahl berechen
    
////////////////////////////////////////Ausgabe der 10er und 1er Stunden
    lcd.setCursor(0, 0);
    lcd.print(stunden10);
    lcd.setCursor(1, 0);
    lcd.print(stunden1);
    lcd.setCursor(0, 1);

    lcd.setCursor(0, 1);//Cursor zu Testzwecken (später entfernen oder verbessern !!!!!)
    lcd.write((byte) 2);
    lcd.setCursor(1, 1);
    lcd.write((byte) 2);
    lcd.setCursor(2, 0);
    sep();
    lcd.setCursor(3, 0);
    lcd.print("00");
    lcd.setCursor(5, 0);




    if (taste == 'U') {// Hochzählen der Tasten eventuell noch "Down" implementieren
      waitbutton();
      initialHours++;
    }
    if (initialHours > 23) {// Wechsel zwischen 23 und 0
      
      initialHours = 0;
    }
 
    if (taste == 'D') {// Hochzählen der Tasten eventuell noch "Down" implementieren
      waitbutton();
       waitbutton();
      initialHours--;
    
    if (initialHours <= 0) {// Wechsel zwischen 0und 23
      initialHours = 23;
    }
    }
 



    if (taste == 'R') {// Weiterschalten je nach menü auf Minuten 



      switch (modus2) {

        case 2://Minuten der Momentanen Zeit einstellen
          anzeige2 = initialHours;

          min1 = initialmin(taste); //Stellen minuten der Momentanzeit
          modus = 1;
          break;

        case 3://Minuten der Start Zeit einstellen
          anzeige3 = initialHours;

          min2 = initialmin(taste); //Stellen der Minuten Startzeit
          modus = 1;
          break;

        case 4://Minuten der Momentanen Zeit einstellen
          anzeige4 = initialHours;

          min3 = initialmin(taste); 
          modus = 1;
          break;
      }
      return initialHours;
    }
  }
  modus = 1;// Zurücksetzen sodass man weider in das Hauptmenü kommt nach dem "Right" gedrückt wurde
}

Teil 3:

unsigned long initialmin(char taste) { //   Funktion zum einstellen der Minuten (ähnlich wie initial Hours)        
                       
  int initialmins = 0; //Per Modulo einzelne stellen errechnen und per taster hochzählen
  unsigned long minuten10 = 0;
  unsigned long minuten1 = 0;

  waitbutton();

  while (taste != 'L') {
    taste = ReadKeypad();

    minuten10 = (initialmins / 10) % 10;
    minuten1 = initialmins % 10;

    switch (modus2) {

      case 2://Ausgabe der zuvor eingestellten Stunden
      
        lcd.setCursor(0, 0);
        printDigits(anzeige2);
        lcd.setCursor(2, 0);
        sep();
   
        break;
      case 3://Ausgabe der zuvor eingestellten Stunden
        lcd.setCursor(0, 0);
        printDigits(anzeige3);
        lcd.setCursor(2, 0);
        sep();
        break;
      case 4://Ausgabe der zuvor eingestellten Stunden
        lcd.setCursor(0, 0);
        printDigits(anzeige4);
        lcd.setCursor(2, 0);
        sep();
        break;
    }
    //Ab jetzt ausgabe der Minuten die in dieser Funktion eingestellt werden
    lcd.setCursor(0,1);
    lcd.print("  ");
    lcd.setCursor(3, 0);
    lcd.print(minuten10);
    lcd.setCursor(3, 1);
    lcd.write((byte) 2);
    
    lcd.setCursor(4, 0);
    lcd.print(minuten1);
    lcd.setCursor(4, 1);
    lcd.write((byte) 2);
    
    lcd.setCursor(5, 0);

    if (taste == 'U') {
      waitbutton();
      initialmins++;
    }
    
    if (initialmins > 59) {
      initialmins = 0;
    }
     if (taste=='D'){
       waitbutton();
      initialmins--;
     }
    if (initialmins < 0) {
      initialmins = 59;
    }

    if (taste == 'R') {

      prev_millis = millis() / 1000;//Zeitberechnen die im Menü verbracht wurde
      return initialmins;
      modus = 1;

    }


  }
}

void schalte_funk(){
bool nach_einschalt = ( (hourvergleich > hour2) || ( (hourvergleich == hour2) && (minvergleich >= min2)) );  // gibt True wenn Zeit1 > zeit 2
bool vor_ausschalt = ( (hourvergleich < hour3) || ( (hourvergleich == hour3) && (minvergleich < min3)) );  // gibt true wenn Zeit1< zeit 3
bool nach_ausschalt = ((hourvergleich  > hour3) || (( hourvergleich ==hour3) &&(minvergleich > min3)));//gibt true zurück wenn zeit 1 > zeit 3
bool vor_einschalt=( (hourvergleich < hour2) || ( (hourvergleich == hour2) && (minvergleich <= min2)) );//gibt true zurück wenn zeit 1 < zeit 2

//Serial.print(hourvergleich);
//Serial.print(hour2);
//Serial.print(hour3);
//Serial.print(nach_einschalt);
////Serial.print("    ");
////Serial.print(vor_ausschalt);

 if(nach_einschalt&&vor_ausschalt){
  if(flag_old!=EIN)
    {
      flag_old=EIN;
      mySwitch.sendTriState("00000FFF0F0F");
      digitalWrite(LED_GRUEN, HIGH);
      digitalWrite(LED_ROT, LOW);
      Serial.print("an");      
      printstatus(0);
    }
 }
 else if(flag_old!=AUS){
  flag_old=AUS;
    mySwitch.sendTriState("00000FFF0FF0");
    digitalWrite(LED_GRUEN, LOW);
    digitalWrite(LED_ROT, HIGH);
    Serial.println("aus");  
    
//    Serial.print("aus");
     printstatus(1);

  }
}

void printstatus(byte z) {
  lcd.setCursor(15, 0);
  lcd.write(z);
 
}

// Laden der Seriellen Schnittstelle
void LOAD_SERIAL_INT()
{
    Serial.begin(9600); // Kontrollausgaben
    while(!Serial)
    { 
    // Wartet auf den seriellen Port
    }
}

// Verbindung mit GSM
void LOAD_GSM_INT ()
{
    boolean NO_CONNECTION = true;
   while (NO_CONNECTION)  // Solange keine Verbindung zum GSM Netz besteht, wird versucht eine aufzubauen
    {
    //INFO zur Funktion:
    // gsmAccess.begin(PIN) liefert mehrere Rückgaben von Datentyp 'char'
    // 0 ERROR
    // 1 IDLE
    // 2 CONNECTING
    // 3 GSM READY
    // 4 CONNECTING
    // 5 TRANSPARENT_CONNECTED
    

      if(gsmAccess.begin() == GSM_READY) //-  Verbindung hergestellt. Mit if(gsmAccess.begin(PIN)== GSM_READY) würde eine PIN Eingabe erfolgen. Diese ist fehlerhaft in der Library implementiert und wird weg gelassen
      {
        NO_CONNECTION = false; 
      }
         
     else // Keine Verbindung
       {
         Serial.println("GSM: Keine Verbindung");
         delay(500);         
       }
   } // Ende while-Schleife
}

void ARDUINO_RDY()
{
   digitalWrite(LED_ROT, HIGH);
   digitalWrite(LED_ORANGE, HIGH);
   digitalWrite(LED_GRUEN, HIGH);
   delay(2000);
   digitalWrite(LED_ROT, LOW);
   digitalWrite(LED_ORANGE, LOW);
   digitalWrite(LED_GRUEN, LOW);
}

void SMS_VERARBEITEN()
{
  char c; // Dient zum Einlesen der SMS Zeichen 
      // Einige Informationen zum Sender
      Serial.println("SMS empfangen von:"); // Kontrollausgabe, XXX: Hier ggf. eine Ausgabe auf dem LCD ?
      sms.remoteNumber(SENDERNUMMER,20); // Kontrollausgabe
      Serial.println(SENDERNUMMER); // Kontrollausgabe
      
      // SICHERHEIT      
      // In GSM können mit * und # Befehlen, diverse Einstellungen getroffen werden. Damit diese nicht
      // zum greifen kommen, werden im folgenden Teil solche SMS verworfen.   
      if (sms.peek()== '#' || sms.peek()=='*') // sms.peek() liefert das erste Zeichen einer SMS ohne es zu verwerfen.
       {
         Serial.println(sms.peek());
         Serial.println("Err100: SMS verworfen");
         sms.flush();
       }
      
      //Inhalt der SMS
      while(c=sms.read()) // Sequentielles einlesen der Zeichen
      {
        Serial.print(c);   // Ausgabe des Zeichens
             switch (c)
                  {
                   case '*' :          
                            sms.flush();
                            Serial.println("Err100: SMS verworfen"); // Kontrollausgabe
                            break;
                 
                   case '#' :         
                            sms.flush();                       
                            Serial.println("Err100: SMS verworfen"); // Kontrollausgabe
                            break;
                 
                   case '1': 
                            // SMS Eingang, Kaffeemaschine wird eingeschaltet, Grüne LED geht an, rote LED geht aus.
                            Serial.println("Switch case 1. SMS Grüne LED an, Funkmodul wird zum Einschalten angesteuert.");   // Kontrollausgabe    
                            flag_old=AUS;                      
                            digitalWrite(LED_GRUEN, HIGH);
                            digitalWrite(LED_ROT, LOW);
                            mySwitch.sendTriState("00000FFF0F0F"); //Ansteuerung der Funksteckdose - einschalten
                            sms.flush();
                            break;
                   
                   case '2' : 
                            // SMS Eingang, Kaffeemaschine wird ausgeschaltet, Grüne LED aus, rote LED geht an.
                            Serial.println("Switch case 2. SMS Rote LED an, Funkmodul wird zum Ausschalten angesteuert.");   // Kontrollausgabe    
                            flag_old=EIN;
                            digitalWrite(LED_GRUEN, LOW);
                            digitalWrite(LED_ROT, HIGH);
                            mySwitch.sendTriState("00000FFF0FF0"); //Ansteuerung der Funksteckdose - ausschalten
                            sms.flush();
                            break;

                   default :// Fehlerhafte Zeichen wurden empfangen, Orangene LED auf HIGH
                            // Fehlerhaft sind alle ERSTEN Zeichen eines Strings außer '1' und '2', sowie alle weiteren Chars eines Strings
                            Serial.println("Err200:Anweisung unbekannt.");  // Kontrollausgabe
                            TIME_BEFORE=millis();
                            sms.flush();
                            break;                                                        
                  } // Ende Switch-Case
      
      } // Ende while (c=sms.read())
    Serial.println("\nSystem: Ende der SMS."); //Kontrollausgabe
    sms.flush();
    Serial.println("System: SMS geloescht.");// Kontrollausgabe
}



// Ergänzung
int FKT_MENU(char taste,int modus)
{
  if (taste == 'U')
  { modus++;
     if (modus > 4)
     {
      modus = 1;
     }
    lcd.clear();
  }
  if (taste == 'D')
  {
    modus--;
    if (modus < 1) {
      modus = 4;
    }
    lcd.clear();

  }
  return modus;
}