mikrocontroller.net

Forum: Compiler & IDEs Zeitvergleich zweier "Uhrzeiten"


Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

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

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

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

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andy M. (medix)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

  test  = stunden_test * 60 + minuten_test   // zu testender Zeitpunkt

  start = stunden1 * 60 + minuten1           // Startzeit des Intervalls
  ende  = stunden2 * 60 + minuten2           // Endzeit des Intervalls

  if( ende < start )
    inside = ( ( test < ende ) || ( test > start ) )
  else
    inside = ( ( test > start ) && ( test < ende ) )

  return inside

Warnung: ungetesteter Code

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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.

  if( stromausfall ){
    uint16t i;
    for( i = 1440; i; i-- )
      vergleich( time_min - i );
  }


Peter

Autor: Andy M. (medix)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.