IL Practical Examples
This section provides practical examples of Instruction List programming. Each example includes the Variables Table definition, the IL code, and an explanation of how it works. Equivalent Structured Text code is shown alongside for comparison.
Basic AND Logic
The simplest IL pattern: combine two inputs with AND logic to drive an output.
Variables
| Name | Type | Class |
|---|---|---|
sensor_a | BOOL | Local |
sensor_b | BOOL | Local |
output | BOOL | Local |
IL Code
codeLD sensor_a (* Load first input *) AND sensor_b (* AND with second input *) ST output (* Store result *)
Equivalent ST
codeoutput := sensor_a AND sensor_b;
Explanation
LD sensor_aloads the value ofsensor_ainto the accumulator.AND sensor_bperforms a logical AND between the accumulator andsensor_b. The result stays in the accumulator.ST outputwrites the accumulator value tooutput.
OR Logic with Negation
Combine OR and NOT to create a safety interlock.
Variables
| Name | Type | Class |
|---|---|---|
start_cmd | BOOL | Local |
auto_start | BOOL | Local |
fault | BOOL | Local |
enable | BOOL | Local |
IL Code
codeLD start_cmd (* Load manual start *) OR auto_start (* OR with auto start *) ANDN fault (* AND NOT fault. Block if fault active *) ST enable (* Store result *)
Equivalent ST
codeenable := (start_cmd OR auto_start) AND NOT fault;
Explanation
- Load
start_cmd. - OR with
auto_start. Accumulator is TRUE if either is TRUE. ANDN fault. AND with NOTfault. This blocks the result iffaultis TRUE.- Store the final result in
enable.
Latch/Unlatch (Set/Reset)
Implement a latching motor control using Set and Reset instructions.
Variables
| Name | Type | Class |
|---|---|---|
start_button | BOOL | Local |
stop_button | BOOL | Local |
motor | BOOL | Local |
IL Code
codeLD start_button (* Check start condition *) S motor (* Set (latch) motor if TRUE *) LD stop_button (* Check stop condition *) R motor (* Reset (unlatch) motor if TRUE *)
Equivalent ST
codeIF start_button THEN motor := TRUE; END_IF; IF stop_button THEN motor := FALSE; END_IF;
Explanation
The S instruction sets motor to TRUE only if the accumulator is TRUE. It does nothing if the accumulator is FALSE. Similarly, R resets motor to FALSE only if the accumulator is TRUE. Since the stop logic comes after the start logic, stop has priority if both buttons are pressed simultaneously.
Arithmetic: Temperature Scaling
Scale a raw sensor reading to engineering units.
Variables
| Name | Type | Class |
|---|---|---|
raw_value | INT | Local |
scaled | REAL | Local |
offset | REAL | Local |
gain | REAL | Local |
temp_real | REAL | Local |
IL Code
codeLD raw_value (* Load raw integer value *) INT_TO_REAL (* Convert to REAL *) ST temp_real (* Store intermediate *) LD temp_real (* Reload for calculation *) MUL gain (* Multiply by gain factor *) ADD offset (* Add offset *) ST scaled (* Store final scaled value *)
Equivalent ST
codetemp_real := INT_TO_REAL(raw_value); scaled := (temp_real * gain) + offset;
Explanation
IL doesn't support nested expressions like (raw * gain) + offset in a single line. You must break the calculation into sequential steps: load, operate, store or chain.
Comparison and Conditional Jump
Implement a bounded counter using comparison and conditional jumps.
Variables
| Name | Type | Class |
|---|---|---|
count_pulse | BOOL | Local |
reset | BOOL | Local |
counter | INT | Local |
max_count | INT | Local |
at_max | BOOL | Local |
IL Code
codeLD reset (* Check for reset *) JMPC do_reset (* Jump to reset if TRUE *) LD count_pulse (* Check for count pulse *) NOT (* Negate: TRUE if no pulse *) JMPC done (* Skip if no pulse *) LD counter (* Load current count *) GE max_count (* Compare: counter >= max_count? *) JMPC done (* Skip increment if at max *) LD counter (* Load current count *) ADD 1 (* Increment *) ST counter (* Store back *) JMP check_max (* Jump to max check *) do_reset: LD 0 (* Load zero *) ST counter (* Reset counter *) check_max: LD counter (* Load count *) GE max_count (* Check if at max *) ST at_max (* Store comparison result *) JMP end_prog done: LD counter (* Load count *) GE max_count (* Check if at max *) ST at_max (* Update at_max flag *) end_prog:
Equivalent ST
codeIF reset THEN counter := 0; ELSIF count_pulse AND (counter < max_count) THEN counter := counter + 1; END_IF; at_max := counter >= max_count;
Explanation
This example shows why IL is verbose compared to ST. The same logic that takes 4 lines in ST requires labels, jumps, and repeated loads in IL. The JMP/JMPC instructions serve as IL's version of IF/ELSE logic. Note that JMPN (jump if FALSE) is not supported. Use NOT followed by JMPC instead.
Parenthesized Expressions
Use parentheses to implement complex Boolean logic without intermediate variables.
Variables
| Name | Type | Class |
|---|---|---|
a | BOOL | Local |
b | BOOL | Local |
c | BOOL | Local |
d | BOOL | Local |
result | BOOL | Local |
IL Code
codeLD a AND( b (* Begin parenthesized expression *) OR c (* b OR c *) ) (* Close parenthesis: a AND (b OR c) *) OR d (* OR d *) ST result (* result = (a AND (b OR c)) OR d *)
Equivalent ST
coderesult := (a AND (b OR c)) OR d;
Explanation
Without parentheses, LD a / AND b / OR c / OR d would evaluate as ((a AND b) OR c) OR d. Parentheses change the evaluation order so that b OR c is computed first, then ANDed with a.
Function Block Call
Call a TON timer function block.
Variables
| Name | Type | Class |
|---|---|---|
enable | BOOL | Local |
timer_out | BOOL | Local |
my_timer | TON | Local |
IL Code
codeLD enable (* Load enable signal *) ST my_timer.IN (* Set timer input *) LD T#5s (* Load preset time *) ST my_timer.PT (* Set timer preset *) CAL my_timer (* Call the timer *) LD my_timer.Q (* Load timer output *) ST timer_out (* Store to output variable *)
Equivalent ST
codemy_timer(IN := enable, PT := T#5s); timer_out := my_timer.Q;
Explanation
In IL, calling a function block requires:
- Setting each input parameter individually using LD/ST.
- Calling the block with
CAL. - Reading outputs with LD.
This is considerably more verbose than ST's single-line call syntax. Another reason ST is preferred for modern projects.
When to Use IL
IL makes sense in a few specific situations:
- Legacy migration: Converting old PLC programs from manufacturers that used IL-like instruction sets.
- Tiny programs: Very short, simple Boolean logic where the overhead of understanding IL is minimal.
- Learning: Understanding IL helps you grasp the fundamentals of how PLC logic is evaluated at the lowest level.
For everything else, use Structured Text. It provides the same capabilities with dramatically better readability.
What's Next?
Explore other programming languages: Structured Text | Ladder Diagram | Function Block Diagram.
On This Page