Forum: Compiler & IDEs Zeitvergleich zweier "Uhrzeiten"


von Andy M. (medix)


Lesenswert?

Hi,

hab folgendes Problem (in C):
Mir liegt aus dem AVR-Script folgender Code-Schnipsel vor:

unsigned int var_array[MAX_VAR_ARRAY] = {12,30,19,15}
unsigned char hh;

unsigned char mm;

unsigned char ss;
..
}// Uhrzeit bestimmen

hh = (time/3600)%24;

mm = (time/60)%60;

ss = time%60;
..

var_array[0]  // Beginn Stunde
var_array[1]  // Beginn Minute
var_array[2]  // Ende Stunde
var_array[3]  // Ende Minute

Bisher war dann eben die if:

if ( hh == var_array[0] && mm == var_array[1]) {

// WEITERE BEDINGUNGEN
// EIN

} else {

 // AUS
}
if ( hh == var_array[2] && mm == var_array[3]) {
 // AUS
}


Die Schleifen werden alle 30 Sekunden gecheckt. Wenn nun mal 
Stromausfall war bzw. die "WEITEREN BEDINGUNGEN" sich innerhalb der 
Schaltzeit geändert haben, finden die so keine Berücksichtigung mehr. 
Ein einfaches:

if ( hh >= var_array[0] && hh <= var_array[2] ) {
...
}

reicht natürlich nicht, da die Zeitspanne von 19:00 Uhr bis 6:00 Uhr so 
nicht erfasst werden kann.


Nun hatte ich folgende Überlegung, die irgendwie Assi ist:

Ist var_array[2] < var_array[0] { var_array[2] += 24; }
Ist var_array[0] <= var_array[2] { ... dann müsste ich nur noch 
nachschauen, ob var_array[3] kleinergleich ist als mm.


Geht das nicht irgendwie einfacher bzw. sinnvoller? Hab eben nur die 
Uhrzeit. mit mktime() in php zB. war das so schön easy.

von Peter (Gast)


Lesenswert?

und wie hat dir mktime bei dem problem weiter geholfen?

aus mktime kommt doch auch bloss eine Zahl, diese hast du doch auf mit 
variable time.

von Andy M. (medix)


Lesenswert?

Fall 1:

$beginn = mktime(12,30,0,1,1,2000); // 12:30 Uhr
$ende   = mktime(19,15,0,1,1,2000); // 19:15 Uhr

if ($beginn <= $ende) { }


Fall 2 (über Mitternacht rüber):

$beginn = mktime(18,0,0,1,1,2000); // 18:00 Uhr
$ende   = mktime(6,0,0,1,2,2000);  // 6:00 Uhr

if ($beginn <= $ende) { }



So

von Rolf Magnus (Gast)


Lesenswert?

Der Grund liegt aber darin, daß das Datum da enthalten ist. Damit ergibt 
sich dein Problem ja gar nicht.

von Andy M. (medix)


Lesenswert?

Ja, nur habe ich bei meinem Code kein Datum dabei sondern nur die beiden 
Uhrezeiten ANFANG und ENDE sowie die JETZT-Zeit.

Jemand eine Idee dazu?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Na, rufe mktime mit dem Datum von heute und den gewünschten End- und 
Anfangszeiten auf.

von Andy M. (medix)


Lesenswert?

Dazu fehlt mir die lib.

Habs nun mit einer if-Anweisung gelöst, die +24 auf die Variable rauf 
schlägt, wenns über Mitternacht geht.

von Andy M. (medix)


Lesenswert?

Hier mal der Ansatz für diejenigen, die auch nur die Uhrzeit aber kein 
Datum dazu haben. Wenn einer eine bessere Idee hat, immer her damit! 
Danke an RoBue für die viele Arbeit, auf die ich zurück greifen konnte!

Sinn der Übung ist wie bereits geschrieben, Code zu haben, der auch nach 
Stromausfall oder Werteänderung funktioniert. Diese Funktion ist bei 
RoBue "nur" als minutengenauer Vergleich enthalten. Mit unten 
aufgeführtem Code kann ich nun Tagestemperaturen variabel zeitabhängig 
schalten.



// Uhrzeit bestimmen

  hh = (time/3600)%24;

  mm = (time/60)%60;

  ss = time%60;

// Wenn es zwischen 0:00 Uhr und 1:00 Uhr ist, muss hh 24 werden
if ( hh == 00 ) { hh = 24; }


// PORTC0:

// Temperatur: var_array[10]
TWert = var_array[10]*10;

// Über Temperatur und Sensor für Fenster: var_array[10] - Sensor0 - 
PORTA0


// Wenn der Zeitraum über Mitternacht geht, addiere zur Endzeit 24
// So wird zB. aus 3:00 Uhr 27:00 Uhr und ist damit mathematisch 
vergleichbar
if ( var_array[20] < var_array[18] ) { var_array[20] += 24; }

if ( hh >= var_array[18] && hh <= var_array[20] ) {

 if ((hh < var_array[20]) || (hh == var_array[20] && mm < 
var_array[21])) {

  if ((PINA&0b00000001) == 0 ) {  // PORTA0: Fenster geschlossen?

    if ( ow_array[0] < TWert ) {

      PORTC |= (1 << PC0); // ein

    } else {

      PORTC &= ~(1 << PC0); // aus

    }

    } else {

      PORTC &= ~(1 << PC0); // aus

    }

  } else { // Minuten- Check

  PORTC &= ~(1 << PC0); // aus

  }

 }  else { // Stunden - Check

     PORTC &= ~(1 << PC0); // aus

 }

// Zurücksetzen der Stunde der Endzeit
if ( var_array[20] >= 24 ) { var_array[20] -= 24; }


Andy

von Andy M. (medix)


Angehängte Dateien:

Lesenswert?

Ach und zum testen:

http://medixx.homeip.net

Fenster 6 und 7 sind permanent offen :) Kontakte nicht gebrückt. 
Sensoren sind nur 1, 2 und 3 angeschlossen. Die anderen kommen erst 
diese Woche.

Port C7 ist eine reine Schaltzeituhr.

Aufbau ist wie auf dem Bild :)

von Karl H. (kbuchegg)


Lesenswert?

Ich hab das Problem ehrlich gesagt immer noch nicht verstanden.
2 Zeitpunkte (ohne Datum) lassen sich grundsätzlich so nicht 
vergleichen.
Da kannst nur feststellen ob ein bestimmter Zeitpunkt in einem 
Zeitintervall liegt.
Dazu brauchst du eine Konvention, nämlich dass der 2. Zeitpunkt des 
Intervalls grundsätzlich immer später als der 1. Zeitpunkt des 
Intervalls ist, auch wenn er numerisch zunächst kleiner ist. Beim 
Intervall 23:00 - 6:00 ist 6:00 später als 23:00, obwohl die Stundenzahl 
kleiner ist.

Dazu ist es hilfreich sich erst mal alle Zeitpunkte in Anzahl der 
Minuten seit Mitternacht umzuwandeln.
Jetzt muss man nur noch berücksichtigen, ob das Intervall über 
Mitternacht läuft oder nicht.

Hat man kein zusätzliches Mitternacht zu berücksichtigen, ist die Sache 
einfach. Der zu untersuchende Zeitpunkt muss größer als Intervall-Start 
und kleiner als Intervall-Ende sein.

Hat man im Intervall Mitternacht mit drinnen, dann liegt der gesuchte 
Zeitpunkt im Intervall, wenn sein Minutenwert kleiner als der originale 
Intervall-Ende oder größer als Intervall-Start ist.
1
  test  = stunden_test * 60 + minuten_test   // zu testender Zeitpunkt
2
3
  start = stunden1 * 60 + minuten1           // Startzeit des Intervalls
4
  ende  = stunden2 * 60 + minuten2           // Endzeit des Intervalls
5
6
  if( ende < start )
7
    inside = ( ( test < ende ) || ( test > start ) )
8
  else
9
    inside = ( ( test > start ) && ( test < ende ) )
10
11
  return inside

Warnung: ungetesteter Code

von Andy M. (medix)


Lesenswert?

Kann mir bitte jemand sagen, welchen Wert "inside" hier annehmen kann?

mein Code:

hh = (time/3600)%24;

mm = (time/60)%60;


jetzt  = hh * 60 + mm;

start = var_array[18] * 60 + var_array[19];

ende  = var_array[20] * 60 + var_array[21];
if ( ende < start )

  inside = ( ( jetzt < ende ) || ( jetzt >= start ) );

else

  inside = ( ( jetzt >= start ) && ( jetzt < ende ) );

if(inside) {
....
} else {
...
}

Wenn ich ein:

return inside;

am Ende einfüge, hängt sich das Script auf.

Bin noch totaler Anfänger in C. Pascal ist auch schon etwas her...

Liegt es daran, dass das script zu bestimmten Zeitpunkten KEINEN Wert 
zurück gibt:

Startzeit: 5:00 Uhr
Ende 18:00 Uhr
 JETZT: 21:42 Uhr

von Peter D. (peda)


Lesenswert?

Was spricht denn gegen die Brute Force Methode?

Einfach nach dem Stromausfall 24h abziehen und dann alle 1440min bis zur 
aktuellen Zeit vergleichen.
Selbst bei 100 Schaltzeiten ist das in weit unter 1s erledigt.
1
  if( stromausfall ){
2
    uint16t i;
3
    for( i = 1440; i; i-- )
4
      vergleich( time_min - i );
5
  }


Peter

von Andy M. (medix)


Lesenswert?

Hab meinen Fehler gefunden.

unsigned char jetzt;



unsigned char start;

unsigned char ende;

unsigned char inside;

nun ist es so:

unsigned int jetzt;



unsigned int start;

unsigned int ende;

unsigned char inside;

und funzt. Muss jedoch lesen, obs da nicht einen besseren Typen als int 
gibt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.