Zeitschaltuhr über Tag und Nacht

Hallo,

Ich versuche grade eine Zeitschaltuhr zu realisieren welche so lang an ist wie ich mir das wünsche.

Bei meiner Aktuellen Variante habe ich das Problem das sich der Ausgang um Mitternacht abschaltet und nicht erst am nächsten morgen in der Frühe…

  unsigned long hcian;
  unsigned long hciaus;

  hcian = 72060; // 20:01:00 - licht an
  hciaus = 25020; // 06:57:00 - licht aus


  long jetzt = hours * 3600L + minutes * 60 + seconds;  //aktuelle tageszeit in sekunden


  if (jetzt >= hcian && jetzt < hciaus && digitalRead(9) == 0)
  {
    digitalWrite(9, HIGH);
  }


  if (jetzt > hciaus && digitalRead(9) == 1)
  {
    digitalWrite(9, LOW);
  }

zeiten umdrehen ist auch nicht die Lösung die ich suche =) da es einige Kanäle sind und die mal so und mal so laufen… sprich teils über tag nur und teils über Mitternacht hinaus

was müsste ich ändern um das ganze so laufen zu lassen?

Hallo,

du mußt deine if bedingungen umfangreicher definieren. Dein 2. if ist zu kurz. Wenn es vor Mitternacht einschaltet, dann mußt du überprüfen ob es vor Mitternacht eingeschalten wurde und ob es auch wirklich eingeschalten ist. Du mußt also sicher wissen, dass du dich gerade in einer Einschalt Phase befindest. Dann kannste warten bis es morgens wird.

evtl. mit Unixtime arbeiten

In einem anderen Thema wurde die Time-Bibliothek dafür vorgeschlagen, da lese ich "Time uses a special time_t variable type, which is the number of seconds elapsed since 1970.", womit dann Relationen leicht möglich sind.

Hallo,

er hat keine RTC.

Die Time Library hat erst mal nichts mit einer RTC zu tun, Die Zeitquelle kann auch was anderes sein oder theoretisch auch der Arduino Oszillator (wird halt ungenau)

Doc_Arduino:
Hallo,

er hat keine RTC.

hab ich.

DS3231, DCF77, TmeLib 1.5

hatte die Lib timealarms mal probiert die funzt bei mir aber hatte oft aussetzer

DCF aktualisiert wenn es neue Daten hat die rtc DS3231. Und ich hole mir die Zeit vom DS3231. Hatte auch mal versucht die RTC vom DUE laufen zu lassen aber Habs wieder rückgängig gemacht aufgrund der Tatsache das dass board keine Bufferbatterie für den Sam3X habe und der pin auch nicht rausgeführt wurde...

Mit "seconds elapsed since 1970" kannst Du Minuten-, Stunden-, Tages-, Jahresübergänge und Schaltjahre unberücksichtigt lassen, vergleichst einfach zwei Zahlen.

Oder Du hast den sportlichen Ergeiz, es selbst zu berechnen, dann mußt Du Dir die Formel für Schaltjahre ansehen:

Ein Schaltjahr ist, wenn

  • Die Jahreszahl durch 4 teilbar ist.
  • Ausnahme 1: Ist die Jahreszahl durch 100 teilbar ist i.d.R. KEIN Schaltjahr.
  • Ausnahme 2: Ist die Jahreszahl durch 400 teilbar ist IMMER ein Schaltjahr.

Wenn Du die Lebensdauer Deines Weckers als endlich betrachtest, reicht die Teilbarkeit durch 4 als Kriterium.

Oder Du nutzt die Schaltjahr-Liste: 2016 2020 2024 2028 2032 2036 2040 2044 2048

(Quelle: www.schnelle-online.info/Wann-ist-ein-Schaltjahr.html)

Dann kannst Du eine Zahl zum Vergleichen selbst berechnen:
( ( ( ( ( ( ( year * 12 ) + month ) * 30 ) + date ) * 24 ) + hours ) * 60 ) + minutes, wobei month * 30 durch eine Funktion zu ersetzen wäre, die die variable Monatslänge im Jahr unter Berücksichtigung der Schaltjahre berechnet.

ok habe jetzt ein kleines problem mit now()

Serial.println(now());

ergibt:

-1328964203
-1328964202
-1328964201
....

zählt rückwärst und ist mit minus vorbehaftet

time_t now(); // return the current time as seconds since Jan 1 1970

Du mußt eine unsigned long Variable nehmen.
Grüße Uwe

hab fehler gefunden und behoben.

jetzt liefert mir now meinen aktuellen unix timestamp.

die monatsabfrage würde ich so abfragen

int getdaysinmonth (int month, int year) {


  int tage;

  if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
    return 31;
  }

  if (month == 2) {

    if (!(year % 4) && (year % 100) || !(year % 400))
    {
      tage = 29;
    }
    else
    {
      tage = 28;
    }

    return tage;
  }

  if (month == 4 || month == 6 || month == 9 || month == 11) {
    return 30;
  }

}

year * 12 ) + month ) * 30 ) + date ) * 24 ) + hours ) * 60 ) + minutes

hast du da nicht fehler drin?

warum jahr x 12 ?

muss ich im nächsten schritt berechnen bei welchem timestamp ich meine on/off zeiten seit 1970 habe? dafür müsste ich doch jedes jahr einzeln berechnen lassen und die sekunden jedes jahres addieren(oder einfach timestamp vom 1.1.2015 00:00:00 als start nehmen) + die bis zu meinem nächsten on/off. Und dann noch die beiden zeiten vergleichen.. bei erreichen des Schaltmomentes müsste ich ja dann meinen nächsten zeitstempel berechnen lassen oder einfach nur 86400 sekunden dazu addieren ?

uwefed:
Du mußt eine unsigned long Variable nehmen.

time_t ist ein typedef für unsigned long

mpl1337:
year * 12 ) + month ) * 30 ) + date ) * 24 ) + hours ) * 60 ) + minutes

hast du da nicht fehler drin?

warum jahr x 12 ?

Ich rechne die Jahre in Monate um, jedes Jahr hat zwölf Monate, also jahr x 12. Da sehe ich keinen Fehler. Oder?

Zu Deinem letzten Absatz: Wenn Du den Unix Timestamp nutzt, mußt Du selbst nichts berechnen:

zeit1 = unixtimestamp(jahr1,monat1,tag1,stunde1,minute1,sekunde1)
zeit2 = unixtimestamp(jahr2,monat2,tag2,stunde2,minute2,sekunde2)
zeit1 > zeit2 -> mach was

mpl1337:
muss ich im nächsten schritt berechnen bei welchem timestamp ich meine on/off zeiten seit 1970 habe? dafür müsste ich doch jedes jahr einzeln berechnen lassen und die sekunden jedes jahres addieren(oder einfach timestamp vom 1.1.2015 00:00:00 als start nehmen) + die bis zu meinem nächsten on/off. Und dann noch die beiden zeiten vergleichen… bei erreichen des Schaltmomentes müsste ich ja dann meinen nächsten zeitstempel berechnen lassen oder einfach nur 86400 sekunden dazu addieren ?

Hast Du in diesem Thread noch ein neues Thema angefangen, oder geht es immer noch um Schaltzeiten über Mitternacht hinweg bei einer Tageszeitschaltuhr?

Die Schaltlogik für Tagesschaltzeiten “über den Tag hinweg” ist fast dieselbe wie bei Schaltzeiten “über Mitternacht hinweg”.

Pseudo-Code:

  • wenn die Einschaltzeit kleiner ist als die Ausschaltzeit (Schalten am selben Tag)
  • dann Einschalten wenn aktuelle Zeit größer Einschaltzeit UND aktuelle Zeit kleiner Ausschaltzeit
  • sonst Ausschalten
  • wenn die Einschaltzeit größer ist als die Ausschaltzeit (Schalten über Mitternacht)
  • dann Einschalten, wenn aktuelle Zeit größer Einschaltzeit ODER aktuelle Zeit kleiner Ausschaltzeit
  • sonst Ausschalten

@jurs: Ich fürchte, den Themensteller mit meinem Beitrag verwirrt zu haben. Ich hoffe, als Weckerexperte kannst Du ihn auf den für ihn richtigen Weg führen. Ich wünsche Dir frohe Festtage!

ja… bin total durcheinander jetzt.

verfolge jetzt mal jurs seine lösung.

  if (hcionh < hcioffh)
  {
    if (hour() >= hcionh && minute() >= hcionm && second() >= hcions && hour() <= hcioffh && minute() <= hcioffm && second() <= hcioffs)

    {
      digitalWrite(9, HIGH);
    } else {
      digitalWrite(9, LOW);

    }
  }


  if (hcionh > hcioffh)
  {
    if (hour() >= hcionh && minute() >= hcionm && second() >= hcions || hour() <= hcioffh && minute() <= hcioffm && second() <= hcioffs)
    {
      digitalWrite(9, HIGH);
    } else {
      digitalWrite(9, LOW);

    }
  }

aber jetzt habe ich das problem das ich die zeit nicht als ganzes vergleiche …

wie bekomme ich nun hour() minute() second() zu einem wert und hcionh, hcionm, hcions ? mit sprintf schonmal nicht :smiley: bzw klappt dann der vergleich nicht mehr xD

okay ich rechne einfach in sekunden jetzt klickt es =)

soo es geht:)

  unsigned long hcian =  hcionh * 3600L + hcionm * 60 + hcions;
  unsigned long hciaus = hcioffh * 3600L + hcioffm * 60 + hcioffs;
  unsigned long jetzt = hour() * 3600L + minute() * 60 + second();

  if (hcian < hciaus){

  //an-aus am selben tag
  if (jetzt >= hcian && jetzt < hciaus)
  {
    if(digitalRead(9) == 0){
    digitalWrite(9, HIGH);
    }
  } else {
    if(digitalRead(9) == 1){
    digitalWrite(9, LOW);
     }
  }

  } else  {

   //schaltzeit über mitternacht hinaus 
  if ( ((hcian < hciaus) && (jetzt >= hciaus)) || ((hcian >= hciaus) && (jetzt < hcian) && (jetzt >= hciaus) ))
{
    if(digitalRead(9) == 1){
    digitalWrite(9, LOW);
    }

    } else {
    if(digitalRead(9) == 0){
    digitalWrite(9, HIGH);
    }

  }
  }

hab noch paar schnipsel im forum gefunden und die haben dann die lösung gebracht =)

mpl1337:
soo es geht:)

Die Schaltlogik für das “Schalten über Mitternacht” sollte nicht komplizierter sein als das “Schalten über den Tag”.

Ich habe mal umgeschrieben und umformatiert:

  if (hcian <= hciaus) //an-aus am selben tag
  {
    if (jetzt >= hcian && jetzt < hciaus)
    {
      if(digitalRead(9) == 0) digitalWrite(9, HIGH);
    } 
    else 
    {
      if(digitalRead(9) == 1) digitalWrite(9, LOW);
    }
  } 
  else  //schaltzeit über mitternacht hinaus 
  {
    if (jetzt >= hcian || jetzt < hciaus)
    {
      if(digitalRead(9) == 1) digitalWrite(9, LOW);
    } 
    else 
    {
      if(digitalRead(9) == 0) digitalWrite(9, HIGH);
    }
  }