Zeitsteuerung

Hi Leute,
ich sitze schon seit einigen tagen über der Aufgabe und komme einfach nicht weiter.
Ich möchte mit dem Arduino uno und der RTC DS1307 eine Zeitsteuerung programmieren die nach Datum und Zeit sich Automatisch einschaltet. Sie soll zusätzlich noch eine Möglichkeit der manuellen Eingabe haben mit der man auch wenn das Datum und die Zeit nicht erreicht ist das Relais das auf dem Digitalen Port 11 angeschlossen ist umschalten. Die Automatische Umschaltung soll im Oktober,November und Dezember 3 mal Täglich stattfinden.

Ich hoffe ihr könnt mir bei meinem Problem helfen

Mit Freundlichen Grüßen
Johannes

Es können hier sicher viele helfen.
Nur dazu müssen wir deinen bisherigen Code sehen.
Poste diesen bitte in Code-Tags hier im Thread.

So hier ist mein bisheriger Code:

#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <DS1307RTC.h>


const char *monthName[12] = {
 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

tmElements_t tm;

void setup() {
 bool parse=false;
 bool config=false;


   


 Serial.begin(9600);
 while (!Serial) ; // wait for Arduino Serial Monitor
 delay(200);
 if (parse && config) 
 
 
   Serial.print("DS1307 configured Time=");
   Serial.print(__TIME__);
   Serial.print(", Date=");
   Serial.println(__DATE__);
   if else(parse); {                                  (Hier wird momentan noch der Fehler exit status expected '(' before 'else' angezeigt)
   Serial.println("DS1307 Communication Error :-{");
   Serial.println("Please check your circuitry");
  else {
   Serial.print("Could not parse info from the compiler, Time=\"");
   Serial.print(__TIME__);
   Serial.print("\", Date=\"");
   Serial.print(__DATE__);
   Serial.println("\"");
 }
}
RTC_DS1307 rtc;
void setup() {


 Wire.begin();

 rtc.begin();

 //check to see if rtc is running
 if (! rtc.isrunning()){
   Serial.println("RTC is NOT running");
  
 }

//set pin 11 as output for the Relay
pinMode(11, OUTPUT);

}
void loop() {
 bool getTime(const char *str)
{
 int Hour, Min, Sec;

 if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
 tm.Hour = Hour;
 tm.Minute = Min;
 tm.Second = Sec;
 return true;
}

bool getDate(const char *str)
{
 char Month[12];
 int Day, Year;
 uint8_t monthIndex;

 if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
 for (monthIndex = 0; monthIndex < 12; monthIndex++) {
   if (strcmp(Month, monthName[monthIndex]) == 0) break;
 }
 if (monthIndex >= 12) return false;
 tm.Day = Day;
 tm.Month = monthIndex + 1;
 tm.Year = CalendarYrToTm(Year);
 return true;
}
 //Get the date and time
   DateTime now = rtc.now();

   //Print out the date and time to the serial time
   Serial.print(now.year(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.day(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(),DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.println();


   Serial.println();
   delay(500);

   //check to see if it is time to switch the relay 
   if (now.month() == 10,11,12)
   if /now.hour() == 8,12,17)
   if (now.minute() == 00)
   
   {
     digitalWrite(11,HIGH);
    }
   else if (now.hour() == 9,13,18)
   {
     digitalWrite(11,LOW);
   }
   
   Serial.println();
   delay(500);
    }

Hallo und willkommen im Forum!
DS3231 ist genauer, das könnte bei den langen Zeitintervallen möglicherweise relevant sein.

Quelle für Inspirationen ohne Bibliothek.

Wenn Du jetzt noch den Button </> nutzen würdest ... :slight_smile: Sieht dann so aus:Dein Sketch
Du kannst Deinen Beitrag auch verändern.

Dank für den Tipp :slight_smile:
Mir reicht momentan noch die Genauigkeit vom Ds1307

Es gibt TimeAlarms als Addon für Time:
https://www.pjrc.com/teensy/td_libs_TimeAlarms.html

Da könnte man mit AlarmRepeat() 3 Alarme auslösen und in der Funktion noch auf den Monat abfragen

Solche Parser kann man übrigens auch schön mit strtok() + atoi() schreiben. Für die Zeit braucht man weder scanf() noch strtok() da die Positionen bekannt sind. Man kann also einfach das machen:

byte hour = atoi(str);
byte minute = atoi(str + 3);
byte second = atoi(str + 6);

Das nutzt aus das atoi() abbricht wenn es auf ein Zeichen trifft das keine Ziffer ist

Dein Code enthält viele delays, die halten den Atmega an. Die musst du unbedingt durch millis (BlinkWithoutDelay) ersetzen.
Dann hast du einen Fehler in der Codezeile: "if (now.hour()", da muss eine Klammer rein.
Da sollte eigentlich eine Fehlermeldung beim kompilieren kommen.

Ja, TimeAlarm ist eine tolle Library. Nutze ich auch.
Kannst sie hier laden.

Mit dem angegebenen Beispiel lässt sich auch schön spielen & testen.

Das ist Test-Code um zu sehen ob der Parser geht! Der ganze Serial Kram kann sowieso raus wenn es funktioniert.

Eine Sache die fehlt ist in setup() setSyncProvider() zu setzen um die Time Library mit der RTC zu synchronisieren. Da muss man eine Funktion angeben die einen time_t (Sekunden seit 1970) zurück gibt. Wenn man das nicht macht läuft Time immer nur über den Takt des µC.

Übrigens:

if (now.minute() == 00)

Vorsicht mit führenden Nullen! Das ist Oktal. Bei 00 ist das egal. Aber bei anderen Zahlen fällt man da schnell rein.

Hanzzz98:
ist umschalten. Die Automatische Umschaltung soll im Oktober,November und Dezember 3 mal Täglich stattfinden.

Also an einem Tag: EIN - AUS - EIN
Und am nächsten Tag: AUS - EIN - AUS (zu denselben Umschaltzeiten wie am Vortag)
Und dann wieder von vorne?

Am einfachsten wäre es, die Zeitsteuerung dann je nach Monat mit unterschiedlicher Logik laufen zu lassen:
Januar bis September ==> manueller Betrieb per Schalter
Oktober bis Dezember ==> automatischer Betrieb per Zeitsteuerung

Oder sollen auch von Oktober bis Dezember zusätzliche manuelle Umschaltungen zu beliebigen Zeitpunkten per Schalter möglich sein?

Also am besten jeden Monat Manuell und von Oktober bis Dezember zusätzlich um 8Uhr an um 9Uhr aus um 12 wieder an um 13 Uhr aus und um 17 Uhr nochmal an und um 18 Uhr wieder aus.

Hanzzz98:
Also am besten jeden Monat Manuell und von Oktober bis Dezember zusätzlich um 8Uhr an um 9Uhr aus um 12 wieder an um 13 Uhr aus und um 17 Uhr nochmal an und um 18 Uhr wieder aus.

Also die Automatikschaltungen soll nicht 3x am Tag umschalten, sondern 3x EIN und 3x AUS am Tag.

Wobei die Ausschaltzeit immer eine Stunde nach der Einschaltzeit liegt.

Und wie sieht es mit den manuellen Schaltungen genau aus:

Möchtest Du nur manuell einschalten, und nach einer Stunde wird auch automatisch wieder ausgeschaltet?

Oder eher so: Wenn manuell eingeschaltet wurde, muss auch manuell wieder ausgeschaltet werden?

Übrigens: Bei den im Handel verfügbaren "RTC Tiny" Modulen mit DS1307 kann die Gangabweichung bei 1 Minute pro Woche liegen, dann schaltest Du nach 50 Wochen um 50 Minuten falsch, wenn Du die Zeit nicht nachstellst? Dir ist schon klar, dass die Gangabweichung eines DS3231 Moduls demgegenüber nur 64 Sekunden pro Jahr beträgt?

Möchtest Du nur manuell einschalten, und nach einer Stunde wird auch automatisch wieder ausgeschaltet?

Und was ist, wenn du um 16:50 manuell einschaltest mit der Periode von 17-18 Uhr?
Und kannst du auch manuell ausschalten, während der 3 Einschalt-Phasen ?

Und was ist, wenn du die Millisekunde 17:00:00.000 zum Einschalten verpasst hast ?

Und was ist mit der Sommer/Winter-Umschaltung ?

Wenn das Ding nur 3 Monate im Winter laufen soll und es auf ein paar Minuten Abweichung nicht ankommt, ist ein DS1307 schon möglich, finde ich. Schade dass die Module heutzutage zum Entsorgen schlechter Quarze dienen.

Bessere Quarze kosten ein paar Cent mehr, aber viele verstehen offenbar den Unterschied nicht und greifen zum billigsten Chinesen. Somit mangels Nachfrage vom Markt genommen :frowning:

Somit mangels Nachfrage vom Markt genommen

Ja, aber: Nur weil ein Modul 10 ct mehr kostet, heisst das leider nicht, dass darauf ein guter Quarz verbaut ist, der 5 ct mehr kostet.
Das typische Lemon Problem

Führt dazu, dass die Chinesen sich inzwischen bei den DS3231 gegenseitig unterbieten.
(0,99 USD incl. LIR2032) :wink:

jurs:
Möchtest Du nur manuell einschalten, und nach einer Stunde wird auch automatisch wieder ausgeschaltet?

Oder eher so: Wenn manuell eingeschaltet wurde, muss auch manuell wieder ausgeschaltet werden?

Am besten wäre es wenn man dann auch manuell Wieder ausschalten kann.

Hanzzz98:
Am besten wäre es wenn man dann auch manuell Wieder ausschalten kann.

Inzwischen wird es etwas klarer.

Jetzt habe ich mir mal den von Dir dazu geposteten Code angeschaut.

Da bin ich ja fast vom Glauben abgefallen: Was hast Du denn da gemacht?

Zwei der von Dir inkludierten Libraries, scheinen für die Ansteuerung der RTC-Hardware zu sein, oder vielleicht nicht?
Ich meine diese beiden:

#include "RTClib.h"
#include <DS1307RTC.h>

Wie sollen die denn zusammenarbeiten?

Außerdem hast Du im Code zwei verschiedene setup() Funktionen.
a) Warum?
b) Woher kommt das zweite setup()?
c) Wie soll das funktionieren?

Kann es angehen, dass Du Dir über eine praktikable Programmstuktur noch gar keine Gedanken gemacht und bisher im wesentlichen nur fremden Code zusammenkopiert hast, und "Prinzip Hoffnung" hat als Programmierprinzip nicht so ganz funktioniert?

Da ich mit dem von Dir geposteten Code wahrscheinlich genau so schlecht klarkomme wie die Arduino-IDE, habe ich noch einige Zusatzfragen:

  1. Wie soll die Uhrzeit einstellbar sein?
    Soll die Uhrzeit nur einstellbar sein, indem Du einen speziellen "Stelle-mir-die-Uhrzeit" Sketch hochlädst?
    Oder soll die Uhrzeit vielleicht über eine Zeiteingabe im "Seriellen Monitor" einstellbar sein?

  2. Soll Deine Zeitschaltuhr vielleicht noch mit weiterer Hardware ausgestattet werden, außer RTC-Modul, Relay und Button-Schalter? Zum Beispiel mit einem LCD-Display?

jurs:
Außerdem hast Du im Code zwei verschiedene setup() Funktionen.
a) Warum?
b) Woher kommt das zweite setup()?
c) Wie soll das funktionieren?

  1. Wie soll die Uhrzeit einstellbar sein?
    Soll die Uhrzeit nur einstellbar sein, indem Du einen speziellen "Stelle-mir-die-Uhrzeit" Sketch hochlädst?
    Oder soll die Uhrzeit vielleicht über eine Zeiteingabe im "Seriellen Monitor" einstellbar sein?

  2. Soll Deine Zeitschaltuhr vielleicht noch mit weiterer Hardware ausgestattet werden, außer RTC-Modul, Relay und Button-Schalter? Zum Beispiel mit einem LCD-Display?

a) Ich hab keine Ahnung
b) Ich denke vom kopieren aus dem beispiel
c) Ich glaub gar nicht

Zu 1.
Es wäre natürlich richtig super wenn man die Zeit über den seriellen Monitor stellen kann.

Zu 2.
Weitere Hardware ist nicht vorgesehen das möchte ich wenn es geht über den Seriellen Monitor regel.

#include "Wire.h"                                         
#include "RTClib.h" 
RTC_DS1307 rtc;                                                                      
RTC_DS1307 RTC;
DateTime now;                          


//--------------------------------------------- / Relais / 


int RelaisOn1 = 8;                      //Einschaltzeit des Relais (HH)
int RelaisOff1 = 9;                     //Ausschaltzeit des Relais (HH)

int RelaisOn2 = 12;                      //Einschaltzeit des Relais (HH)
int RelaisOff2 = 13;                     //Ausschaltzeit des Relais (HH)
                      
int RelaisOn3 = 17;                      //Einschaltzeit des Relais (HH)
int RelaisOff3 = 18;                     //Ausschaltzeit des Relais (HH)
               



void setup()
{
  Serial.begin(57600);                                   
  rtc.begin();                        
   Wire.begin();
  
    if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  
  
  pinMode(11, OUTPUT);                 //Legt Pin 11 als Ausgang fest (Relais)
    }           
}

void loop()  
{
           
 now = rtc.now();                    
  int st = now.hour();                
  int mi = now.minute();              
                
  
 if (digitalRead(11) == HIGH)       //Status des Relais
    Serial.print("Ein");               
  else
    Serial.print("Aus");

  
//---------------------------------------------Steuerung das Relais
    
   
  if(now.hour() >=RelaisOn1 && now.hour() <RelaisOff1)//Relais einschalten wen die momentane Stundenzeit gleich oder 
  if(now.hour() >=RelaisOn2 && now.hour() <RelaisOff2)
  if(now.hour() >=RelaisOn3 && now.hour() <RelaisOff3)
   {                                                //über der Einschaltzeit und unter der Ausschaltzeit ist.
     digitalWrite(11, HIGH);
   }
   else
   {
     digitalWrite(11, LOW);
   }
        

delay(5);


DateTime now = RTC.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
  
    delay(500);
}

Ich habe inzwischen meinen Code Überarbeitet und er lässt sich hochladen gibt dann auch die Uhrzeit, dass Datum und den Zustand des Relais an schaltet es aber nicht um.

Könnt ihr mir sagen warum?
und wie ich es hin bekomme das der Arduino die Taster erkennt und dann manuell das Relais umschaltet und dann auch wieder ausschaltet?`
lg Johannes

  1. etwas mehr die Interpunktionsregeln beachten
  2. Basics lernen

Wieso einmal ein RTC und ein anderes rtc Objekt?