In dieser Richtung, einen "Zähler" zu verwenden, hatte ich auch schon tendiert - jedenfalls um die Phänomene beim Wechsel von W->S bzw. S->W aufzufangen bzw. zu "puffern". Ein weiteres Phänomen, nämlich ein StromAusfall - so finde ich - lässt sich gut in dieses Konzept integrieren.
Der Aufwand hierfür beschränkt sich eigentlich darauf, zu ermitteln, wie viele Impulse nachzuliefern sind. Die Abarbeitung der Impulse wäre, dann schon erledigt, weil identisch mit dem Vorstellen der Uhr beim Wechsel W->S.
Das Unterdrücken der Impulse beim Wechsel S->W hatte ich mir so vorgestellt, dass der Zähler im negativen Bereich arbeitet.
D.h., der Zähler wird statt beim "normalen" Minuten-Impuls um 1 erhöht und statt beim Wxl S->W um 61 erhöht zu werden, beim Wxl W->S um 59 vermindert.
Die Auswertung des Zählers und die (Nicht-)Umsetzung in reale Impulse an die Uhren sieht dann so aus:
- ist der Zählerstand <= 0, so passiert nichts
- ist der Zählerstand > 0, so wird 1 Impuls ausgegeben und der Zähler um 1 dekrementiert.
Für den Fall, dass der Zählerstand > 1 ist, muss natürlich dafür gesorgt werden, dass die ImpulsFolge entspechend einem "speziellen" Takt erfolgt.
Allerdings neige ich dazu, weder CTU noch CTD zu verwenden, sondern eine "stinknormale", aber statische INT-Variable.
D&T? Weiss ich nicht. Stelle mir vor, dass die "Datümer" (letzter Sonntag im Mrz und Okt) nicht in jedem Zyklus berechnet werden, aber natürlich ständig zum Vergleich mit dem aktuellen Datum zur Verfügung stehen müssen. Ferner denke ich, dass die Zeit in einer Form zur Verfügung steht, die ein Vielfaches von s oder ms oder µs oder ns darstellt.
Du benötigst
- die Stunde 2 für die Wxl W->S und S->W
- die Minute bei jedem Wxl der Minute
- z.B. einen 0,5 Hz Takt zum Aufholen der "geschlabberten" Minuten-Impulse.
Die Stunden, Minuten und Sekunden lassen sich Leicht per Division und MOD aus z.B. einem Vielfachen von ms isolieren.
So in etwa hatte ich mir das gedacht (noch recht rudimentär, gänzlich ungetestet und ohne StromAusfallBerücksichtigung):
Code:
// Pulse vorbereiten
tbSecond0 := tiSecond = 0 ;
tbHour2 := tiHour = 2 ;
IF sbSecond0Prev OR NOT tbSecond0 THEN
; // wenn nicht positive Flanke der Sekunde: nichts tun
ELSIF sbHour2Prev OR NOT tbHour2 THEN
PulseCounter := PulseCounter + 1 ; // 1 min vor, normaler Impuls, wenn nicht Beginn der "magischen" Stunde
ELSIF tdateChgWin2Sum = actualDate THEN
PulseCounter := PulseCounter + 61 ; // 1 min vor und 1 h vor
ELSIF tdateChgSum2Win = actualDate THEN
PulseCounter := PulseCounter - 59 ; // 1 min vor und 1 h zurück
ELSE
PulseCounter := PulseCounter + 1 ; // 1 min vor, normaler Impuls, wenn Beginn der "magische" Stunde, aber kein Wxl-Datum
END_IF ;
sbSecond0Prev := tbSecond0 ; // für FlankenErkennung
sbHour2Prev := tbHour2 ; // für FlankenErkennung
// Pulse ausgeben bzw. unterdrücken
tbClock := ( tiSecond MOD 2 ) = 0 ; // für z.B. tbClock 0,5 Hz
output_pulse := output_pulse AND tbClock ; // Rücksetzen des Ausgabe-Impulses
IF sbClockPrev OR NOT tbClock THEN
; // wenn nicht positive Flanke des AusgabeTaktes: nichts tun
ELSIF PulseCounter <= 0 THEN
; // wenn ZählerStand <= 0: nichts tun
ELSE
output_pulse = TRUE ; // wenn Zählerstand > 0: Impuls setzen und Zähler dekrementieren
PulseCounter := PulseCounter - 1 ;
ENDIF ;
sbClockPrev := tbClock ; // für FlankenErkennung