SPS-Programmierung: 8 Best Practices für sauberen, wartbaren Code
Praxis-Leitfaden für sauberen, wartbaren SPS-Code mit Siemens TIA Portal: Namenskonventionen, FB/FC-Struktur, Alarmhandling und systematische Fehlersuche.

Das Wichtigste in Kürze
Sauberer SPS-Code bedeutet schnellere Fehlersuche und weniger Stillstand. Dieser Praxis-Leitfaden zeigt 8 Best Practices aus über 10 Jahren TIA-Portal-Projekten. Direkt zum gesuchten Thema:
- Die 5 IEC-Programmiersprachen im Überblick – wann SCL, LAD, FBD, ST oder SFC die richtige Wahl ist
- Systematische Fehlersuche in SPS-Programmen – eingrenzen statt raten
- Checkliste für Ihr nächstes SPS-Projekt – zum direkten Abhaken
1.Einleitung
SPS-Programmierung ist mehr als nur Logikbausteine aneinanderreihen. In über 10 Jahren als Automatisierungsingenieur habe ich unzählige SPS-Projekte gesehen – viele davon mit typischen Problemen:
- Unlesbare Variablennamen wie
M0.0,DB1.DBX0.0oder%MW100 - Inkonsistente Programmiersprachenmischung – KOP, FUP, AWL und SCL wild durcheinander im selben Projekt
- Fehlende Dokumentation – der Original-Programmierer hat das Unternehmen längst verlassen
In diesem Artikel teile ich die wichtigsten Best Practices für wartbare SPS-Programme mit Siemens TIA Portal.
Zielgruppe
Dieser Artikel richtet sich an SPS-Programmierer mit Grundkenntnissen in TIA Portal. Für Einsteiger empfehle ich zunächst einen IEC 61131-3-Grundlagenkurs.
2.Warum Best Practices in der SPS-Programmierung?
2.1.Das Problem: Legacy-Code
Typisches Szenario aus meiner Praxis:
Ein Maschinenbauer ruft an: "Unsere Anlage steht. Können Sie helfen?"
Vor Ort die Ernüchterung:
- Variablennamen wie
M0.0,DB1.DBX0.0,%MW100– niemand weiß, was dahinter steckt - KOP, FUP, AWL und SCL wild durcheinander im selben Projekt
- Keine Kommentare, keine Strukturierung
- Original-Programmierer hat das Unternehmen vor Jahren verlassen
Die Fehlersuche dauert unnötig lange, weil sich niemand im Code zurechtfindet.
2.2.Die Lösung: Professionelle Programmierung
Strukturierte, wartbare SPS-Programme bringen klare Vorteile:
- Schnellere Fehlersuche durch sprechende Variablennamen
- Kürzere Einarbeitungszeit für neue Programmierer
- Weniger Maschinenstillstände durch bessere Fehlerbehandlung
3.Best Practice 1: IEC 61131-3-Standards konsequent nutzen
IEC 61131-3 ist der internationale Standard für SPS-Programmierung und Pflicht für CE-zertifizierte Maschinen.
3.1.Die 5 Programmiersprachen im Überblick
| Norm (IEC) | Siemens | Verwendung | Nachteile |
|---|---|---|---|
| LD – Ladder Diagram | KOP | Verriegelungen, simple Logik | Unübersichtlich ab ca. 50 Netzwerken |
| FBD – Function Block Diagram | FUP | Regelung, Datenfluss-Logik | Schwer wartbar bei großen Programmen |
| IL – Instruction List | AWL | Nur noch Bestandscode | Seit 2013 als veraltet eingestuft |
| ST – Structured Text | SCL | Algorithmen, Berechnungen, Bibliotheken | Für reine Verriegelungen weniger anschaulich |
| SFC – Sequential Function Chart | GRAPH | Ablaufsteuerungen (GRAFCET) | Overhead für simple Logik |
Achtung, verbreiteter Irrtum: SCL und ST sind dieselbe Sprache — SCL ist Siemens' Implementierung von Structured Text. Wer beide getrennt aufzählt, zählt eine Sprache doppelt und lässt dafür meist AWL weg.
Meine Empfehlung
Nutzen Sie SCL/ST für 80% des Codes (Logik, Berechnungen, Ablaufsteuerungen) und LAD nur für simple Verriegelungen (z.B. NOT-AUS-Logik). FBD für Regelkreise, SFC für komplexe State-Machines.
Ausführlich: Welche Sprache sich wofür eignet, wie die Norm-Bezeichnungen zu den Siemens-Namen passen und warum SCL und ST dieselbe Sprache sind, steht im eigenen Artikel Die 5 SPS-Programmiersprachen nach IEC 61131-3.
3.2.Strukturierte Programmierung: Die Pyramide

OB1 (Main)
└── FC_SystemControl (Betriebsarten)
├── FB_PackMLStateMachine (Ablaufsteuerung)
│ ├── FB_MotorControl (Anlagenteil)
│ ├── FB_ValveControl (Anlagenteil)
│ └── FB_ConveyorControl (Anlagenteil)
└── FC_AlarmHandler (Utility)
Regel: Jede Ebene hat genau EINE klare Verantwortung.
4.Best Practice 2: Namenskonventionen etablieren
4.1.Das Problem: Variable-Namen-Chaos
Negativ-Beispiel (aus der Praxis):
// ❌ SCHLECHT
M0.0 // Was ist das?
DB1.DBX0.0 // Welcher Motor?
%MW100 // Temperatur? Druck?
Positiv-Beispiel:
// ✅ GUT
bMotorPumpMainRun : BOOL; // Motor Hauptpumpe läuft
iTemperatureTank1 : INT; // Temperatur Tank 1 in °C
rPressureSetpoint : REAL; // Sollwert Druck in bar
4.2.Standardisierte Präfixe (Hungarian Notation)
| Präfix | Datentyp | Beispiel |
|---|---|---|
b | BOOL | bMotorRun, bAlarmActive |
i | INT | iCounter, iTemperature |
r | REAL | rSpeed, rPressure |
s | STRING | sAlarmText, sRecipeName |
dt | DATE_TIME | dtStartTime, dtLastMaintenance |
t | TIME | tDelayStart, tCycleTime |
udi | UDINT | udiPartCounter, udiTotalProduction |
4.3.Ein/Ausgänge mit Prefix
// Eingänge: ix (Input X)
ixMotorFeedbackRun : BOOL AT %I0.0; // "x" = Bool
iwTemperatureSensor : WORD AT %IW0; // "w" = Word
// Ausgänge: qx (Output X)
qxMotorStart : BOOL AT %Q0.0;
qwValvePosition : WORD AT %QW0;
Konsistenz ist König: Entscheiden Sie sich im Team für EINE Konvention und dokumentieren Sie sie.
Tooling
Siemens TIA Portal v18+ bietet den Code Quality Check, der Namenskonventionen automatisch prüft.
Ausführlich: Warum eine Präfix-Tabelle allein noch kein Standard ist — und was Schnittstellenvertrag, versionierte Bibliothek und Ausnahmeweg damit zu tun haben — steht im eigenen Artikel SPS-Coding-Standards: von Namenskonventionen zur versionierten Bibliothek.
5.Best Practice 3: Funktionsbausteine vs. Funktionen richtig einsetzen
5.1.Funktionsbausteine (FB) - Zustandsbehaftet
Wann verwenden?
- Anlagenteile mit Zustand (Motor, Ventil, Förderband)
- Alarm-Handler
- State-Machines
Beispiel: Motor-Steuerung
FUNCTION_BLOCK FB_MotorControl
VAR_INPUT
bStart : BOOL; // Startbefehl
bStop : BOOL; // Stoppbefehl
bFeedback : BOOL; // Rückmeldung Motor läuft
END_VAR
VAR_OUTPUT
qxStart : BOOL; // Ausgang Motorstart
bRunning : BOOL; // Status: Motor läuft
bAlarm : BOOL; // Störung aktiv
END_VAR
VAR
tDelayStart : TON; // Verzögerung beim Start
tTimeoutFeedback : TON; // Timeout für Rückmeldung
bAlarmLatched : BOOL; // Gespeicherte Störung
END_VAR
// Programmlogik hier...
END_FUNCTION_BLOCK
Aufruf:
// Im OB1 oder FC
dbMotorPumpMain(
bStart := bSystemRun AND NOT bEmergencyStop,
bStop := bSystemStop OR bEmergencyStop,
bFeedback := ixMotorPumpMainFeedback
);
qxMotorPumpMainStart := dbMotorPumpMain.qxStart;
5.2.Funktionen (FC) - Zustandslos
Wann verwenden?
- Berechnungen ohne Zustand
- Skalierungen
- Mathematische Operationen
- Hilfsfunktionen
Beispiel: Temperatur-Skalierung
FUNCTION FC_ScaleTemperature : REAL
VAR_INPUT
iwRawValue : INT; // Rohwert von Sensor (0-27648)
rMinTemp : REAL; // Minimale Temperatur (z.B. -50°C)
rMaxTemp : REAL; // Maximale Temperatur (z.B. +150°C)
END_VAR
// Skalierung 0-27648 → rMinTemp bis rMaxTemp
FC_ScaleTemperature := rMinTemp +
(REAL#iwRawValue / 27648.0) * (rMaxTemp - rMinTemp);
END_FUNCTION
Aufruf:
rTemperatureTank1 := FC_ScaleTemperature(
iwRawValue := iwTempSensor1,
rMinTemp := -50.0,
rMaxTemp := 150.0
);
Faustregel
Hat es einen Zustand (Speicher zwischen Aufrufen)? → FB Ist es eine Berechnung oder Hilfsfunktion? → FC
6.Best Practice 4: Fehlerbehandlung nach NAMUR NE 107
NAMUR NE 107 ist der Industriestandard für Selbstüberwachung und Diagnose in der Prozessindustrie. Im Maschinenbau hat er sich ebenfalls etabliert.
6.1.Die 4 Zustände

6.2.Implementierung mit FB_AlarmHandler
FUNCTION_BLOCK FB_AlarmHandler
VAR_INPUT
bTrigger : BOOL; // Alarm-Auslöser
eAlarmLevel : INT; // 1=Info, 2=Warning, 3=Error, 4=Critical
sAlarmText : STRING[80]; // Alarm-Text
END_VAR
VAR_OUTPUT
bAlarmActive : BOOL; // Alarm ist aktiv
bAckRequired : BOOL; // Quittierung erforderlich
END_VAR
VAR
bAlarmLatched : BOOL; // Gespeicherter Alarm
dtTimestamp : DATE_TIME; // Zeitstempel des Alarms
END_VAR
// Logik: Alarm speichern, Zeitstempel setzen, ggf. quittieren
IF bTrigger AND NOT bAlarmLatched THEN
bAlarmLatched := TRUE;
dtTimestamp := CURRENT_TIMESTAMP();
bAlarmActive := TRUE;
// Logging zu HMI/SCADA
// ...
END_IF;
bAckRequired := bAlarmLatched AND eAlarmLevel >= 3;
END_FUNCTION_BLOCK
Best Practice: Ein zentraler Alarm-Manager sammelt alle Alarme und kommuniziert sie gebündelt zum HMI.
Wichtig
Jeder Alarm benötigt eine eindeutige ID (z.B. ALM-001) und eine Beschreibung in der Dokumentation. Bei FDA-regulierten Anlagen ist das Pflicht.
7.Best Practice 5: Versionierung mit Git
Ja, Git funktioniert auch für SPS-Code! Seit TIA Portal v18 ist die Integration deutlich einfacher geworden.
7.1.Setup: TIA Portal mit Git
1. Multiuser Engineering aktivieren
TIA Portal → Projekt → Eigenschaften → Multiuser Engineering → Aktivieren
2. Projekt in Git-freundlichem Format speichern
# .gitignore für TIA Portal
*.ap18
*.zap18
__OPNB*
*.bak
3. Git-Repository initialisieren
git init
git add .
git commit -m "Initial commit: TIA Portal project setup"
7.2.Branching-Strategie für SPS-Projekte
main (Produktiv-Code)
├── develop (Entwicklung)
│ ├── feature/motor-control-update
│ ├── feature/add-safety-logic
│ └── bugfix/alarm-text-typo
└── hotfix/critical-emergency-stop-bug
Workflow:
- Feature-Branch erstellen:
git checkout -b feature/new-conveyor-logic - Änderungen committen:
git commit -m "Add conveyor start delay 2s" - Pull Request erstellen (GitHub, GitLab)
- Code-Review durch zweiten Programmierer
- Merge in
develop - Testing auf Entwicklungs-SPS
- Release-Branch →
main
Vorteile
- Team-Collaboration ohne Datenverlust
- Historische Versionen jederzeit abrufbar
- Paralleles Arbeiten an verschiedenen Features
- Automatische Backups (GitHub, GitLab Cloud)
8.Best Practice 6: Kommentare und Dokumentation
8.1.Code-Kommentare: Die 3-Zeilen-Regel
Schlecht:
// ❌ Offensichtlich, bringt nichts
bMotorRun := TRUE; // Motor starten
Gut:
// ✅ Erklärt WARUM, nicht WAS
// Verzögerung 2s wegen Druckaufbau im Hydraulik-Kreislauf
// (Siehe Anforderung REQ-HYD-012)
tDelayStart(IN := bStartRequest, PT := T#2S);
qxMotorStart := tDelayStart.Q;
8.2.Dokumentations-Standards
Für jeden FB/FC:
(*
Name: FB_MotorControl
Version: 1.2.0
Autor: David Prybisch
Datum: 2025-11-22
Beschreibung:
Standardisierter Motorsteuerung mit Anlaufverzögerung,
Rückmeldungsüberwachung und Störungsspeicherung.
Änderungshistorie:
v1.2.0 - 2025-11-22 - Timeout-Überwachung hinzugefügt
v1.1.0 - 2025-10-15 - NAMUR-Alarm-Integration
v1.0.0 - 2025-09-01 - Erste Version
*)
FUNCTION_BLOCK FB_MotorControl
// ...
END_FUNCTION_BLOCK
UML-Diagramme für Systemarchitektur:
Nutzen Sie Tools wie PlantUML oder Microsoft Visio, um die Gesamtarchitektur zu visualisieren.
Ausführlich: Was vollständig in eine Anlagendokumentation gehört, welche 12 Punkte bei der Übergabe zählen und wie sich eine verlorene Bestandsdokumentation rekonstruieren lässt, steht im eigenen Artikel SPS-Dokumentation: Was hineingehört, was bei der Übergabe zählt.
9.Best Practice 7: Testing und Simulation
9.1.Simulation mit PLCSIM
Siemens PLCSIM Advanced ermöglicht das Testen von SPS-Programmen ohne physische Hardware:
Workflow:
- SPS-Programm im TIA Portal entwickeln
- PLCSIM Advanced starten und Projekt laden
- Variablen über Beobachtungstabelle setzen und prüfen
- Ablaufsteuerungen systematisch durchtesten
Vorteile:
- Fehler früh erkennen – im Büro statt beim Kunden
- Neue Programmierer können gefahrlos testen
- Änderungen vor der Inbetriebnahme validieren
Tipp
Nutzen Sie die Beobachtungstabellen in TIA Portal, um Ein- und Ausgänge systematisch zu forcieren und das Programmverhalten zu prüfen.
10.Best Practice 8: Performance-Optimierung
10.1.CPU-Auslastung im Blick behalten
Häufige Performance-Killer:
- Zu viele Timer/Counter → Nutzen Sie Arrays statt einzelner Variablen
- String-Operationen in Echtzeitzyklen → Lagern Sie in niederpriorisierte Tasks aus
- Komplexe Berechnungen in OB1 → Verwenden Sie zyklische Interrupts (OB35)
Beispiel: Array-basierte Timer-Verwaltung
// ❌ SCHLECHT: 100 einzelne Timer
VAR
tMotor1 : TON;
tMotor2 : TON;
// ... 98 weitere Timer
END_VAR
// ✅ GUT: Array von Timern
VAR
atMotorTimers : ARRAY[1..100] OF TON;
END_VAR
// Aufruf in Schleife
FOR i := 1 TO 100 DO
atMotorTimers[i](IN := abMotorStart[i], PT := T#2S);
aqxMotorStart[i] := atMotorTimers[i].Q;
END_FOR;
10.2.Speicher-Optimierung mit Multi-Instanzen
Problem: Jeder FB-Instanz verbraucht eigenen DB (Instanz-DB).
Lösung: Multi-Instanzen für wiederkehrende Bausteine.
// FB_ConveyorLine enthält 10x FB_MotorControl als Multi-Instanz
FUNCTION_BLOCK FB_ConveyorLine
VAR
Motor1 : FB_MotorControl; // Multi-Instanz
Motor2 : FB_MotorControl;
// ...
END_VAR
// Nur EINE Instanz von FB_ConveyorLine anlegen
dbConveyorLine : FB_ConveyorLine; // Spart 90% Speicher vs. 10 separate FBs
11.Fehlersuche in SPS-Programmen: systematisch statt Trial-and-Error
Alle bisherigen Best Practices zahlen sich spätestens dann aus, wenn eine Anlage steht und der Fehler unter Zeitdruck gefunden werden muss. Wer strukturiert programmiert, sucht Fehler nicht – er grenzt sie ein. Trial-and-Error kostet dagegen Stunden und riskiert Folgeschäden.
11.1.Systematisch eingrenzen statt raten
Jede effiziente Fehlersuche folgt derselben Kette: Symptom → betroffener Baustein → Signalpfad → Ursache. Beginnen Sie mit dem konkreten Symptom („Förderband läuft nicht an"), lokalisieren Sie den zuständigen Baustein (FB_ConveyorControl) und verfolgen Sie das Signal rückwärts vom Ausgang zu seinen Bedingungen. Genau hier zahlt sich eine klare Bausteinstruktur aus: Ist jeder Anlagenteil in einem eigenen FB gekapselt und sprechend benannt, wissen Sie sofort, wo Sie suchen müssen – statt sich durch tausende Netzwerke in OB1 zu wühlen.
11.2.Die richtigen TIA-Portal-Werkzeuge
- Beobachtungstabellen zeigen Live-Werte, ohne den Prozess zu stören – das Standardwerkzeug zum Mitlesen von Signalen.
- Querverweise (Cross-References) verraten, wo eine Variable geschrieben und gelesen wird – das erste Mittel gegen Doppelzuweisungen.
- Die Aufrufstruktur deckt auf, ob ein Baustein überhaupt zyklisch aufgerufen wird.
- Der Diagnosepuffer der CPU protokolliert Hardware-Ereignisse, Baugruppenausfälle und STOP-Ursachen mit Zeitstempel – der erste Blick bei jeder Störung.
- Ein Online-/Offline-Vergleich entlarvt undokumentierte Änderungen „von der letzten Nachtschicht".
Forcen mit Bedacht
Forcen überschreibt physische Ein- und Ausgänge und bleibt aktiv, bis es explizit aufgehoben wird – auch nach einem CPU-Neustart. An laufenden Anlagen mit bewegten Achsen ist das ein Sicherheitsrisiko. Zum reinen Beobachten nutzen Sie die Beobachtungstabelle; forcen Sie nur gezielt und dokumentiert.
11.3.Typische Fehlerklassen kennen
- Doppelzuweisungen: Dieselbe Variable wird in zwei Bausteinen geschrieben – der zuletzt bearbeitete „gewinnt". Über Querverweise sofort sichtbar.
- Flankenfehler: Eine Aktion feuert dauerhaft statt einmalig, weil eine steigende Flanke (R_TRIG) fehlt oder ein Flankenmerker mehrfach genutzt wird.
- Zeit- und Zykluszeitprobleme: Ein Timer, dessen Bedingung im selben Zyklus zurückgesetzt wird, läuft nie ab; zu lange Zykluszeiten lösen den Zeitfehler-OB (OB80) aus.
- Hardware vs. Software: Grenzen Sie ein, bevor Sie im Code suchen. Zeigt der Diagnosepuffer einen Baugruppenausfall oder meldet eine Peripherie-LED einen Fehler, liegt die Ursache nicht im Programm.
11.4.Sauberer Code beschleunigt jede Diagnose
Die FC/FB-Trennung, sprechende Namen und die klare Hierarchie aus den vorherigen Kapiteln sind kein Selbstzweck: Sie verwandeln stundenlanges Rätselraten in ein gezieltes Eingrenzen von Minuten. Ein kommentierter Baustein mit eindeutiger Verantwortung sagt Ihnen schon beim Draufschauen, was er tun soll – und damit auch, wo er vom Soll abweicht.
Ausführlich: Die vollständige Vorgehensweise – Hardware zuerst ausschließen, die fünf häufigsten Fehlerklassen und die Reihenfolge, die unter Zeitdruck trägt – steht im eigenen Artikel Fehlersuche in SPS-Programmen: systematisch eingrenzen.
12.Fazit: Professionelle SPS-Programmierung zahlt sich aus
Die Investition in strukturierte, wartbare SPS-Programme rentiert sich mehrfach:
- Schnellere Fehlersuche durch sprechende Variablennamen und klare Struktur
- Kürzere Einarbeitungszeit für neue Programmierer
- Weniger Maschinenstillstände durch bessere Fehlerbehandlung
- Einfachere Wartung über die gesamte Anlagenlebensdauer
12.1.Checkliste für Ihr nächstes SPS-Projekt
- Namenskonventionen mit Team vereinbart und dokumentiert
- Hierarchische Programmstruktur geplant (UML-Diagramm)
- IEC 61131-3-Standards eingehalten
- Alarm-Management nach NAMUR NE 107 implementiert
- Git-Repository angelegt und
.gitignorekonfiguriert - Simulation mit PLCSIM vorbereitet
- Code-Review-Prozess etabliert
- Dokumentation (FB-Header, Systemarchitektur) erstellt
Nächster Schritt
Starten Sie klein: Nehmen Sie ein bestehendes Projekt und refactoren Sie EINEN FB nach diesen Best Practices. Der Zeitaufwand (2-4 Stunden) amortisiert sich bei der nächsten Störungsbehebung.
13.Infografik: SPS Best Practices auf einen Blick

14.Weiterführende Ressourcen
- IEC 61131-3 Standard: PLCopen.org
- Siemens TIA Portal Best Practices: Siemens Support
- NAMUR NE 107: NAMUR.net
- Git für SPS: PlcGit Documentation
Über den Autor: David Prybisch ist seit über 10 Jahren als SPS-Programmierer tätig. Er unterstützt Maschinenbauer bei strukturierter Programmierung mit Siemens TIA Portal, Code-Reviews und Inbetriebnahme – im Saarland, in Luxemburg und der Region Trier ebenso wie für Kunden in der Schweiz.
Fragen zu Ihrem Automatisierungsprojekt?
Als Automatisierungsingenieur in Stadtbredimus, Luxemburg biete ich kostenlose Erstberatungen für Unternehmen in der Großregion Saar-Lor-Lux.
David Prybisch · SPS · HMI · Inbetriebnahmen
Weitere Artikel

WinCC Unified und React: Synergien für moderne HMI-Entwicklung
Du kennst React oder JavaScript? Dann kannst du WinCC Unified schneller lernen. Konkrete Synergien, Code-Beispiele und Praxis-Tipps vom Experten.
Weiterlesen: WinCC Unified und React: Synergien für moderne HMI-Entwicklung
Automatisierung in Luxemburg 2025: Trends, die die Großregion prägen
SPS-Programmierung & Industrieautomatisierung in Luxemburg: 6 Trends für 2025, konkrete Projekte bei Goodyear, Husky & Co. + Förderprogramme für KMU.
Weiterlesen: Automatisierung in Luxemburg 2025: Trends, die die Großregion prägen
Die 5 SPS-Programmiersprachen nach IEC 61131-3 im Vergleich
KOP, FUP, AWL, SCL und GRAPH: Was die IEC 61131-3 wirklich definiert, wie die Siemens-Bezeichnungen dazu passen und welche Sprache für welche Aufgabe die richtige ist.
Weiterlesen: Die 5 SPS-Programmiersprachen nach IEC 61131-3 im Vergleich