Zeitfenster welches über Mitternacht hinausgeht definieren

Hallo zusammen,

ich baue eine Steuerung Heizung.
Dazu möchte ich gerne ein Zeitfenster festlegen in dem geheizt werden soll.
Das ganze funktioniert auch solange Start- und Endzeit nicht über Mitternacht (00:00) laufen.
Die Zeit kommt aus einem RTC der via DCF77 gestellt wird.

Sobald mein Zeitfenster aber (beispielsweise) von 22:00 bis 07:30 beträgt klappt meine Mathematik im Code nicht mehr. Ich frage mich jetzt was der eleganteste Weg ist das Problem zu lösen. Komme ich mit meinem Code da überhaupt weiter? Muss (sollte) ich da irgendwie mit epoch arbeiten? Gibts für sowas vielleicht schon Funktionen oder Libs?

byte NachtStundeStart = 21;
byte NachtMinuteStart = 50;
byte NachtStundeEnde = 8;
byte NachtMinuteEnde = 30;
byte ZeitfensterAktivState = 0;


void loop() {

  int meldung = ZeitfensterAktiv();
  if (meldung == 1 )  lcd.print ("Steuerung AKTIV!!");
  if (meldung == 0 )  lcd.print ("Steuerung STANDBY");


}







int ZeitfensterAktiv() {
  byte aktStunde = hour();
  byte aktMinute = minute();

  if (
    (aktStunde == NachtStundeStart && aktMinute >= NachtMinuteStart) || (aktStunde > NachtStundeStart)
    && ((aktStunde == NachtStundeEnde && aktMinute < NachtMinuteEnde)  || (aktStunde < NachtStundeEnde) )) {
    ZeitfensterAktivState = 1;

  } else {
    ZeitfensterAktivState = 0;
    { digitalWrite(SwitchPin, LOW);
    }
    return ZeitfensterAktivState;
  }
}

Die Rechnungen werden wesentlich einfacher, wenn Du alle Zeiten als einfache Werte behandelst, also in Minuten oder Millisekunden.

Ebenfalls einfacher wird eine Behandlung als Startzeit und Dauer, dann kann das Schema von BlinkWithoutDelay verwendet werden, das mit Überläufen klarkommt. Die Zeitumstellung auf den nächsten Tag sollte dann mit den Ereignissen synchronisiert werden, d.h. die aktuelle Zeit wird zurückgesetzt, wenn ein Ereignis am nächsten Tag (>24 Uhr) eingetreten ist.

Du könntest berücksichtigen, dass der Abschaltzeitpunkt nicht am gleichen Tag ist. Also nicht nur die Stunden, sondern auch den Tag verwursteln.

Grüße

Deine ZeitfensterAktiv - Logik ist doch schon fast richtig, wenn 1 = aktiv nachts ist, und immer ein Tageswechsel zwischen NachtAnfang und NachtEnde liegt.
Oder hab ich mich vertan?

Oder fehlen Klammern?

Hi

Mein Weg wäre ebenfalls, die Zeiten in Minuten (o.Ä.) umzurechnen.
Dann hast Du zwei Werte Start und Stop.
Wenn Stop < Start, dann ist eine Nacht dazwischen - die Abfrage wäre aktZeit>=Start || aktZeit<=Stop
Wenn Stop > Start, dann ist das Ende am gleichen Tag - die Abfrage wäre aktZeit>=Start && aktZeit<=Stop

Einziger Unterschied ist das && <-> ||, Welches Dir 'die Zeit dazwischen' bzw. 'die Zeit außerhalb' gibt.

Auch würden dann Deine IFs wesentlich einfacher zu lesen :wink:
(vll. ein Kommentar dahinter, was diese 'Magic Number' bedeuten soll, oder die Schaltzeiten global und const deklarieren)

MfG

Hallo,

du verwendest doch sicherlich eine Temperaturtabelle die sich wöchentlich wiederholt.

Ich verwende in meiner Heizungssteuerung "Wochenminuten".

Sonntag = Tag 0

Tag * 24 * Stunde *60 + Minute = Wochenminute

Gruß Aron

postmaster-ino:
Wenn Stop < Start, dann ist eine Nacht dazwischen - die Abfrage wäre aktZeit>=Start || aktZeit<=Stop
Wenn Stop > Start, dann ist das Ende am gleichen Tag - die Abfrage wäre aktZeit>=Start && aktZeit<=Stop

Einziger Unterschied ist das && <-> ||, Welches Dir 'die Zeit dazwischen' bzw. 'die Zeit außerhalb' gibt.

Vielen Dank! So habe ich es gemacht und habe nun funktionierenden Code - wenn auch keinen schönen :wink:

int ZeitfensterAktiv() {
  int aktStunde = hour();
  int aktMinute = minute();
 
  if ( Stoppzeit_Stunde == Startzeit_Stunde) {
    if ( aktMinute >= Startzeit_Minute && aktMinute < Stoppzeit_Minute ) {
      ZeitfensterAktivState = 1;
      return ZeitfensterAktivState;
    }
    else {
      ZeitfensterAktivState = 0;
      { digitalWrite(SwitchPin, LOW);
      }
      return ZeitfensterAktivState;
    }
  }



  if ( Stoppzeit_Stunde < Startzeit_Stunde) {  // Tageswechsel - Zeit nach mitternacht
    if (
      (aktStunde == Startzeit_Stunde && aktMinute >= Startzeit_Minute) || (aktStunde > Startzeit_Stunde)
      || ((aktStunde == Stoppzeit_Stunde && aktMinute < Stoppzeit_Minute)  || (aktStunde < Stoppzeit_Stunde) )) {
      ZeitfensterAktivState = 1;
      ZeitfensterAktivState = 1;
      return ZeitfensterAktivState;
    } else {
      ZeitfensterAktivState = 0;
      { digitalWrite(SwitchPin, LOW);
      }
      return ZeitfensterAktivState;
    }

  }
  if ( Stoppzeit_Stunde > Startzeit_Stunde) {
    if (
      (aktStunde == Startzeit_Stunde && aktMinute >= Startzeit_Minute) || (aktStunde > Startzeit_Stunde)
      && ((aktStunde == Stoppzeit_Stunde && aktMinute < Stoppzeit_Minute)  || (aktStunde < Stoppzeit_Stunde) )) {
      ZeitfensterAktivState = 1;
      ZeitfensterAktivState = 1;
      return ZeitfensterAktivState;
    } else {
      ZeitfensterAktivState = 0;
      { digitalWrite(SwitchPin, LOW);
      }
      return ZeitfensterAktivState;
    }

  }

wenn auch keinen schönen  ;) Dann ändere deine Funktion zu

bool ZeitfensterAktiv()

und mach aus ZeitfensterAktivState eine lokale Variable.

Sonst ist alles ok, finde ich :slight_smile:

Hi

Ob's Da unbedingt ein INT braucht ... lässt durchblicken, daß man sich keine Gedanken dazu gemacht hat.
Ganz nebenbei braucht ein INT zwei Byte Speicherplatz, ein Byte / uint8_t oder boolean nur ein Byte (wobei boolean nur ja/nein aka true/false aufnehmen kann).

MfG