Bild in lightbox öffnen

How To cinnamon Teil 1: Alarme und Meldungen

Einführung

Die Nachrichten- und Ereignisverarbeitung in cinnamon basiert derzeit auf dem TwinCAT 3 EventLogger. Dieser ist gut in das TwinCAT-Ökosystem integriert und ermöglicht die einfache Generierung von Alarmen und Meldungen auf der HMI.

Die Ereignisklassen in cinnamon sind daher im Wesentlichen nur Wrapper-Klassen um die TwinCAT 3 EventLogger-Objekte, die sie mit zusätzlichen Funktionen und den von cinnamon benötigten Schnittstellen ausstatten. Wie beim EventLogger wird zwischen Alarmen und Meldungen unterschieden. Während Meldungen einfach ausgelöst werden können und keine Reaktion des Bedieners erfordern, müssen Alarme vom Bediener quittiert werden. Bei Bedarf können für Alarme Stoppkategorien definiert werden, die in Kombination mit der OpMode-Verarbeitung von cinnamon dazu führen, dass eine Maschine mit unterschiedlichen Geschwindigkeiten stoppt.

Nachrichtendienste dienen zur Verwaltung von Alarmen und Ereignissen; diese Dienste verarbeiten ausgelöste Ereignisse eigenständig. Außerdem implementieren sie ein Beobachtermuster, das Benutzer abonnieren können. Jedes Mal, wenn ein Alarm ausgelöst oder zurückgesetzt wird, benachrichtigen sie alle Abonnenten durch Aufruf von Benachrichtigungsmethoden.

Die Nachrichten- und Ereignisverarbeitung umfasst drei cinnamon-Bibliotheken:

  • Message Interfaces

  • Message Services

  • Concrete Messages

Einen Alarm für den EventLogger erstellen

Klicke mit der rechten Maustaste auf Type System und füge ein neues Item hinzu. Es öffnet sich ein Speicherdialog für eine neue *.tmc-Datei.

Klicke dann mit der rechten Maustaste auf die neue TMC-Datei im Type System und wähle Edit Project File (Projektdatei bearbeiten).

Füge eine neue Ereignisklasse hinzu und gib ihr einen aussagekräftigen Namen.

Die neue Klasse verfügt bereits über einen Event. Bei Bedarf kannst du weitere hinzufügen, indem du mit der rechten Maustaste auf die Ereignisklasse klickst.

Nach dem Erstellen stehen die Ereignisklassen und -strukturen über Global.TC_EVENTS zur Verfügung.

Bei Bibliotheksprojekten musst du eine „ExternalTypes.tmc“-Datei erstellen, um in einem anderen Projekt auf die Ereignisse der Bibliothek zugreifen zu können.

Vorgehen

Klicke mit der rechten Maustaste auf das SPS-Projekt und füge einen globalen Datentyp hinzu.

Wähle die Struktur mit dem Namen deiner Event-Klasse aus (das Präfix „ST_“ wird automatisch hinzugefügt).

cinnamon

Gegenwärtig gibt es im cinnamon Framework zwei Ereignisklassen:

  • TcMessage

  • TcError

Das Präfix Tc weist darauf hin, dass es sich bei beiden um Wrapper für die entsprechenden EventLogger-Klassen FB_TcMessage und FB_TcAlarm handelt.

Deklaration

Beide Klassen erwarten identische Parameter für die Methode FB_Init. Der erste ist das spezifische Ereignis vom Typ TcEventEntry. Dieses darf nicht null sein. Der zweite Parameter ist jedoch optional und kann verwendet werden, um einen bestimmten Nachrichtendienst einzubinden (der die Schnittstelle CNM_MessageInterfaces.IMessageService implementieren muss). Das Ereignis meldet sich dann entsprechend bei diesem Dienst. Wenn kein Dienst eingebunden ist (injectedService := 0), wird standardmäßig der globale Nachrichtendienst verwendet.

myError :CNM_ConreteMessages.TcError(Global.TC_EVENTS.Alarms.myError, 0);
myMessage :CNM_ConreteMessages.TcMessage(Global.TC_EVENTS.Alarms.myMessage, 0);

Wenn ein Ereignis zu einer Funktionsgruppe, einer Funktionseinheit oder einem Gerätetreiber gehört, kann es den zugehörigen Knoten über das Auftreten des Ereignisses benachrichtigen. Jeder Knoten verfügt über einen NodeMessageService, der die entsprechenden HMI-Zustände für den Knoten verwaltet und das Ereignis an den globalen Nachrichtendienst weiterleitet.

Das bedeutet, dass knotenspezifische Fehler, wie zum Beispiel ein Timeout bei einem Zylinder oder eine ungültige Achsposition bei einem Achsentreiber, innerhalb des Knotens mithilfe des Nachrichtendienstes des Knotens behandelt werden:

timeoutError :CNM_ConcreteMessages.TcError(
    Global.TC_EVENTS.CylinderErrors.TimeoutExtend, 
    THIS^.messageService
);

Fehlerbehandlung

Eines der Kernkonzepte hinter den benutzerdefinierten Ereignismechanismen von cinnamon war es, die Fehlerbehandlung so unkompliziert wie möglich zu gestalten. Fehler sollten nach dem „Fire-and-Forget“-Prinzip von jeder Stelle im Code aus ausgelöst werden können, sodass du nicht regelmäßig den aktuellen HMI-Status abfragen musst. Standardmäßig übernimmt der globale Nachrichtendienst das Löschen der Fehler, sobald diese vom Benutzer bestätigt wurden. Das bedeutet, dass es zum Auslösen eines Fehlers ausreicht, die Methode throw() einmal aufzurufen. Natürlich hast du weiterhin die Möglichkeit, Fehler von der SPS aus zu löschen, indem du die Methode clear() einmal aufrufst.

Wenn ein Fehler mit einer bestimmten Ursache zusammenhängt und erst dann gelöscht werden kann, wenn diese Ursache behoben wurde, kannst du den Fehler sperren. Setze dazu die Eigenschaft canBeClearedAutomatically auf FALSE. Der globale Meldungsdienst löscht den Fehler dann nicht automatisch, selbst wenn er vom Bediener bestätigt wurde. Erst wenn canBeClearedAutomatically wieder auf TRUE gesetzt wird, wird der Fehler aus der HMI entfernt und gelöscht.

Standardmäßig ist canBeClearedAutomatically auf TRUE gesetzt.

StopCategories

Alarme definieren Stoppkategorien, die das Verhalten der Maschine steuern:

  • DONT_STOP löst keinen Stopp aus und die Maschine läuft weiter.

  • STOP_AT_END_OF_CYCLE fordert einen Stopp an, nachdem der aktuelle Prozess ordnungsgemäß beendet wurde, wobei sich Zyklus auf den aktuellen Prozess bezieht und nicht auf den SPS-Aufgabenzyklus.

  • STOP_IMMEDIATELY bricht Betriebsmodi sofort ab und ruft auf allen Knoten stopImmediate() auf.

  • DISABLE_MACHINE bricht ebenfalls Betriebsmodi sofort ab und ruft auf allen Knoten disable() auf.

TYPE AlarmStopCategory :
(
	(*do not react to the error*)
	DONT_STOP,
	(*trigger a stop at end of cycle*)
	STOP_AT_END_OF_CYCLE,
	(*stop the machine immediately*)
	STOP_IMMEDIATELY,
	(*disable the machine*)
	DISABLE_MACHINE
)DINT;
END_TYPE

Der OpmodeHandler ist beim globalen Nachrichtendienst abonniert und reagiert entsprechend der jeweiligen Stoppkategorie. Standardmäßig wird die Stoppkategorie anhand der übermittelten Severity des Ereignisses initialisiert: INFO, WARNING und VERBOSE entsprechen DONT_STOP; ERROR entspricht STOP_AT_END_OF_CYCLE; und CRITICAL entspricht STOP_IMMEDIATELY. Die Eigenschaft stopCategory ist bei jedem Alarm vorhanden und kann zur Laufzeit über ihren Setter angepasst werden; DISABLE_MACHINE muss explizit über eine Eigenschaft gesetzt werden.

Automatische Fehlerbehandlung mit CycleManager

CycleManager optimiert die Fehlerbehandlung, indem du cycleManager.handle(error) aufrufen kannst: Die Funktion löst den Fehler einmal aus, prüft regelmäßig, ob er noch aussteht, und fährt automatisch fort, sobald er behoben ist. Wenn der vorherige Schritt den Fehler ausgewertet hat, kann handle zu diesem Schritt zurückkehren. Und wenn du cycleManager.handle(error, resumeWithLastStep := FALSE) aufrufst, fährt CycleManager mit dem nächsten Schritt fort, sobald der Fehler behoben ist – das Verhalten entspricht dem von cycleManager.evaluate(SUCCESS).

VAR_INST
    pusherTimeoutError :CNM_ConcreteMessages.TcError(
        GLOBAL.TcEvents.Alarms.PusherTimeout, 
        THIS^.messageService
    );
END_VAR

EXTEND_PUSHER:
    (* if the pusher.extend() method returns ERROR, the cycleManager will 
    transit to the step PUSHER_TIMEOUT *)
    cycleManager.evaluate(
        state := THIS^.pusher.extend(execute := cycleManager.executeStep),
        errorStep := PUSHER_TIMEOUT
    );
(* there can be a couple of other Steps in between *)
PUSHER_TIMEOUT:
    (* handle throws the error, checks the isPending property of the event. 
    if the error is not pending anymore, the cycleManager will automatically 
    proceed with the step EXTEND_PUSHER and retry the command *)
    cycleManager.handle(pusherTimeoutError);

Wenn die Eigenschaft canBeClearedAutomatically auf FALSE gesetzt ist, bleibt die Methode handle blockiert, bis sie auf TRUE gesetzt und das Ereignis bestätigt wird. Stell sicher, dass im Schritt handle kein Timeout festgelegt ist.

Message Services

Message Services verwalten ausgelöste Ereignisse, wobei ihr genaues Verhalten von der jeweiligen Implementierung abhängt. Jeder Dienst folgt dem Beobachtermuster, sodass Clients sich anmelden oder abmelden können und benachrichtigt werden, sobald Alarme oder Nachrichten ausgelöst oder zurückgesetzt werden. Der globale Message Service überprüft regelmäßig, ob ein Alarm quittiert wurde, und setzt ihn entsprechend zurück, während jeder Knoten einen internen Nachrichtendienst bereitstellt, der die HMI-Signalflags des Knotens verwaltet. Die Provider-Klasse GlobalMessageService macht den globalen Dienst anwendungsweit zugänglich; um darauf zuzugreifen, deklarierst du eine lokale Instanz von CNM_ConcreteMessages.MessageServiceProvider(0). Dieser Provider stellt zwei Mitglieder bereit: messageObserver zum Abonnieren von Benachrichtigungen über ausgelöste oder zurückgesetzte Ereignisse und messageService zur Interaktion mit dem globalen Message Service (z. B. zum Zurücksetzen aller Nachrichten oder zum Prüfen, ob noch welche ausstehen).

Die run Methode des globalen Nachrichtendienstes wird innerhalb von CNM_OpmodeHandling.BaseHmi automatisch aufgerufen. Wird BaseHmi nicht verwendet, muss die run Methode des globalen Nachrichtendienstes einmal pro SPS-Zyklus explizit aufgerufen werden.

Aufruf von GlobalMessageService.run in MAIN()

VAR
    globalService :CNM_MessageServices.GlobalMessageService;
END_VAR

globalService.run();

cinnamon ist verfügbar auf GitHub