Forum: Mikrocontroller und Digitale Elektronik Uhrzeit vergleichen


von Karlo (Gast)


Lesenswert?

Hallo,

ich hab hier bei einem kleinen Testprojekt (Mikrocontroller in C 
programmiert) gerade eine Blockade.

Meine Software kennt die aktuelle Uhrzeit. Außerdem ist bekannt wann das 
Gerät aktiv und wann inaktiv sein soll.
Das Gerät schaltet sich einmal am Tag an und einmal aus.

Jetzt muss ich herausfinden, ob ich mich gerade im Zustand "AN" oder 
"AUS" befinde.

Mein erster Ansatz war eine Ansammlung an verschachtelten If-Abfragen. 
Das hat auch soweit funktioniert, sah aber sehr wüst und unverständlich 
aus.

Imho ist das ja eher ein mathematisches Problem. Es muss doch eine 
kurze, elegante Lösung dafür geben.
Ich habe noch eine weitere Bekannte, nämlich die "Endzeit", nämlich 
23:59. Danach springt meine Zeit wieder auf 00:00.
Wie ich diese Info mit in eine Formel einbaue weiß ich aber auch nicht.

Kann mir jemand einen Denkanstoß geben?

MFG,
Karlo

von Peter II (Gast)


Lesenswert?

In selcher Form hast du denn die Uhrzeit?

von Berd Seifert (Gast)


Lesenswert?

Such mal nach "UNIX Zeit".

von dev (Gast)


Lesenswert?

Kannst Du Daten irgendwie persistent speichern?

Dann würde ich eine Statusvariable (boolean) einführen. z.B. 
"is_running"
Sobald AN stattfindet stellst Du die auf true. Bei AUS auf false.

Dann kannst Du problemlos jederzeit mit:

if (is_running) {...} else {...}

Abfragen, ob's grade läuft...

von 6A66 (Gast)


Lesenswert?

Karlo schrieb:
> Jetzt muss ich herausfinden, ob ich mich gerade im Zustand "AN" oder
> "AUS" befinde.

Wenn ich richtig verstehe willst Du anhand der Istzeit und der EIN-Zeit 
udn AUS-Zeit wissen, ob Du einen Ausgang ein- oder Ausschalten sollst.
Denn für den Controller herauszufinden ob er selbst eingeschaltet ist 
oder ausgeschaltet ist ... :)

Karlo schrieb:
> Imho ist das ja eher ein mathematisches Problem. Es muss doch eine
> kurze, elegante Lösung dafür geben.

Was hälst Du davon, die Zeiten in eine "Sekundenzeit" (oder Minutenzeit) 
umzurechnen, die schön linear ist. 12:00:00 wäre dann 12*3600 = 43200. 
Brauchst Du dann 32bit dafür. Die Minuten gingen in 16 bit hinein.

rgds

von dev (Gast)


Lesenswert?

Achja, da du ja weist, wann es AN oder AUS sein sollte kannst Du auch 
ohne Persistenz diese Hilfevariable setzen:

if (current_time => start_time && current_time <= end_time) {
    is_running = true;
} else {
    is_running = false;
}

Das ganze geht, wenn du einen UNIX-Timestamp als int in current_time, 
start_time und end_time stehen hast.

Ab dann immer if (is_running) abfragen...

von Karl H. (kbuchegg)


Lesenswert?

Karlo schrieb:

> Imho ist das ja eher ein mathematisches Problem. Es muss doch eine
> kurze, elegante Lösung dafür geben.
> Ich habe noch eine weitere Bekannte, nämlich die "Endzeit", nämlich
> 23:59. Danach springt meine Zeit wieder auf 00:00.

Gibt es auch.
Wieviele Minuten sind seit Mitternacht vergangen?

  MinSinceMidnight = 60 * Stunde + Minuten;

dsselbe für die Einschaltzeit und die Ausschaltzeit und schon hast du 
eine schöne lineare Zahl, die während des Tages von 0 bis 1339 anwächst 
und mit der du wunderbar gegen 2 Grenzwerte vergleichen kannst (aben die 
Einschalt bzw. Ausschaltzeit) vergleich kanns, ob die aktuelle Zeit 
zwischen diesen beiden liegt oder nicht. Liegt sie dazwischen, dann 
'Gerät ein'. Liegt sie nicht dazwischen dann 'Gerät aus'.

Wenn du nicht auf gemeinsame Minuten gehen willst, dann geht es fast 
genau so einfach. Du musst dir nur darüber im klaren sein, wann genau 
denn eine Zeit vor einer anderen liegt. Wenn die Stunden von A schon mal 
kleiner sind als die Stunden von B, dann liegt A vor B. Sind die beiden 
gleich, dann entscheiden die Minuten wer vorne liegt.
1
   if( actHour < onHour || ( actHour == onHour && actMin < onMin ) )
2
     TurnOff;
3
   else if( actHour > offHour || ( actHour == offHour && actMin > offMin ) )
4
     TurnOff;
5
   else
6
     TurnOn;

Die Phase rund um Mitternacht hab ich jetzt noch nicht vollständig 
durchdacht, da es aber relativ selten vorkommt, dass man in dieser Zeit 
schalten muss, ignoriere ich diesen Sonderfall mal.
D.h. wir tun so, dass man sich einen Tag hernimmt
1
    +------------------------------------------------+
2
                    |                  |
3
                   Ein                Aus
Alles was zwischen Ein und Aus liegt ist die 'Gerät ist eingeschaltet' 
Zeit. Alles was nicht zwischen diesen beiden Zeitpunkten liegt ist 
'Gerät aus'. Also das hier
1
    +------------------------------------------------+
2
     ###############|                  |#############
3
                   Ein                Aus

stellst du also fest, dass die aktuelle Zeit vor 'Ein' liegt, also im 
schraffierten Bereich ist, dann -> Gerät aus.
Selbiges für den Fall, dass die aktuelle Zeit nach 'Aus' liegt.
Und alles was dann noch übrig bleibt -> 'Gerät ein'

Du kannst jetzt den nicht schraffierten Teil nach links oder rechts 
verschieben. Solange du dabei nicht über Mitternacht drüber kommst, gibt 
es da kein Problem.

von Karlo (Gast)


Lesenswert?

Danke erstmal.
Ich habe meine Zeit in Minuten seit Mitternacht vorliegen, was aber für 
die grundsätzliche Lösung weniger wichtig ist.

Die letzten beiden hier genannten Vorschläge (current > ein && current < 
aus) haben imho beide einen Denkfehler: aus kann kleiner sein als ein.

Bsp: ein= 21:00; current=22:00; aus=6:00
Schon klappt die obige Abfrage nicht mehr, denn eigentlich müsste ich 
jetzt"EIN" sein.

Mit verschachtelten, hässlichen Abfragen lösbar. Aber wie gehts kürzer?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Du kannst jetzt den nicht schraffierten Teil nach links oder rechts
> verschieben. Solange du dabei nicht über Mitternacht drüber kommst, gibt
> es da kein Problem.
>

Kommst du über Mitternacht drüber
1
    +------------------------------------------------+
2
        |####################################|              
3
       Aus                                  Ein
dann drehen sich ein paar Sachen um.
Die Skizze zeigt dir aber auch, wie man diesen Fall erkennen kann. Die 
Aus-Zeit ist kleiner als die Ein-Zeit (im Gegensatz zu oben).
Und die Skizze sagt dir auch, wie du die Abfragen umdrehen musst, damit 
das Ergebnis wieder stimmt.
Schon toll - so eine Skizze. Oder?

von Karl H. (kbuchegg)


Lesenswert?

Karlo schrieb:
>
> Mit verschachtelten, hässlichen Abfragen lösbar. Aber wie gehts kürzer?
1
  turnOn = ( current > ein && current < aus );
2
  // wenn die Schaltzeit über Mitternacht drüber geht, dann dreht sich
3
  // alles um
4
  if( aus < ein )
5
    turnOn = !turnOn;

was ist denn da verschachtelt und hässlich?

Oder wenn du es lieber etwas expliziter magst
1
  if( aus < ein )
2
    turnOn = ( current < aus || current > ein );  // Mitternacht ist drinnen
3
  else
4
    turnOn = ( current > ein && current < aus );  // Tagsüber

oder noch etwas expliziter
1
  turnOn = FALSE;
2
3
  if( aus < ein )  // SChaltzeit geht über Mitternacht?
4
  {
5
    if( current < aus || current > ein )
6
      turnOn = TRUE;
7
  }
8
  else
9
  {
10
    if( current > ein && current < aus )
11
      turnOn = TRUE;
12
  }

von Nosnibor (Gast)


Lesenswert?

Eleganter als mit verschachtelten ifs geht es wohl nur noch, wenn man 
einen geeigneten Zahlentyp hat, der beim Rechnen auch um Mitternacht 
überläuft. Dann ist die Bedingung nämlich (current - ein) < (aus - ein). 
Aber der Aufwand, die Uhrzeiten entsprechend umzurechnen (oder die 
entsprechende Subtraktionsfunktion zu schreiben), ist wohl größer als 
die paar verschachtelten Verzweigungen.

von Reinhard Kern (Gast)


Lesenswert?

Hallo,

ich würde das etwas allgemeiner angehen, nämlich dass es mehr als je 
eine Ein- und Auszeit gibt. dann gehst du einfach die Liste der 
Schaltzeiten durch, die letzte, die noch kleiner ist als die aktuelle, 
bestimmt den Schaltzustand.

Gruss Reinhard

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.