WinCC Skripte in verschiedenen HMIs? Skript abbrechen/resetten?

Geisterkarle

Level-2
Beiträge
126
Reaktionspunkte
9
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe in meinem HMI (in diesem Falle ein KT770F Mobile) Rezepte für meine Anlage angelegt. Mit einem Triggerbit starte ich von meiner SPS aus einen Rezeptwechsel bzw. laden im HMI. (bevor jemand fragt, warum ich ein Skript benutze: Ich muss das Rezept mit dem DatensatzNAMEN laden. Das geht - meines Wissens nach - nicht über einen Steuerungsauftrag).
Prinzipiell klappt das auch ... außer es tut nicht! Irgendwas passiert dann im HMI und steigt aus! Anstatt ein Rezept zu laden lande ich immer in einem programmierten Timeout. Die "Lösung" ist dann, die HMI-Runtime zu beenden, neuzustarten und das Triggerbit neu zu senden. Schon geht es!
Die Frage ist: Was ist los? Ich benutze das identische Skript und Programmierung auf SPS Seite an einer anderen Maschine, da gibt es keine Probleme! Der einzige Unterschied ist, dass wir hier ein festverbautes TP700 Comfort Panel nutzen. Hat das Mobile Panel hier bekannte Probleme oder so?
Und wie könnte man das lösen? Ich bekomme auf SPS Seite durch den Timeout den Fehler sozusagen mit. Ich könnte irgendwie reagieren ... Theorie von mir ist ja, dass da irgendwas im Skript sich aufhängt. Daher die Frage: Kann ich irgendwie das HMI veranlassen, alle Skripte abzubrechen (möglicherweise mit einem Skript - höhö) oder sowas?
Ich kann gerne auch mein wildes Skript zeigen. (Rezepte laden ausm Panel ist ein Schund!) Möglicherweise ist ja mein Handshake mit dem Panel (ja, ich mach so was verrücktes...) ein Problem!
Oder hat wer noch Ideen?

grüßle
 
Moin Gesterkarle,

zunächst einmal: Du meinst ein KTP700F mobile (ein KT770F mobile gibt es meines Wissens nicht!?)?

Wird das Triggerbit denn irgendwann auch einmal zurückgesetzt?
Kann es ein Kommunikationsproblem sein (mobile-Panel an Profinet / festes Panel an Ethernet)?
Benutzt Du im Skript das Fehlerhandling "ON ERROR RESUME NEXT", so dass das Skript bei einem Fehler nicht einfach an der Stelle "stehen" bleibt?
Bei Skripten, die durch die Steuerung angestoßen werden, ist ein Handshake sehr zu empfehlen (ein Handshake ist in fast allen Kommunikationsbereichen zu empfehlen).

Ja, zeig doch mal Dein "wildes Skript" :ROFLMAO:

VG

MFreiberger
 
Oh, ja, vertippt. KTP700F!

Ja, das Triggerbit wird auch in meinem Fehlerfalle zurückgesetzt.

"ON ERROR RESUME NEXT" ... Nein! Das klingt sehr interessant!

Das Panel ist aktuell eigentlich immer an der gleichen Box angesteckt! Hab auch gar keine zweite im System ;)

Hier mal mein Skript:
Code:
Sub Rezept_laden()

HmiRuntime.Trace "Rezept wird geladen"


' Daten ablöschen
SmartTags("INT_Rezept_Laden")=0
ResetBit "DB_Rezept_Handling_Laden_Laden_ok"
ResetBit "DB_Rezept_Handling_Laden_Laden_nok"
' Skript gestartet zur Überwachung in SPS
SetBit "DB_Rezept_Handling_Laden_Laden_laeuft"


SmartTags("DB_Rezept_Handling_Laden_TestPos")=1
' Warten auf Stationsnummer >0 / Rezept <> 0
Do Until SmartTags("DB_Rezept_Handling_Laden_StationsNr")>0
    'wait
Loop
    ' Aufruf Rezept laden
SetDataRecordToPLC SmartTags("DB_Rezept_Handling_Laden_StationsNr"), SmartTags("DB_Rezept_Handling_Laden_RezeptName"), hmiOn, "INT_Rezept_Laden"
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=2
    
' Warten bis Ergebnis da 
Do             
    'wait 
Loop Until (SmartTags("INT_Rezept_Laden")>2)
    
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=3
' Ladestatus in SPS schreiben zur Überwachung    
SmartTags("DB_Rezept_Handling_Laden_Lade_Status")=SmartTags("INT_Rezept_Laden")
    
' Ergebnis Auswerten    
If SmartTags("INT_Rezept_Laden")=4 Then
        SmartTags("DB_Rezept_Handling_Laden_TestPos")=4
     SetBit "DB_Rezept_Handling_Laden_Laden_ok"
Else
        SmartTags("DB_Rezept_Handling_Laden_TestPos")=5
    SetBit "DB_Rezept_Handling_Laden_Laden_nok"
End If
    
    
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=6
' "Handshake" über Schrittkette der SPS // Startsignal hat irgendwie nicht funktioniert...
Do Until (SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=125 Or SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=150)
    'wait
Loop
         
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=7
' Warten auf Stationsnummer=0    
Do Until (SmartTags("DB_Rezept_Handling_Laden_StationsNr")=0)
    'wait
Loop
' Ergebnisbits zurücksetzen
ResetBit "DB_Rezept_Handling_Laden_Laden_ok"
ResetBit "DB_Rezept_Handling_Laden_Laden_nok"


SmartTags("DB_Rezept_Handling_Laden_TestPos")=8
HmiRuntime.Trace "Rezept laden fertig"
' Skript ist beendet für SPS
ResetBit "DB_Rezept_Handling_Laden_Laden_laeuft"



End Sub

Die TestPos war nur für mich, um zu sehen, wo ich hängen bleibe! Habe hier auch schon einen Fehler gefunden, dachte "8, ich bin ja durch" aber gab - hier entfernt - mittendrin eine Zeile, wo ich mir auch "8" ausgegeben habe! Vielleicht hing ich an ner doofen Stelle...
Und das Triggerbit wird über die Schrittkette 125/150 zurückgesetzt (das Bit abzufragen hat irgendwie nicht funktioniert...)

Bitte den Kaffee abstellen vor dem Hände über den Kopf zusammenschlagen ;)

Aber diese Errorroutine ... wie funktioniert die? Wenn ich
Code:
On Error Resume Next
Einfüge, dann geht das ... aber würde gerne im Fehlerfalle irgendwelche Bits noch zurück setzen.
Lese, man kann angeblich auch ein Skript aufrufen, aber
Code:
On Error GoTo [COLOR=#3E3E3E][FONT=Courier]ErrorHandling[/FONT][/COLOR]
und ein neues Skript
Code:
Sub ErrorHandling()       
       ResetBit "DB_Rezept_Handling_Laden_Laden_ok"
    ResetBit "DB_Rezept_Handling_Laden_Laden_nok"
    ResetBit "DB_Rezept_Handling_Laden_Laden_laeuft"
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=9


End Sub
Schmeisst mir wieder Fehlermeldung... hm...

Danke aber soweit mal!
 
und ein neues Skript
NEIN! Kein "neues" Script, sondern im vorhanden integrieren!!!
Code:
SUB irgendwas
    ON ERROR GOTO ErrorHandling
    ' das Script
EXIT SUB ' Hier das "eigentliche" ProgrammEnde - ErrorHandling überspringen!
    ErrorHandling:
    ' z.B. Ausgabe im DirektBereich:
    Debug.Print Err.Number, Err.Description  ', Err.Source, Err.HelpFile, Err.HelpContext
    RESUME NEXT
END SUB

'ErrorHandling:' ist ein ganz "stinknormales" Sprungziel, aber das kennt ja heutzutage keiner mehr, weil das Benutzen von GOTO ach so verpönt ist. ;)
Darum heisst bei mir das Sprungziel nicht 'ErrorHandling:', sondern kurz und bündig 'Hell:' und die Aktivierung 'ON ERROR GOTO Hell' :ROFLMAO:
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Geisterkarle,

mit

Code:
If Err.Number <> 0 Then
    "Irgendein Ausgabefeld".text = Err.Description
    Exit Sub
End If

kannst Du Dir die Fehlerbeschreibung in einem IOFeld oder TextFeld oder so anzeigen lassen. Oder sonst irgend etwas machen.

VG

MFreiberger
 
Code:
SUB irgendwas
    ON ERROR GO TO ErrorHandling
    ' das Script
EXIT SUB ' Hier das "eigentliche" ProgrammEnde - ErrorHandling überspringen!
    ErrorHandling:
    ' z.B. Ausgabe im DirektBereich:
    Debug.Print Err.Number, Err.Description  ', Err.Source, Err.HelpFile, Err.HelpContext
    RESUME NEXT
END SUB
Also wenn ich genau das mache, dann meckert mein Debugger schon das "Go" an, kennt er nicht.
GoTo akzeptiert er, aber dann kennt er "hell" (von mir aus ;) ) nicht!
Genau das Beispiel hatte ich auch Online gefunden, das Siemens Panel macht das aber irgendwie nicht mit... Hab in der offiziellen Hilfe was gefunden, aber ist etwas komisch...
Code:
Sub OnClick(ByVal Item)'VBS27
  Dim objScreenItem
'
  'Activation of errorhandling:
  On Error Resume Next
  For Each objScreenItem In ScreenItems
    If "HMIRectangle" = objScreenItem.Type Then
    '
      '=== Property "RoundCornerHeight" only available for RoundRectangle
      objScreenItem.RoundCornerHeight = objScreenItem.RoundCornerHeight * 2
      If 0 <> Err.Number Then
        HMIRuntime.Trace objScreenItem.Name & ": no RoundedRectangle" & vbCrLf
        '
        'Delete error message
        Err.Clear
      End If
    End If
  Next
  On Error Goto 0  'Deactivation of errorhandling
End Sub
GoTo gibts anscheinend nicht so wirklich...
Anscheinend muss ich da nach jeder Anweisung, die einen Fehler produzieren könnte, ein Fehlerhandling machen... das ist umständlich!
 
Du hast Recht: das Leerzeichen zwischen GO und TO darf nicht sein. Sorry.

Du findest das Beispiel aus der offiziellen Hilfe komisch. Ist es auch. Für die FOR-Schleife mit allem drum und drin wird dafür gesorgt, dass im FehlerFall der Fehler-produzierende Befehl ignoriert und mit dem folgenden Befehl fortgesetzt wird. Das kann durchaus sinnvoll sein. Kann aber auch dafür sorgen, dass man im FehlerFall den eigentlichen Auslöser übersieht.
Immerhin wird nach der Schleife die FehlerBehandlung mit 'On Error Goto 0' wieder auf "normal" zurückgestellt.
Aber damit sehen wir hier auch, dass VBS das Goto kennt und nicht bemeckert.

Du schreibst GoTo gibt's anscheinend nicht wirklich. Woran scheitert's denn jetzt noch?
Du musst beachten, dass das Sprungziel am Anfang der FehlerBehandlung (mit dem ':' als SprungzielKennzeichnung) in derselben Function oder Sub steht wie der "bedingte SprungBefehl" 'On Error Goto Sprungziel'.
Und, dass die FehlerBehandlung nicht durchlaufen wird, wenn kein Fehler auftritt. Darum parke ich die Routine vor das 'End Sub' (bzw. 'End Function') und setze 'Exit Sub' (bzw. 'Exit Function') vor die Routine.

PS:
... Anscheinend muss ich da nach jeder Anweisung, die einen Fehler produzieren könnte, ein Fehlerhandling machen... das ist umständlich!
Ja, FehlerBehandlung ist leider umständlich ... und wird deshalb leider oft "vergessen".
Manchmal mache ich es im Programm so, dass ich an mehreren Stellen verschiedene KennZiffern in eine (in Worten: 1) Variable speichere. Die kann ich dann in der FehlerBehandlung abfragen und weiss, in welchem Bereich des Programms der Fehler liegen muss.
Stattdessen kann man aber auch verschiedene FehlerBehandlungsRoutinen anlegen, die natürlich alle ein eigenes Sprungziel benötigen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
' Warten auf Stationsnummer >0 / Rezept <> 0
Do Until SmartTags("DB_Rezept_Handling_Laden_StationsNr")>0
    'wait
Loop
...
Do Until (SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=125 Or SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=150)
    'wait
Loop
...
' Warten auf Stationsnummer=0    
Do Until (SmartTags("DB_Rezept_Handling_Laden_StationsNr")=0)
    'wait
Loop
Kann es sein, daß Dein Skript in diesen Schleifen festhängt? Die Schleifen haben keinen Notausgang oder Timeout.

In der WinCC RT kann immer nur 1 Skript ausgeführt werden. Solange ein Skript ausgeführt wird (z.B. in einer Schleife festhängt), kann kein weiteres Skript ausgeführt werden. Also fällt schon mal aus, ein Skript mit einem anderen Skript abzubrechen...

Wie lange dauert das Warten auf die Schrittkette? Stehen die Schritte 125 und 150 auch lange genug an, daß das Panel die Schritte mitbekommt? Besser: die Schrittkette setzt eine separate Fertig-Variable.

Du könntest das Skript vor dem Warten auf die Schrittkette beenden, und auf die Variable "DB_Rezept_Handling_Laden_Schrittkette" (oder die Fertig-Variable) ein Ereignis "Wertänderung" projektieren, das ein zweites Skript mit den restlichen Anweisungen aufruft. (Dem Skript kannst Du gleich den Wert der Variable mitgeben, dann vereinfacht sich die Wert-Prüfung am Anfang des Skriptes.)
Code:
If Not (SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=125 Or SmartTags("DB_Rezept_Handling_Laden_Schrittkette")=150) Then
    Exit Sub 'falscher 
Else 'Anweisungen nur bei 125 oder 150 ausführen
   ...
End If


Code:
' Warten bis Ergebnis da 
Do             
    'wait 
Loop Until (SmartTags("INT_Rezept_Laden")>2)
    
    SmartTags("DB_Rezept_Handling_Laden_TestPos")=3
' Ladestatus in SPS schreiben zur Überwachung    
SmartTags("DB_Rezept_Handling_Laden_Lade_Status")=SmartTags("INT_Rezept_Laden")
Ich würde das wohl so machen, da kann die SPS (und Du) den Status beim Rezept-Laden beobachten:
Code:
' Warten bis Ergebnis da 
Do             
    ' Ladestatus in SPS schreiben zur Überwachung    
    SmartTags("DB_Rezept_Handling_Laden_Lade_Status")=SmartTags("INT_Rezept_Laden")
    'wait 
Loop Until (SmartTags("INT_Rezept_Laden")>2)
oder gleich "DB_Rezept_Handling_Laden_Lade_Status" als Statusvariable verwenden:
Code:
SetDataRecordToPLC SmartTags("DB_Rezept_Handling_Laden_StationsNr"), SmartTags("DB_Rezept_Handling_Laden_RezeptName"), hmiOn, "DB_Rezept_Handling_Laden_Lade_Status"
dann könnte man sogar nach dem SetDataRecordToPLC das Skript beenden und auf das Ereignis "Wertänderung" von "DB_Rezept_Handling_Laden_Lade_Status" ein Fortsetzungs-Skript aufrufen.

Harald
 
@Heinilein:
Der erkennt die untergeordnete Routine nicht!
Hab mal ein mega leeres Skript erstellt und die Fehlermeldung des Mousehovers gescreenshotted:

fehlferfehler.png

Oder was wäre an dem Code falsch?

@PN/DP:
Kann durchaus sein, dass ich da irgendwo festhänge! Und ja, könnte auch sein, dass das Panel die Signale nicht mitbekommt! Das war ja z.B. meine erste Schleife: Eigentlich wird das Triggerbit und diese Stationsnummer gleichzeitig gesetzt und ich hatte es öfters, dass zwar der Trigger durch kam und das Skript gestartet wurde, aber die Stationsnummer wurde noch als 0 erkannt. Da ist irgendwas sehr asynchron!
Sind gute Tipps! Werde ich mal umsetzen und "prüfen" (kann schwer den Fehler simulieren...)

Die Fehlerauswertung wäre aber auch was nettes, wenn ich da was umsetzen könnte! Mal sehen wie sich das entwickelt :)
 
Hallo Karle,

grundsätzlich kann hier kein ErrorHandling à la "On Error GoTo ErrorHandler" verwendet werden, da keine Sprungmarken unterstützt werden.

Funktionieren würde die Kombination aus "On Error Resume Next" und Auswertung des Err-Objekts, wie MFreiberger schon rudimetät beschrieben hat.
Ich verwende z.B.

"If Err.number <> 0 then ..."

nach jedem Codeblock, wo Berechnungen/Schleifen/Arraybearbeitungen vorkommen, um so auf Laufzeitfehler reagieren zu können.
Wenn möglich fange ich Problemfälle (z.B. eine mögliche Division durch 0) schon vorher ab.


Zusätzlich habe ich mir vor einiger Zeit mal Hilfsskripte erstellt, die mir (eingeschränkt) eine Programmierung nach dem Try/Catch-Pinzip ermöglicht:
Code:
...
Try(TRY_FIRST)
    <Codeblock>
If Try(TRY_NEXT) Then
    <Codeblock>
end if
if Catch(EId_ALL) Then
    <Fehlerbehandlung>
End if
Kenne ich von Java und fand ich immer sehr elegant und gut lesbar.


Gruß, Fred
 
Zurück
Oben