Fundamentals
PLC Data Types Explained: INT, REAL, BOOL & Type Conversion in Structured Text
Understand every IEC 61131-3 data type, when to use each one, and how to safely convert between them in Structured Text programs.
Why Data Types Matter in PLC Programming
Choosing the correct data type is one of the most critical decisions in PLC programming. The wrong type can cause overflow errors, precision loss, or unexpected behavior that's difficult to debug on a live machine. IEC 61131-3 defines a rich type system — mastering it is essential for reliable automation code.
Boolean: The Foundation of PLC Logic
BOOL is the most fundamental PLC data type, representing a single TRUE/FALSE value. Every digital I/O point maps to a BOOL.
VAR
StartButton : BOOL; // Digital input
MotorRunning : BOOL; // Internal state
AlarmActive : BOOL := FALSE; // Initialized
END_VAR// Boolean operations
MotorRunning := StartButton AND NOT AlarmActive;
Boolean Best Practices
bMotorRunning not M001Integer Types: INT, SINT, DINT, LINT, UINT
IEC 61131-3 defines several integer types with different ranges:
| Type | Size | Range |
|---|---|---|
| SINT | 8-bit signed | -128 to 127 |
| INT | 16-bit signed | -32,768 to 32,767 |
| DINT | 32-bit signed | -2,147,483,648 to 2,147,483,647 |
| LINT | 64-bit signed | ±9.2 × 10¹⁸ |
| USINT | 8-bit unsigned | 0 to 255 |
| UINT | 16-bit unsigned | 0 to 65,535 |
| UDINT | 32-bit unsigned | 0 to 4,294,967,295 |
| ULINT | 64-bit unsigned | 0 to 18.4 × 10¹⁸ |
VAR
PartCount : INT; // Typical counter
BatchTotal : DINT; // Large accumulator
SensorRaw : UINT; // Analog input (0–65535)
MotorSpeed : INT; // Signed speed reference
END_VAR// Overflow danger! INT max is 32767
PartCount := PartCount + 1;
IF PartCount > 30000 THEN
// Consider switching to DINT before overflow
END_IF;
Choosing the Right Integer Type
Floating-Point Types: REAL and LREAL
REAL (32-bit) and LREAL (64-bit) handle decimal numbers for analog processing, PID control, and engineering calculations.
VAR
Temperature : REAL; // 32-bit float
PreciseAngle : LREAL; // 64-bit double
ScaleFactor : REAL := 0.00610352; // 20mA / 3277 counts
END_VARTemperature := INT_TO_REAL(SensorRaw) * ScaleFactor;
Floating-Point Pitfalls
Never compare REALs with equality:
// WRONG — floating-point precision errors
IF Temperature = 25.0 THEN ...// CORRECT — use a tolerance band
IF ABS(Temperature - 25.0) < 0.01 THEN ...
Precision loss with REAL:
// REAL has ~7 significant digits
// Values like 16777217.0 cannot be represented exactly
// Use LREAL for high-precision applications
Type Conversion Functions
IEC 61131-3 requires explicit type conversion — there is no implicit casting. Every conversion uses a function named SourceType_TO_TargetType.
Common Conversion Functions
| Function | Description | Example |
|---|---|---|
| INT_TO_REAL | Integer to float | rVal := INT_TO_REAL(iCount); |
| REAL_TO_INT | Float to integer (truncates) | iVal := REAL_TO_INT(rTemp); |
| BOOL_TO_INT | FALSE→0, TRUE→1 | iFlag := BOOL_TO_INT(bRun); |
| INT_TO_BOOL | 0→FALSE, else→TRUE | bActive := INT_TO_BOOL(iState); |
| DINT_TO_REAL | Large int to float | rTotal := DINT_TO_REAL(diCount); |
| INT_TO_STRING | Integer to text | sDisplay := INT_TO_STRING(iVal); |
| STRING_TO_INT | Text to integer | iVal := STRING_TO_INT(sInput); |
| INT_TO_DINT | Widen integer | diVal := INT_TO_DINT(iSmall); |
VAR
RawAnalog : UINT; // 0-65535 from ADC
EngValue : REAL; // Scaled engineering units
DisplayStr : STRING; // For HMI display
END_VAR// Step 1: Convert unsigned integer to REAL for math
EngValue := UINT_TO_REAL(RawAnalog) * 100.0 / 65535.0;
// Step 2: Format for display
DisplayStr := CONCAT(REAL_TO_STRING(EngValue), ' %');
REAL_TO_INT: Truncation vs Rounding
A common source of bugs: REAL_TO_INT truncates (rounds toward zero) in most PLC platforms.
VAR
rValue : REAL := 3.7;
iResult : INT;
END_VARiResult := REAL_TO_INT(rValue); // Result: 3 (not 4!)
// To round properly, add 0.5 before converting:
iResult := REAL_TO_INT(rValue + 0.5); // Result: 4
Byte and Bit-Level Types: BYTE, WORD, DWORD
These types are essential for communication protocols, register mapping, and bit manipulation.
VAR
StatusWord : WORD; // 16-bit register
ErrorByte : BYTE; // 8-bit status
bBit3 : BOOL; // Extracted bit
END_VAR// Extract bit 3 from a status word
bBit3 := (StatusWord AND 16#0008) <> 0;
// Set bit 5
StatusWord := StatusWord OR 16#0020;
// Clear bit 5
StatusWord := StatusWord AND NOT 16#0020;
TIME, DATE, and STRING Types
VAR
CycleTime : TIME := T#100ms;
StartDate : DATE := D#2026-01-15;
Greeting : STRING := 'Hello PLC';
LongText : STRING(200); // Extended length
END_VAR// TIME arithmetic
CycleTime := CycleTime + T#50ms; // T#150ms
// STRING operations
LongText := CONCAT('Batch: ', INT_TO_STRING(BatchNum));
Structured Types: STRUCT and ARRAY
For organizing related data:
TYPE MotorData :
STRUCT
Speed : REAL;
Current : REAL;
Running : BOOL;
FaultCode : INT;
END_STRUCT
END_TYPEVAR
Motor1 : MotorData;
Drives : ARRAY[1..4] OF MotorData;
END_VAR
Motor1.Speed := 1500.0;
Drives[2].Running := TRUE;
Common Type Conversion Mistakes
1. Integer Overflow
VAR iCount : INT; END_VAR
// If iCount = 32767:
iCount := iCount + 1; // Wraps to -32768!
// Fix: Use DINT for large accumulators
2. Division Precision Loss
VAR
iNumerator : INT := 7;
iDenominator : INT := 2;
rResult : REAL;
END_VAR// WRONG: integer division happens first → 3.0
rResult := INT_TO_REAL(iNumerator / iDenominator);
// CORRECT: convert before dividing → 3.5
rResult := INT_TO_REAL(iNumerator) / INT_TO_REAL(iDenominator);
3. BOOL-to-INT Ambiguity
// Some platforms: TRUE = 1, others: TRUE = -1 (16#FFFF)
// Always use explicit conversion:
iVal := BOOL_TO_INT(bFlag); // Guaranteed 0 or 1
Practice data type conversions in our online ST editor — experiment with INT, REAL, and STRING operations in real time.