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
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
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
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
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
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
goto SetzSommer '
#Maerz
if (Day – Dow < 25) then goto
NichtSommer ' Winterzeit bis letzten Sonntag
if Dow = 0 and hour < 3 then goto NichtSommer '
Winterzeit
#SetzSommer
SommerBit =
ON ' Sommerzeit
Goto Ende
142
#NichtSommer
SommerBit =
OFF ' Normalzeit
#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 SommerBit = OFF and hour < 3 then goto Ende143
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
if Dow = 0 and hour < 3 then goto NichtSommer '
Winterzeit
#SetzSommer
SommerBit =
ON ' Sommerzeit
Goto Ende
143
#NichtSommer
SommerBit =
OFF ' Normalzeit
#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
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
#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