PLC Data Types: From Single Bits to Complex Structures
Basic Types: BOOL, INT, and REAL
The IEC 61131-3 standard defines a set of elementary data types that every PLC programmer must master. These types determine how much memory a variable occupies and what operations can be performed on it.
BOOL: The simplest type, representing TRUE or FALSE. Every digital input, output, and internal flag uses BOOL.
Integer Types: Store whole numbers without decimal points.
| Type | Size | Range |
|---|---|---|
| SINT | 8 bits | -128 to 127 |
| INT | 16 bits | -32768 to 32767 |
| DINT | 32 bits | -2,147,483,648 to 2,147,483,647 |
| UINT | 16 bits | 0 to 65535 |
| UDINT | 32 bits | 0 to 4,294,967,295 |
INT is the most commonly used for counters, part counts, and raw analog values. DINT is used when values exceed 32767, such as production totals or encoder positions.
REAL and LREAL: Floating-point types for temperature readings, pressure values, and PID calculations. REAL provides approximately 7 decimal digits of precision (32-bit). LREAL provides approximately 15 digits (64-bit).
Text and Time: STRING, TIME, and DATE
STRING: Stores text data such as product names, batch IDs, and operator messages.
VAR
sProductName : STRING(40) := 'Olive Oil 500ml';
sBatchID : STRING(20) := 'B2026-04-001';
END_VAR
The number in parentheses sets the maximum length. String operations include LEN, CONCAT, LEFT, RIGHT, MID, and FIND.
TIME and DATE: Critical for timers, delays, and production scheduling.
VAR
tCycleDelay : TIME := T#2s500ms; // 2.5 seconds
tLongDelay : TIME := T#1h30m; // 1 hour 30 minutes
dToday : DATE := D#2026-04-15;
todNow : TIME_OF_DAY := TOD#08:30:00;
dtStamp : DATE_AND_TIME := DT#2026-04-15-08:30:00;
END_VAR
The TIME type is used with all timer function blocks (TON, TOF, TP). DATE and TIME_OF_DAY are used for scheduling operations, such as running a cleaning cycle at midnight.
Arrays: Storing Multiple Values
Arrays store multiple values of the same type under a single name, accessed by index. They are essential for handling groups of sensors, conveyor zones, or recipe parameters.
VAR
aTemperatures : ARRAY[0..9] OF REAL; // 10 temperature readings
aSensorOK : ARRAY[1..16] OF BOOL; // 16 sensor status flags
END_VAR
// Find maximum temperature
rMaxTemp := aTemperatures[0];
FOR i := 1 TO 9 DO
IF aTemperatures[i] > rMaxTemp THEN
rMaxTemp := aTemperatures[i];
END_IF;
END_FOR;
Arrays are commonly used in filling machines where multiple nozzles must be monitored independently, or in conveyor systems with multiple zones sharing identical control logic.
Structs: Grouping Sensor Data
Structures group related variables of different types into a single unit, invaluable for organizing sensor data or motor parameters.
TYPE ST_SensorData :
STRUCT
rValue : REAL; // current reading in engineering units
bFault : BOOL; // sensor fault detected
bInRange : BOOL; // value within acceptable limits
rHighLimit : REAL; // upper alarm threshold
rLowLimit : REAL; // lower alarm threshold
END_STRUCT
END_TYPE
VAR
stTemperature : ST_SensorData;
END_VAR
stTemperature.rHighLimit := 85.0;
stTemperature.rLowLimit := 10.0;
stTemperature.bInRange :=
(stTemperature.rValue >= stTemperature.rLowLimit) AND
(stTemperature.rValue <= stTemperature.rHighLimit);
You can create arrays of structs. For a filling machine with 8 nozzles: astNozzles : ARRAY[0..7] OF ST_SensorData; gives each nozzle its own value, fault flag, and limits.
Enumerations: Machine States
Enumerations define a set of named constants, making state machines far more readable than raw integer values.
TYPE E_MachineState :
(
IDLE := 0,
STARTING := 1,
RUNNING := 2,
STOPPING := 3,
FAULTED := 4
);
END_TYPE
VAR
eMachineState : E_MachineState := E_MachineState.IDLE;
END_VAR
CASE eMachineState OF
E_MachineState.IDLE:
bMotorRun := FALSE;
IF bStartCmd THEN eMachineState := E_MachineState.STARTING; END_IF;
E_MachineState.RUNNING:
bMotorRun := TRUE;
IF bFaultDetected THEN eMachineState := E_MachineState.FAULTED; END_IF;
E_MachineState.FAULTED:
bMotorRun := FALSE;
bAlarmLight := TRUE;
IF bResetCmd THEN eMachineState := E_MachineState.IDLE; END_IF;
END_CASE;
Using E_MachineState.RUNNING instead of the number 2 makes the code self-documenting.
Memory Organization: Areas and Addresses
PLCs organize memory into distinct areas, each serving a specific purpose:
| Area | Prefix | Purpose | Example |
|---|---|---|---|
| Input image | I | Physical input states | I0.0 (bit), IW0 (word) |
| Output image | Q | Physical output states | Q0.0 (bit), QW0 (word) |
| Markers / Memory | M | Internal flags and data | M0.0 (bit), MW10 (word) |
| Data blocks | DB | Structured data storage | DB1.DBX0.0 (bit) |
Addressing modes include bit (I0.0), byte (IB0), word (IW0, 16 bits), and double word (ID0, 32 bits). In modern programming environments like TIA Portal and CODESYS, symbolic addressing using variable names is preferred over absolute addresses. Instead of I0.0, you assign the input to bStartButton in the I/O configuration, making programs portable and easier to maintain.
Summary
IEC 61131-3 data types range from simple BOOL and INT to complex structures and enumerations. Arrays allow efficient handling of repeated data such as multiple sensor readings or conveyor zones. Structs group related variables into logical units that mirror real-world devices. Enumerations transform cryptic state numbers into readable names for state machines. Understanding memory organization and addressing connects these software types to the physical I/O modules in the PLC rack. Choosing the right data types from the start leads to cleaner, more maintainable industrial control programs.