WinCC WinCC 7.3 C-Script Uhrzeit des Rechners stellen

PBO-WE

Level-1
Beiträge
165
Reaktionspunkte
6
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich habe über ein Script die Lokalzeit des Rechners gestellt.
Als Trigger hatte ich 1h gewählt.

Code:
#pragma code("kernel32.dll")
VOID SetLocalTime(SYSTEMTIME *lpst);
#pragma code();
SYSTEMTIME zeit;
zeit.wYear=GetTagWord("varname");
zeit.wMonth=GetTagWord("varname");
zeit.wDayOfWeek=GetTagWord("varname");
zeit.wDay=GetTagWord("varname");
zeit.wHour=GetTagWord("varname");
zeit.wMinute=GetTagWord("varname");
zeit.wSecond=GetTagWord("varname");
zeit.wMilliseconds=GetTagWord("varname");
SetLocalTime(&zeit);

Ein paar Tage später viel mir auf, dass die Kurvenarchive alle 2 Stunden eine Lücke von 6 Minuten haben.
Dann habe ich mir das ganze noch mal genauer angesehen und festgestellt, dass bei der Ausführung des Scripts nicht immer die richtige Zeit aus der Variablen ausgelesen wird.
Wie soll ich es erklären?

SPS Variable "Minute" in WinCC 7.3 beobachtet: immer aktuell
Script ausgeführt: Minute im Rechner abweichend der Variablen.

Bei einem Trigger von 5 Minuten ist die Abweichung ca. 1 Minute. Bei einem Aufruf, wird die Zeit korrekt gesetzt, beim nächsten eine Minute zurück.

Ich hoffe das ist verständlich.
Vielleicht hat einer eine Idee woran es liegen könnte.

Danke
Gruß
Thomas
 
In dem gezeigten Skript weist Du allen Zeit-Bestandteilen den selben Wert aus der selben Variable "varname" zu - ist das wirklich so oder nur falsch gepostet? Bist Du sicher, daß die PC-Uhr durch das Skript gestellt wird? Darf der angemeldete Windows-User die PC-Uhr stellen? Auf welchem Windows werkelt Dein WinCC?

Wo kommt die Zeit her, auf die Du die PC-Uhr stellen willst? Was für einen Datentyp hat/haben die WinCC-Variable(n) mit der Soll-Zeit?
- Falls das eine DATE_AND_TIME aus einer S7-300/400 ist - Du weißt daß da bei SFC1 READ_CLK die Zeitbestandteile im BCD-Format vorliegen? Und wie stellst Du da sicher, daß die Zeitbestandteile konsistent aus der SPS in WinCC eingelesen werden? Zur Übertragung von der SPS ins WinCC solltest Du besser das Beispiel mit der Rohdatenvariable GetTagRaw(...) benutzen.

Wieso willst Du die Uhr des WinCC-PC stellen - hat der PC keine Verbindung zu einem Uhrzeitserver?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,

Das Script ist nur die Vorlage, natürlich habe ich die entsprechenden Variable mit Werten versorgt und dort eingefügt. Zumal die Funktion SetTime auch nicht ausgeführt wird, wenn keine Plausiblen Werte drin sind.

Die Uhrzeit wird definitiv gestellt. Benutzerkontensteuerung ist aus. Win7 32.

Die Zeit kommt von einer Fernwirkzentrale, setzt falls abweichend die CPU Zeit. Date_Time wird in der SPS in Worte zerlegt, BCD Wandlung und in einem DB gespeichert und von dort per WinCC Variable abgeholt.
Wie schon erwähnt, ist diese abgeholte Zeit auch aktuell. Auf Sekunden kommt es nicht an. Aber jede Stunde 6 minuten vor und zurück ist doof.

Der PC ist nicht am Netzwerk. Fernwirkanlage -> RS232 ->SPS -> TCP/IP -> Rechner.

Gruß
Thomas
 
Zuletzt bearbeitet:
Die Zeit kommt von einer Fernwirkzentrale, setzt falls abweichend die CPU Zeit. Date_Time wird in der SPS in Worte zerlegt, BCD Wandlung und in einem DB gespeichert und von dort per WinCC Variable abgeholt.
Wird nun die PC-Uhr nach der SPS-Uhr gestellt oder nach der Uhrzeit von der Fernwirkzentrale? Falls nach der Uhrzeit von der FWZ dann sollte der Trigger vom Empfang der Uhrzeitmessage kommen und nicht irgendwann später die Uhrzeit von vielleicht ein paar Minuten alten Nachrichten nehmen. Bzw besser stelle die PC-Uhr nach der SPS-Uhr.

Was heißt "falls abweichend"? Kann man der Uhrzeit von der Fernwirkzentrale trauen? Gibt es eine Plausibilitätskontrolle der empfangenen Uhrzeit? Kannst Du das SPS-Uhr stellen nach der FWZ mal abstellen? Sind vielleicht Fehler im SPS-Programm beim SPS-Uhr-stellen oder beim konvertieren für WinCC, evtl. falsche Verwendung von TEMP-Variablen?

Du könntest in dem Skript mal die PC-Uhrzeit von vor dem Uhr stellen sowie die neue Stellzeit in eine Datei oder einen Ringpuffer der SPS schreiben (mitloggen) um später Sprünge zu identifizieren.

Und nochmal der Hinweis, daß Datum+Uhrzeit konsistent mit nur 1 Variable von der SPS in WinCC eingelesen werden sollte (GetTagRaw), und nicht per mehrere einzelne Variablen im normalen Aktualisierungszyklus.

Harald
 
Also die FW Zeit kommt ca. alle 1 bis 2 Sekunden. Dieser Zeit kann man trauen. Und nochmal, es geht nicht um ein paar Sekunden.
Die CPU wird mit der FW Zeit abgeglichen, wenn dort eine Abweichung von 1 Minute überschritten wird.
Die CPU Zeit wird in Worte Zerlegt und Dezimal an WinCC gegeben.

ABER.... Das spielt alles keine Rolle, da die Zeit-Variablen in WinCC richtig und aktuell angezeigt werden.
Ich habe mir die Systemzeit und die Zeit der CPU (Variablen) übereinander in einem Bild angelegt.
Man kann also genau sehen, dass beim ausführen des Scripts nicht die Minute aus der Variablen genommen wird, sondern mal eine Minute abgezogen wird und beim nächsten mal die richtige Zeit genommen wird. (bei 5 min Trigger) bei 1h Trigger war es 6 Minuten.

Ich weiß nicht, was mir das RAW bringen soll, denn die Variable ist ja aktuell, wie man im Bild und auch im Variablenhaushalt beobachten kann.

Vielleicht gibt es in Windoof eine Plausibilität, oder sowas, die in einer bestimmten Zeit nur eine bestimmte Abweichung der Systemzeit zulässt???
:confused:

Gruß
Thomas
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sicher dass du kein Aktualisierungsproblem mit deinen Datenpunkten von der SPS hast?
Schon mal mit GetTagWordWait anstelle dem GetTagWord probiert?
 
Also ich glaube nicht, daß das Windows die PC-Uhr auf eine andere Zeit setzt als bei SetLocalTime(&zeit) übergeben. Da geht wohl irgendwas schief beim Zusammenstellen der SYSTEMTIME-Variable, entweder haben die Einzelvariablen beim Skriptdurchlauf nicht aktuelle Werte oder das Zusammenstellen erfolgt fehlerhaft. Vielleicht kannst Du uns mal den "geheimen" Code Deines Skriptes zeigen, so wie Du es wirklich programmiert hast.

Harald
 
Die CPU wird mit der FW Zeit abgeglichen, wenn dort eine Abweichung von 1 Minute überschritten wird.
Vielleicht geht auch da schon etwas schief, daß schon die Uhr der CPU manchmal falsch gestellt wird, daß vielleicht die Uhrzeit von der FW fehlerhaft in DATE_AND_TIME konvertiert wird? Vielleicht zeigst Du uns auch den relevanten Code zum stellen der CPU-Uhr?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
83503d4ecdae4140144bd5ac3c19fafe.jpg


Wie schon mehrfach gesagt, die variablen der CPU zeit werden mir in der Runtime und auch im variablenhaushalt aktuell angezeigt.
Wieso sollte dann die Synchronisation zwischen SPS und fw nicht richtig sein?

ecb1006b34c7a96717567237acd9d2ac.jpg


Oben system unten CPU var

Ich habe mich mal in das wait eingelesen, dass werde ich noch mal testen. Obwohl die variable ja beim ausführen des Scripts aktuelle werte anzeigt.
 
Ich weiß nicht, was mir das RAW bringen soll, denn die Variable ist ja aktuell, wie man im Bild und auch im Variablenhaushalt beobachten kann.
Meinen Tip, die Variablenwerte im Skript mitzuloggen hast Du vermutlich nicht realisiert? Du vertraust dem Augenschein ...

Die Variablen im Script sind nur dann aktuell, wenn Du sie beobachtest. Wenn Du nicht draufschaust, dann werden die Variablen nicht aktualisiert - wozu auch, wenn kein Objekt die Werte benötigt. :cool:

Du könntest alle Deine GetTagWord durch GetTagWordWait ersetzen. Dann wird sich das Verhalten verbessern, doch auch dies ist nicht sicher, weil nacheinander mehrere Variablen aus der SPS gelesen werden - um die Konsistenz der Variablengruppe zu erhalten darf die SPS in der Zeit keine Variable verändern. Die SPS weiß aber gar nichts davon, daß WinCC angefangen hat die Variablen zu lesen und beschreibt munter weiter die Variablen - dadurch kann es passieren, daß es z.b. beim Lesen der Stunde noch 11:59 Uhr war und beim Lesen der Minute schon 12:00 Uhr ist --> das WinCC-Skript würde die PC-Uhr auf 11:00 Uhr setzen. Falls das gleiche um Mitternacht passiert, dann würde das WinCC-Skript die PC-Uhr auf 23:00 Uhr des Vortages setzen.

Um Datum + Uhrzeit konsistent ins WinCC zu bekommen mußt Du alle Variablen zusammen lesen (als Rohdatenvariable mit GetTagRaw) oder ein Handshake mit der SPS durchführen, damit die SPS die Variablen nicht ändert während das WinCC-Skript liest.

Hier mal ein Beispiel für eine Krücke mit Handshake (die PC-Uhr wird dadurch immer bis zu 1 Sekunde nachgehen).
Die CPU muß die Uhrzeit in die WinCC-Variablen schreiben, wenn das Handshake-Bit = 0 ist. Wenn das Handshake-Bit = 1 ist, dann müssen die WinCC-Variablen unverändert (eingefroren) bleiben.
Code:
#pragma code("kernel32.dll")
VOID SetLocalTime(SYSTEMTIME *lpst);
#pragma code();
SYSTEMTIME zeit;

[COLOR="#008000"]//falls das Handshake-Bit in der CPU noch 1 ist - kurz Uhrzeit eintragen erlauben[/COLOR]
SetTagBitWait("Ber_Sys_CPU_DT_Handshake", 0);

[COLOR="#008000"]//der SPS mitteilen, daß jetzt gelesen werden soll
//die SPS stoppt daraufhin das Schreiben in die DT-Variablen (die Uhrzeit wird eingefroren)[/COLOR]
SetTagBitWait("Ber_Sys_CPU_DT_Handshake", 1);

[COLOR="#008000"]//die eingefrorene Uhrzeit in WinCC einlesen ...[/COLOR]
zeit.wYear=GetTagWordWait("Ber_Sys_CPU_DT_Jahr" + 2000);
zeit.wMonth=GetTagWordWait("Ber_Sys_CPU_DT_Monat");
zeit.wDayOfWeek=GetTagWordWait("Ber_Sys_CPU_DT_Wochentag");
zeit.wDay=GetTagWordWait("Ber_Sys_CPU_DT_Tag");
zeit.wHour=GetTagWordWait("Ber_Sys_CPU_DT_Stunde");
zeit.wMinute=GetTagWordWait("Ber_Sys_CPU_DT_Minute");
zeit.wSecond=GetTagWordWait("Ber_Sys_CPU_DT_Sekunde");
zeit.wMilliseconds=GetTagWordWait("Ber_Sys_CPU_DT_Millisekunden");

[COLOR="#008000"]//... und die PC-Uhr nach dieser Uhrzeit stellen[/COLOR]
SetLocalTime(&zeit);

[COLOR="#008000"]//der SPS mitteilen, daß das Lesen fertig ist und sie wieder in die Variablen schreiben darf[/COLOR]
SetTagBitWait("Ber_Sys_CPU_DT_Handshake", 0);

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
GetTagWord : die Funktion liest den Wert aus der WinCC-Kopie der PLC-Variable, dadurch wird ein Lesen der Variable aus der PLC ausgelöst, die Funktion wartet aber nicht auf den neuen Wert sondern liefert den Wert der vorher drinstand (der Wert kann 1 Sekunde alt sein oder 1 Stunde oder noch nie gelesen worden sein, wenn noch kein Objekt diese Variable benötigt hat)

GetTagWordWait : die Funktion löst das Lesen der Variable aus der PLC aus und wartet auf den neuen Wert und liefert den neu gelesenen Wert

Harald
 
Zurück
Oben