先抓住核心 邊緣是事件 不是狀態
按鈕維持 ON 代表『現在仍被按住』;上升緣代表『剛從 OFF 變成 ON』,下降緣代表『剛從 ON 變成 OFF』。如果你的動作是加一筆、送出一次命令、清除一次警報,就應該使用邊緣事件,而不是把按鈕接點直接串到動作。這樣長按十個掃描,事件只出現一個掃描;放開後再按一次,才產生下一個事件。
邊緣判斷至少需要目前值與前次值。上升緣條件是目前值=1 且前次值=0;下降緣條件是目前值=0 且前次值=1。判斷完成後,前次值必須更新,否則程式會一直把同一個 ON 當成新的按下。這個前次值就是邊緣記憶狀態,不能只當成普通中間位元隨意重設。
| 名稱 | 判斷 | 輸出意義 | 適合用在哪裡 |
|---|---|---|---|
| 上升緣 | 目前=1、前次=0 | 只在剛按下時為 1 | 計數、啟動一次流程、送出一次請求 |
| 下降緣 | 目前=0、前次=1 | 只在剛放開時為 1 | 記錄放開、結束點動、確認一段輸入已結束 |
| 電平狀態 | 目前=1 或目前=0 | 只反映目前狀態 | 按住才動、持續允許、互鎖條件 |
以下內容是通用控制概念。R_TRIG、F_TRIG、P_TRIG 或一次脈衝接點的名稱和呼叫方式,必須以目標 PLC 手冊為準。偽碼須依目標 PLC 語法調整。
先把邊緣記憶放在一定會執行的位置
邊緣功能塊不是只看輸入,它還要保存前次輸入。最穩妥的安排是:每次主循環都呼叫一次邊緣判斷;其他條件只使用它產生的單掃描事件。不要把邊緣功能塊藏在『設備允許』或『某一步驟』的分支裡,卻沒有定義分支未執行時記憶如何更新。否則輸入在分支外已經由 OFF 變 ON,等分支重新開放時,可能把舊變化誤認成新按壓,或完全漏掉事件。
先定義輸入的來源和有效電平:實體按鈕、HMI 位元或通訊資料都要先確認 ON 的意義。
每次主循環呼叫一次上升緣與下降緣判斷,使用獨立的記憶狀態;同一實例不要在不同程式段重複呼叫。
把上升事件接到一次性命令,例如 Cmd_StartPulse;把目前電平留給需要持續允許的邏輯。
把下降事件接到放開或結束處理;若不需要下降事件,不要用它取代安全或停止條件。
在監看畫面同時觀察輸入、前次值、上升事件、下降事件與動作計數,逐掃描核對。
通用偽碼(需依目標 PLC 語法調整):
Rise := Button AND NOT Prev;
Fall := NOT Button AND Prev;
Prev := Button;
IF Rise THEN Count := Count + 1; END_IF;
兩個事件都用更新前的 Prev 計算,最後才更新 Prev。使用內建 R_TRIG/F_TRIG 時,改依原廠介面配置各自的實例,不要再從外部改寫其內部記憶。
十二掃描觀察連續十掃描長按
先用合成按鈕做離線逐掃描推算,不接真實輸出。初始 Prev=0、Count=0。第 1 掃描為 OFF,第 2~11 掃描連續 ON 十個掃描,第 12 掃描放開。上升事件應只在第 2 掃描出現,下降事件應只在第 12 掃描出現,Count 最後為 1。表中的前次值取自本次計算前;本表是依公式推算的合成案例。
| 掃描 | 目前值 | 前次值 | 上升緣 | 下降緣 | 事件計數 | 解讀 |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 0 | 0 | 待機 |
| 2 | 1 | 0 | 1 | 0 | 1 | 剛按下 |
| 3 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 4 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 5 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 6 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 7 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 8 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 9 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 10 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 11 | 1 | 1 | 0 | 0 | 1 | 長按不重複 |
| 12 | 0 | 1 | 0 | 1 | 1 | 剛放開 |
核對時先找事件出現在哪一列,再看計數。第 3~11 掃描,Button 與 Prev 均為 1,因此 Rise 為 0。若每列都加一,先查是否把 Button 直接用作計數條件,或是否在每次判斷前把 Prev 清成 0。一般監看畫面更新可能慢於掃描,短暫 Rise 不一定肉眼可見;可用事件計數和可用的追蹤功能交叉確認。
六種最容易漏判的輸入情境
| 情境 | 輸入序列 | 合理預期 | 先查的設計點 |
|---|---|---|---|
| 長按 | 0→1→1→1 | 一個上升事件 | 前次值是否每掃描更新 |
| 短脈衝 | 0→1→0 | 一個上升、一個下降;若短於取樣可能兩者都漏 | 輸入濾波、任務週期與脈衝寬度 |
| 連按 | 0→1→0→1 | 兩個上升、一個下降 | 放開是否真的被 PLC 取樣 |
| 開機已 ON | 啟動時已是 1 | 依需求決定:視為新事件或忽略 | 初始化前次值與開機策略 |
| 分支未執行 | 輸入先變 1,分支後開 | 可能延遲或漏判,不可猜測 | 邊緣實例是否在固定週期呼叫 |
| 重複呼叫 | 同一掃描呼叫兩次 | 第二次可能看見不同記憶狀態 | 每一輸入只使用一個邊緣實例 |
開機已 ON 特別需要先定義需求。若按鈕在 PLC 啟動前就已經是 ON,『目前值=1』本身不代表操作員剛按下。常見策略有兩種:第一掃描把前次值初始化為目前值,讓開機既有 ON 不產生事件;或明確把開機狀態視為一次請求,但要在規格中寫出來。不能只因使用了 R_TRIG 就宣稱所有平台都會採同一個初始行為。
短脈衝也不能只靠邏輯補救。如果輸入在兩次 PLC 取樣之間完成 ON→OFF,週期程式可能完全看不到它。需要查輸入模組濾波、快速輸入、事件鎖存或外部保持電路;採用哪一種要依目標硬體手冊和脈衝最短時間決定。邊緣偵測只能處理『已被程式取樣到的變化』。
重新按壓與失敗案例 不要讓事件卡住
重新按壓要完整經過 ON→OFF→ON,而且 OFF 必須被程式取樣。第一次按下 Count 加一;放開不增加 Count;第二次按下再加一。若第二次無效,查看程式採樣的 Button 和 Prev 是否曾回到 0。關鍵是記憶是否更新到 OFF;Fall 訊號本身不是產生下一次 Rise 的必要條件。
| 失敗現象 | 可能證據 | 先處理哪裡 |
|---|---|---|
| 長按每掃描重複動作 | Rise 長時間為 1 或程式直接使用 Button | 把動作條件改接邊緣事件,確認記憶更新 |
| 按一下完全沒動 | 輸入監看未變或 Rise 未變 | 先查輸入位址、有效電平與取樣週期 |
| 第二次按壓無效 | 第一次後沒有看到下降事件 | 查放開訊號、濾波與前次值 |
| 開機自動執行一次 | 啟動時輸入已是 ON | 確認規格,設定開機初始化策略 |
| 偶爾少算短按 | 脈衝落在掃描間隔內 | 查輸入模組與脈衝保持方案 |
| 同一按鈕不同段結果不同 | 邊緣實例被多次呼叫或放在條件分支 | 集中在固定週期呼叫並只輸出一個事件 |
『未每掃描呼叫』是一個常被忽略的失敗案例。假設邊緣功能塊只在 Step=RUN 時呼叫,而按鈕在 Step=WAIT 時被按下;若輸入在進入 RUN 前又放開,事件可能永遠漏掉。若需求是『任何時候按下都要記錄』,就把邊緣判斷放在固定週期,讓事件先鎖存,再由狀態機消費;若需求是『只在 RUN 接受』,則要明確記錄 WAIT 期間的輸入應被忽略。
完成判定 適用範圍與限制
按住按鈕至少十個掃描:事件計數只能增加一次,Rise 只在第一次 OFF→ON 出現。
放開按鈕:下降事件只出現一次;輸入和記憶值最後都回到 0。
完整放開後再按一次:事件計數再增加一次,代表重新按壓被辨識。
開機時保持 ON:依事先選定的初始化策略,確認是忽略或產生一次事件;監看畫面應能看出採用哪一種。
若做短脈衝測試:先記錄 PLC 掃描時間與輸入模組規格;未確認取樣能力前,不把漏判當成邊緣邏輯錯誤。
適用型號與限制:本文適用於具週期掃描、布林輸入和邊緣偵測能力的 PLC 控制概念,包括 Q 系列、FX 系列、S7、Schneider 等,但沒有為任何特定型號指定指令名稱、實例記憶區、初始值或編譯結果。實際套用 Q06UDVCPU、QJ71C24N 或其他模組時,必須另查該 CPU 的程式語言、掃描模型、輸入更新與邊緣指令手冊;QJ71C24N 是通訊模組,本文不把它當作按鈕輸入模組。本文也不取代安全回路、急停、硬體互鎖或機械風險評估。
若完成後仍不符合預期,先查三件事:第一,輸入位址和有效電平是否正確;第二,邊緣功能塊是否在每個需要的掃描都被呼叫且只有一個實例;第三,前次值、初始化和輸入取樣時間是否符合目標平台。把這三項證據記下來,再處理計數或流程本身,通常比先改一堆接點更快找到原因。
| 常見問題 | 回答 |
|---|---|
| 長按一定要用上升緣嗎? | 若動作是一次事件,通常需要;若是按住才允許或點動,應使用電平狀態,並另設停止條件。 |
| 用一個 M 位元記憶就能套所有程式嗎? | 不能。不同輸入、不同邊緣實例應有獨立記憶;功能塊若已內含記憶,不要重複改寫。 |
| 短脈衝漏掉是不是 R_TRIG 壞了? | 不一定。先確認脈衝是否被 PLC 取樣到,再查輸入濾波、快速輸入或鎖存機制。 |
| 開機已 ON 為什麼有的平台會觸發? | 初始記憶狀態可能不同,且功能塊實作不同;請依目標手冊與需求明確初始化。 |
| 可以把邊緣事件當安全停止嗎? | 不可以。安全功能需要符合設備風險、硬體安全鏈與適用標準的設計和驗證。 |