Remanente Variablen - RETAIN, PERSISTENT

Remanente Variablen können ihren Wert über die übliche Programmlaufzeit hinaus behalten. Sie können remanente Variablen als RETAIN-Variablen oder noch strenger als persistente Variablen in der Applikation deklarieren. Voraussetzung für die volle Funktionalität ist ein entsprechender Speicherbereich auf der Steuerung (NVRam, USV). Wenn es den entsprechenden Speicherbereich nicht gibt, gehen bei einem Stromausfall auch die Werte von VAR RETAIN oder VAR PERSISTENT Variablen verloren!

Hinweis

  • CODESYS behandelt eine VAR PERSISTENT-Deklaration gleich wie eine VAR PERSISTENT RETAIN- oder VAR RETAIN PERSISTENT-Deklaration.
  • Wenn Sie ein CoDeSys V2.3-Projekt öffnen, bleiben die Deklarationen von Retain-Variablen erhalten und unverändert wirksam. Die Deklarationen von persistenten Variablen jedoch müssen Sie überarbeiten oder neu erstellen. Für V3 müssen Sie eine eigene globale Variablenliste erstellen!
  • Die AT-Deklaration dürfen Sie nicht in Kombination mit VAR RETAIN oder VAR PERSISTENT verwenden!

RETAIN-Variablen

Sie deklarieren RETAIN-Variablen, indem Sie im Deklarationsteil von Programmierobjekten hinter dem Schlüsselwort für den Variablentyp (VAR, VAR_GLOBAL, etc.) das Schlüsselwort RETAIN hinzufügen.

RETAIN-Variablen behalten ihren Wert nach einem unkontrollierten Beenden (oder Onlinebefehl Reset warm). Bei erneutem Start des Programms arbeitet das System mit den gespeicherten Werten weiter. In diesem Fall initialisiert CODESYS “normale” Variablen neu, entweder mit ihren explizit vorgegebenen Initialwerten oder mit den Standardinitialisierungen.

Als RETAIN deklarierte Variablen werden zielsystem-abhängig, aber typischerweise in einem eigenen Speicherbereich verwaltet, der gegen Stromausfall gesichert sein muss.

CODESYS initialisiert RETAIN-Variablen neu bei

  • dem Befehl Reset Ursprung
  • dem Befehl Reset kalt (im Gegensatz zu persistenten Variablen)
  • einem erneutem Programm-Download

Beispiele

In einer POU:

VAR RETAIN
 iRem1 : INT;
END_VAR

In einer GVL:

VAR_GLOBAL RETAIN
 gvarRem1 : INT;
END_VAR

Der Grad der Werteerhaltung von RETAIN-Variablen ist automatisch in der von PERSISTENT-Variablen enthalten.

Eine mögliche Anwendung ist ein Stückzähler in einer Fertigungsanlage, der nach einem Stromausfall weiterzählen soll.

Hinweis

  • Wenn Sie eine lokale Variable in einem Programm als RETAIN deklarieren, speichert CODESYS genau diese Variable im Retain-Bereich (wie eine globale Retain-Variable).
  • Wenn Sie eine lokale Variable in einem Funktionsbaustein als RETAIN deklarieren, speichert CODESYS die komplette Instanz dieses Funktionsbausteins im Retain-Bereich (alle Daten des Bausteins), wobei jedoch nur die deklarierte RETAIN-Variable als solche behandelt wird.
  • Wenn Sie eine lokale Variable in einer Funktion als RETAIN deklarieren, hat dies keine Auswirkung. CODESYS speichert die Variable nicht im Retain-Bereich. Wenn Sie eine lokale Variable in einer Funktion als PERSISTENT deklarieren, bleibt dies ebenfalls ohne Wirkung.

Persistente Variablen

PERSISTENT-Variablen behalten wie die RETAIN-Variablen ihre Werte bei einem Reset kalt, bei einem erneuten Download der Applikation und bei einem Reset warm (deshalb entspricht VAR PERSISTENT immer einer VAR PERSISTENT RETAIN bzw. VAR RETAIN PERSISTENT Deklaration) CODESYS initialisiert PERSISTENT-Variablen somit nur bei Reset Ursprung neu.

Ein Anwendungsbeispiel für persistente Variablen ist ein Betriebsstundenzähler, der nach einem Stromausfall und auch nach einem erneuten Download der Applikation weiter zählen soll.

2 Möglichkeiten, um persistente Variablen zu definieren

  • Deklaration mit dem Persistenzeditor in einer speziellen globalen Variablenliste des Objekttyps Persistente Variablen, die zu einer Applikation gehört (VAR_GLOBAL PERSISTENT). Es kann nur EINE solche Liste pro Applikation geben und nur in dieser Liste mit PERSISTENT deklarierte Variablen behandelt CODESYS als persistent. VAR PERSISTENT-Deklarationen, die in anderen POUs vorliegen, fügen Sie mit dem Menübefehl Deklarationen ‣ Alle Instanzpfade hinzufügen der Liste hinzu. Globale PERSISTENT-Deklarationen in anderen Bausteinen sind nicht erlaubt. Für persistente Variablenlisten muss es wie für Retain-Variablen einen entsprechend gesicherten Speicherbereich auf der Steuerung geben, um die Werteerhaltung auch bei Stromausfall zu garantieren!
  • Definition im Persistence Manager des Application Composer. Dies erfolgt über einen komplett anderen Mechanismus als bei der Deklaration der VAR PERSISTENT im Persistenzeditor und erfordert beispielsweise keine spezielle Speicherausstattung. Weitere Informationen hierzu finden Sie in den Kapiteln zum Persistence Manager des Application Composers.

Bemerkung

Ab CODESYS V3.3.0.1 bewirkt eine Deklaration mit VAR_GLOBAL PERSISTENT dasselbe wie eine Deklaration mit VAR_GLOBAL PERSISTENT RETAIN oder VAR_GLOBAL RETAIN PERSISTENT.

Beispiel

Persistente Variablenliste:

VAR_GLOBAL PERSISTENT RETAIN
 iVarPers1 : DINT; (* 1. persistent+retain variable App1 *)
 bVarPers : BOOL;  (* 2. persistent+retain variable App1 *)
    // instance path of the persistent variables created
    PLC_PRG.PERS: INT;
END_VAR

Hinweis

  • Sie sollten die Verwendung des Datentyps POINTER TO in persistenten Variablenlisten vermeiden, da sich die Adresswerte bei erneuten Downloads der Applikation verändern können! CODESYS gibt entsprechende Compilerwarnung aus.
  • Bei jedem erneuten Laden der Applikation vergleicht CODESYS die persistente Variablenliste auf der Steuerung mit der des Projekts. Bei Inkonsistenzen, also Veränderungen von Deklarationen und Positionen innerhalb der Liste, fordert Sie CODESYS vor dem Download zu einer Re-Initialisierung aller persistenten Variablen auf. Inkonsistenz entsteht durch Umbenennen oder Löschen oder sonstige Veränderung bestehender persistenter Variablendeklarationen.

Mechanismus der Persistenz über VAR PERSISTENT

Persistente Variablen sollten verwendet werden, wenn Variablen benötigt werden, deren Wert auch nach einem Download erhalten bleiben soll. Prinzipiell können Sie eine Applikation komplett ändern: solange die Applikation den gleichen Namen hat wie eine auf der Steuerung befindliche Applikation und die gleiche Liste von persistenten Variablen, dann werden die Werte der vorhergehenden Liste übernommen. “Gleich” bedeutet in diesem Zusammenhang, die Variablen in der Liste müssen in der gleichen Reihenfolge deklariert sein, sie müssen den gleichen Namen haben und den gleichen Datentyp wie die Variablen auf der Steuerung. Dies wird überprüft durch eine Checksumme über die Liste der Variablen, die auch auf der Steuerung gespeichert wird.

Der Mechanismus funktioniert nur dann gut, wenn die Variablen selbst nicht gravierend geändert werden. Änderungen in einer bestehenden persistenten Variablenliste können zu Neu-Initialisierungen, also Verlust der Persistenz führen. Wenn Sie aufgrund des Anwendungsbereichs häufige Änderungen vorausehen, ist eine solche Liste grundsätzlich nicht zu empfehlen. Das betrifft in erster Linie die Veränderung des Namens oder Datentyps einer bereits deklarierten Variable (siehe unten: “Änderung einer bestehenden Deklaration”). Persistente Variablen sind bei einem Online-Change gegen Datentypänderungen weniger robust als normale Variablen. Der Editor handhabt das Einfügen neuer Deklarationen oder Löschen bestehender Deklarationen bei neueren CODESYS-Versionen (> V3.5 SP1) folgendermaßen:

Der Editor für die Persistente Variablenliste ordnet die persistenten Variablen so wie die Variablen auf der Steuerung erwartet werden. Die Technik ist die Folgende: Auf der Steuerung hinterlegt CODESYS eine Checksumme und die Länge der persistenten Variablen. Beim Download lädt CODESYS diese Werte hoch und vergleicht sie mit den aktuellen Werten. Alle Variablen bis zu der angegebenen Länge werden mit den aktuellen Variablen im Projekt verglichen. Wenn die Variablen noch gleich sind, dann bleiben sie uninitialisiert, die neuen Variablen werden initialisiert. Der Editor greift in die Variablenliste ein, das heißt, er ersetzt gelöschte Variablen im Speicher durch Platzhalter-Variablen und verschiebt neu eingefügte Variablen an das Ende der Liste. Die Reihenfolge im Editor entspricht dann nicht mehr der Reihenfolge im Speicher. Dadurch können Sie scheinbar beliebig ändern, aber Sie erzeugen Lücken. Diese Lücken führen dazu, dass unter Umständen der Speicher für Platzhalter-Variablen nicht mehr ausreicht. Deswegen sollten Sie nach einiger Zeit die Lücken bereinigen (Befehl Liste neu ordnen und Lücken bereinigen). Nach dem Bereinigen wird die Liste jedoch nicht mehr zu der Liste auf der Steuerung passen und die persistenten Variablen werden initialisiert werden.

Daten retten über den Rezepturverwalter: Um die Daten zu retten, speichern Sie die Daten mit Hilfe des Rezepturverwalters in einer Rezeptur. Dadurch wird im Rezepturverwalter eine neue Liste für alle Variablen der persistenten Variablenliste erzeugt und gleichzeitig werden die aktuellen Werte von der Steuerung als Rezeptur abgespeichert. Anschließend führen Sie den Befehl Liste neu ordnen und Lücken bereinigen aus und führen Sie einen erneuten Download aus. Wenn Sie nur den Befehl Werte aus Rezeptur wiederherstellen auswählen, werden die in der Rezeptur gespeicherten Werte wieder hergestellt.

Änderung einer bestehenden Deklaration in der Persistenten Variablenliste: Wenn Sie den Namen oder Datentyp einer Variablen ändern, gilt das als neue Deklaration und bewirkt beim nächsten Online-Change oder Download eine Neu-Initialisierung der Variablen! Eine Änderung eines benutzerdefinierten Datentyps liegt beispielsweise vor: Wenn eine neue Variable in einer Struktur hinzugefügt wird, oder wenn sich in der Tiefe einer verwendeten Struktur der Typ einer Variablen von INT nach UINT ändert. Somit sind komplexe benutzerdefinierte Datentypen für die Verwaltung in einer Persistenten Variablenliste nicht geeignet, zumindest wenn die Definition des benutzerdefinierten Datentyps voraussichtlich immer wieder geändert werden muss.

Abbilden auf bestehende Variable: Eine beliebige Variable in einem Funktionsbaustein, einer globalen Variablenliste oder in einem Programm kann als PERSISTENT RETAIN markiert werden. Damit diese Variable wirklich persistent ist, muss sie mit dem Befehl Alle Instanzpfade hinzufügen in die Liste der persistenten Variablen eingetragen werden. In die Liste der persistenten Variablen wird dann ein Platzhalter für die jeweilige Variable eingefügt. Die Persistenz der Variable wird über folgenden Mechanismus garantiert:

  • Es wird ermittelt in welchen zyklischen Tasks ein Zugriff auf die Variable erfolgt
  • Am Ende der ersten zyklischen Task wird die Variable in die persistenten Variablen kopiert (und zwar in jedem Zyklus)
  • Nach dem Neustart der Steuerung wird der Wert von der persistenten Variable in die normale Variable kopiert

Diese persistenten Variablen belegen doppelten Speicherplatz: zum einen an der Deklarationsstelle und zum anderen im Bereich der persistenten Variablen, und sie müssen in jedem Zyklus kopiert werden. Insbesondere wenn es sich um große strukturierte Werte handelt, kann das zeitintensiv sein. Es ist in jedem Fall zu bevorzugen, persistente Variablen direkt in der Liste der persistente Variablen zu deklarieren.

Hinweis

Wenn Sie eine Variable in einem Funktionsbaustein, einer globalen Variablenliste oder in einem Programm als PERSISTENT RETAIN markieren und in die Liste der persistenen Variablen übernehmen, werden der Speicherverbrauch und die Zykluszeit belastet.

Speicherlokation von Funktionsbaustein-Instanzen

Neben der Doppelbelegung von Speicher muss folgende Eigenschaft von Funktionsbausteinen berücksichtigt werden: Funktionsbaustein-Instanzen liegen immer am Stück im Speicher. Das ist notwendig, damit der gleiche Code auf verschiedenen Instanzen arbeiten kann. Das bedeutet aber, wenn eine Variable in einem Funktionsbaustein mit RETAIN markiert ist (auch mit RETAIN PERSISTENT), dann wird jede Instanz des Funktionsbausteins komplett in den Retain-Bereich gelegt. Auch Variablen, die nicht mit RETAIN markiert sind und die beim Reset initialisiert werden, liegen dann physikalisch im Speicher für RETAIN-Variablen. Meist ist dies speziell gesicherter Speicher (SRAM), der nicht in gleichem Umfang zur Verfügung steht wie normaler Speicher.

Diese Eigenschaft vererbt sich sogar über Funktionsbausteine: wenn ein Funktionsbaustein eine Instanz enthält die im SRAM liegt, dann müssen auch alle Instanzen dieses Funktionsbausteins im SRAM gespeichert werden. Das heisst, man kann mit Deklaration einer einzigen VAR RETAIN PERSISTENT in einem Funktionsbaustein sehr schnell seinen gesamten Retain-Speicher aufbrauchen.

Das ist im übrigen nicht der Fall, wenn ein Funktionsbaustein einen POINTER auf eine Instanz im SRAM enthält. Deshalb sollte man mit der Deklaration von RETAIN in Funktionsbausteinen grundsätzlich vorsichtig sein.

Übersichtstabelle zum Verhalten mit RETAIN und PERSISTENT deklarierten Variablen

Nach Onlinebefehl VAR VAR RETAIN

VAR RETAIN PERSISTENT

VAR PERSISTENT RETAIN

Reset warm   x x
Reset kalt     x
Reset Ursprung      
Download     x
Online-Change x x x

Siehe auch