Step 7 Zeitumstellung aktuelle Zeit um 1 Stunde erhöhen bzw. vermindern

trabajador73

Level-2
Beiträge
112
Reaktionspunkte
5
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

S7-400 CPU wird verwendet.
Eine Sommer- und Winterzeitumstellung soll vorgenommen werden. Die CPU-Zeit mit "Date and Time" wird ausgelesen und danach die Info in Datum und Zeit getrennt in einen DB gespeichert.
Dann je nach Umstellung der Zeit sollen der Zeitvariablen der Wert 3600000ms hinzu- bzw. abgezogen werden.

Ist es möglich mit folgender Berechnung dies zu praktizieren?

L DB10.DBD10 // Typ ([FONT=Verdana,Arial,Tahoma,Calibri,Geneva,sans-serif]TIME_OF_DAY) und enthält die aktuelle CPU-Zeit
L 3.600.000 // Wert für 1 Stunde in MS angegeben
+I
T DB10.DBD14 //[/FONT]
// Typ (
[FONT=Verdana,Arial,Tahoma,Calibri,Geneva,sans-serif]
TIME_OF_DAY) und enthält die neue Zeit für die CPU

Danach wird Datum und neue Zeit wieder zu Date and Time zusammengeführt und der CPU zugewiesen.

Wenn die Variable DB10.DBD10 im Baustein beobachtet wird, ist ein Festwert zu beobachten, daher sollte dies so funktionieren, oder?

Danke für jeden Beitrag.

[/FONT]
 
Dann je nach Umstellung der Zeit sollen der Zeitvariablen der Wert 3600000ms hinzu- bzw. abgezogen werden.
Was kommt bei deiner Berechnung raus, wenn die aktuelle Uhrzeit bei 23:30 liegt und du eine Stunde addierst?

Oder 0:15 und eine Stunde abziehst?

+I wäre auch falsch, wenn schon dann +D

Aber ich denke mal es gibt viel bessere Lösungen für Sommer / Winterzeitumschaltung.
 
zu DeltaMikeAir:
Ok, das D statt I werde ich berücksichtigen. Der Einwand mit 23:30 und 0:15 Uhr ist berechtigt, aber werde ich vernachlässigen.

zu hucki:
Warum MOD benötigt wird, ist mir nicht verständlich. Ich addiere und subtrahiere nur. Es fällt doch dabei kein Rest an. Von einer Ganzzahl wird eine Ganzzahl addiert bzw. subtrahiert.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, die manuell beeinflusste Zeitumschaltung erfolgt in der Regel nicht um diese Zeit und die automatisierte zwischen 2 und 3 Uhr. Daher wird der Fall sehr wahrscheinlich nicht auftreten.
Manuell heißt die CPU wird von Stopp in Run geschaltet und hat z.B. eine Zeitumschaltung verpasst. Dies wird nicht um Mitternacht passieren.
 
Ja, die manuell beeinflusste Zeitumschaltung erfolgt in der Regel nicht um diese Zeit und die automatisierte zwischen 2 und 3 Uhr. Daher wird der Fall sehr wahrscheinlich nicht auftreten.
Manuell heißt die CPU wird von Stopp in Run geschaltet und hat z.B. eine Zeitumschaltung verpasst. Dies wird nicht um Mitternacht passieren.

Ich verstehe dich nicht ganz. Auch wenn du die Uhrzeit um 14 Uhr umstellst, sobald es irgenwann mal 23:30 ist auf der reelen Uhrzeit, dann wird
deine berechnete Uhrzeit auf 24:30 stehen??

Vielleicht fällt dass ja niemandem auf usw. aber ein sauberer Weg ist dass nicht gerade.
 
Ich verstehe dich nicht ganz. Auch wenn du die Uhrzeit um 14 Uhr umstellst, sobald es irgenwann mal 23:30 ist auf der reelen Uhrzeit, dann wird
deine berechnete Uhrzeit auf 24:30 stehen??
Den Einwand von Dir verstehe ich nicht. Die Zeit wird anschließend der CPU zugewiesen und wenn es 0:00 Uhr ist, beginnt ein neuer Tag.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Verwende doch den "AD_DT_TM" aus der Standard-Bibliothek. Damit kannst du dem DATE_AND_TIME einen Wert dazuaddieren (z.B. "T#1H").
Zum subtrahieren gibt es den "SB_DT_TM" oder du addierst "T#-1H".
Wenn du unbedingt Datum und Uhrzeit einzeln brauchst, kannst du sie ja danach erzeugen.

Ich finde das ist die sauberste Lösung, wenn du fertige / dokumentierte Bausteine von Siemens benutzt.
 
OK, von dem zugewiesen habe ich vorher nichts gelesen oder evtl. überlesen ( ich dachte du berechnest kontinuierlich +/- 1 Std )
Davon bin ich auch ausgegangen.


zu hucki:
Warum MOD benötigt wird, ist mir nicht verständlich. Ich addiere und subtrahiere nur. Es fällt doch dabei kein Rest an. Von einer Ganzzahl wird eine Ganzzahl addiert bzw. subtrahiert.
Das MOD rechnet bei eventuellen Datumsüberschreitungen diese nach dem Addieren aus dem Ergebnis raus:
z.B. bei 23:30 + 1h = 24:30 MOD 24:00 = Rest 0:30

PS:
Datum müsste man in diesen Fällen auch noch korrigieren.
Aber laut Deiner letzten Beschreibung wird das Ganze ja nicht ständig und dann auch nicht zu solch speziellen Zeiten gehandthabt.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Danach wird Datum und neue Zeit wieder zu Date and Time zusammengeführt und der CPU zugewiesen.
Das würde ich nicht machen. Das erzeugt nur Probleme, besonders beim Zurückstellen um 1 Stunde oder wenn man die Uhr synchronisiert wie die Profis es machen :cool: Üblicherweise verstellt man nicht die Uhr der CPU, sondern berechnet aus der Uhr (Systemzeit) die Lokalzeit.

Wird die Uhr Deiner S7-400 mit einem Zeitserver synchronisiert z.B. per NTP? In welcher Zeitzone läuft Deine S7-400-Uhr?

Die Umrechnung von Systemzeit (Zeit der CPU-Uhr) in Lokalzeit (mit Berücksichtigung Sommerzeit) gibt es schon als fertige Bausteine, z.B. FC61 BT_LT oder von mir eine abgespeckte Version BT_LT_3 bzw. BT_LT_3_CET
Wenn man bei einer S7-300-PN-CPU oder S7-400-PN-CPU oder ET200-PN-CPU die Uhrzeitsynchronisation per NTP aktiviert, dann läuft die CPU-Uhr in UTC - weil man für diese CPU keine Zeitzone einstellen kann und NTP ja UTC liefert.

Wenn man bei einem IE-CP CP343-1 oder CP443-1 die Uhrzeitsynchronisation per NTP aktiviert, dann berücksichtigt der CP eine einstellbare Zeitzonenkorrektur, so daß die CPU-Uhr bei standardmäßig eingestellter Zeitzone "(GMT +01:00)" "trotz" NTP-Synchronisation in UTC+1 läuft. (Bei flüchtiger Betrachtung könnte der Eindruck entstehen, NTP würde die Uhrzeit in UTC+1 liefern.) Damit auch bei NTP-Synchronisation via CP die CPU-Uhr in UTC läuft, müßte man die Korrektur abschalten, indem man die Zeitzone auf "(GMT)" einstellt.

Welche SIMATIC S7-300/S7-400 Baugruppen unterstützen das NTP-Uhrzeittelegramm zur Synchronisation der Systemzeit und wie aktiviere ich diese Art der Zeitsynchronisation?

Weil nun wegen dieser CP-Geschichte manche meiner SPS-Uhren in UTC und manche in UTC+1 laufen, gibt es meinen Baustein BT_LT_3 in 2 Versionen, einmal für UTC+1 bei CP in GMT+1, und einmal für UTC bei PN-CPU oder CP mit GMT-Einstellung.

Große Linkliste: Uhrzeitsynchronisation - Zeitsynchronisation im Automatisierungsumfeld

Harald
 
Verwende doch den "AD_DT_TM" aus der Standard-Bibliothek. Damit kannst du dem DATE_AND_TIME einen Wert dazuaddieren (z.B. "T#1H").
Zum subtrahieren gibt es den "SB_DT_TM" oder du addierst "T#-1H".
Wenn du unbedingt Datum und Uhrzeit einzeln brauchst, kannst du sie ja danach erzeugen.
Danke "Windoze" für den Hinweis mit den Bausteinen "AD_DT_TM" und "SB_DT_TM", welche ich auch integrieren werde.

Die Umrechnung von Systemzeit (Zeit der CPU-Uhr) in Lokalzeit (mit Berücksichtigung Sommerzeit) gibt es schon als fertige Bausteine, z.B. FC61 BT_LT oder von mir eine abgespeckte Version BT_LT_3 bzw. BT_LT_3_CET
Danke "PN/DP" (Harald) auch für Deinen Beitrag und der Ansatz von Dir mit Systemzeit (CPU) und Lokalzeit findet für ein neues Projekt bzw. SPS-Programm auf jeden Fall Zustimmung. Zudem werde ich mir die von Dir vorgeschlagenen Bausteine ansehen, welche bestimmt eine bessere Lösung ermöglicht, als meine aktuelle mit dem Oscat-Baustein "DST" für die Ermittlung, ob gerade die Sommerzeit aktiv ist.
Hier bei der S7 400 CPU geht es um eine Übermittlung von Maschinendaten auf einen Server und die 400er CPU dient als Vermittler der Daten (Sample-SPS). Der Server bekommt die Daten mit einem Zeitstempel der Systemzeit übermittelt und an dem bestehenden SPS-Programm werde ich diese Zeitquelle nicht ändern.
Es gibt auch keinerlei Uhrzeitsynchronisation z.B. per NTP.
Hier waren ursprünglich 1 redundantes CPU-Paar im Einsatz, welche Maschinendaten auf 1 redundantes Serverpaar geschrieben haben. Jedoch dieses Konzept wurde vom Kunden geändert und jetzt schreiben beide S7 400er CPUs auf den gleichen Bereich des Servers. Damit es keine Datenüberschneidung gibt, ist eine der beiden CPUs in stopp und wird manuell zugeschaltet, wenn die andere CPU eine Störung hat. Dies alles hat der Kunde ohne meinen Einfluss mit anderen Automatisierern in der Vergangenheit festgelegt.
Der Ansatz mit dem Oscat-Baustein "DST" hat in meinem Fall alle Anforderungen erfüllt, dass jederzeit die Sommer- oder Winterzeitinfo verfügbar ist, also habe ich mich dafür entschieden. Jetzt für das nächste Projekt werden Eure hier genannten Lösungen berücksichtigt.
Für die Zukunft waren Eure Beiträge sehr förderlich.
Die bedenken der Zeitzone (deutsche Zeit bzw. UTC-Zeit) kann ebenfalls vernachlässigt werden.
 
welche bestimmt eine bessere Lösung ermöglicht, als meine aktuelle mit dem Oscat-Baustein "DST" für die Ermittlung, ob gerade die Sommerzeit aktiv ist.
(...)
Der Ansatz mit dem Oscat-Baustein "DST" hat in meinem Fall alle Anforderungen erfüllt, dass jederzeit die Sommer- oder Winterzeitinfo verfügbar ist, also habe ich mich dafür entschieden.
Du verwendest den OSCAT-Baustein DST in Deinem Programm? Mit welcher Uhrzeit? Wo bekommst Du die Uhrzeit in UTC her, wenn Du die Uhr der SPS verstellst?

Am letzten Sonntag im Oktober (Rückstellung der Uhr von Sommer auf "Winter"zeit) wenn Deine SPS-Uhr sagt, daß es zwischen 02:00 und 03:00 ist, kann nicht festgestellt werden, ob Sommer- oder "Winter"zeit ist. Auch der OSCAT-Baustein DST kann das nicht, wenn er mit Lokalzeit anstatt UTC "gefüttert" wird.

Harald
 
Die gute alte Uhrzeit bei Siemens.
CPU (300) unterstützt keine Zeitzone bei NTP, CP Unterstützt sie, aber Sommer Winterzeit fängt es schon wieder an ;)

Vielleicht kann dir der Beistein helfen.
Dieser Baustein berechnet den Umschalttag und gibt basierend auf einer UTC Zeitvorgabe die MEZ oder MESZ aus.
Achtung, die Umschaltung um 2 bzw. 3 Uhr ist in diesem Baustein nicht programmiert. Er schaltet um Mitternacht um.
Grund für diesen Baustein war es vor einigen Jahren auch Fremdsteuerungen an den NTP Server anzubinden, zum Teil waren dort die Bausteinnummern für die Datums und Zeitbausteine aus der Siemens Lib bereits verwendet. Daher ist dieser komplett eigenständig und macht dafür viele Dinge selbst.
Und die Umschaltung um Mitternacht war für uns damals vollkommend ausreichend.

Die CPU auf Lokalzeit zu betreiben davon würde ich in diesem Zusammenhang abraten. Ja es ist schön für den Diagnosepuffer etc. aber Zeitsync bedeutet Systemzeit UTC und bei diesem sollte man es auch belassen.
Und auch die Thematik ist die CPU aktuell auf Sommerzeit oder nicht, wenn der Baustein reinitalisiert wird aus irgend einem Grund und Nachts umschaltet......

Code:
FUNCTION fcZeitKorrektur : INT
//fcZeitKorrektur    FC    XXX    FC    XXX    Zeitkorrektur von GMT auf MEZ/MESZ


//Uhr wird auf UTC/GMT Synchronisiert
//      CALL  "fcZeitKorrektur"
//       RET_VAL  :=#RetVal
//       LokalZeit:=#TimeDate




TITLE = 'fcZeitKorrektur'
//  Dieser Baustein dient dazu die Lokale Zeit zu berechnen.
//  Über Uhrzeitsynchronisation erhält man GMT/UTC ohne Zeitzone und Sommer/Winterzeit
//  Dieser Baustein errechnet die Umschaltung der MEZ/MESZ und gibt die aktuelle Mitteleuropäische Zeit aus
//  Achtung der Abgleich der Zeitüberlauf funktioniert nur bei Positiven Zeitzonen.
VERSION : '1.0'
AUTHOR  : CHBG


// ===================================================
// History:
//
//   CHBG 20.04.2016    erstellt
//   
//   
//
//
// ===================================================


VAR_TEMP
    tCPU_Time        :   DATE_AND_TIME;             //Zwischenspeicher Datum/Uhrzeit
    ArrayDT AT tCPU_Time : ARRAY[0..7] OF BYTE;
    UTCMonatTag       :   INT;                      
    UTCTag, UTCMonat, UTCJahr, UTCStunde, UTCWochentag : INT;
    RetVal          :   INT;
    TagSommerzeit   :   INT;                        //Umschaltpunkt Sommerzeit
    TagWinterzeit   :   INT;                        //Umschaltpunkt Winterzeit
    TageFeb         :   INT;                        
END_VAR


VAR_OUTPUT
    LokalZeit       :   DATE_AND_TIME;
END_VAR    


BEGIN


    fcZeitKorrektur := 100;
    //Lese Uhrzeit
    RetVal:= READ_CLK(CDT := tCPU_Time // OUT: DATE_AND_TIME
             ); // INT
    UTCJahr := BCD_TO_INT(ArrayDT[0]);        
    UTCMonat := BCD_TO_INT(ArrayDT[1]);
    UTCTag := BCD_TO_INT(ArrayDT[2]);
    UTCStunde := BCD_TO_INT(ArrayDT[3]);
    
    //Berechnung der Sommer/Winterzeit Umschaltung
    //Monat mal 100+Tag z.B. 25 März = 325
    TagSommerzeit := (300 + (31 - ((UTCJahr + 5 +(UTCJahr/4)) MOD 7)));  
    TagWinterzeit := (1000 + (31 - ((UTCJahr + 2 +(UTCJahr/4)) MOD 7)));
    UTCMonatTag := (UTCMonat * 100 + UTCTag);
    
    //Addiere Zeitzone
    UTCStunde := UTCStunde + 1;
    //Addiere Sommerzeit
    //Wenn Aktuelles Datum < TagSommerzeit, oder Aktuelles Datum > TagWinterzeit ist Winterzeit
    IF ((UTCMonatTag >= TagSommerzeit) AND (UTCMonatTag <= TagWinterzeit)) THEN
    UTCStunde := UTCStunde + 1;  
    END_IF;


    //Abfrage Schaltjahr
    //Dividiere Jahreszahl durch 4 bei Rest 0 Haben wir ein Schaltjahr
    //Jahrhundertwenden sind keine Schaltjahre, wird hier aber nicht berüchsichtigt
    TageFeb := 28;
    IF ((UTCJahr MOD 4) = 0) THEN
        TageFeb := 29;
    END_IF;


    //Korrektur Zeitüberlauf und Datum
    //Wenn Studen >= 24 werden 24 Stunden subtrahiert und ein Tag addiert.
    //Wenn Tage >= "Tage des Monats" Werden die "Tage des Monats" subtrahiert und ein Monat addiert
    //Wenn Monate >=13 werden 12 Monate Subtrahiert und ein Jahr addiert
    IF (UTCStunde >= 24) THEN
    UTCStunde:= UTCStunde - 24;
    UTCTag:= UTCTag + 1;
    //Monate mit 31 Tagen
        IF ((UTCTag > 31) AND ((UTCMonat = 1) OR (UTCMonat = 3) OR (UTCMonat = 5) OR (UTCMonat = 7) OR (UTCMonat = 8) OR (UTCMonat = 10) OR (UTCMonat = 12))) THEN
        UTCMonat:= UTCMonat + 1;
        UTCTag:= UTCTag - 31;
    //Korrektur Jahr    
            IF (UTCMonat = 13) THEN
            UTCJahr:=  UTCJahr + 1;
            UTCMonat:= UTCMonat - 12;
            END_IF;     
    //Februar ohne Schaltjahr
        ELSIF ((UTCTag > TageFeb) AND (UTCMonat = 2)) THEN
        UTCMonat:= UTCMonat + 1;
        UTCTag:= UTCTag - TageFeb;
        ELSIF (UTCTag > 30) THEN
        UTCMonat:= UTCMonat + 1;
        UTCTag:= UTCTag - 30;
        END_IF;  
    END_IF;  
   
   //Ausgabe 
   ArrayDT[3]:= WORD_TO_BYTE(INT_TO_BCD(UTCStunde));  
   ArrayDT[2]:= WORD_TO_BYTE(INT_TO_BCD(UTCTag)); 
   ArrayDT[1]:= WORD_TO_BYTE(INT_TO_BCD(UTCMonat)); 
   ArrayDT[0]:= WORD_TO_BYTE(INT_TO_BCD(UTCJahr)); 
   LokalZeit := tCPU_Time;
   fcZeitKorrektur := RetVal; 
    
END_FUNCTION
 
Zuletzt bearbeitet:
Zurück
Oben