Home > IEC 61131-3 > IEC 61131-3: Vorteile der objektorientierten Spracherweiterungen

IEC 61131-3: Vorteile der objektorientierten Spracherweiterungen

IEC 61131-3 wird in naher Zukunft mit Sprachmitteln erweitert, die bisher nur den objektorientierten Programmiersprachen vorbehalten waren. Welche neuen Möglichkeiten ergeben sich hierdurch dem SPS-Programmierer?

‘Hardware without Software is Noware’. Die Bedeutung wird einem sehr schnell klar, wenn ein Computer ohne installiertes Betriebssystem gestartet wird. Trotzdem wird bei der geschichtlichen Betrachtung von Computern die Entwicklung der Software gerne übergangen. Ein Computer aus den 70er Jahren unterscheidet sich gegenüber einem modernen PC nicht nur in der Größe des Arbeitsspeichers, der CPU-Frequenz oder der Grafikauflösung. Gerade die Leistungsfähigkeit der Betriebssysteme und deren Anwendungen hat sich im gleichen Tempo verändert, wie die Hardware. Mit den Programmiersprachen und Programmiermethoden aus den Anfängen des Computerzeitalters wäre man heute kaum in der Lage, konkurrenzfähige Software zu entwickeln. Was hat sich aber in den letzten Jahrzehnten bei den Programmiersprachen so wesentlich verändert? Von Bedeutung für den SPS-Programmierer sind die Konzepte der objektorientierten Programmierung, die in naher Zukunft auch in CoDeSys V3 zur Verfügung stehen werden. Hilfreich für das Verständnis ist ein kurzer Rückblick in die Geschichte der Programmiersprachen.

In den Anfängen der Computertechnik, also in den frühen 50er Jahren, erfolgte die ‘Programmierung’ sehr hardwarenah. Die einzelnen, binären Operationen wurden direkt in Maschinencode geschrieben. Jeder Befehl der Maschinensprache bestand aus einer Folge von 0 und 1. Die Befehle beschränkten sich hierbei auf grundlegende Operationen, wie z.B. das Addieren zweier Speicherzellen. Ein entsprechendes Programm sah dann wie folgt aus (Befehlssatz eines Z80):

21 00 10
11 00 20
19
22 00 30

Programme in Maschinensprache sind sehr schwer zu lesen. Hinzu kommt, dass fast jede CPU seinen eigenen Befehlssatz hat. Dadurch konnten Programmteile nur mit großem Aufwand auf anderen Systemen wieder verwendet werden.

Um die Lesbarkeit von Maschinencode zu erhöhen, wurde jeder Befehl durch eine Buchstabenfolge dargestellt. Ein Konvertierungsprogramm, der Assemler, hat diese, für den Menschen optimierte Darstellung (den Assemblercode), in Maschinensprache (Binärcode) umgewandelt. Das oben gezeigte Programm wurde dann wie folgt abgebildet:

LD HL, 1000H
LD DE, 2000H
ADD HL, DE
LD (3000H), HL

Assembler hatten relativ lang eine große Bedeutung. Insbesondere, wenn es um das Entwickeln von hardwarenaher Software ging (z.B. Treiber oder zeitkritischen Programmteilen). Der Assembler änderte aber nichts daran, dass die geschriebene Software stark an den Typ der CPU gebunden war. Auch war das Strukturieren von Assemblerprogrammen sehr schwer. Dieser Nachteil machte sich besonders bei größeren Projekten bemerkbar. Um diese Nachteile zu umgehen, musste eine ‘Sprache’ entwickelt werden, die zum einen nicht mehr an die Hardware gebunden war und zum anderen die Lesbarkeit der Programme verbesserte. Somit entstanden die ersten höheren Programmiersprachen. Hochsprache deshalb, weil sie die Hardware abstrahiert. Hardware und Programmiersprache waren dadurch voneinander getrennt. Ein Compiler übersetzte hierbei den Quelltext des Programmierers (eine Textdatei, mit den Befehlen) in Maschinencode. Die ersten Programmiersprachen dieser Art waren FORTRAN und COBOL, die Ende der 50er Jahre entstanden.

C PROGRAMM:SUMME
C
  INTEGER S
  S = 0
  DO 15 I = 1,10
  S = S + I
15 CONTINUE
  WRITE (5,20) S
20 FORMAT (1H1,10X,I4)
  STOP
  END

Sehr schnell wurden Programmiersprachen für sehr unterschiedliche Gebiete entwickelt, wie z.B. die Naturwissenschaft oder kaufmännische Aufgaben. Inbesondere entstanden in den 70er Jahren sehr viele Sprachen, da sich die Hardware der Computer rasend verbesserte. Die Strukturierung der Daten wurde duch das Konzept der Prozeduren erreicht. Einzelne Bereiche eines Programms wurden zu einer Einheit zusammengefasst und konnten somit von verschiedenen Stellen des Programms immer wieder aufgerufen werden. Sehr beliebt war in den 80ern die Sprache Pascal. Pascal setzte den Gedanken der strukturierten Programmierung bei Daten fort. Es war nun möglich, eigene Datentypen zu erschaffen und zusammengehörige Daten zu einem Record zusammenzufassen. Modula führte die Strukturierung der Daten und Code weiter fort. Basis war das Modul. Eine Einheit aus Daten und Code, die man als Blackbox nutzen konnte und man sich nicht um die Implementierung im Detail kümmern musste. Turbo-Pascal übernahm das Konzept von Modula als sogenannte Units. In der IEC 61131-3 ist das Modul von Modula vergleichbar mit dem Konzept des FUNCTION_BLOCK und die Records aus Pascal mit der Anweisung STRUCT.

Ein Funktionsblock ist ein eigenständiger Befehlsabschnitt, dem beim Aufruf Daten übergeben werden, diese werden bearbeitet und über Ausgangsvariablen an den Aufrufer zurückgegeben. Für die Verarbeitung der Daten können eigene, lokale Variablen benutzt werden. Diese lokalen Variablen befinden sich innerhalb des Funktionsblocks und sind dadurch von den anderen Variablen des Programms logisch getrennt. Dieser Gedanke wurde Ende der 70er Jahre durch die Sprache Smalltalk konsequent erweitert. Diese Veränderungen waren damals so wesentlich, dass der Begriff des ‘Objektes’ in der Softwareentwicklung entstanden ist. Ein Objekt kann (stark vereinfacht) als eine Zusammenfassung von Speicherplätzen mit sämtlichen Operationen, die den Wert dieser Speicherplätze verändern können, verstanden werden. Die Beschreibung solch eines Objektes wird als Klasse bezeichnet und ein Objekt ist die Instanz seiner Klasse.

In der Erweiterung der IEC 61131-3 wird eine Klasse durch ein Funktionsblock definiert. Das Konzept des Funktionsblocks wird hierbei erweitert. So können in einem Funktionsblock mehrere Funktionen definiert werden, die ausschließlich dazu dienen, die internen Variablen zu verändern. Diese Art der Funktionen, die sich in einer Klasse befinden, werden auch als Methoden bezeichnet. Die internen Variablen sind nur von außen über klar definierte Methoden veränderbar. Sind interne Daten von außen änderbar, so werden diese als Eigenschaft bezeichnet. Der Zugriff erfolgt über eine Get- und eine Set-Methode.

Neben den Eigenschaften und Methoden prägt der Begriff der Vererbung die objektorientierte Programmierung. Die Vererbung vereinfacht die Wiederverwendung von Klassen durch andere Klassen. Hierbei erbt die Kindklasse alle Methoden und Eigenschaften der Vaterklasse. Die Kindklasse hat somit erstmal das gleiche Verhalten wie die Vaterklasse. Die Kindklasse kann aber zusätzliche Methoden und Eigenschaften anlegen. Auch kann die Implementierung von Methoden der Vaterklasse durch die Kindklasse überschrieben werden. Ein Löschen oder Verdecken von Methoden der Vaterklasse durch die Kindklasse ist nicht möglich. Dadurch wird sichergestellt, das eine Kindklasse mindestens die gleichen Methoden wie die Vaterklasse hat. Das Prinzip der Vererbung kann über beliebig viele Ebenen erfolgen. Eine Kindklasse kann also wiederum als Vaterklasse dienen. Es kann aber immer nur von einer Klasse geerbt werden. Mehrfachvererbung ist nicht möglich.

Eine besondere Art von Funktionsblöcken sind Interfaces (Schnittstellen). Ein Interface definiert nur Methoden und Eigenschaften. In den Methoden ist kein Programmcode enthalten. Erbt eine Vater-Funktionsblock von einem Interface, so muss der Vater-Funktionsblock alle Methoden und Eigenschaften implementieren die das Interface vorgibt. Dafür kann eine Variable des Interfaces zum Aufrufen von Objekten, die von diesem Interface erben, genutzt werden. Welche Implementierung tatsächlich dadurch aufgerufen wird, kann zur Laufzeit verändert werden. Ein Leistungsmerkmal, das völlig neue Möglichkeiten eröffnet.

Beispiel

Das folgende Beispiel soll dieses verdeutlichen. Es soll der Funktionsblock FB_LightControl zur einfachen Lichtsteuerung definiert werden. Dieser enthält Methoden zum Ein- und Ausschalten. Eine Eigenschaft zeigt die aktuelle Stellgröße an. Die eigentliche Definition, wie das Licht geschaltet werden soll, wird in separaten Funktionsblöcken implementiert. Bei diesem Beispiel gibt es einen Funktionsblock für eine einfache Lichtschaltung (FB_StandardLight) und für eine Lichtschaltung mit automatischer Abschaltung (FB_StairwellLight). Hier ist die Besonderheit: nicht FB_LightControl enthält die eigentliche Logik, sondern separate Funktionsblöcke. Das Bindeglied zwischen diesen Bausteinen ist das Interface ILight.

image

Dieses Interface müssen FB_StairwellLight und FB_StandardLight verwenden. Durch das Schlüsselwort IMPLEMENTS kann dieses bei der Deklaration des Funktionsblockes vorgegeben werden.

FUNCTION_BLOCK FB_StandardLight IMPLEMENTS ILight

In den Klassen, die das Interface verwenden, müssen die Methoden mit Logik gefüllt werden. Der Compiler überprüft, ob die Methoden und das Property in den Funktionsblöcken enthalten sind. Es ist damit sichergestellt, dass jeder Funktionsblock, der ILight implementiert, die Methoden M_On(), M_Off() und das Property P_ControlValue enthält. Der Aufruf der Methoden kann somit auch über eine Instanz des Interfaces erfolgen.

PROGRAM Main
VAR
  fbStandardLight : FB_StandardLight;
  LightInterface  : ILight;
END_VAR

LightInterface := fbStandardLight;
LightInterface.M_On();
LightInterface := fbStairwellLight;
LightInterface.M_On();

Je nachdem, welcher Funktionsblock der Instanz des Interfaces zugewiesen wurde, werden die verschiedenen Implementierungen der Methode M_On() aufgerufen. Diese kann jetzt dazu genutzt werden, um den Datentyp ILight als Eingangsparameter an unseren Funktionsblock FB_LightControl zu übergeben.

FUNCTION_BLOCK FB_LightControl
VAR_INPUT
  bOn            : BOOL;
  bOff           : BOOL;
  LightType      : ILight;
END_VAR
VAR_OUTPUT
  bControlValue  : BOOL;
END_VAR
VAR
  rtrigOn        : R_TRIG;
  rtrigOff       : R_TRIG;
END_VAR

rtrigOn(CLK := bOn);
rtrigOff(CLK := bOff);
IF (rtrigOn.Q) THEN
  LightType.M_On();
END_IF
IF (rtrigOff.Q) THEN
  LightType.M_Off();
END_IF
LightType.M_Execution();
bControlValue := LightType.P_ControlValue;

Die Variable LightType vom Typ ILight kann dazu benutzt werden, die Methoden zum Schalten aufzurufen. Ebenfalls ist das Property P_ControlValue mit der aktuellen Stellgröße über das Interface erreichbar. Wie sich der Funktionsblock FB_LightControl verhält, ist davon abhängig, welche Instanz die Variable LightType (vom Datentyp ILight) zugewiesen bekommt. Die Anwendung des Bausteins könnte dann wie folgt aussehen:

PROGRAM Main
VAR
  fbLightControlRoom01    : FB_LightControl;
  bSwitchOn01             : BOOL;
  bSwitchOff01            : BOOL;
  bValue01                : BOOL;
  fbStandardLight         : FB_StandardLight;
  fbLightControlRoom02    : FB_LightControl;
  bSwitchOn02             : BOOL;
  bSwitchOff02            : BOOL;
  bValue02                : BOOL;
  fbStairwellLight        : FB_StairwellLight;
END_VAR

fbLightControlRoom01(bOn := bSwitchOn01,
                     bOff := bSwitchOff01,
                     LightType := fbStandardLight,
                     bControlValue => bValue01);
fbLightControlRoom02(bOn := bSwitchOn02,
                     bOff := bSwitchOff02,
                     LightType := fbStairwellLight,
                     bControlValue => bValue02);

Die Funktionsblöcke FB_LightControl, FB_StandardLight, FB_StairwellLight und das Interface ILight könnten zu einer Library zusammengefasst werden. Der Anwender der Library hätte jetzt die Möglichkeit, das Verhalten des Funktionsblocks FB_LightControl zu verändern, ohne den Programmcode an der Library ändern zu müssen. Es ist nur notwendig, einen eigenen Funktionsblock (z.B. ein Baustein, der das Licht verzögert ausschaltet) zu schreiben. Dieser Funktionsblock muß ebenfalls das Interface ILight implementieren. Eine Instanz von diesem Funktionsblock wird dann dem Baustein FB_LightControl übergeben.

Die Möglichkeiten von Interfaces, welche in der objektorientierten Programmierung fester Bestandteil sind, kann somit auch in der IEC 61131-3 genutzt werden. Insbesondere Software, die wieder verwendet werden soll, kann dadurch noch flexibler gestaltet werden.

Beispiel (CoDeSys V3.4 SP1)

Beispiel (TwinCAT V3.1.4020)

Advertisements
  1. prozol@hotmail.com
    February 12, 2016 at 11:15 am

    Hi,

    ich kann nicht Beispiel unterladen.

    mfg

    frank

    • February 13, 2016 at 10:14 pm

      Hi,
      kannst du das Problem etwas genauer beschreiben?
      Kommst du nicht bei mir auf OneDrive oder treten die Schwierigkeiten später auf?
      Stefan

  2. Jannis Rätz
    June 1, 2017 at 3:57 pm

    Hi,
    ich arbeite gerade an meiner Bachelorarbeit die sich mit IEC 61131-3 beschäftigt und war von einem mir zur Verfügung gestellten Beispiel, dass Methoden benutzte sehr verwirrt, weil ich sie nirgends in der Spezifikation von IEC 61131-3 finden konnte und Ihre Artikel zu diesem Thema haben mir sehr geholfen. Können sie mir eine Arbeit empfehlen, die die Erweiterungen zur Objektorientierung in IEC 61131-3 genauer bescheibt?
    Mit freundlichen Grüßen,
    Jannis Rätz

    • June 1, 2017 at 10:49 pm

      Hi,
      vielen Dank für das Lob. Eine Buchempfehlung habe ich jetzt nicht. Aber vielleicht hilft unsere Online Hilfe weiter infosys.beckhoff.com.
      Gruß
      Stefan

  1. April 4, 2017 at 11:49 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: