Newbie sucht Hilfe... DS3231 RTC mit MEZ/MESZ Umschaltung gesucht

Hi Doc,

was hat es damit auf sich?

%02d.%02d.%04d ; %02d:%02d:%02d

Definiert dies eine jeweils 2stellige Variable?

danach folgen die "Zeit"-Variablen...richtig?

und einmal ne 4stellige fürs Jahr?

Nein. Das hat nichts mit Variablen zu tun. Das ist einfach für die Formatierung der Ausgabe auf eine konstante Breite (2 oder 4 stellen mit führenden Nullen):
http://www.cplusplus.com/reference/cstdio/printf/

sprintf() schreibt den formatierten String in einen Puffer und den gibt man dann auf Serial aus.

Loschder: Uijuijui... des hab ich nicht kapiert...

ich lasses mal sacken...

Vielleicht fängt Du auch erstmal mit der sprintf() Funktion an und schaust Dir die Erläuterungen dieser C-Standardfunktion auf verschiedenen Seiten an, bis Du das kapiert hast.

Und dann arbeitest Du Dich langsam über die snprintf() Funktion bis zu snprintf_P() vor, die den Formatierungsstring RAM-speichersparend aus dem Flash-Programmspeicherbereich verwendet.

Im Formatierungsstring steht das Prozentzeichen % für einen Platzhalter, die nachfolgende 0 für "führende Nullen auffüllen", danach folgt die Stellenzahl und 'd' steht für eine int-Dezimalzahl. D.h. "%02d" formatiert auf zwei Stellen mit ggf. führenden Nullen, und "%04d" auf vier Stellen mit ggf. führenden Nullen".

Oder Du formatierst Deine Zeitausgaben erstmal weiter "zu Fuß".

Es gibt ja immer mehrere Möglichkeiten.

Hallo,

ja genau, damit werden 2 stellige dezimale Zahlen formatiert, also mit führender Null. Die Jahreszahl ist 4stellig. Links das Datum, rechts die Uhrzeit. Dargestellt/getrennt mit Semilikolon. Das ; kannste rausnehmen, brauch ich später zur Spaltentrennung in Excel.

Hast Du noch die alte Version von jurs?

Ich würde sagen wollen, die Wochentagkorrektur gehört mit in in die Funktion
void timeAddTimezone(sTime &time)
und
void timeSubTimezone(sTime &time)
rein.
Wenn er den Tag mit ++ oder – korrigiert, kannste auch den Wochentag mit korrigieren lassen.
Mußt nur die gesamte Lib mit einer Variablen für den Wochentag ergänzen usw.

Edit: jurs war schneller. Wegen dem Wochentag, ich will da nicht noch reinpfuschen. Entweder jurs baut es ein oder jeder für sich wenn er es braucht. Sonst haben wir hier das Kaos. :wink:

Hallo Leute

so...hab endlich mal wieder etwas Zeit hierfür gefunden und denke ich habs jetzt verstanden mit snprintf für Zeit und Datumsausgabe:

char localTimeBuf[21];                     // Deklarieren der localTimebuf; Zahl in Klammer = Stellen-1
  snprintf(localTimeBuf,21,"%02d:%02d:%02d  %02d.%02d.%04d",time.bHour,time.bMinute,time.bSecond,time.bDay,time.bMonth,time.iYear);

  Serial.print(localTimeBuf);
  lcd2.setCursor(0, 0);                      // Anfang auf Stelle 16, Zeile 0 setzen
  lcd2.print(localTimeBuf);                     // Jahr auf LCD ausgeben

für n 20 stelliges LCD... warum muss ich dann 21 eingeben? Worin liegt jetzt der Vorteil hieran - benötigt mehr Speicher als mit "Print-Befehle alle einzeln ausschreiben"... rein die Übersichtlichkeit?

@jurs, für meine zukünftig benötigten Schaltzeiten...kannst mir das nochmal im Detail erklären? Schaltzeiten sollen zw. 05.00-23.00 sein, so im wechsel 30min ein/3Std. aus(hier soll später noch eine variable eingebaut werden(abs. Luftfeuchte/Taupunkt-Auswertung)). Wäre ein array hierfür gut? Wie sag ich dem dass es ab "localTime 00:00:00" anfangen soll?

MfG Chris

Loschder: für n 20 stelliges LCD... warum muss ich dann 21 eingeben?

http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/011_c_arrays_011.htm#mja452663858fd23e86c51cfa3b9139f64 http://www.c-howto.de/tutorial-strings-zeichenketten-nullterminiert.html

Besser ist hier übrigens:

snprintf_P(localTimeBuf,21, PSTR("%02d:%02d:%02d  %02d.%02d.%04d"), ....);

Damit belegt der Format-String kein RAM

Loschder: @jurs, für meine zukünftig benötigten Schaltzeiten...kannst mir das nochmal im Detail erklären? Schaltzeiten sollen zw. 05.00-23.00 sein, so im wechsel 30min ein/3Std. aus(hier soll später noch eine variable eingebaut werden(abs. Luftfeuchte/Taupunkt-Auswertung)). Wäre ein array hierfür gut? Wie sag ich dem dass es ab "localTime 00:00:00" anfangen soll?

Ja, Schaltzeiten legt man am besten in einem Array ab.

Wie das im Prinzip gemacht werden kann, habe ich mal hier anhand eines Programmierbeispiels erklärt.

Es kommt natürlich im Detail darauf an, ob Du nur minutengenaue Schaltzeiten brauchst, oder ob Du auf die Sekunde genaue Schaltzeiten festlegen möchtest. Ob Du nur an einem einzigen Pin verschiedene Schaltungen durchführen möchtest. Oder ob für jede Schaltfunktion auch ein Pin festgelegt werden soll, an dem geschaltet werden soll. Ob ein Schaltprogramm jeden Tag gleich ablaufen soll, oder ob das Schaltprogramm je nach Wochentag unterschiedlich sein soll. Ob Schaltzeiten grundsätzlich so liegen, dass nach Mitternacht ein- und am selben Tag vor Mitternacht wieder ausgeschaltet wird. Oder ob Schaltzeiten auch "über Mitternacht laufen" sollen.

Es gibt da viele verschiedene Möglichkeiten, etwas im Detail anders zu implementieren.

Aber vom Grundsatz her gibt es bei einer digitalen Zeitschaltuhr ein struct-array mit Ein- und Ausschaltzeiten, das ständig in einer for-Schleife von einem Algorithmus abgearbeitet wird, ob eine Schaltfunktion ausgeführt werden muss.

Grrr…hab mir deinen Beispielcode mal angeschaut…aber komm da leider nicht weiter

Habe es mal soweit umgestrickt:

#define EIN HIGH
#define AUS LOW

struct schaltRelais_t{
  byte pin;
  int ein; 
  int aus;
};

// Hier die Relais-Pins definieren mit Ein- und Ausschaltzeiten
schaltRelais_t schaltRelais[3]={
  {10, 800, 1930},  // pin, Einschaltzeit, Ausschaltzeit
  {10, 805, 1935},
  {10, 810, 1940},
};

void relaisSchaltenNachZeit(int time.bHour, int time.bMinute)   
// Schaltet die Zeitschaltuhr ein und aus und setzt den Ausgang entsprechend
{
  boolean state;
  // Aus der aktuellen Zeit eine Schaltzeit bilden
  int thisTime= time.bHour*100+time.bMinute;
  // Alle Schaltzeiten durchgehen, falls eine davon EIN sagt, einschalten
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    state=AUS;  // Amnahme: Es sei nichts geschaltet
    if (schaltRelais[i].ein < schaltRelais[i].aus) 
    { // normale Schaltzeit von bis
      if (thisTime>=schaltRelais[i].ein && thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else if (schaltRelais[i].ein > schaltRelais[i].aus) 
    { // Schaltzeit über Mitternacht hinweg wenn die Einschaltzeit größer als die Ausschaltzeit ist
      if (thisTime>=schaltRelais[i].ein || thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else ; // gleiche Ein- und Ausschaltzeit ignorieren
    if (digitalRead(schaltRelais[i].pin)!=state) // Falls geschaltet werden soll
    { // ein paar Debug-Ausgaben machen
      Serial.print("Relais ");
      Serial.print(i+1);  // Relais-Index zählt ab 0, einfach 1 dazuzählen
      Serial.print(": ");
      if (state==EIN) Serial.println("EIN"); else Serial.println("AUS");
    }
    digitalWrite(schaltRelais[i].pin, state); // Schaltzustand setzen
  }
}

Und dann bekomm ich folgende fehler:

LCD_MEZMESZ-Uhr.ino:36: error: expected ',' or '...' before '.' token
LCD_MEZMESZ-Uhr.ino: In function 'void relaisSchaltenNachZeit(int)':
LCD_MEZMESZ-Uhr.ino:41: error: request for member 'bHour' in 'time', which is of non-class type 'int'
LCD_MEZMESZ-Uhr.ino:41: error: request for member 'bMinute' in 'time', which is of non-class type 'int'

Das da was mit meinen Stunden und Minuten nicht stimmt…des weiß ich schon…aber wie genau muss ich denn nun was wo noch deklarieren?

@jurs
dachte time.bHour und time.bMinute sind in deinem Sketch global? Global heißt doch für alle Routinen sichtbar…oder wo hab ich jetzt meinen Denkfehler

update:

hab keine Änderungen gemacht und dann waren die Fehler weg…?!

#define EIN HIGH
#define AUS LOW

struct schaltRelais_t{
  byte pin;
  int ein; 
  int aus;
};

// Hier die Relais-Pins definieren mit Ein- und Ausschaltzeiten
schaltRelais_t schaltRelais[3]={
  {10, 800, 1930},  // pin, Einschaltzeit, Ausschaltzeit
  {10, 805, 1935},
  {10, 810, 1940},
};



void relaisSchaltenNachZeit(int thishour, int thisminute)   
// Schaltet die Zeitschaltuhr ein und aus und setzt den Ausgang entsprechend
{
  boolean state;
  // Aus der aktuellen Zeit eine Schaltzeit bilden
  int thisTime= thishour*100+thisminute;
  // Alle Schaltzeiten durchgehen, falls eine davon EIN sagt, einschalten
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    state=AUS;  // Amnahme: Es sei nichts geschaltet
    if (schaltRelais[i].ein < schaltRelais[i].aus) 
    { // normale Schaltzeit von bis
      if (thisTime>=schaltRelais[i].ein && thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else if (schaltRelais[i].ein > schaltRelais[i].aus) 
    { // Schaltzeit über Mitternacht hinweg wenn die Einschaltzeit größer als die Ausschaltzeit ist
      if (thisTime>=schaltRelais[i].ein || thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else ; // gleiche Ein- und Ausschaltzeit ignorieren
    if (digitalRead(schaltRelais[i].pin)!=state) // Falls geschaltet werden soll
    { // ein paar Debug-Ausgaben machen
      Serial.print("Relais ");
      Serial.print(i+1);  // Relais-Index zählt ab 0, einfach 1 dazuzählen
      Serial.print(": ");
      if (state==EIN) Serial.println("EIN"); else Serial.println("AUS");
    }
    digitalWrite(schaltRelais[i].pin, state); // Schaltzustand setzen
  }
}

Welche Uhrzeit wird denn so genommen mit thishour und thisminute?
Die UTC oder korrigierte Sommer/Winterzeit wenn ich das so einfüge???

MfG Chris

void relaisSchaltenNachZeit(int time.bHour, int time.bMinute)

Was willst du damit bezwecken? Auch da fehlen dir Programmier-Grundlagen. Das ist nicht mal C-spezifisch

Funktionsparameter richtig deklarieren: http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/009_c_funktionen_014.htm#mjf226932554e147030a8b6a27568f5620

Erweitert (aber hier erst mal nicht nötig): http://www.willemer.de/informatik/cpp/parameter.htm

Jedoch vielleicht ein relevantes Zitat von der zweiten Seite:

Der Parameter stellen ist aus Sicht der Funktion eine ganz gewöhnliche lokale Variable, in die beim Funktionsaufruf der Wert des Aufrufers hineinkopiert worden ist

Hmm...d.h.

wenn ich eine lokale Variable innerhalb einer Funktion nach außen geben möchte dann kommt sie in die

void XY (hier rein) ?

Richtig?

Nein. Andere Richtung. Funktionsparameter dienen dazu Werte von Außen an Funktionen zu übergeben. Das sind aber für sich normale Variablen die nur innerhalb der Funktion gültig sind.

Loschder: wenn ich eine lokale Variable innerhalb einer Funktion nach außen geben möchte dann kommt sie in die

void XY (hier rein) ?

Richtig?

Funktionen in C/C++ kennen verschiedene Arten der Parameterübergabe: - Call by value - Call by reference

Die per Deklaration "by value" übergebenen Parameter sind in der Funktion wie neu deklarierte lokale Variablen zu betrachten, Änderungen an den Parametern haben keinerlei Auswirkungen auf das aufrufende Programm.

Die per Deklaration "by reference" übergebenen Parameter sind quasi die originalen Parameter des aufrufenden Programms. Jede in der Funktion durchgeführte Änderung an den Variablen bleibt auch bei der Variablen im Aufrufenden Programm genau so, wie sie die Funktion durchgeführt hat.

In C++ achte auf den Adressoperator '&' bei der Variablendeklaration, genau das macht den Unterschied, ob die Funktion einen "by value" Parameter oder einen "by reference" übergeben bekommt!

Hallo,

am Besten immer mit Beispiel.

int Variable-Ausgabe Funktionsname (int Variable-Übergabe) { Befehle ... mit Variable-Übergabe ... return Variable-Ausgabe; }

Daran sieht man, dass man einer Funktion viele Variablen übergeben kann, aber nur eine wieder ausgeben kann. Möchte man mehrere Variablen wieder mit ausgeben, muß man entweder globale Variablen verwenden oder mit Zeigern arbeiten.

Oder suche mal nach "C funktionen definieren".

Hallo Leute, hab mich heute mal durch das angesprochene “Funktionen definieren” durchgelesen…

Muss ganz ehrlich sagen für Neulinge ist sowas echt schwierig zu lesen…

Also mal soweit ich das verstanden habe:

int thisTime ist lokal in der Funktion und nur in der Funktion(deswegen lokal).
thisTime wird aus time.bHour und time.bMinute errechnet(mit formel *100+ fürs format).
time.bHour und time.bMinute werden von außen durch das schreiben von sTime time in der Funktionsklammer rein geholt!?

Soweit richtig?

Also so?

#define EIN HIGH
#define AUS LOW

struct schaltRelais_t{
  byte pin;
  int ein;
  int aus;
};

// Hier die Relais-Pins definieren mit Ein- und Ausschaltzeiten
schaltRelais_t schaltRelais[3]={
  {10, 800, 1930},  // pin, Einschaltzeit, Ausschaltzeit
  {10, 805, 1935},
  {10, 810, 1940},
};



void relaisSchaltenNachZeit(sTime time)   
// Schaltet die Zeitschaltuhr ein und aus und setzt den Ausgang entsprechend
{
  boolean state;
  // Aus der aktuellen Zeit eine Schaltzeit bilden
  int thisTime= time.bHour*100+time.bMinute;
  // Alle Schaltzeiten durchgehen, falls eine davon EIN sagt, einschalten
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    state=AUS;  // Amnahme: Es sei nichts geschaltet
    if (schaltRelais[i].ein < schaltRelais[i].aus)
    { // normale Schaltzeit von bis
      if (thisTime>=schaltRelais[i].ein && thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else if (schaltRelais[i].ein > schaltRelais[i].aus)
    { // Schaltzeit über Mitternacht hinweg wenn die Einschaltzeit größer als die Ausschaltzeit ist
      if (thisTime>=schaltRelais[i].ein || thisTime<schaltRelais[i].aus)
        state=EIN;
    }
    else ; // gleiche Ein- und Ausschaltzeit ignorieren
    if (digitalRead(schaltRelais[i].pin)!=state) // Falls geschaltet werden soll
    { // ein paar Debug-Ausgaben machen
      Serial.print("Relais ");
      Serial.print(i+1);  // Relais-Index zählt ab 0, einfach 1 dazuzählen
      Serial.print(": ");
      if (state==EIN) Serial.println("EIN"); else Serial.println("AUS");
    }
    digitalWrite(schaltRelais[i].pin, state); // Schaltzustand setzen
  }
}

Hallo Jurs, kannst mir mal Überbrückungshilfe für die Schaltzeiten geben...komme gar nicht mehr weiter :roll_eyes:

MfG Chris

Hallo,

@ Post 74, richtig erkannt.

Als Online Buch, lege ich Dir das mal nahe, auch wenn man am Anfang nicht alles gleich versteht, mit der Zeit wächst man rein und das Forum zum fragen gibts auch noch.

http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/index.htm

Loschder:
Hallo Jurs, kannst mir mal Überbrückungshilfe für die Schaltzeiten geben…komme gar nicht mehr weiter :smiley-

Also Du brauchst zu dem in Reply #45 geposteten Beispielprogramm zur RTC mit Sommer-/Winterzeitumschaltung noch ein erweitertes Beispiel als “Zeitschaltuhr mit Schaltzeiten”?

Was für eine Zeitschaltuhr soll es denn werden:

  • normale Tageszeitschaltuhr mit mehreren Schaltzeiten an einem einzigen Ausgang?
  • Multiausgang-Tageszeitschaltuhr mit je einer Schaltzeit pro Tag an diversen Ausgängen?
  • Tageszeitschaltuhr mit Tagesblöcken Mo-Fr / Mo-Sa / Sa / So für Wochentage?
  • Wochenschaltuhr?
  • Was anderes oder eine Kombination davon?
  • Schaltzeiten fest im Programm kompiliert?
  • Oder auch einstellbare Schaltzeiten mit erweitertem Befehlsinterpreter zum Ändern von Schaltzeiten per seriellem Kommando so wie beim Stellen der Uhrzeit?

Hallo,

@ doc

Da bin ich schon eifrig dran am lesen 8) Aber danke für den Tip

@ jurs

Benötige eine Zeitschaltfunktion die zu definieren Zeiten einen Relaisausgang ein/aus schaltet und das ganze auf die "automatisch umschaltende Uhrzeit MEZ/MESZ".

Einschaltzeiten : 5.00-5.30, 8.30-9.00,12.00-12.30, 15.30-16.00, 19.00-19.30, 22.30-23.00; Keine Schaltzeit über 00.00(tageswechsel).

Zu o.g. Schaltezeiten soll im Anschluss dann auch noch die Auswertung der Humidycontrolle später dazu kommen

So in etwa dann später:

void Lüftersteuerung( jurs Timer, deltaH)
{
if  ((jurs timer = 1) & (deltaH =1))       // deltaH ist Taupunktdifferenz, auf 1.0 definiert
{ serial.Print("Lüfter ein");
   digitalWrite(13, LOW);      // Lüfter-Relais an Output13 
}

else
{
 serial.Print("Lüfter aus");
 digitalWrite(13, HIGH);       //Lüfter-Relais ausschalten
}

Hallo,

ein Bsp. von mir. Ich messe zu unterschiedlichen Uhrzeiten mit verschiedenen Meßintervallen. Dazu habe ich mir folgende Funktion geschrieben. Die geänderten Intervallzeiten werden dann wieder woanders ausgewertet und entsprechend läuft die Messung ab. Die Zeitbereiche kannste Dir ja definieren wie du sie brauchst.

void Messintervall ()
{   // Reihenfolge spät nach früh
    static byte alter_Zeitbereich = 0;
    byte Zeitbereich = 0;  // default
    
    if ( _Stunde == 22 && _Minute <= 30 ) {   // zwischen 22:00 - 22:30 Uhr
      Zeitbereich = 5;   
    } 
    if ( _Stunde == 17 && _Minute <= 30 ) {   // zwischen 17:00 - 17:30 Uhr
      Zeitbereich = 4;   
    }  
    if ( _Stunde == 10 && _Minute <= 30 ) {   // zwischen 10:00 - 10:30 Uhr
      Zeitbereich = 3;   
    }  
    if ( _Stunde ==  4 && _Minute <= 30 ) {   // zwischen 04:00 - 04:30 Uhr
      Zeitbereich = 2;
    }  
    if ( _Stunde ==  1 && _Minute <= 30 ) {   // zwischen 01:00 - 01:30 Uhr
      Zeitbereich = 1;
    }
       
    switch (Zeitbereich)  { 
       case 1 : _Intervallzeit =  1; break;  //  1 _Minute
       case 2 : _Intervallzeit =  3; break;  //  3 _Minuten
       case 3 : _Intervallzeit =  5; break;  //  5 _Minuten
       case 4 : _Intervallzeit =  6; break;  //  6 _Minuten
       case 5 : _Intervallzeit =  8; break;  //  8 _Minuten
      default : _Intervallzeit =  15;        // 15 _Minuten
    }   
   
}