Go Down

Topic: Schaltuhr fehlerhafte Berechnung der Schaltzeit beim Übergang Mitternacht (Read 4738 times) previous topic - next topic

Rudi01

Hallo Beieinander

Bei der Realisierung meines Schaltuhr Projekts hänge ich mal wieder fest.

Das Problem besteht beim Übergang der Einschaltzeit über die Mitternachtsgrenze also von 23:59 auf 0:00
Die Einschaltzeit wird folgendermaßen berechnet:

Feste Ausschaltzeit : hier 6:59
Einschaltdauer ist variabel und wird mittels Inkrementalgeber eingestellt ( zwischen 0 und 8 Stunden)
Einschaltzeit wird aus Ausschalzeit und Schaltdauer berechnet aber natürlich dann rückwärtz

Beispiel Ausschaltzeit:      6:59     6:59
           Schaltdauer:        2:00    1:30
errechnete Einschaltdauer 4:59    5:29

Fehler:
- beim Übergang der errechneten Einschaltzeit von 23:59 auf 0:00 wird nicht 0:00 angezeigt sondern 0:59 und wird dann wider     
                            runtergezählt
- Die Schaltzeitberechnung funktioniert nur wenn ich die Minuten der Ausschaltzeit auf 59 setze ( Das ligt an der berechnung die nicht 
                            richtig funkt wenn die errechnete Einschaltzeit von 0:00 auf 0:-1 geht )

Hier noch der Code:
Code: [Select]
// Schaltuhr für Elektroheizung
//


// noch zu erledigen:  Entprellen des Inkrementalgebers verfeinern
//                     Errechnen des Ladebeginns
//                     Festlegen des Ladeendes
//                     Ladedauer in 10er Schritten erhöhen





// Anschluß DS1302
// DS1302:  RST pin    -> Arduino Digital 10
//          DAT pin   -> Arduino Digital 11
//          CLK pin  -> Arduino Digital 12
//          VCC über eine Diode an +5V da sich die Batterei sonst eventuell entladen kann
// Anschluss Incrementalgeber
// Gemeinsamer Pin auf Masse
// ein Pin auf Digital 2
// ein Pin auf Digital 3

#include <LiquidCrystal.h>
#include <DS1302.h>

int AusgangLadung = 13;
int MinutenLadeende;
int StundenLadeende;
Time t;
int LadeZeitMinuten=00;
int LadeZeitStunden=6; // bei Stromausfall wird mit 6 Stunden gestartet
int encoderPin1 = 2;
int encoderPin2 = 3;
int LadeendeMinuten = 30; // Eingabe nur 59
int LadeendeStunden = 6;
int LadeanfangStunden = 23;
int LadeanfangMinuten;
int LadeanfangTag = 1; //wird nur benötigt für den Übergang Mitternacht

// Den DS1302 initialisieren
DS1302 rtc(10, 11, 12);

// Das LCD initialisieren
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup()
{
digitalWrite(encoderPin1, HIGH); //der Pullupwiderstand wird aktiviert
digitalWrite(encoderPin2, HIGH); //der Pullupwiderstand wird aktiviert

attachInterrupt(0, updateEncoder, FALLING);//Der Interrupt reagiert auf fallende Flanke


rtc.halt(false);  // setzt die Uhr in den run-Modus
rtc.writeProtect(false);  // Hebt den Schreibschutz auf

  // Einstellen auf ein LCD mit 16x4 Zeichen
  lcd.begin(20, 4); //Achtung imme richtige Anzahl der Spalten und Zeilen eingeben

  // hier wird die Zeit gesetzt ( Achtung wenn das Einstellen erfolgt ist dann auskommentieren und nochmals übertragen )
  ////////rtc.setTime(21, 05, 0);
 
 

}
void updateEncoder ()
{                            // Eingabewert auf 8 Stunden begrenzt
if (digitalRead(encoderPin2) & LadeZeitStunden < 8) {LadeZeitMinuten ++;}
else {LadeZeitMinuten--;}
if (LadeZeitMinuten >59)
{ LadeZeitMinuten = 0;
LadeZeitStunden ++;}

if (LadeZeitMinuten < 0)
if (LadeZeitStunden > 0)
{ LadeZeitMinuten = 59 ;
  LadeZeitStunden --;}
else
{ LadeZeitMinuten = 0;}

}


void loop()
{
//Berechnung der Zeit Ladeanfang
LadeanfangStunden = LadeendeStunden - LadeZeitStunden ;
LadeanfangMinuten = LadeendeMinuten - LadeZeitMinuten ;





  // Uhrzeit anzeigen
  lcd.setCursor (0, 0);
  lcd.print("Uhrzeit");
  lcd.setCursor(8, 0);
  lcd.print(rtc.getTimeStr());
 
   lcd.setCursor (0, 1);
  lcd.print ("Ladedauer=");
  lcd.setCursor (12, 1);
lcd.print (LadeZeitStunden);

lcd.setCursor (13, 1);
  lcd.print (":");
  if (LadeZeitMinuten <10) lcd.print("0"); // wenn Minuten einstellig wird eine 0 dafor geschrieben
  lcd.print (LadeZeitMinuten);

 
  // Ladeende anzeigen
  lcd.setCursor (0, 2);
  lcd.print("Ladeende=");
  lcd.setCursor (12, 2);
  lcd.print (LadeendeStunden);
  lcd.print (":");
  lcd.print (LadeendeMinuten); 
 

//ladeanfang in Zeitformat umsetzen
if (LadeanfangMinuten >59)
{ LadeanfangMinuten = 0;  //Bei Ladeanfang von 59 auf 60 Minuten auf 0 setzen
LadeanfangStunden ++;}    //Bei Ladeanfang von 59 auf 60 Minuten Stunden um eins erhöhen

if (LadeanfangStunden >23)
{ LadeanfangStunden = 0;   //Bei Ladeanfang von 23 auf 24 Sunden auf 0 setzen
LadeanfangTag ++;}         //Bei Ladeanfang von 23 auf 24 Tag um eins erhöhen


if (LadeanfangMinuten < 0)
if (LadeanfangStunden > 0)
{ LadeanfangMinuten = 59 ;
  LadeanfangStunden --;}
else
{ LadeanfangStunden = 0;}
if (LadeanfangStunden < 0)
if (LadeanfangTag > 0)
{ LadeanfangStunden = 23 ;
  LadeanfangTag --;}
else
{ LadeanfangStunden = 0;}


  // errechnete Ladeanfang anzeigen
  lcd.setCursor (0, 3);
  lcd.print ("Ladeanfang=");
  lcd.setCursor (12, 3);
  lcd.print (LadeanfangTag);
  lcd.print (":");
  lcd.print (LadeanfangStunden);
   if (LadeanfangStunden <10) lcd.print("0"); // wenn Stunden einstellig wird eine 0 dafor geschrieben
lcd.print (":");
  if (LadeanfangMinuten <10) lcd.print("0"); // wenn Minuten einstellig wird eine 0 dafor geschrieben
lcd.print (LadeanfangMinuten);



  t = rtc.getTime();
 
  delay(10); //just here to slow down the output, and show it will work  even during a delay


}



Eventuell hat ja Jemand eine Idee an was es liegen könnte.

Schonmal Danke im Vorraus Rudi

michael_x

Ist der Ladeanfang fühestens 23:xx  Uhr (kleinere Ladeanfangstunden als -1 kommen nicht vor) ?

Ansonsten ist mir erstmal aufgefallen, bei Ladeanfangstunde < 10 die führende null nach der Stunde geschrieben wird , aber das scheint nicht dein Problem zu sein

kduin

Neben > und < gibts auch noch <= und >=, vielleicht löst das dein Problem?

pylon

Ich würde die Stunden in Minuten umrechnen, dann kannst Du einfach Integer-Arithmetik verwenden:

Code: [Select]
int zeit = stunden * 60 + minuten;
int ladezeit = lstunden * 60 + lminuten;
int anfangszeit = zeit - ladezeit;
uint8_t tage = anfangszeit / 1440;
anfangszeit %= 1440; // macht den Tagesübergang
uint8_t astunden = anfangszeit / 60;
uint8_t aminuten = anfangszeit % 60;

Rudi01

Hallo Zusammen
nach etwas längerer Pause widme ich mich wieder meinem Schaltuhr-Projekt.
Den Vorschlag von pylon möchte ich gerne weitrverfolgen.
Schon taucht mein erstes Problem auf.
- Die Uwandlung der Uhrzeit in ein Variable die ich weiterverarbeiten kann.
  Die Uhrzeit zeige ich mit folgendem Befehl auf dem LCD an [font=Verdana]lcd.print(rtc.getTimeStr());[/font]
  jetzt ist meine Frage : wie wandle ich dieses Format in ein anderes das ich nachher weiterverarbeiten kann (z.B. in Minuten umwandeln)
  Ein Vorschlag aus einem vorgen Tread
                                                                                           wenn du ein array deklarierst:
                                                                                                 int UhrDaten[7];
                                                                                                  dann stehen nach
                                                                                                 RTC.get(UhrDaten,true);
                                                                                                folgende Werte in den Variablen

                                                                                                 UhrDaten[0]) die Sekunden
                                                                                                  UhrDaten[1]) die Minuten;
                                                                                                  UhrDaten[2]) die Stunden;
                                                                                                  UhrDaten[3] der Tag der Woche;
                                                                                                  UhrDaten[4]) der Tag;
                                                                                                  UhrDaten[5]) der Monat;
                                                                                                  UhrDaten[6]) das Jahr;
   führt leider zur Fehlermeldung: In function 'void setup()':
                                              'class DS1302' has no member named 'get'

ich vermute mal dass meine Libary den Befehl get nicht kennt?

Könnte mir hier mal jemand weiterhelfen.

Vielen dank Rudi


uwefed

Hat die Bibliothek keine Beispiele mitgeliefert?
Sieh Dir die mal an.
Ansonsten gib uns bitte den link wo Du die Bibliothek heruntergeladen hast.
Grüße Uwe

Rudi01

Hallo Uwe

danke für die Antwort.
Ich habe die Libary von hier: [font=Verdana] http://www.henningkarlsen.com/electronics/library.php?id=5[/font]


pylon

Nimm die Methode getTime():

Code: [Select]
Time t = rtc.getTime();

Dann kannst Du die Zeit-Variable aus meinem Pseudo-Code einfach berechnen:

Code: [Select]
int zeit = t.hour * 60 + t.min;

adgrex

Ich habe mir dazu diese Funktion erstellt.
Die Arbeitet mit der Time.h zusammen.

Siehe:
http://www.pjrc.com/teensy/td_libs_TimeAlarms.html

Und mein Beispiel...
Gerade geschrieben, scheint aber zu funktionieren...

Code: [Select]
#include <Time.h>

unsigned int starthour=7;
unsigned int startminute=15;
unsigned int endhour=23;
unsigned int endminute=10;


void setup()
{
  Serial.begin(9600);
  setTime(23,9,30,1,1,11); // set time

}

void  loop(){ 
  digitalClockDisplay();
 
  Serial.println(inTIME(&starthour,&startminute,&endhour,&endminute));
 
  delay(1000); // wait one second between clock display
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}


// inTIME

boolean inTIME(unsigned int *starthour, unsigned int *startminute, unsigned int *endhour, unsigned int *endminute){
  unsigned long nowtimesecond = (unsigned long)hour() * 3600 +  (unsigned long)minute() * 60 + (unsigned long)second();
  unsigned long starttimesecond = (unsigned long)*starthour * 3600 + (unsigned long)*startminute * 60;
  unsigned long endtimesecond = (unsigned long)*endhour * 3600 + (unsigned long)*endminute * 60;

  if(starttimesecond < endtimesecond){  // bsp. 6-13 Uhr
    if(starttimesecond < nowtimesecond && nowtimesecond < endtimesecond) return true; // startzeit < aktuelle zeit < endzeit
  }
  else if(starttimesecond > endtimesecond){ // bsp. 22-6 Uhr
    if(starttimesecond < nowtimesecond) return true; // bsp. startzeit 22 Uhr und aktuell ist 23 Uhr
    else if(nowtimesecond < endtimesecond) return true; // bsp. startzeit 22 Uhr und aktuell ist 2 Uhr
  }
// alles andere ist false 
return false;
}

// ENDE inTIME


Go Up