Objektorientiertes Denken in die SPS-Programmierung bringen
Objektorientiertes SPS-Design reduziert das Risiko von Copy-and-paste-Fehlern durch gekapselte Komponenten, explizite Schnittstellen, Komposition, Zustandsmodelle, Tests und Versionsverwaltung – un...
Objektorientiertes Denken kann SPS-Software leichter wiederverwendbar, testbar und wartbar machen, ist jedoch kein einheitlicher Funktionsumfang. Einige IEC-61131-3-Umgebungen unterstützen Methoden, Schnittstellen, Eigenschaften, Vererbung und Polymorphie. Andere Controller-Plattformen bieten wiederverwendbare Funktionsbausteine, Add-on-Instruktionen, benutzerdefinierte Datentypen oder Bibliotheken, ohne das vollständige objektorientierte Modell zu implementieren. Ingenieure müssen für die exakt eingesetzte Plattform und Version entwickeln.
Das praktische Ziel besteht nicht darin, Unternehmenssoftware nachzuahmen. Es geht darum, nicht jedes Ventil, jeden Motor, jeden Analogkanal und jede Package Unit als neue Copy-and-paste-Aufgabe zu behandeln. Eine klar definierte Softwarekomponente gibt jedem Gerät eine einheitliche Schnittstelle, ein Zustandsmodell, ein Alarmverhalten, einen Simulationspfad und einen Diagnoseeintrag, während maschinenspezifische Verdrahtung und Prozessgrenzen außerhalb des wiederverwendbaren Kerns bleiben.

Hardware ist von Grund auf modular aufgebaut; wiederverwendbare Software sollte die Schnittstelle, den Zustand und das Ausfallverhalten jedes Moduls ebenso eindeutig festlegen.
Mit Kapselung statt mit Vererbung beginnen
Kapselung bedeutet, zusammengehörige Zustände und Verhaltensweisen hinter einer definierten Schnittstelle zu platzieren. Eine Ventilkomponente könnte Befehle, Freigaben, Rückmeldungen, Betriebsart und Konfiguration entgegennehmen. Sie könnte die Zustände geöffnet, geschlossen, in Bewegung, gestört, verriegelt und Diagnose ausgeben. Der interne Timer, die Erkennung von Zustandsübergängen, die Wiederholungsstrategie und die Alarmlogik bleiben im Verantwortungsbereich der Komponente.
Das ist auch auf einer Plattform ohne Vererbung wertvoll. Ein Funktionsbaustein oder eine Add-on-Instruktion kann den internen Zustand schützen, das Verhalten standardisieren und doppelte Programmierung reduzieren. Vererbung ist nur sinnvoll, wenn eine echte „ist-ein“-Beziehung besteht und der abgeleitete Typ die Basisschnittstelle einhalten kann. Tiefe Vererbungsstrukturen sind online schwer zu diagnostizieren und können dazu führen, dass eine kleine Änderung an der Basis viele Maschinen beeinflusst.
Typdefinition, Instanzdaten und I/O-Zuordnung trennen
Eine wiederverwendbare Definition beschreibt das Verhalten. Eine Instanz speichert den Zustand eines physischen oder logischen Geräts. Die I/O-Zuordnung verbindet diese Instanz mit realen Signalen. Werden diese Verantwortlichkeiten vermischt, wird die Bibliothekslogik von Rackadressen abhängig und ein sicherer Offline-Test verhindert.
Physische Eingangs- und Ausgangstags sollten an der Integrationsgrenze verbleiben. Wandeln Sie Rohsignale in eindeutige boolesche Werte oder Werte in technischen Einheiten um, rufen Sie anschließend die wiederverwendbare Komponente auf und ordnen Sie die freigegebenen Ausgangsanforderungen wieder der Hardware zu. Diese Struktur unterstützt Simulation, Ersatz-I/O und eine schrittweise Migration. Außerdem zeigt das Top-Level-Programm die Prozessabsicht statt wiederholter Adressmanipulation.
Controller und I/O-Familien können in der Sammlung SPS- und PAC-Systeme verglichen werden. Die gewählte Softwarearchitektur muss jedoch den unterstützten Sprachen, dem Speichermodell, den Regeln für Online-Änderungen und der Sicherheitszertifizierung des Controllers entsprechen.
Schnittstellen als Verhaltensverträge verwenden
Wenn die Plattform Schnittstellen unterstützt, definieren Sie die Operationen, auf die Aufrufer vertrauen dürfen, ohne Implementierungsdetails offenzulegen. CODESYS dokumentiert beispielsweise objektorientierte Funktionsbausteine mit Methoden, Schnittstellen, Eigenschaften, Vererbung und virtuellen Methodenaufrufen in der offiziellen Referenz zur objektorientierten Programmierung. Diese Funktionalität ist real, sollte jedoch nicht auf jede SPS-Umgebung übertragen werden.
Eine Schnittstelle kann unterschiedlichen Motorimplementierungen ermöglichen, gemeinsame Befehle und Statusinformationen bereitzustellen. Ein einfacher Starter, ein Frequenzumrichter und ein Servoantrieb können alle Aktivieren, Stoppen, Rücksetzen, Betriebsart, Bereitschaft, Betrieb und Störungsinformationen unterstützen und dennoch unterschiedliche interne Diagnosen beibehalten. Die Aufrufsequenz hängt dann vom Vertrag ab und nicht von jedem herstellerspezifischen Parameter.
Für Maschinen und Skids die Komposition bevorzugen
Die meisten Industrieanlagen sind naturgemäß zusammengesetzt. Eine Pumpenanlage enthält einen Motor, Absperrventile, Freigaben, Analogmessungen und Ablaufsteuerung. Ein Tanksystem enthält Füllstandmessgeräte, Ventile, Pumpen, Alarme und Betriebsarten. Bauen Sie solche größeren Einheiten, indem Sie kleinere, geprüfte Komponenten enthalten, statt jedes Gerät von einer universellen Basisklasse abzuleiten.
Die Komposition macht Zuständigkeiten sichtbar. Die Pumpenablaufsteuerung kann ihren Motor und ihre Ventile ansteuern, aber die Motorkomponente bleibt für Starterrückmeldung, Startzeitüberschreitung und motorspezifische Fehlerzustände verantwortlich. Die Analogkomponente übernimmt die Signalgültigkeit und Skalierung. Die Einheit koordiniert diese Komponenten und meldet der übergeordneten Logik einen kompakten Zustand.

Die Komposition bildet die Anlagenhierarchie ab und ermöglicht zugleich, dass jede Motor-, Ventil- und Instrumentenkomponente ihre eigene Diagnose beibehält.
Ein explizites Zustandsmodell entwerfen
Eine Komponente sollte ihren Betriebszustand beobachtbar machen. Eine reine boolesche Befehlslogik erzeugt häufig unmögliche Kombinationen wie gleichzeitig laufend und gestoppt, automatisch und manuell oder betriebsbereit und gestört. Ein Aufzählungsmodell kann Zustände wie bereit, startend, laufend, stoppend, gestört und wartend auf Wartung mit bewusst definierten Übergängen ausdrücken.
Jeder Übergang benötigt Eintrittsbedingungen, einen Nachweis der Fertigstellung, ein Verhalten bei Zeitüberschreitung und Abbruchregeln. Befehle sollten Anforderungen und keine direkten Zustandszuweisungen sein. Ein Rücksetzen sollte einen gespeicherten Fehler nur löschen, wenn die zugrunde liegende Bedingung dies zulässt. Der Handbetrieb sollte festlegen, welche Schutzfunktionen aktiv bleiben und wer den Ausgang steuert.
Konfiguration und Laufzeitstatus getrennt halten
Zur Konfiguration gehören Zeitgrenzen, technische Messbereiche, Alarmschwellen, Geräteoptionen und aktivierbare Funktionen. Zum Laufzeitstatus gehören Timer-Akkumulatoren, die aktuelle Betriebsart, die Befehlszuständigkeit, die Fehlerhistorie und der Status von Übergängen. Die Trennung macht Änderungsprüfungen und Rezeptverwaltung übersichtlicher.
Nicht jede Einstellung sollte über ein HMI schreibbar sein. Definieren Sie Bereichsprüfungen, Rollenberechtigungen, Änderungsprotokollierung und den Zeitpunkt, zu dem ein neuer Wert aktiv wird. Auch für remanente Daten ist eine ausdrückliche Regelung erforderlich. Eine Komponente, die nach einem Spannungsausfall fortsetzt, darf keinen unsicheren Befehl wiederherstellen, nur weil alle internen Variablen als persistent konfiguriert wurden.
Komponenten testen, bevor Instanzen vervielfacht werden
Der Vorteil der Wiederverwendung zeigt sich nur, wenn die Definition zuverlässig ist. Erstellen Sie einen Testaufbau, der normales Rückmeldeverhalten, verzögerte Rückmeldungen, widersprüchliche Eingänge, Kommunikationsausfall, schlechte Analogqualität, Betriebsartwechsel, Rücksetzversuche, Einschalten und Grenzfälle von Zeitüberschreitungen abbildet. Bestätigen Sie für jeden Fall Ausgänge, Alarme und Zustandsübergänge.
Testen Sie anschließend mehrere Instanzen, um Fehler durch gemeinsam genutzte Zustände aufzudecken. Prüfen Sie Auswirkungen auf Zykluszeit und Speicher bei realistischer Skalierung. Ein kompakter Aufruf auf der obersten Ebene bedeutet nicht, dass die Implementierung keinen Rechenaufwand verursacht. Online-Änderungen, Bibliotheksaktualisierungen und die Migration von Instanzdaten sollten vor der Inbetriebnahme auf dem Zielcontroller geprobt werden.
Änderungen und Versionierung von Bibliotheken steuern
Eine wiederverwendbare Komponente kann eine Korrektur weit verbreiten, aber auch einen Fehler. Vergeben Sie für jeden freigegebenen Typ eine Version und dokumentieren Sie Schnittstelle, Testprotokoll und Änderungshistorie. Klassifizieren Sie Änderungen als kompatibel oder inkompatibel. Ändern Sie in einer etablierten Definition nicht stillschweigend Alarminterpretationen, Standardzeiten, Ausgangsverhalten oder die Struktur remanenter Daten.
Projekte sollten dokumentieren, mit welchen Bibliotheksversionen kompiliert und welche Versionen heruntergeladen wurden. Wenn eine Plattform Quellcodekopien einbettet, muss festgelegt werden, wie freigegebene Aktualisierungen verglichen und importiert werden. Wenn sie auf eine verwaltete Bibliothek verweist, müssen Verfügbarkeit und Rückfallstrategie geplant werden. Bedienbilder und Faceplates müssen sich gemeinsam mit der Steuerschnittstelle weiterentwickeln, statt davon auszugehen, dass alte Elementnamen weiterhin gültig sind.
Diagnosen in die Bedienebene integrieren
Eine nützliche Komponente meldet, warum sie nicht handeln kann: fehlende Freigabe, widersprüchliche Rückmeldung, Zeitüberschreitung beim Übergang, lokale Zuständigkeit, ungültige Konfiguration, schlechte Eingangsqualität oder aktive Sicherheitsfunktion. Das HMI sollte diesen strukturierten Status in eine verständliche und handlungsorientierte Meldung übersetzen, ohne die Zuständigkeit des Controllers zu umgehen. Geeignete Bediengeräte finden Sie unter HMI und industrielle Computertechnik, doch der Diagnosevertrag beginnt im Steuerungscode.
Perspektive der Automatisierungstechnik
Die objektorientierte SPS-Programmierung ist vor allem als Disziplin klarer Schnittstellen, gekapselter Zustände, Komposition, Prüfung und kontrollierter Wiederverwendung wertvoll. Vollständige Vererbung und Polymorphie können auf Plattformen hilfreich sein, die diese Funktionen implementieren, sind jedoch keine Ausgangsvoraussetzung. Beginnen Sie mit einem klar abgegrenzten Gerätetyp, weisen Sie sein Fehlerverhalten nach, dokumentieren Sie seine Schnittstelle und skalieren Sie erst, wenn die Testergebnisse belastbar sind. Das Ergebnis sollte die Inbetriebnahme und Fehlersuche für den nächsten Ingenieur erleichtern und nicht lediglich den Quellcode anspruchsvoller erscheinen lassen.