Learning Objectives
- 說出 IEC 61131-3 的語言,以及各自適合的情境
- 讀懂結構化文字(ST)的指派、IF 與功能區塊呼叫
- 說明函數與功能區塊的差別:功能區塊的實例有自己的記憶
- 把一段 ST 翻成階梯圖
一個標準,好幾種語言
PLC 剛出現時,每家廠牌都有自己的程式語言與寫法,換一家 PLC 就要重學一次。國際電工委員會(IEC)在 1993 年 12 月發布 IEC 61131-3,統一 PLC 程式語言的語法與語意,之後改版過幾次,目前是 2025 年 5 月發布的第 4 版。
現在的版本定義了這些語言:
| 語言 | 樣子 | 適合 |
|---|---|---|
| LD 階梯圖(Ladder Diagram) | 圖形,像繼電器電路 | 開關邏輯、聯鎖;電機背景的人最熟悉,現場維修看得懂 |
| FBD 功能區塊圖(Function Block Diagram) | 圖形,方塊用線連起來 | 訊號處理、類比量、程序控制,像畫訊號流程圖 |
| ST 結構化文字(Structured Text) | 文字,像 Pascal | 計算、迴圈、資料處理、複雜判斷 |
| SFC 順序功能圖(Sequential Function Chart) | 圖形,步驟與轉移 | 有先後順序的流程(第 06 課) |
| IL 指令表(Instruction List) | 文字,像組合語言 | 早期的 PLC;2013 年第 3 版列為不建議使用,2025 年第 4 版已移除 |
同一個專案可以混用:順序用 SFC 排、每一步的動作用 LD 或 ST 寫、計算放在 ST 函數裡。 各廠牌的開發軟體支援的語言與細節不完全相同,以手冊為準;本課程只用標準裡共通的部分。
下面的小工具把上一課的自保持電路用五種寫法並排。切換分頁、按住啟動、按下停止,看五種寫法怎麼對應到同一個結果; ST 分頁可以一行一行執行。
結構化文字(ST)入門
ST 的寫法很像 Python、C 這類程式語言,但有幾個 PLC 特有的習慣:
VAR
Start, StopOK : BOOL; (* 布林:TRUE/FALSE *)
Motor : BOOL;
Count : INT := 0; (* 整數,起始值 0 *)
Temp : REAL; (* 實數 *)
Delay : TON; (* 計時器功能區塊的一個實例 *)
END_VAR
Motor := (Start OR Motor) AND StopOK; (* 指派用 :=,每句以分號結束 *)
IF Temp > 80.0 THEN
Alarm := TRUE;
ELSIF Temp > 70.0 THEN
Warning := TRUE;
ELSE
Alarm := FALSE;
Warning := FALSE;
END_IF;
Delay(IN := Motor, PT := T#2S); (* 呼叫計時器實例,PT=2 秒 *)
Ready := Delay.Q; (* 讀它的輸出 Q *)
| ST | Python 的對照 |
|---|---|
:= 指派、= 比較 |
= 指派、== 比較 |
AND、OR、NOT、XOR |
and、or、not、^ |
IF … THEN … ELSIF … ELSE … END_IF; |
if … elif … else |
CASE Step OF 1: … 2: … END_CASE; |
match/一串 if |
FOR i := 1 TO 10 DO … END_FOR; |
for i in range(1, 11) |
(* 註解 *) |
# 註解 |
T#2S、T#500MS |
時間常數,沒有直接對應 |
最大的不同是整個程式每輪掃描從頭跑一次:不會停在某一行等待。所以 ST 裡不要寫等待的迴圈
(例如 WHILE NOT Sensor DO END_WHILE;),那會讓這一輪掃描永遠結束不了,看門狗會讓 PLC 停機。
要等待,就用計時器或步驟變數,下一輪掃描再檢查一次。
逐步看:ST 的自保持用 Python 寫
把 ST 的那一行翻成 Python,外面包一個迴圈代表一輪一輪的掃描。注意 Motor 不在迴圈裡重新設成 False,所以上一輪的值會留下來,這就是自保持。
函數與功能區塊
IEC 61131-3 把程式切成程式組織單元(POU),有三種:
| POU | 有沒有記憶 | 例子 |
|---|---|---|
| 函數(function) | 沒有:同樣的輸入永遠得到同樣的輸出 | ADD、SQRT、比較大小 |
| 功能區塊(function block) | 有:每個實例各自記得自己的內部狀態 | 計時器 TON、計數器 CTU、PID |
| 程式(program) | 有 | 最上層,由 PLC 依工作排程呼叫 |
計時器一定要記得「已經累加了多久」,所以它是功能區塊。宣告兩個實例 FanDelay : TON;、PumpDelay : TON;,
它們各自計時,互不干擾。這和 Python 的類別與物件很像:類別是設計圖,每個物件有自己的屬性。
逐步看:兩個 TON 實例
用 Python 類別模擬 TON 功能區塊:fan 與 pump 是兩個實例,設定時間不同。看右側兩個物件的 et 怎麼各自累加。
小測驗:語言與 POU
要寫一段「把 10 筆量測值平均、再和上下限比較」的計算,哪一種語言最順手?
關於指令表(IL),下面哪一個敘述正確?
為什麼計時器 TON 是「功能區塊」而不是「函數」?
小測驗:讀 ST
下面這段 ST 想等感測器變成 TRUE 才往下做,問題在哪裡?
WHILE NOT Sensor DO
END_WHILE;
Motor := TRUE;
用 Python 模擬這段 ST 跑 4 輪:Motor := (Start OR Motor) AND StopOK;,會印出什麼?
Motor = False
for Start, StopOK in [(1, 1), (0, 1), (0, 0), (1, 0)]:
Motor = bool((Start or Motor) and StopOK)
print(int(Motor), end=" ")
重點整理
- IEC 61131-3 統一 PLC 的程式語言:LD、FBD、ST、SFC;IL 在 2013 年列為不建議使用、2025 年第 4 版移除。
- 選語言看工作:開關邏輯用 LD、訊號流程用 FBD、計算與資料處理用 ST、先後順序用 SFC,可以混用。
- ST:
:=指派、分號結束、IF … END_IF、CASE、FOR、(* 註解 *)、T#2S時間常數。 - 整個程式每輪掃描從頭跑一次,不要寫等待的迴圈;要等就用計時器或步驟變數。
- POU:函數沒有記憶,功能區塊(TON、CTU)的每個實例有自己的狀態,程式是最上層。
- 同一個邏輯可以在語言之間互相翻譯:AND=串聯、OR=並聯、NOT=常閉接點、IF 加 ELSE=普通線圈。
下一課寫有先後順序的控制:紅綠燈與輸送帶加工站,認識步驟與轉移(SFC 的觀念)。