Datentypen und Variablen in der SPS

Eine SPS rechnet nicht mit losen Zahlen. Jeder Wert, den eine Steuerung speichert oder verarbeitet, steckt in einer Variablen – und jede Variable hat einen Datentyp. Der Datentyp entscheidet über drei Dinge: wie viel Speicher der Wert belegt, welchen Zahlenbereich er abdecken kann und welche Operationen erlaubt sind. Wer das nicht beachtet, bekommt früher oder später Überläufe, falsche Vergleiche oder verschenkten Speicher. Dieser Beitrag zeigt, welche Datentypen es gibt, wann man welchen nimmt und wie man Variablen sauber deklariert.

Vorwissen

  • Was ist eine SPS? Aufbau und Funktion
  • Zahlensysteme: binär, hex, BCD

Lernziele

Nach diesem Beitrag kannst du:

  • erklären, was eine Variable in der SPS ausmacht und welche Rolle der Datentyp dabei spielt
  • die wichtigsten Datentypen nach Größe, Wertebereich und Verwendungszweck unterscheiden
  • den passenden Datentyp für eine Aufgabe auswählen und typische Überlauf-Fallen vermeiden
  • erklären, warum signed-Datentypen negative Zahlen darstellen können und wie das Zweierkomplement dahintersteht
  • Variablen korrekt deklarieren und den Unterschied zwischen lokalen und globalen Variablen sowie Konstanten benennen

1. Warum Datentypen?

Stell dir vor, eine SPS soll sich einen Wert merken – etwa die Stückzahl an einem Förderband. Dieser Wert muss irgendwo im Speicher liegen, und das Programm muss wissen, wo. Genau dafür gibt es Variablen. Eine Variable ist ein benannter Platz im Speicher, unter dem ein Wert abgelegt wird. Statt mit kryptischen Speicheradressen zu hantieren, schreibt man im Programm einfach Stueckzahl und meint damit immer denselben Wert.

Eine Variable besteht aus drei Teilen: einem Namen (Stueckzahl), einem Datentyp (etwa eine Ganzzahl) und dem aktuellen Wert (zum Beispiel 42). Der Name ist für den Menschen da, der Datentyp und der Wert für die Steuerung.

Warum reicht es nicht, einfach „alles als Zahl“ zu speichern? Weil eine SPS nur begrenzten Speicher hat und mit klaren Regeln arbeiten muss. Der Datentyp legt drei Dinge fest:

  • Speicherbedarf: Ein einzelnes Ja/Nein-Signal braucht nur ein Bit. Eine große Zählnummer braucht mehr Platz. Würde man jedem Signal denselben großen Speicher zuweisen, wäre der Merkerbereich schnell voll.
  • Wertebereich: Jeder Datentyp kann nur einen bestimmten Zahlenbereich abdecken. Wer das überschreitet, bekommt falsche Ergebnisse.
  • Erlaubte Operationen: Auf einem Wahrheitswert kann man UND und ODER rechnen, aber keine Division. Auf einer Zahl umgekehrt. Der Datentyp sorgt dafür, dass nur sinnvolle Operationen zugelassen werden.

Es gibt noch einen vierten, oft übersehenen Aspekt: Datentypen schützen vor Flüchtigkeitsfehlern. Wenn das Programmiersystem weiß, dass Stueckzahl eine Ganzzahl ist, meldet es einen Fehler, sobald jemand versehentlich einen Wahrheitswert zuweisen will. Diese Prüfung passiert schon beim Übersetzen des Programms, lange bevor die Anlage läuft.

In der SPS gibt es zwei Wege, einen Wert anzusprechen. Die absolute Adressierung zeigt direkt auf eine Speicherstelle, etwa %I0.0 für einen Eingang, %Q0.1 für einen Ausgang oder %MW10 für ein Merkerwort. Die symbolische Variable dagegen trägt einen Namen wie Starttaster und überlässt es dem System, sich um die Speicherstelle zu kümmern. Moderne Programme arbeiten fast nur noch symbolisch. Wie genau Eingänge, Ausgänge und Merker adressiert werden, ist ein Thema für sich und wird in einem eigenen Beitrag behandelt – hier reicht das Grundverständnis, dass hinter jeder Variablen letztlich eine Speicherstelle mit einem Datentyp steht.

Eine Variable in der SPS besteht aus drei Bestandteilen. Welche Aufzählung ist vollständig und korrekt?

  • a) Adresse, Spannung, Wert
  • b) Name, Datentyp, Wert
  • c) Name, Farbe, Speicheradresse
  • d) Datentyp, Zykluszeit, Wert

Richtig: b)

Eine Variable verbindet einen Namen (für den Menschen) mit einem Datentyp (legt Speicher und erlaubte Operationen fest) und dem aktuellen Wert. Spannung und Zykluszeit haben mit dem Aufbau einer Variablen nichts zu tun; eine Farbe gibt es nicht.

Warum ist es sinnvoll, dass eine SPS überhaupt zwischen Datentypen unterscheidet, statt jeden Wert gleich zu behandeln?

  • a) Damit alle Variablen gleich viel Speicher belegen
  • b) Damit das Programm langsamer und dadurch sicherer läuft
  • c) Weil nur so absolute Adressen möglich sind
  • d) Weil der Datentyp Speicherbedarf, Wertebereich und erlaubte Operationen festlegt

Richtig: d)

Der Datentyp steuert Speicherbedarf, zulässigen Wertebereich und erlaubte Operationen und ermöglicht zusätzlich eine Prüfung schon beim Übersetzen. Gleicher Speicher für alle (a) wäre Verschwendung, langsamer läuft nichts (b), und absolute Adressen funktionieren auch ohne diese Unterscheidung (c).

Was unterscheidet eine symbolische Variable von einer absoluten Adresse?

  • a) Die symbolische Variable trägt einen Namen, das System verwaltet die Speicherstelle
  • b) Die symbolische Variable braucht keinen Speicher
  • c) Die absolute Adresse kann keine Datentypen haben
  • d) Absolute Adressen sind in der IEC nicht erlaubt

Richtig: a)

Hinter beiden steckt letztlich eine Speicherstelle mit Datentyp. Der Unterschied: Bei der symbolischen Variablen vergibt man einen Namen und überlässt die Zuordnung zur Speicherstelle dem System. Speicher braucht auch die symbolische Variable (b), Datentypen gelten für beide (c), und absolute Adressen sind weiterhin zulässig (d).

2. Bit-Datentypen: BOOL, BYTE, WORD, DWORD

Die kleinste Informationseinheit in der SPS ist ein einzelnes Bit – es kann nur zwei Zustände annehmen: 0 oder 1, falsch oder wahr. Genau dafür gibt es den Datentyp BOOL (von „boolean“, also Wahrheitswert). Ein BOOL belegt logisch ein Bit und kennt nur die Werte TRUE und FALSE. Jeder Eingang, jeder Ausgang, jeder Verriegelung, jedes Meldebit ist im Kern ein BOOL.

Oft will man aber nicht ein einzelnes Bit betrachten, sondern eine ganze Gruppe von Bits als Block. Dafür gibt es drei Datentypen, die reine Bitmuster sind – also Sammlungen von Bits ohne eine feste Bedeutung als Zahl:

Datentyp Größe Anzahl Bits
BOOL 1 Bit 1
BYTE 8 Bit 8
WORD 16 Bit 16
DWORD 32 Bit 32

Wichtig ist der Unterschied zwischen einem logischen Wert und einer Bitsammlung. Ein BOOL steht für eine klare Ja/Nein-Aussage: Der Taster ist gedrückt oder nicht. BYTE, WORD und DWORD dagegen sind einfach Behälter für mehrere Bits. Sie sagen nichts darüber aus, ob es sich um eine Zahl, ein Zeichen oder eine Gruppe einzelner Meldebits handelt. Man verwendet sie überall dort, wo es auf die einzelnen Bits ankommt und nicht auf einen rechnerischen Wert – etwa bei einem Statuswort, in dem jedes Bit eine andere Meldung trägt, oder bei Bitmasken.

Wann nimmt man ein WORD und wann eine Zahl wie INT? Faustregel: Sobald man mit dem Wert rechnen will (addieren, vergleichen, multiplizieren), nimmt man einen Zahlentyp. Will man dagegen einzelne Bits setzen, abfragen oder maskieren, ist ein Bitmuster-Typ wie WORD die richtige Wahl. Beide belegen bei gleicher Größe denselben Speicher – der Unterschied liegt allein darin, wie das Programm den Inhalt interpretaiert.

Aufbau eines BYTE (8 Bit) Bit 7 ist das höchstwertige Bit (MSB), Bit 0 das niederwertigste (LSB). 1 0 1 1 0 0 1 0 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 MSB LSB Ein WORD (16 Bit) = 2 Byte High-Byte (Bit 15 … 8) Low-Byte (Bit 7 … 0) Ein DWORD (32 Bit) setzt sich entsprechend aus zwei WORD bzw. vier Byte zusammen.

Welcher Datentyp ist die kleinste Informationseinheit und kann ausschließlich TRUE oder FALSE annehmen?

  • a) BOOL
  • b) BYTE
  • c) WORD
  • d) DWORD

Richtig: a)

BOOL belegt logisch ein einziges Bit und kennt nur die zwei Zustände TRUE und FALSE. BYTE (8 Bit), WORD (16 Bit) und DWORD (32 Bit) sind Sammlungen mehrerer Bits und können entsprechend viele verschiedene Muster annehmen.

Ein Statuswort fasst 16 einzelne Meldebits zusammen, die unabhängig voneinander gesetzt werden. Welcher Datentyp passt am besten und warum?

  • a) INT, weil 16 Bit eine Zahl ergeben
  • b) WORD, weil es ein 16-Bit-Bitmuster ohne feste Zahlenbedeutung ist
  • c) BOOL, weil es um Meldungen geht
  • d) REAL, weil many Werte gespeichert werden

Richtig: b)

Geht es um einzelne, unabhängige Bits, ist ein Bitmuster-Typ richtig – ein WORD bietet genau 16 Bit. INT würde den Inhalt als eine einzige vorzeichenbehaftete Zahl deuten (a), ein BOOL fasst nur ein Bit (c), und REAL ist ein Fließkommatyp ohne Bezug zu Meldebits (d).

Ein WORD und ein INT belegen beide 16 Bit. Worin liegt der entscheidende Unterschied?

  • a) Das WORD ist doppelt so groß im Speicher
  • b) Der INT kann keine negativen Werte speichern
  • c) Beide sind identisch, nur der Name ist anders
  • d) Das WORD ist ein reines Bitmuster, der INT eine vorzeichenbehaftete Zahl

Richtig: d)

Bei gleicher Größe unterscheidet sich allein die Interpretation: WORD ist ein Bitmuster, INT eine Zahl mit Vorzeichen. Sie belegen gleich viel Speicher (a), der INT kann sehr wohl negativ werden (b), und identisch sind sie gerade nicht (c).

Wann sollte man statt eines Bitmuster-Typs (z. B. WORD) einen Zahlentyp (z. B. INT) wählen?

  • a) Wenn man einzelne Bits maskieren will
  • b) Wenn der Wert im Speicher liegen soll
  • c) Immer, da Zahlentypen weniger Speicher brauchen
  • d) Wenn man mit dem Wert rechnen will – addieren, vergleichen, multiplizieren

Richtig: d)

Sobald gerechnet, addiert oder verglichen wird, nimmt man einen Zahlentyp. Für das Setzen oder Abfragen einzelner Bits ist ein Bitmuster-Typ besser (a). Im Speicher liegen beide (b), und bei gleicher Bitbreite ist der Speicherbedarf identisch (c).

3. Ganzzahl-Datentypen: INT, DINT, SINT und die unsigned-Varianten

Sobald die SPS mit ganzen Zahlen rechnen soll – Stückzahlen, Positionen, Zählwerte – kommen die Ganzzahl-Datentypen ins Spiel. Sie unterscheiden sich in zwei Eigenschaften: in der Bitbreite (wie viele Bits, also wie groß der Wertebereich) und im Vorzeichen (ob nur positive Werte oder auch negative möglich sind).

Datentypen mit Vorzeichen heißen signed, solche ohne unsigned. Bei den signed-Typen wird ein Teil des Wertebereichs für negative Zahlen reserviert. Die unsigned-Varianten nutzen den ganzen Bereich für positive Zahlen, können dafür aber gar nicht negativ werden.

Datentyp Bits Vorzeichen Wertebereich
SINT 8 signed −128 bis +127
USINT 8 unsigned 0 bis 255
INT 16 signed −32768 bis +32767
UINT 16 unsigned 0 bis 65535
DINT 32 signed −2147483648 bis +2147483647
UDINT 32 unsigned 0 bis 4294967295
LINT 64 signed sehr großer Bereich (±9,2 · 10¹⁸)

Den Wertebereich kann man ausrechnen. Bei einem unsigned-Typ mit n Bit gilt:

Anzahl = 2 ** n

Wertebereich = 0 bis (2 ** n) – 1

  • n … Anzahl der Bits

Ein USINT mit 8 Bit deckt also 2⁸ = 256 Werte ab, nämlich 0 bis 255. Bei signed-Typen wird etwa die Hälfte der Werte für negative Zahlen verwendet:

Minimum = -(2 ** (n – 1))

Maximum = (2 ** (n – 1)) – 1

  • n … Anzahl der Bits

Bei einem INT mit 16 Bit ergibt das ein Minimum von −2¹⁵ = −32768 und ein Maximum von 2¹⁵ − 1 = +32767.

Warum kann ein signed-Typ überhaupt negative Zahlen darstellen? Die Antwort liegt im Zweierkomplement – der Methode, mit der praktisch alle Steuerungen negative Ganzzahlen im Speicher ablegen. Die Grundidee: Das höchstwertige Bit (MSB) bekommt eine besondere Rolle als Vorzeichenbit. Ist es 0, ist die Zahl positiv (oder null), ist es 1, ist sie negativ. Aber es ist kein bloßes „Minus-Schild“, das man davorhängt. Stattdessen werden die negativen Zahlen so kodiert, dass die normale Addition automatisch das richtige Ergebnis liefert – die Hardware muss für die Subtraktion also nichts Besonderes können, sie addiert einfach.

Eine negative Zahl bildet man im Zweierkomplement, indem man alle Bits des Betrags umkehrt (aus 0 wird 1, aus 1 wird 0) und anschließend 1 addiert. Bei 8 Bit wird aus +1 (0000 0001) durch Umkehren 1111 1110 und nach dem Addieren von 1 schließlich 1111 1111 – das ist die Darstellung von −1.

Gelöstes Beispiel

Ein Zählwert soll in einem 16-Bit-signed-Datentyp (INT) gespeichert werden. Wie groß ist der darstellbare Wertebereich, und wie viele verschiedene Werte sind das?

Gegeben: Bitbreite n = 16 Bit, Typ: signed

Gesucht: Minimum, Maximum und Anzahl der Werte

Lösungsweg:

  1. Schritt 1 — Anzahl der Werte:
    Anzahl = 2^16 = 65536 Werte
  2. Schritt 2 — Minimum (signed):
    Minimum = −(2^(16−1)) = −(2^15) = −32768
  3. Schritt 3 — Maximum (signed):
    Maximum = 2^(16−1) − 1 = 2^15 − 1 = 32767

Ergebnis: Der INT deckt −32768 bis +32767 ab, das sind insgesamt 65536 verschiedene Werte.

Übungen

Wie viele verschiedene Werte kann ein 8-Bit-Datentyp darstellen?

2^8 = 256 Werte.

Welchen Wertebereich hat ein USINT (8 Bit, unsigned)?

0 bis 2^8 − 1 = 0 bis 255.

Welchen Wertebereich hat ein DINT (32 Bit, signed)?

Minimum = −2^31 = −2147483648, Maximum = 2^31 − 1 = 2147483647.

Ein UINT (16 Bit, unsigned) steht auf seinem Maximalwert. Welcher Wert ist das, und was passiert, wenn um eins weitergezählt wird?

Maximum = 2^16 − 1 = 65535. Beim Weiterzählen läuft der Wert über und springt zurück auf 0.

Eine Anlage summiert pro Sekunde 1000 Impulse und läuft im Dauerbetrieb. Reicht ein DINT, um die Impulse eines vollen Tages (86400 s) zu zählen, oder ist LINT nötig? Begründe rechnerisch.

Impulse pro Tag = 1000 · 86400 = 86 400 000. Das liegt deutlich unter dem DINT-Maximum von rund 2,1 · 10⁹, ein DINT reicht also für einen Tag. Erst bei sehr langem Aufsummieren (etwa über Jahre) oder höheren Impulsraten nähert man sich der DINT-Grenze und sollte auf LINT wechseln.

Ein SINT (8 Bit, signed) steht auf seinem Maximum +127. Im nächsten Zyklus wird er um eins erhöht. Welcher Wert steht danach im Speicher?

  • a) −128
  • b) +128
  • c) 0
  • d) +255

Richtig: a)

Im Zweierkomplement läuft 0111 1111 (+127) bei +1 auf 1000 0000 über, und das ist −128 – das Minimum des SINT. +128 (b) existiert im SINT gar nicht, 0 (c) wäre ein vollständiger Umlauf, und +255 (d) gehört zum unsigned USINT.

Wozu dient das Zweierkomplement bei signed-Ganzzahlen?

  • a) Es verdoppelt den Wertebereich
  • b) Es kodiert negative Zahlen so, dass die Subtraktion über normale Addition funktioniert
  • c) Es spart Speicherplatz gegenüber unsigned
  • d) Es verhindert jeden Überlauf

Richtig: b)

Das Zweierkomplement legt negative Zahlen so ab, dass die Hardware nur addieren muss, um auch zu subtrahieren. Der Wertebereich wird nicht verdoppelt, sondern in positiv und negativ aufgeteilt (a), der Speicher is gleich groß wie bei unsigned (c), und Überläufe verhindert es gerade nicht (d) – es ist sogar deren Ursache.

Ein Positionswert kann bis etwa 5 000 000 ansteigen und ist immer positiv. Welcher Datentyp ist am sinnvollsten?

  • a) INT (16 Bit, signed)
  • b) SINT (8 Bit, signed)
  • c) DINT (32 Bit, signed)
  • d) BOOL

Richtig: c)

5 000 000 sprengt den INT-Bereich (max. 32767) und erst recht den SINT (max. 127); ein 32-Bit-DINT (bis rund 2,1 · 10⁹) deckt den Wert mit Reserve ab. Ein UDINT wäre auch möglich, steht aber nicht zur Wahl; ein BOOL (d) kann nur TRUE/FALSE.

Worin unterscheiden sich INT und UINT bei gleicher Bitbreite von 16 Bit?

  • a) UINT belegt mehr Speicher
  • b) INT reicht von 0 bis 65535, UINT von −32768 bis +32767
  • c) INT reicht von −32768 bis +32767, UINT von 0 bis 65535
  • d) Beide haben denselben Wertebereich

Richtig: c)

Beide sind 16 Bit groß, also 65536 Werte. Der signed INT teilt diese in negativ und positiv (−32768 bis +32767), the vorzeichenlose UINT nutzt sie alle für positive Werte (0 bis 65535). Antwort b vertauscht die beiden, der Speicher ist gleich (a), und die Bereiche sind unterschiedlich (d).

4. Gleitkomma und Zeit: REAL und die Zeittypen

Ganze Zahlen reichen nicht für alles. Sobald gebrochene Werte ins Spiel kommen – ein Temperatursollwert von 21,5 °C, ein Druck von 4,75 bar, ein Verstärkungsfaktor von 0,8 – braucht man einen Datentyp, der Nachkommastellen kann. Das ist der REAL, ein 32-Bit-Datentyp für Fließkommazahlen (auch Gleitkommazahlen genannt). Er speichert die Zahl nicht starr, sondern in der Form „Wert mal Zehnerpotenz“, ähnlich der wissenschaftlichen Schreibweise. Dadurch deckt er einen riesigen Bereich von sehr kleinen bis sehr großen Werten ab.

Der Komfort hat einen Preis: begrenzte Genauigkeit. Ein REAL hat etwa sieben signifikante Stellen. Viele Dezimalzahlen lassen sich im Binärsystem nicht exakt darstellen, sondern nur sehr nah angenähert. Das führt zu winzigen Rundungsabweichungen. Für die meisten Mess- und Stellgrößen ist das völlig unkritisch, aber es hat eine wichtige Folge für Vergleiche.

Deshalb gilt eine zentrale Regel: REAL-Werte nie direkt mit „gleich“ vergleichen. Eine Abfrage wie „ist der Istwert exakt gleich 100,0?“ schlägt in der Praxis fast immer fehl, weil der berechnete Wert vielleicht 99,99999 oder 100,00001 ist. Statt auf Gleichheit prüft man auf einen Bereich: „liegt der Wert nahe genug an 100,0, etwa zwischen 99,9 und 100,1?“. Bei Ganzzahlen ist der Gleichheitsvergleich dagegen unproblematisch, weil sie exakt gespeichert werden.

Wer höhere Genauigkeit braucht – etwa bei langen Rechenketten oder sehr feinen Messwerten – greift in modernen Steuerungen zum LREAL, einem 64-Bit-Fließkommatyp mit rund fünfzehn signifikanten Stellen. In Systemen wie TIA Portal oder TwinCAT is LREAL bei anspruchsvollen Berechnungen längst Standard. Das Grundproblem der nicht ganz exakten Darstellung bleibt allerdings auch beim LREAL bestehen – der Gleichheitsvergleich ist also weiterhin tabu.

Eine eigene Gruppe bilden die Zeit-Datentypen. Der wichtigste ist TIME: Er speichert eine Zeitdauer, etwa für Verzögerungen. Geschrieben wird ein solcher Wert mit dem Präfix T#, gefolgt von der Dauer – zum Beispiel T#5s für fünf Sekunden, T#500ms für eine halbe Sekunde oder T#1m30s für anderthalb Minuten. TIME ist kein Datum und keine Uhrzeit, sondern reine Zeitspanne. Genau diese Werte braucht man, um Zeitfunktionen wie die Einschalt- oder Ausschaltverzögerung zu parametrieren – das Thema dieser Zeitfunktionen wird in einem eigenen Beitrag ausführlich behandelt; hier reicht zu wissen, dass deren Zeitvorgaben vom Typ TIME sind.

Warum soll man zwei REAL-Werte nie direkt mit „gleich“ vergleichen?

  • a) Weil REAL keine Vergleiche unterstützt
  • b) Weil REAL-Werte oft nur sehr genau angenähert gespeichert werden und kleine Abweichungen entstehen
  • c) Weil der Vergleich zu viel Speicher braucht
  • d) Weil REAL immer auf ganze Zahlen gerundet wird

Richtig: b)

Viele Dezimalzahlen lassen sich binär nicht exakt darstellen, sodass winzige Abweichungen bleiben und ein exakter Gleichheitstreffer ausbleibt. Vergleiche sind grundsätzlich möglich (a), Speicher ist nicht das Problem (c), und REAL rundet gerade nicht auf ganze Zahlen (d) – sonst bräuchte man ihn nicht.

Eine Regelung soll melden, dass 50,0 °C erreicht sind. Welche Abfrage ist robust?

  • a) Istwert = 50.0
  • b) Istwert liegt zwischen 49,8 und 50,2
  • c) Istwert > 50.0 und Istwert < 50.0
  • d) Istwert ist eine ganze Zahl

Richtig: b)

Robust ist die Prüfung auf ein Toleranzfenster um den Sollwert. Der exakte Gleichheitsvergleich (a) trifft bei REAL praktisch nie; die Bedingung in c kann niemals gleichzeitig wahr werden; und ob der Wert ganzzahlig ist (d), sagt nichts über das Erreichen der Temperatur.

Was bedeutet der Wert T#1m30s und welchen Datentyp hat er?

  • a) Eine Zeitdauer von 90 Sekunden, Typ TIME
  • b) Eine Uhrzeit, Typ DATE
  • c) Eine Frequenz von 1,3 Hz, Typ REAL
  • d) Eine Position von 1,30 m, Typ DINT

Richtig: a)

Das Präfix T# kennzeichnet eine Zeitdauer vom Typ TIME; 1 Minute und 30 Sekunden ergeben 90 Sekunden. Es ist kein Datum/Uhrzeit (b), keine Frequenz (c) und keine Längenangabe (d).

Wann greift man statt REAL zum LREAL?

  • a) Wenn man Zeitdauern speichern will
  • b) Wenn weniger Speicher gebraucht wird
  • c) Wenn höhere Genauigkeit für anspruchsvolle Berechnungen nötig ist
  • d) Wenn man nur ganze Zahlen braucht

Richtig: c)

LREAL ist der 64-Bit-Fließkommatyp mit deutlich mehr signifikanten Stellen und wird bei feinen Messwerten oder langen Rechenketten genutzt. Zeitdauern speichert TIME (a), LREAL braucht mehr statt weniger Speicher (b), und für ganze Zahlen nimmt man Ganzzahltypen (d).

5. Variablen richtig deklarieren und verwenden

Bevor eine Variable im Programm benutzt werden kann, muss sie deklariert werden – also angemeldet mit Name und Datentyp. In der Deklaration legt man fest, wie die Variable heißt, welchen Typ sie hat und optional, mit welchem Startwert sie beim Programmstart beginnt. Eine typische Deklaration sieht sinngemäß so aus: Name Fuellmenge, Typ INT, Startwert 0. Ab diesem Moment kennt das System die Variable und weiß, was mit ihr erlaubt ist.

Bei den Namen lohnt sich Disziplin. Namenskonventionen sorgen dafür, dass man im Programm sofort erkennt, was gemeint ist. Bewährt haben sich sprechende Namen ohne Umlaute und Leerzeichen, oft mit einer kurzen Vorsilbe für die Art der Variablen – etwa eine Kennung für Eingänge, Ausgänge oder Merker. Wichtig ist vor allem Einheitlichkeit: Wer einmal Sollwert_ml schreibt, sollte nicht an anderer Stelle sollwertMilliliter verwenden. Konsequente Benennung spart bei der Fehlersuche mehr Zeit als jede andere Maßnahme.

Variablen unterscheiden sich auch in ihrer Gültigkeit. Eine lokale Variable ist nur innerhalb des Programmbausteins bekannt, in dem sie deklariert wurde – außerhalb existiert sie nicht. Eine globale Variable dagegen ist im ganzen Projekt sichtbar und kann von mehreren Bausteinen genutzt werden. Faustregel: So lokal wie möglich, so global wie nötig. Lokale Variablen halten die Bausteine übersichtlich und verhindern, dass sich verschiedene Programmteile versehentlich gegenseitig Werte überschreiben. Global macht man nur das, was wirklich mehrere Bausteine gemeinsam brauchen.

Eine besondere Form ist die Konstante: ein Wert, der nach der Festlegung nicht mehr verändert wird, etwa ein fester Umrechnungsfaktor oder eine maximale Stückzahl. Konstanten bekommen einen sprechenden Namen und machen das Programm lesbarer – MAX_STUECKZAHL sagt mehr als eine nackte Zahl mitten im Code, und ändert sich der Grenzwert, muss man ihn nur an einer Stelle anpassen.

Ein häufiger Stolperstein ist die Typumwandlung. Will man einer REAL-Variablen das Ergebnis einer INT-Rechnung zuweisen oder umgekehrt, müssen die Typen zusammenpassen. Viele Systeme verlangen dafür eine ausdrückliche, explizite Typumwandlung mit Funktionen wie INT_TO_REAL oder REAL_TO_INT. Das ist kein Schikane, sondern Schutz: Beim Umwandeln von REAL nach INT gehen die Nachkommastellen verloren, und der Programmierer soll bewusst entscheiden, dass das in Ordnung ist. Eine implizite Umwandlung, bei der das System ungefragt selbst umrechnet, ist bei manchen Typen erlaubt, sollte aber mit Vorsicht genossen werden – sie verschleiert, was tatsächlich passiert.

Was bedeutet es, eine Variable zu „deklarieren“?

  • a) Ihren Wert im laufenden Betrieb zu ändern
  • b) Sie mit Name und Datentyp anzumelden, bevor sie verwendet wird
  • c) Sie aus dem Speicher zu löschen
  • d) Sie von lokal auf global umzustellen

Richtig: b)

Deklarieren heißt, die Variable mit Name, Datentyp und optionalem Startwert anzumelden, damit das System sie kennt. Den Wert ändern (a) ist die Verwendung, nicht die Deklaration; Löschen (c) und Sichtbarkeit ändern (d) sind etwas anderes.

Eine Variable wird nur in einem einzigen Baustein gebraucht und soll andere Programmteile nicht beeinflussen. Wie deklariert man sie sinnvoll?

  • a) Als globale Variable
  • b) Als Konstante
  • c) Als lokale Variable
  • d) Als absolute Adresse im Merkerbereich

Richtig: c)

Wird die Variable nur in einem Baustein benötigt, gehört sie lokal deklariert – das hält den Baustein übersichtlich und verhindert ungewolltes Überschreiben durch andere Programmteile. Global (a) wäre unnötig weit sichtbar, eine Konstante (b) ließe sich nicht mehr ändern, und eine absolute Merkeradresse (d) macht sie gerade projektweit zugänglich.

In einem Programm wird Ergebnis := A / B gerechnet, wobei A, B und Ergebnis vom Typ INT sind. A = 7, B = 2. Welcher Wert steht in Ergebnis?

  • a) 3,5
  • b) 4
  • c) 0
  • d) 3

Richtig: d)

Bei der Division zweier INT-Werte fällt der Nachkommaanteil weg – das Ergebnis wird nicht gerundet, sondern abgeschnitten, also 3. Für 3,5 (a) müsste man vorher nach REAL umwandeln; aufgerundet auf 4 (b) wird nicht, und 0 (c) wäre nur bei A kleiner als B die Folge.

Warum verlangen viele Systeme eine explizite Typumwandlung wie REAL_TO_INT, statt automatisch umzurechnen?

  • a) Weil automatische Umwandlung technisch unmöglich ist
  • b) Damit der Programmierer bewusst entscheidet, dass z. B. Nachkommastellen verloren gehen dürfen
  • c) Weil explizite Umwandlung schneller läuft
  • d) Weil REAL und INT denselben Wertebereich haben

Richtig: b)

Die ausdrückliche Umwandlung zwingt zur bewussten Entscheidung – etwa, dass beim Weg von REAL nach INT die Nachkommastellen wegfallen dürfen. Automatisch ginge es technisch durchaus (a), die Geschwindigkeit ist nicht der Grund (c), und die Wertebereiche von REAL und INT sind sehr verschieden (d).

Abschlusstest

Aufgabe 1: Bestimme den Wertebereich und die Anzahl der darstellbaren Werte eines DINT (32 Bit, signed).

Gegeben: n = 32 Bit, signed

Gesucht: Minimum, Maximum, Anzahl

Lösungsweg:

  1. Anzahl = 2^32 = 4294967296
  2. Minimum = −2^(32−1) = −2^31 = −2147483648
  3. Maximum = 2^(32−1) − 1 = 2^31 − 1 = 2147483647

Ergebnis: −2147483648 bis +2147483647, insgesamt 4294967296 Werte.

Aufgabe 2: Ein Prozesswert wird in einem UINT (16 Bit, unsigned) gespeichert und steht aktuell auf 65530. Pro Zyklus wird er um 10 erhöht. Welcher Wert steht nach dem nächsten Zyklus im Speicher?

Gegeben: UINT, Wertebereich 0 bis 65535, Startwert 65530, Zuwachs 10

Gesucht: Wert nach dem Überlauf

Lösungsweg:

  1. Ohne Begrenzung wäre das Ergebnis 65530 + 10 = 65540.
  2. Der UINT-Bereich endet bei 65535 (das sind 65536 Werte, 0 … 65535).
  3. Über das Maximum hinaus läuft der Wert um: 65540 − 65536 = 4.

Ergebnis: Im Speicher steht 4. Der Wert ist durch den Überlauf von oben nach unten umgesprungen.

Welche Aussage über den Datentyp BOOL trifft zu?

  • a) Er kann nur TRUE oder FALSE annehmen
  • b) Er belegt 8 Bit und speichert eine kleine Zahl
  • c) Er ist ein Fließkommatyp
  • d) Er speichert eine Zeitdauer

Richtig: a)

BOOL ist die kleinste Einheit mit genau zwei Zuständen, TRUE und FALSE. 8 Bit hätte ein BYTE/SINT (b), Fließkomma ist REAL (c), und Zeitdauern speichert TIME (d).

Ein Wert kann zwischen 0 und 200 liegen und ist nie negativ. Welcher Datentyp ist am sparsamsten und ausreichend?

  • a) DINT
  • b) INT
  • c) USINT
  • d) REAL

Richtig: c)

Ein USINT (8 Bit, unsigned) deckt 0 bis 255 ab und reicht damit für 0 bis 200 bei minimalem Speicher. INT (b) und DINT (a) können es auch, brauchen aber mehr Platz; REAL (d) ist für Ganzzahlen überdimensioniert und ungenau im Vergleich.

Ein INT steht auf +32767. Er wird um eins erhöht. Was passiert?

  • a) Der Wert bleibt bei +32767 stehen
  • b) Es entsteht ein Laufzeitfehler, der die SPS stoppt
  • c) Der Wert springt auf −32768
  • d) Der Wert springt auf 0

Richtig: c)

Beim signed-Überlauf springt der INT vom größten positiven Wert auf den kleinsten negativen, also von +32767 auf −32768. Er bleibt nicht stehen (a), die meisten Steuerungen lösen keinen Stopp aus (b), und 0 (d) wäre kein einfacher Überlauf um eins.

Warum ist der direkte Gleichheitsvergleich zweier REAL-Werte problematisch?

  • a) REAL unterstützt keine Vergleichsoperatoren
  • b) Der Vergleich dauert mehrere Zyklen
  • c) REAL kann nur mit INT verglichen werden
  • d) REAL-Werte werden oft nur angenähert gespeichert, exakte Gleichheit tritt selten ein

Richtig: d)

Die binäre Annäherung von Dezimalzahlen führt zu winzigen Abweichungen, sodass zwei „eigentlich gleiche“ REAL-Werte selten exakt übereinstimmen. Vergleiche sind möglich (a), dauern nicht mehrere Zyklen (b), und ein Vergleich nur mit INT (c) ist frei erfunden.

Was unterscheidet ein WORD von einem INT bei gleicher Bitbreite?

  • a) Das WORD ist ein Bitmuster, der INT eine vorzeichenbehaftete Zahl
  • b) Das WORD speichert Nachkommastellen
  • c) Der INT ist doppelt so groß
  • d) Sie sind vollkommen identisch

Richtig: a)

Bei gleicher Größe (16 Bit) liegt der Unterschied in der Interpretation: WORD als reines Bitmuster, INT als Zahl mit Vorzeichen. Nachkommastellen kann keiner von beiden (b), der INT ist gleich groß (c), und identisch sind sie nicht (d).

Ein Mengenzähler summiert über Monate sehr große Stückzahlen, die den DINT-Bereich überschreiten können. Welcher Datentyp ist geeignet?

  • a) SINT
  • b) INT
  • c) LINT
  • d) BOOL

Richtig: c)

Überschreitet der Wert den DINT-Bereich (rund 2,1 · 10⁹), braucht man den 64-Bit-Typ LINT, der praktisch nicht überläuft. SINT (a) und INT (b) sind viel zu klein, BOOL (d) speichert keine Zahl.

Eine lokale Variable in Baustein A und eine gleichnamige lokale Variable in Baustein B – was gilt?

  • a) Sie sind dieselbe Variable und teilen sich den Wert
  • b) Es sind zwei unabhängige Variablen, jede nur im eigenen Baustein gültig
  • c) Das System meldet einen Namenskonflikt und übersetzt nicht
  • d) Beide werden automatisch global

Richtig: b)

Lokale Variablen gelten nur im jeweiligen Baustein; der gleiche Name in zwei Bausteinen meint daher zwei getrennte Variablen ohne gemeinsamen Wert. Sie teilen sich nichts (a), es gibt keinen Konflikt (c), und global werden sie nicht (d).

Ergebnis := 9 / 4 mit allen Größen vom Typ INT. Welcher Wert steht in Ergebnis?

  • a) 2,25
  • b) 3
  • c) 4
  • d) 2

Richtig: d)

Die INT-Division schneidet die Nachkommastellen ab: 9 / 4 = 2,25 wird zu 2. Gerundet auf 2,25 (a) oder 3 (b) wird nicht, und 4 (c) ergibt sich gar nicht. Für 2,25 müsste man vor der Division nach REAL umwandeln.

Wozu dient die explizite Typumwandlung INT_TO_REAL?

  • a) Sie wandelt einen ganzzahligen Wert bewusst in einen Fließkommawert um
  • b) Sie verdoppelt den Wertebereich des INT
  • c) Sie löscht die Nachkommastellen eines REAL
  • d) Sie macht aus einer lokalen eine globale Variable

Richtig: a)

INT_TO_REAL überführt einen Ganzzahlwert kontrolliert in einen REAL, etwa um danach mit Nachkommastellen rechnen zu können. Der Wertebereich wird nicht verdoppelt (b), Nachkommastellen löscht eher REAL_TO_INT (c), und mit Sichtbarkeit hat die Funktion nichts zu tun (d).

Welcher Wert beschreibt eine Zeitdauer von zwei Sekunden im Datentyp TIME?

  • a) 2.0 als REAL
  • b) %MW2
  • c) T#2s
  • d) 2000 als INT

Richtig: c)

Zeitdauern vom Typ TIME schreibt man mit dem Präfix T#, hier T#2s. Ein REAL-Wert 2.0 (a) ist eine Zahl ohne Zeitbezug, %MW2 (b) ist eine Merkeradresse, und ein INT 2000 (d) ist eine reine Zahl, die das System nicht als Zeitdauer interpretiert.

Welche Variablenart eignet sich für einen festen Umrechnungsfaktor, der sich im Programm nie ändert?

  • a) Globale BOOL-Variable
  • b) Konstante
  • c) Lokale TIME-Variable
  • d) Absolute Eingangsadresse

Richtig: b)

Ein unveränderlicher Wert gehört in eine Konstante – sie ist sprechend benannt, zentral gepflegt und kann nicht versehentlich überschrieben werden. Eine BOOL (a) speichert keinen Faktor, TIME (c) ist für Zeitdauern, und ein Eingang (d) ändert sich ständig.

Ein USINT soll einen Wert von 300 aufnehmen. Was ist das Problem?

  • a) USINT kann keine geraden Zahlen speichern
  • b) USINT speichert nur negative Werte
  • c) Es gibt kein Problem, USINT reicht bis 1000
  • d) 300 überschreitet den USINT-Bereich von 0 bis 255

Richtig: d)

Ein USINT (8 Bit, unsigned) reicht nur von 0 bis 255; 300 passt nicht hinein und würde zu einem Überlauf führen. Gerade Zahlen sind kein Problem (a), USINT ist gerade unsigned und damit nicht negativ (b), und bis 1000 (c) reicht er bei Weitem nicht.

Glossar

Variable
Ein benannter Speicherplatz in der SPS, bestehend aus Name, Datentyp und aktuellem Wert.
Datentyp
Festlegung, wie ein Wert gespeichert wird; bestimmt Speicherbedarf, Wertebereich und erlaubte Operationen.
BOOL
Datentyp für einen einzelnen Wahrheitswert; kennt nur TRUE und FALSE und belegt logisch ein Bit.
BYTE / WORD / DWORD
Reine Bitmuster-Datentypen mit 8, 16 bzw. 32 Bit, ohne feste Bedeutung als Zahl.
SINT / INT / DINT / LINT
Vorzeichenbehaftete (signed) Ganzzahltypen mit 8, 16, 32 bzw. 64 Bit.
USINT / UINT / UDINT
Vorzeichenlose (unsigned) Ganzzahltypen, die nur nichtnegative Werte speichern.
signed / unsigned
Eigenschaft eines Ganzzahltyps: signed kann negative Werte darstellen, unsigned nur nichtnegative.
Zweierkomplement
Verfahren zur Speicherung negativer Ganzzahlen, bei dem die normale Addition auch die Subtraktion liefert; Ursache der Überlauf-Falle.
Überlauf
Über- oder Unterschreiten des Wertebereichs; der Wert springt unvermittelt auf das andere Ende des Bereichs.
REAL
32-Bit-Datentyp für Fließkommazahlen mit etwa sieben signifikanten Stellen; für gebrochene Werte.
LREAL
64-Bit-Fließkommatyp mit höherer Genauigkeit (rund fünfzehn signifikante Stellen) für anspruchsvolle Berechnungen.
TIME
Datentyp für eine Zeitdauer, geschrieben mit dem Präfix T#, etwa T#5s; liefert Zeitvorgaben für Zeitfunktionen.
Deklaration
Anmeldung einer Variablen mit Name, Datentyp und optionalem Startwert vor ihrer Verwendung.
lokale Variable
Nur innerhalb des Bausteins gültig, in dem sie deklariert wurde.
globale Variable
Im ganzen Projekt sichtbar und von mehreren Bausteinen nutzbar.
Konstante
Benannter Wert, der nach der Festlegung nicht mehr verändert wird.
Typumwandlung
Überführung eines Werts von einem Datentyp in einen anderen, etwa mit INT_TO_REAL; explizit bevorzugt.
Scroll to Top