WinCC fehlende Inhalte bei Datei Export über WinCC RT Advanced

Laruso

Level-2
Beiträge
10
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebes Forum,

für eine Protokollierung werden (String) Daten in der SPS gesammelt und über WinCC RT Advanced in Dateien gespeichert. Leider gibt es ab und zu unterschiedlich viele leere Inhalte ab Zeile 87 (bzw. jeweils 87tes Element), die ich bislang nicht erklären oder beseitigen konnte.

Berücksichtigt wurde dass
- die SPS die Daten mit Puffern und Handshakes konsistent vorhält, während das HMI Skript die Daten verarbeitet
- die HMI Variablen auf die Erfassungsart "zyklisch fortlaufend" eingestellt sind (etwas schlimmeres Verhalten im Gegensatz zu "zyklisch im Betrieb")
- die Handshake Zeiten mindestens dem Erfassungszyklus der HMI-Variablen entsprechen (um die Daten nicht vorschnell abzulöschen)
- die Kommunikationslast nicht zu hoch ist (<5 %)
- kein anderes Skript während der Ausführung läuft (Verrieglung in SPS mit "busy" flag)
- Array Bereiche von SPS (beliebig beginnend) und HMI (bei 0 beginnend)

Die Anzahl der zu schreibenden Elemente wird über eine Variable angegeben.
Projektiert wird mit TIA V16 Update 6, einem Open Controller mit der Firmware V 21.9.8 und das HMI mit der Firmware V16 Update .
Wenn der Fehler vorkommt (ca. jedes 2-5 mal wenn mehr als 87 Inhalte geschrieben werden sollen), konnte bislang keine Änderung Abhilfe schaffen oder an der Nummer 87 etwas ändern. Versucht wurden unterschiedliche Zeiten bei den Handshakes, Erfassungszyklus der HMI-Variablen und DB ohne Attribute wie "optimierter Bausteinzugriff)

Ich bin um jede Hilfe dankbar.


Hier der Code vom Skript, wobei etliche Zeilen mit ... entfernt wurden, um es hier darstellen zu können:

Code:
Sub Log_DatenSpeichern()
'Tip:
' 1. Verwenden Sie die Tastenkombination <CTRL+SPACE> oder <CTRL+I>, um eine Liste aller Objekte und Funktionen zu öffnen
' 2. Schreiben Sie den Code unter Verwendung des HMI Runtime Objekts.
'  Beispiel: HmiRuntime.Screens("Screen_1").
' 3. Verwenden Sie die Tastenkombination <CTRL+J>, um eine Objektreferenz zu erstellen.
'Schreiben Sie den Code ab dieser Position:



'Declaration of local tags - Deklaration von lokalen Variablen
Dim fso, f, ts, DSString, i, FileName

SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenGeschrieben") = False
SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenNichtGeschrieben") = False

'Error Routine - Fehlerroutine
On Error Resume Next

'Create object - File Objekt erstellen
SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 1
FileName = SmartTags("Log_DB_scriptHandling_sFileName")
Set fso = CreateObject("Scripting.FileSystemObject")
If Err.Number <> 0 Then
    'ShowSystemAlarm "Error #" & CStr(Err.Number) & " " & Err.Description
    SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenNichtGeschrieben") = True
    SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 101
    Err.Clear
    Exit Sub
End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 3
'File path and name has to be either with:
'- UNC (Universal Naming Convention) path / shared names (\\<server>\<share>\<file>) (e.g. \\10.0.0.11\Logs\Log_yyyy-mm-dd)
'- Full qualified path / absolute path (<drive>\<directory>\<file>) (e.g. D:\\Logs\Log_yyyy-mm-dd) (prefered)
'- NT device namespace UNC (\\?\<server>\<share>\<file>) (e.g. \\?\10.0.0.11\Logs\Log_yyyy-mm-dd)
'- NT device namespace / Extended path (\\?\<drive>\<directory>\<file>) (e.g. \\?\D:\\Logs\Log_yyyy-mm-dd)
If Not fso.FileExists(FileName) Then
    fso.CreateTextFile FileName
End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 4
Set f = fso.GetFile(FileName)
If Err.Number <> 0 Then
    'ShowSystemAlarm "Error #" & CStr(Err.Number) & " " & Err.Description
    SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenNichtGeschrieben") = True
    SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 104
    Err.Clear
    Exit Sub
End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 6
Set ts = f.OpenAsTextStream(8, -2)
' mode "8" to append to file
If Err.Number <> 0 Then
    'ShowSystemAlarm "Error #" & CStr(Err.Number) & " " & Err.Description
    SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenNichtGeschrieben") = True
    SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 106
    Err.Clear
    Exit Sub
End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 8
If f.Size = 0 Then
    DSString = "Date" & "    "
    DSString = DSString & "Time of day" & "    "
    DSString = DSString & "Type" & "    "
    DSString = DSString & "Data"
    ts.WriteLine(DSString)
    SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 9
End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 10
' Leider nicht in FOR-Schleife möglich, da Skripte nicht so einfach mit Array of String arbeiten können (B. Baumeister)
' In HMI Skripten kann zwar iniziert auf Array Elemente zugegriffen werden, allerdings nicht mit String Elementen (S. Manko 07.03.2022)

' Falls das Array voll ist, braucht es keine Überprüfung der Anzahl (Performance Gewinn)
If Log_DB_writeBuffer_usiCounter = 200 Then
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[0]")
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[1]")
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[2]")
...
...
...
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[3]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[3]") & "    " &  SmartTags("Log_DB_writeBuffer_arrType[197]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[197]")
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[198]")
    ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[199]")
End If
'If Err.Number <> 0 Then
'    SmartTags("Skript_Log_SchrittZaehler") = 110
'    Err.Clear
'    Exit Sub
'End If

' Falls das Array nicht voll ist, braucht es eine Überprüfung der Anzahl
If Log_DB_writeBuffer_usiCounter < 200 Then
    If Log_DB_writeBuffer_usiCounter >= 1 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[0]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[0]")
    End If
 
    If Log_DB_writeBuffer_usiCounter >= 2 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[1]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[1]")
    End If
 
    If Log_DB_writeBuffer_usiCounter >= 3 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[2]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[2]")
    End If
 
...
...
...
 
    If Log_DB_writeBuffer_usiCounter >= 198 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[197]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[197]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[197]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[197]")
    End If
 
    If Log_DB_writeBuffer_usiCounter >= 199 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[198]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[198]")
    End If
 
    If Log_DB_writeBuffer_usiCounter >= 200 Then
        ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[199]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[199]")
    End If
End If
'If Err.Number <> 0 Then
'    SmartTags("Skript_Log_SchrittZaehler") = 110
'    Err.Clear
'    Exit Sub
'End If

SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 13
'Tidy up --Aufräumen
ts.Close
Set ts = Nothing    ' Necessary to clean up the file handle object
'Set f = Nothing    ' Not necessary and no benefit to clean off bc/o no open handles to be closed
Set fso = Nothing    ' Optional but recommended bc/o open handles and references that are best cleaned off
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 14
'fertig melden
SmartTags("Log_DB_scriptHandling_SkriptKomm_DatenGeschrieben") = True
SmartTags("Log_DB_scriptHandling_iScriptWriteSequenceStep") = 15
'ShowSystemAlarm "Erfolgreich geschrieben!"

End Sub

Hier die Deklaration in der SPS:
1765454480875.png

Und hier die Deklaration im HMI:
1765454730968.png
 
Zuletzt bearbeitet:
Ein Versuch die Arrays auf 86 anstatt 200 zu begrenzen (in Verbindung mit angepassten Erfassungszyklus von 1 s auf 100 ms und angepassten Handshake Zeiten von 2 s auf 200 ms), resultierte darin dass dann teilweise leere Inhalte ab Zeile 58 (bzw. jeweils 58tes Element) fehlen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mich wundert, dass du nach deiner Aussage überhaupt ein paar richtige Einträge in deiner Export-Datei erhältst - oder habe ich dich falsch verstanden?

Ein paar Bemerkungen:
Probiere dein Skript erstmal mit nur 1 bis 10 Variablen anstatt 800 - bei dieser Menge und den langen verschachtelten Variablennamen verliert man die Übersicht.
Ich kann nicht erkennen, wo/wie du da irgendein "Handshake" zwischen HMI und SPS machst. :unsure: Nur einfach Wartepausen > Erfassungszyklus einfügen ist kein Handshake
Deaktiviere mal das On Error Resume Next. Vermutlich entstehen in dem Skript Runtime-Errors, die du aber einfach ignorierst weil du sie nicht siehst? Und baue eine Meldeanzeige für Meldungen der Meldeklasse System aus dem Meldepuffer in ein Bild ein, damit du die Runtime-Error-Meldungen sehen kannst.

Z.B. SmartTags("Log_DB_writeBuffer_arrDate[0]") ist gar kein Element der HMI-Variable "Log_DB_writeBuffer_arrDate". Wenn du auf ein Element des Arrays "Log_DB_writeBuffer_arrDate" zugreifen willst, dann müsstest du schreiben SmartTags("Log_DB_writeBuffer_arrDate")(index)
Ich bin mir auch nicht sicher, ob man überhaupt Strings garantiert aktualisiert aus der SPS ins HMI bekommt, geschweige denn Arrays of String. Variableninhalte garantiert aktualisiert ins HMI bekommt man nur als Rezeptur, oder mit einem ausgefeilten Handshake. Die WinCC RT Advanced ist dafür nicht gut geeignet. Kannst du vielleicht ein externes Programm benutzen, was deine DBs aus der SPS ausliest und speichert?

Ein schnellerer Erfassungszyklus bringt nichts, wenn die Runtime nichts von der Verwendung einer Variable weiß und deshalb die Variable erst nach der Verwendung aktualisiert -egal wie schnell danach

TIA V16 Update 6 ist nicht aktuell.
 
Z.B. SmartTags("Log_DB_writeBuffer_arrDate[0]") ist gar kein Element der HMI-Variable "Log_DB_writeBuffer_arrDate". Wenn du auf ein Element des Arrays "Log_DB_writeBuffer_arrDate" zugreifen willst, dann müsstest du schreiben SmartTags("Log_DB_writeBuffer_arrDate")(index)
:oops: Hmm, gerade mal ausprobiert mit TIA V16 Upd 8. Das Ansprechen von Array-Elementen z.B. SmartTags("Log_DB_writeBuffer_arrDate[0]") funktioniert doch - da wurde wohl in TIA was geändert gegenüber WinCC flex? :unsure:
 
Danke erstmal für deine Antwort und Hilfsbereitschaft!

Mich wundert, dass du nach deiner Aussage überhaupt ein paar richtige Einträge in deiner Export-Datei erhältst - oder habe ich dich falsch verstanden?
Du hast mich schon richtig verstanden. Ich habe grundsätzlich richtige Einträge in meiner Export-Datei. Nur ab und zu gibt es leere Zeilen und/oder leere "Zellen" in der Datei. Zur näheren Untersuchung habe ich vor jeden Eintrag den Laufindex des Arrays geschrieben und so festgestellt dass, wenn was fehlt, es ab einer bestimmten Array Index fehlt. Wie viele Einträge ab diesem Index fehlen ist dann wieder variabel.

Probiere dein Skript erstmal mit nur 1 bis 10 Variablen anstatt 800 - bei dieser Menge und den langen verschachtelten Variablennamen verliert man die Übersicht.
Es sind im Grunde genommen nur vier indizierte Array Variablen (Datum, Uhrzeit, Typ und Daten), mit denen ich 200 Einträge schreiben will (Datum, Uhrzeit, Typ und Daten) und soll letztlich eine allgemeingültige Protokollierung/Log erstellen. Das Ganze passiert dann einfach bis zu 200 Mal. Je nachdem wie viele Einträge sich im Puffer angesammelt haben und geschrieben werden sollen. Das Ergebnis sieht dann z.B. so aus:
Code:
2025-12-11    16:00:00    Step number    +10/+64Process:41
2025-12-11    16:00:00    Step number    +11/+64Process:42
usw.
2025-12-11 16:00:00 Step number +10/+64Process:41
2025-12-11 16:00:00 Step number +11/+64Process:42
usw.

Im Fehlerfall sieht das dann z.B. so aus:
Code:
2025-12-11    16:00:00    Step number    +85/+92Process:41
2025-12-11    16:00:00    Step number    +86/+92Process:42



2025-12-11    16:00:00    Step number    +90/+92Process:43
2025-12-11    16:00:00    Step number    +91/+92Process:43
usw.
Oder z.B. auch mal so:
Code:
2025-12-11    16:00:00    Step number    +85/+92Process:41
2025-12-11    16:00:00    Step number    +86/+92Process:42



    Step number    +90/+92Process:43
2025-12-11    16:00:00    Step number    +91/+92Process:43
usw.

Ich kann nicht erkennen, wo/wie du da irgendein "Handshake" zwischen HMI und SPS machst. :unsure: Nur einfach Wartepausen > Erfassungszyklus einfügen ist kein Handshake
Das liegt daran dass ich es nicht in Gänze dargestellt hatte.

Zum Ablauf:
1. In der SPS wird alles erst in einem "stage buffer" gesammelt.
2. Wenn dieser voll ist oder nach Ablauf einer bestimmten Zeit, wird dieser Puffer in einen "write buffer" kopiert, der dort so lange konsistent die Daten bereithält, wie das Skript zum Schreiben braucht.
3. Eine mit dem HMI verbundene Variable wird durch die SPS erhöht, im HMI auf Wertüberschreitung überwacht und löst somit die Ausführung des Skripts aus.
4. Wenn das Skript fertig ist, setzt dieses eine Variable, auf die wiederum die SPS hört um den Trigger wieder zurückzusetzen.
5. Dann kann das Ganze von vorne beginnen und der zwischenzeitlich wieder gefüllte "stage buffer" in den "write buffer" kopiert werden um die Inhalte in die Datei zu schreiben.

Die erwähnten Wartezeiten in der SPS gibt es damit das HMI auch die Wertänderung der Variablen zum Steuern des Skripts mitbekommt.

Ich denke das ist ein sauberes Vorgehen mit Handshakes. Korrigiert mich gerne, wenn ich was übersehen haben sollte.

Deaktiviere mal das On Error Resume Next. Vermutlich entstehen in dem Skript Runtime-Errors, die du aber einfach ignorierst weil du sie nicht siehst? Und baue eine Meldeanzeige für Meldungen der Meldeklasse System aus dem Meldepuffer in ein Bild ein, damit du die Runtime-Error-Meldungen sehen kannst.
Werde ich testen.
Braucht es dazu neben dem auskommentieren von "On Error Resume Next" auch noch die folgenden Einträge an bestimmten Stellen?:
Code:
If Err.Number <> 0 Then
        ShowSystemAlarm "Error #56" & CStr(Err.Number) & " " & Err.Description
        Err.Clear  
        Exit Sub
End If
Ich hatte das versuchsweise mal so implementiert und dann deutlich weniger oft den Fehler (allerdings ohne bisher "On Error Resume Next" auszukommentieren oder eine Meldeanzeige in einem Bild zu platzieren; das hole ich nun nach):
Code:
...
ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[55]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[55]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[55]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[55]")
ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[56]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[56]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[56]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[56]")
If Err.Number <> 0 Then
    ShowSystemAlarm "Error #56" & CStr(Err.Number) & " " & Err.Description
    Err.Clear  
    Exit Sub
End If
ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[57]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[57]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[57]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[57]")
If Err.Number <> 0 Then
    ShowSystemAlarm "Error #57" & CStr(Err.Number) & " " & Err.Description
    Err.Clear  
    Exit Sub
End If
ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[58]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[58]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[58]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[58]")
ts.WriteLine SmartTags("Log_DB_writeBuffer_arrDate[59]") & "    " & SmartTags("Log_DB_writeBuffer_arrTimeOfDay[59]") & "    " & SmartTags("Log_DB_writeBuffer_arrType[59]") & "    " & SmartTags("Log_DB_writeBuffer_arrData[59]")
...
Funktioniert das mit der Fehlerbehandlung (If Err.Number <> 0) in Skripten überhaupt, wenn "On Error Resume Next" verwendet wird? Oder gehe ich richtig in der Annahme dass entweder das eine oder das andere greift, aber nicht beides verwendet werden sollte?

Z.B. SmartTags("Log_DB_writeBuffer_arrDate[0]") ist gar kein Element der HMI-Variable "Log_DB_writeBuffer_arrDate". Wenn du auf ein Element des Arrays "Log_DB_writeBuffer_arrDate" zugreifen willst, dann müsstest du schreiben SmartTags("Log_DB_writeBuffer_arrDate")(index)
Ich denke es geht wohl beides. Wie gesagt gibt es kein generelles Problem sondern nur ab und an mal Fehler mit leeren Inhalten in einer Zeile bzw. komplett leeren Zeilen.

Ich bin mir auch nicht sicher, ob man überhaupt Strings garantiert aktualisiert aus der SPS ins HMI bekommt, geschweige denn Arrays of String.
Worin begründen sich deine Bedenken? Es sind doch ganz normale HMI Variablen. Ob die nun in einem E/A-Feld angezeigt oder im Skript verwendet werden, sollte doch keinen Unterschied machen.

Variableninhalte garantiert aktualisiert ins HMI bekommt man nur als Rezeptur, oder mit einem ausgefeilten Handshake.
Ja, das lese ich immer wieder von dir. Einen ordentlichen Handshake habe ich allerdings implementiert, so dass die Integrität der Daten gewährleistet ist.

Die WinCC RT Advanced ist dafür nicht gut geeignet.
Wie kommst du darauf? Es ist doch allgemeingültige Praxis, etwaige Daten der SPS über das HMI und ein Skript in eine Datei zu schreiben.

Kannst du vielleicht ein externes Programm benutzen, was deine DBs aus der SPS ausliest und speichert?
Generell ja. Aber ich würde es schon gerne hinbekommen dass über die gewöhnliche Methode zu realisieren.

Ein schnellerer Erfassungszyklus bringt nichts, wenn die Runtime nichts von der Verwendung einer Variable weiß und deshalb die Variable erst nach der Verwendung aktualisiert -egal wie schnell danach
Den schnelleren Erfassungszyklus hatte ich zu Versuchszwecken implementiert, um zu sehen ob sich an der Position des möglichen Fehlers etwas ändert. Aber keine meiner Versuche hatte daran etwas geändert.
Lediglich als ich mir zuletzt gesagt hatte, "OK, wenn es potentiell einen Fehler ab Zeile 87 geben kann, dann reduziere ich mein Array von 220 auf 86 Einträge", hat sich etwas verändert. Dann gab es Fehler ab Zeile 58.
Wenn die Erfassungsart der Variable auf "zyklisch fortlaufend" eingestellt ist, sollte doch die Aktualisierung unabhängig von deren Verwendung passieren. Nicht? Bei meinen Versuchen sah es zumindest so aus, als wenn die Fehler häufiger auftreten als noch mit der Erfassungsart "zyklisch im Betrieb".

Hier mal ein Auszug aus der Dokumentation zu WinCC RT Advanced:
Wenn die benutzerdefinierte VB-Funktion aufgerufen wird und die HMI-Variable nicht in dem aktuell angezeigten Bild verwenden wird, projektieren Sie die HMI-Variable mit der Erfassungsart "Zyklisch fortlaufend". Dadurch ist sichergestellt, dass zu jedem Zeitpunkt der aktuelle Werte der Variable zur Verfügung steht.
Quelle: https://docs.tia.siemens.cloud/r/de...ls-comfort-panels-rt-advanced-rt-professional
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann nicht erkennen, wo/wie du da irgendein "Handshake" zwischen HMI und SPS machst. :unsure: Nur einfach Wartepausen > Erfassungszyklus einfügen ist kein Handshake
Das liegt daran dass ich es nicht in Gänze dargestellt hatte.

Zum Ablauf:
1. In der SPS wird alles erst in einem "stage buffer" gesammelt.
2. Wenn dieser voll ist oder nach Ablauf einer bestimmten Zeit, wird dieser Puffer in einen "write buffer" kopiert, der dort so lange konsistent die Daten bereithält, wie das Skript zum Schreiben braucht.
3. Eine mit dem HMI verbundene Variable wird durch die SPS erhöht, im HMI auf Wertüberschreitung überwacht und löst somit die Ausführung des Skripts aus.
4. Wenn das Skript fertig ist, setzt dieses eine Variable, auf die wiederum die SPS hört um den Trigger wieder zurückzusetzen.
5. Dann kann das Ganze von vorne beginnen und der zwischenzeitlich wieder gefüllte "stage buffer" in den "write buffer" kopiert werden um die Inhalte in die Datei zu schreiben.
Mir scheint, das erkennt nur, ob die am Handshake beteiligten Variablen aktualisiert wurden, aber nicht ob die Nutzdaten im Buffer auch komplett aktualisiert wurden?


Z.B. SmartTags("Log_DB_writeBuffer_arrDate[0]") ist gar kein Element der HMI-Variable "Log_DB_writeBuffer_arrDate". Wenn du auf ein Element des Arrays "Log_DB_writeBuffer_arrDate" zugreifen willst, dann müsstest du schreiben SmartTags("Log_DB_writeBuffer_arrDate")(index)
Ich denke es geht wohl beides. Wie gesagt gibt es kein generelles Problem sondern nur ab und an mal Fehler mit leeren Inhalten in einer Zeile bzw. komplett leeren Zeilen.
Nein, geht nicht beides. Wie ich mit einem kurzen Test festgestellt habe, geht die VBS-konforme Behandlung von Arrays mit HMI-Variablen in WinCC TIA nicht (mehr) - "Ungültige Array-Verwendung". In WinCC TIA trickst das SmartTags-Objekt den Zugriff auf Array-Elemente über Manipulation des Variablenname.


Ich bin mir auch nicht sicher, ob man überhaupt Strings garantiert aktualisiert aus der SPS ins HMI bekommt, geschweige denn Arrays of String.
Worin begründen sich deine Bedenken? Es sind doch ganz normale HMI Variablen. Ob die nun in einem E/A-Feld angezeigt oder im Skript verwendet werden, sollte doch keinen Unterschied machen.
Vor Jahren hatte hier im Forum mal ein User über Tests berichtet, Strings aus der SPS konsistent in die HMI einzulesen, wo immer wieder Fehler auftraten. (ich glaube das war @Thomas_v2.1)
Bei einem E/A-Feld ist es ziemlich egal, ob da der aktuelle und korrekte Wert nach 1, 2 oder 3 Sekunden angezeigt wird. Will man den Wert in eine Datei wegschreiben, dann muss der aktuelle Wert schon beim ersten Lesezugriff drinstehen.


Variableninhalte garantiert aktualisiert ins HMI bekommt man nur als Rezeptur, oder mit einem ausgefeilten Handshake.
Ja, das lese ich immer wieder von dir. Einen ordentlichen Handshake habe ich allerdings implementiert, so dass die Integrität der Daten gewährleistet ist.
Es sieht aber so aus, dass dein Handshake die garantierte Aktualisierung eben nicht gewährleistet. Manchmal ist mehr als die Hälfte der Variablen noch leer ... weil die Nutzdaten nicht kontrolliert aktualisiert werden.


Die WinCC RT Advanced ist dafür nicht gut geeignet.
Wie kommst du darauf? Es ist doch allgemeingültige Praxis, etwaige Daten der SPS über das HMI und ein Skript in eine Datei zu schreiben.
Klar kann man auch mit WinCC RT Advanced Daten aus der SPS ins HMI einlesen und in eine Datei schreiben. Man muss aber explizit dafür sorgen, dass die Werte auch wirklich "garantiert" aktualisiert wurden, bevor man die in eine Datei schreibt. Die WinCC RT Advanced unterstützt das Warten auf die Aktualisierung nicht mit einfachen Systemfunktionen. Tagread-Funktionen mit explizitem Wait gibt es nicht. Skripte warten nicht auf die Aktualisierung. Man kann nicht vorgeben oder "erzwingen", wann eine HMI-Variable aktualisiert wird und erhält auch keine Info, ob/wann sie aktualisiert wurde. Man kann höchstens erkennen, ob sich der Wert geändert hat (durch der Aktualisierung). Explizites Lesen aktueller Werte geht nur mit der Systemfunktion GetDataRecordTagsFromPLC für Rezeptur-Variablen. Manchen Programmierern ist das allerdings zu viel Arbeit ... und stümpern eine "Lösung" mit alle Variablen zweimal lesen und dazwischen 1 Minute warten und hoffen, dass dann "aber bestimmt" die Werte aktualisiert wurden ... Alternativen: ein "richtiges" WinCC (V7.x ... V8.x) oder WinCC Professional verwenden. Oder externe Programme mit eigener Kommunikation zur SPS. Da gibt es mehrere fertige Lösungen, die man einfach konfigurieren kann.


Hier mal ein Auszug aus der Dokumentation zu WinCC RT Advanced:
Wenn die benutzerdefinierte VB-Funktion aufgerufen wird und die HMI-Variable nicht in dem aktuell angezeigten Bild verwenden wird, projektieren Sie die HMI-Variable mit der Erfassungsart "Zyklisch fortlaufend". Dadurch ist sichergestellt, dass zu jedem Zeitpunkt der aktuelle Werte der Variable zur Verfügung steht.
Quelle: https://docs.tia.siemens.cloud/r/de...ls-comfort-panels-rt-advanced-rt-professional
Ja, ganz clevere Idee! :rolleyes: 800 Variablen, deren Wert man einmal am Tag braucht, ständig auf Vorrat zu lesen ... womöglich noch alle 100ms ...
 
Vor Jahren hatte hier im Forum mal ein User über Tests berichtet, Strings aus der SPS konsistent in die HMI einzulesen, wo immer wieder Fehler auftraten. (ich glaube das war @Thomas_v2.1)
 
Zurück
Oben