2. Tipps und Tricks    Teil 2 ab 2.2.13  (zurück zu Teil 2 Anfang , zu Teil_1)

Uhr  (Stand: 22.9.2008)          (Schaltuhr siehe Softwarebausteine)

Sytem-Uhr und Funk-Uhr   Anschluss und Grundlagen siehe Linkliste     

Ausgabe Dow-Text  Mo Di Mi Do Fr Sa So  Zugriff auf Tabelle

Letzter Tag im Monat  , Tag-Nummer im Jahr ,   DOW  Tag-Nummer in der Woche berechnen

 Sommerzeit_bestimmen    Beispiel für remanentes Merker-Bit

        Datum_berechnen   

Tagnummer im Jahr, Tagnummer in der Woche, Wochen-Nummer im Jahr

Osterdatum und Rosenmontag, Karfreitag, Himmelfahrt, Pfingsten  NEU überarbeitet

 Datum von Buß- und Bettag, Muttertag, Sommerzeit  berechnen, Advent

 Steuern mit Feiertagsbit für Heizung und Rollladen

Weiter zu Tipps und Tricks Teil 3

Zeittakte mit Uhrzeit und TIMER, Wartezeit,

(Schaltuhr siehe Softwarebausteine)

Weiter zu Tipps und Tricks Teil  4

Überschreitung von 32767 beim Rechnen, Begrenzen      

Zählen bis 65535 im word, Zahl  0 bis 65535, Anzeigen mit 1 bis 2 Kommastellen

Zahlen über 65535  Zähler, Addition, Multiplikation, Division NEU 


Phantasie ist wichtiger als Wissen.  (Albert Einstein)

2.2.13)   System-Uhr und Funk-Uhr

(1)   Fehlerbeseitigung Hardware

Für einwandfreies Signal der Funkuhr ist wichtig, dass Ground „geerdet“ ist, z.B. an Wasserleitung, Heizungsrohr, Potenzialausgleichschiene. Die LED leuchtet mit gleichmäßigen Impulsen und nicht flackernd.

(2)   Fehlerbeseitigung Software

Die interne Uhr hat grundsätzliche Fehler, die korrigiert werden müssen.

Beim Wechsel der Stunde wird manchmal die Minute schon auf 00 geschaltet und dabei noch die alte Stunde gezeigt, z.B.:

 16:59 à 16:00 à 17:00

Lösung: Vor der Abfrage wird eine Befehleszeile eingefügt

 If second = 0 or second = 59 then goto EndeZeitabfrage

Vor jeder Abfrage bzw. Ausgabe des Wochentags soll zur Fehlerkorrektur folgende Zeile gesetzt werden:

  If  DOW > 6  then DOW = 0 möglich ist auch DOW = DOW MOD 7

Hierbei ist DOW  0=Sonntag, 1=Montag,.....6=Samstag, wie im geschäftlichen Bereich üblich ist der Sonntag nicht Tag 7.

(3)   Betrieb ohne Funk-Uhr

Die System-Uhr in der C-Control kann auch ohne Funk-Uhr laufen. Sie muss dann von Hand eingestellt werden.

z.B. second = second +1  

Die Umschaltung auf Stellen der  Minute, Stunde, Tag, usw. wird mit dem Schrittregister (siehe Softwarebausteine) erledigt.

Das Jahr setzt man zweckmäßig hinter dem Teil „Definitionen“ direkt auf  das aktuelle Jahr z.B. year = 04

Eventuell startet man das Programm mit komplett vorbesetztem Datum und vorbesetzter Uhrzeit und minimiert dadurch das Einstellen.

Auch der Wochentag DOW muss eingestellt werden, weil er im Betriebssystem nicht aus dem Datum berechnet wird.

Weiter unten steht ein Basic-Programm zur Berechnung von DOW aus Tag, Monat und Jahr einschließlich Schaltjahre.

Beim Übergang von 23 Uhr 59 auf  00:00 wird DOW vom System weiter geschaltet.

(4)   Betrieb mit Funkuhr (DCF77-Signal)

Hier stellt sich die Frage „Erhält die c-Control das Signal?“

Test des Signals:

Define Signal FREQ

If Signal then goto SignalVorhanden

Nächste Frage: „Ist die Uhrzeit von der Funk-Uhr gestellt?“

Nach dem Neustart steht die Uhr auf Jahr 97.

If   year > 90 then goto FunkUhrFehlt

Hiermit kann ausgewertet werden, ob die Uhr von der Funk-Uhr eingestellt (synchronisiert) wurde.

„Wie wird nun festgestellt, ob die Uhr auch später immer wieder von der Funk-Uhr synchronisiert wird?“ Folgend werden drei Möglichkeiten gezeigt:

(5)    Ein Byte der Uhrdaten  abfragen.

define UhrSynchronisiert Byte [66] ' (Variablen-Erweiterung siehe Stolpersteine)

If  UhrSynchronisiert = 1 then ... ' Uhr ist synchronisiert

Das Byte bleibt auf  1 stehen, wenn die Impulse ausbleiben. Eventuell muss man obige Abfrage Freq berücksichtigen. 

If  UhrSynchronisiert >< 1 then ... ' Uhr Synchronisierung durch Funkuhr läuft

Beispiel einer Auswertung:

If  UhrSynchronisiert >< 1 then  goto  Ueberwachungszeit

(6)   Die Funkuhr aktualisiert ständig eine Speicherstelle, die man indirekt abfragen kann.

If second < 5 then goto weiter   ' (hierdurch wird nicht bei Minutenwechsel abgefragt)

If  Minute ><  ReadMinAlt   then  Funkuhr = OFF else Funkuhr  = ON ... ' z.B. Meldebit Funkuhr

Bei Ausbleiben des Signals oder fehlerhaftem Empfang wird der DCF-Minutenwert „ReadMinAlt“ nicht aktualisiert.

Dadurch kann man auch feststellen, wie lange das Signal fehlt. Das Beispiel ist unvollständig und soll nur das Prinzip zeigen:

If  Minute - ReadMinAlt  > 20   then goto Fehlermeldung ... 'nach 20 Minuten, Beispiel unvollständig, neue Stunde fehlt.

(7)   Synchronisation starten

Das Betriebssystem synchronisiert die Uhr jede Stunde. Falls man selbst die Synchronisation starten möchte, muss dieser Altwert der Funk-Uhr mit einer Zahl 60 bis 255 überschrieben werden.

Wert2 = 255 : gosub writeMinAlt

Unterprogramme:

#ReadMinAlt

     table readTabMA

     2937   '11*256+$7A-1

     tabend

   return

#writeMinAlt

  wert2 =wert2 'var = var

     table writetabMA

     4464 'Hex7a    17*256+$7a-10

     tabend

   return

 

(8)   Aufwändiger ist das Verfahren mit dem Statusregister anstelle des obigen Verfahrens.

define Wert1 byte ' Byte 3 Zwischenspeicher 1 (zu wert12 word [2])

define wert1Bit0 Bit [17] ' für bit-Handling des byte Wert1 (Zwischenspeicher 1)

define wert1Bit4 Bit [21]

define AusfallMerker Bit [xx]

 

goto EndePseudoVariable ' muss übersprungen werden

   #ccstatus

       table ccstatustab

       2938    '11*256+$7b-1 (Auslesen des Statusregisters)

       tabend

   RETURN

#EndePseudoVariable

 

#Anfang '  Hauptprogramm

Programmteil im Hauptprogramm:

Während die Funk-Uhr die System-Uhr synchronisiert, wird Status nicht ausgewertet.

If minute < 2 OR minute > 57 then goto EndeUhr

wert1 = ccstatus ' Statusregister in Zwischenspeicher zur Bit-Abfrage

Bit 4 zeigt an, ob die System-Uhr synchronisiert wurde,

if wert1Bit4 = ON then print "Uhr gestellt " else print "Uhr falsch?  "

Bit 0 zeigt an, ob aktuell die Funk-Uhr das DCF77-Signal komplett empfängt, also die Uhr weiterhin synchronisiert wird.

if wert1Bit0 = ON then print "Funk-Uhr aktiv " else print "Funk-Uhr fehlt  "

Der Ausfall-Merker zeigt an, ob seit dem ersten Empfang ein Funkuhr-Ausfall war, also die System-Uhr allein lief.

if wert1Bit4 = ON AND wert1Bit0 = ON then AusfallMerker = ON

#EndeUhr

nach_oben

2.2.14)   Ausgabe Dow-Text  Mo Di  ... So

define Wert1 byte ' 3 Zwischenspeicher 1 (zu wert12)

define Wert2 byte ' 4 Zwischenspeicher 2 (zu wert12)

define Wert12 word [2]'= Byte 3,4 Zwischenspeicher

(1) Ausgabe auf dem Bildschirm

 print "  Tag-Nr ";dow;" "; ' Dow Ziffer TagNr als Kontrolle

gosub DowText ' Unterprogramm gibt Tag als Text  aus, Mo, Di, Mi,....

print "   ";day;".";month;".200";year;" " ' Ausgabe Datum

(2) 1. Möglichkeit: Unterprogramm mit On ... goto

#DowText  ' Anwedung gosub DowText

Dow = DOW Mod 7

ON Dow  goto Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag

#sonntag

print "So"; : Return

#Montag

print "Mo"; : Return

 #Dienstag

 print "Di"; : Return

 #Mittwoch

 print "Mi"; : Return

 #Donnerstag

 print "Do"; : Return

 #Freitag

 print "Fr"; : Return

 #Samstag

 print "Sa"; : Return

(3) 2. Möglichkeit: Unterprogramm mit Tabelle

braucht weniger Speicherplatz

#DowText  ' Anwedung gosub DowText

Dow = DOW Mod 7

LookTab TagText, Dow, wert12

Nun liegen die 2 Buchstaben (Ascii-Werte) in Byte wert1 und wert2 für Ausgabe z.B. auf LCD

Die Befehle für Ausgabe über die serielle Schnittstelle z.B.  für Anzeige PC lauten:

put wert1 : put wert2 ‘Ausgabe serielle Schnittstelle

Return

'Tabelle am Ende des Programms

Table TagText ' Code für So Mo Di Mi Do Fr Sa

21359   19823   17513  19817 17519  18034  21345

TabEnd

Erläuterung zur Herstellung der Zahlen für So Mo Di Mi Do Fr Sa

Der Anwender kann obige Tabelle kopieren. Wie kann man sie selbst herstellen?

Im Kapitel „Softwarebausteine“ befindet sich ein LCD-Programm zur Umformung ASCII-Zeichen in Dezimal.

Man kann auch mit dem PC-Hilfsrechner umformen:

Aus einer ASCII-Tabelle werden die HEX-Zahlen für die zwei Buchstaben abgelesen

S = Hex 53  o = Hex 6F für So

'&H536F &H4D6F &H4469 &H4D69 &H446F &H4672 &5361

Eingabe der Hex-Zahl 536F  in den PC-Hilfsrechner, Umschalten auf Dezimal, Anzeige 21359

nach_oben

2.2.15)  Letzter Tag des Monats

Das Datum des letzten Tages (28, 29, 30 oder 31) im aktuellen Monat liegt in der c-control  bereit.

define LetzterTag Byte [67] 'Anzahl Tage im aktuellen Monat

Beispiel: Wie lautet das Datum in 14 Tagen bei Monatsüberschreitung?

Datum = day + 14

If  Datum > LetzterTag  then Datum = Datum – LetzterTag

nach_oben

2.2.16)   Tag-Nummer der Woche berechnen (DOW)

Die Berechnung DOW ist notwendig, wenn keine Funkuhr benutzt werden kann.

Zunächst ist die Tag-Nummer des Jahres auszurechnen.

Wert12 = 30 *(Month -1)+ (Month+Month / 8) / 2 +Day +(Month >2)*(2+ (year MOD 4 = 0))

Hier wird die temporäre Variable wert12 anstelle TagNr angewendet, um Variable zu sparen.            

Für 2000 bis 2099 wird mit Hilfe des Jahres (zweistellig) einschließlich Schaltjahre die Tag-Nummer der Woche bestimmt.

(1) Tag (0 bis 6) der Woche

DOW = ((year +23) / 4 + year + wert12 ) MOD 7   ' Tag 0 bis 6 (year 2-stellig)

Die Berechnung muss nur einmalig nach Stellen des Datums (day, month, year) durchgeführt werden.

Die Systemuhr stellt bei jedem Tagwechsel DOW weiter.

Die Korrektur des DOW-Fehlers beim Weiterschalten muss durchgeführt werden DOW = DOW MOD 7 .

(2) Tag (1 bis 7) der Kalenderwoche

TagKW = ((year +19) / 4 + year  + wert12 ) MOD 7 +1    ' Tag 1 bis 7 (year 2-stellig)

(3)         Weitere Formeln für Datum, Wochennummer, Feiertage, Sommerzeit, usw. siehe Teil 2  Datum_berechnen

nach_oben

2.2.17)   Sommerzeit bestimmen

Das Bit Sommerzeit der Funk-Uhr steht nicht zu Verfügung, deshalb wird es hier errechnet.

(Merkhilfe o): Bei  S(o)mmerzeit  wird die Uhr v(o)rgestellt von 2:00 auf 3:00 am letzten Sonntag im März.

Die Sommerzeit endet am letzten Sonntag im Oktober. Dabei wird die Uhr 3:00 auf  2:00 zurück gestellt.

Es muss also der letzte Sonntag im März und Oktober bestimmt werden. Wäre das der 31., muss der Sonntag davor am 24. ausgeschlossen werden.

Hieraus ergibt sich  die Bedingung  Day – Dow > 24 bzw. Day – Dow < 25 .

Define SommerBit  Bit [  ]

Dow = Dow MOD 7 ' Dow-Fehler-Korrektur

' Mit dem Minuten-Impuls ist auch der Uhrenfehler in der c-control beseitigt (Uhr siehe oben).

If not MinutenImpuls then goto Ende.. ' Programm wird nur einmal je Minute durchlaufen (siehe Zeittakte).

SommerBit = OFF  ' Vorbesetzung (Normalzeit)

(1)   Einfaches Programm ohne Uhrzeit

Am Sonntag wird bereits 00:00 Uhr umgeschaltet.

If month <  3  or  month > 10 then goto Ende141

If month =  3  and  (Day – Dow < 25) then goto Ende141 ' Winterzeit bis letzten Sonntag März

If month = 10 and  (Day – Dow > 24) then goto Ende141 ' Winterzeit ab letzten Sonntag Oktober

SommerBit = ON  ' Sommerzeit

#Ende141

(2)   Mit Uhrzeit wird das Programm umfangreicher.

Die Sommerzeit wird 1 Stunde zu früh (ein kleiner Fehler) ausgeschaltet.

If month <  3  or  month > 10 then goto  NichtSommer

If month =  3  then goto Maerz   '

If month ><  10 then goto  SetzSommer

' Oktober
if (Day – Dow < 25) then goto SetzSommer
' Sommerzeit bis letzten Sonntag 
'  vom letzten Sonntag bis 31.10.

if Dow >< 0 then goto NichtSommer ' Wochentage bis 31.10.

 '  letzter Sonntag Oktober
if   hour >= 2 then goto NichtSommer ' ab 2:00 Winterzeit (1 Stunde zu früh)

goto  SetzSommer  '  

#Maerz

if (Day – Dow < 25) then goto NichtSommer  ' Winterzeit bis letzten Sonntag 
' vom  letzten Sonntag bis 31.3. 
if Dow = 0 and   hour < 3 then goto NichtSommer 
' Winterzeit bis 1:59 Uhr danach ab 3:00 Sommerzeit  

#SetzSommer

SommerBit = ON  ' Sommerzeit

Goto Ende 142

#NichtSommer

SommerBit = OFF  ' Normalzeit (Winterzeit)

#Ende142

(3)   Mit richtiger Uhrzeit

Die Uhrzeit am letzten Sonntag im Oktober läuft zweimal von 2:00 bis 3:00. Einmal als Sommerzeit und einmal als Winterzeit.

If month <  3  or  month > 10 then goto  NichtSommer

If month =  3  then goto Maerz   '

If month ><  10 then goto  SetzSommer

' Oktober
if (Day – Dow < 25) then goto SetzSommer
' Sommerzeit bis letzten Sonntag 
'  vom letzten Sonntag bis 31.10.

if Dow >< 0 then goto NichtSommer ' Wochentage bis 31.10.

 '  letzter Sonntag Oktober
if   hour >= 3 then goto NichtSommer ' ab 3:00 Winterzeit

if SommerBit = OFF and hour < 3 then goto Ende143 ' 2. Durchlauf ab 2:00 Uhr Winterzeit  

if   hour = 2 and minute = 59  then goto NichtSommer ' Abschaltung Sommerzeit nach 1. Durchlauf  bis 2:59 Uhr  

goto  SetzSommer  ' 1. Durchlauf  bis 2:59 Uhr Sommerzeit 

#Maerz

if (Day – Dow < 25) then goto NichtSommer  ' Winterzeit bis letzten Sonntag 
' vom  letzten Sonntag bis 31.3. 
if Dow = 0 and   hour < 3 then goto NichtSommer 
' Winterzeit bis 1:59 Uhr danach ab 3:00 Sommerzeit  

#SetzSommer

SommerBit = ON  ' Sommerzeit

Goto Ende 143

#NichtSommer

SommerBit = OFF  ' Normalzeit (Winterzeit)

#Ende143

Das Bit der Funk-Uhr für den zweiten Durchlauf steht nicht zur Verfügung. Hierdurch kann folgender Fehler entstehen:

Bei einem Reset  während des 2. Durchlaufs wird Sommerzeit bis 3:00 eingeschaltet. Für diesen Fall ist Lösung (2) besser. Allerdings kann man auch diesen Fehler minimieren:

Gleichzeitig ein Beispiel für Anwendung „ Remanentes Merker-Bit “ 

Das fehlende Bit „ zweiter Durchlauf “ kann man mit remanenter EEPROM-Variable erzeugen (siehe Kapitel Softwarebausteine).

'  letzter Sonntag Oktober

if   hour = 1 and minute = 59  then goto ResetMerker '  1:59

if   hour = 2 and minute = 59  then goto SetzMerker ' für 2. Durchlauf (Winterzeit) 2:59  

if   hour <  2  then goto  SetzSommer   ' bis  2:00 Sommerzeit

if   hour >= 3 then goto  NichtSommer ' ab  3:00 Winterzeit

Zeiger = 4 : input# wert12   ' Abfrage Merker „ 2. Durchlauf “

if wert12 = 1  then goto NichtSommer ' 2. Durchlauf ab 2:00 Uhr Winterzeit  

goto  SetzSommer  ' 1. Durchlauf  bis 2:59 Uhr Sommerzeit 

#ResetMerker ' 2. Durchlauf aus  

wert12 = 0

Zeiger = 4 : print# wert12   'z.B. Speicherplatz 4

#SetzSommer

SommerBit = ON  ' Sommerzeit

Goto Ende 144

#SetzMerker ' 2. Durchlauf ab 2:00 Uhr Winterzeit  

wert12 = 1

Zeiger = 4 : print# wert12   'z.B. Speicherplatz 4

#NichtSommer

SommerBit = OFF  ' Normalzeit (Winterzeit)

#Ende144

Sicherheitslücken gibt es immer genauso wie auf anderen Gebieten auch hier:

Ist die Steuerung am letzten Sonntag im Oktober um 1:59 Uhr ausgeschaltet und wird während des 1. Durchlaufs zwischen 2:00 und 2:59 eingeschaltet, ist vorzeitig Winterzeit eingeschaltet. Aber fällt die Funkuhr wegen schlechter Empfangsverhältnisse aus und schaltet nach 2:59 Uhr nicht zurück auf 2:00, hat man auch eine Lücke. Allgemein wird Lösung (1) oder (2) ausreichen.

 

Weiter zu Datum_berechnen

------------------------------------------------  ENDE   Tipps und Tricks  Teil  2 ------------  nach_oben

 --------------------- weiter zu  Teil 3   Teil 4    zurück zu Tipps und Tricks Teil_1                        Startseite 

 

Kostenlose Zähler und Statistiken für Ihre Website bei www.motigo.com