系列: PLC
latex
1135 行
· 更新于 2026-07-06
PLC_Ladder_Diagrams.tex
PLC/PLC_Ladder_Diagrams.tex
% !TEX program = xelatex
\documentclass[11pt,a4paper]{article}
% ---------- 版面與字型 ----------
\usepackage[top=2.4cm,bottom=2.6cm,left=2.4cm,right=2.4cm]{geometry}
\usepackage{fontspec}
\usepackage{xeCJK}
\setCJKmainfont{PingFang TC}
\setCJKsansfont{PingFang TC}
\setCJKmonofont{PingFang TC}
\setmainfont{Helvetica Neue}
\setmonofont{Menlo}[Scale=0.85]
\usepackage{setspace}
\setstretch{1.15}
% ---------- 套件 ----------
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{enumitem}
\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,calc}
\usepackage{caption}
\usepackage{fancyhdr}
\usepackage{titlesec}
\usepackage[hidelinks]{hyperref}
% ---------- 色彩 ----------
\definecolor{critical}{HTML}{C0392B}
\definecolor{major}{HTML}{D68910}
\definecolor{minor}{HTML}{2471A3}
\definecolor{good}{HTML}{1E8449}
\definecolor{headgray}{HTML}{34495E}
\definecolor{railgray}{HTML}{2C3E50}
% ---------- 標題樣式 ----------
\titleformat{\section}
{\Large\bfseries\color{headgray}}{\thesection}{0.8em}{}
\titleformat{\subsection}
{\large\bfseries\color{headgray}}{\thesubsection}{0.8em}{}
% ---------- 頁首頁尾 ----------
\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{\small PLC 審查問題對應階梯圖}
\fancyhead[R]{\small 2026-07-06}
\fancyfoot[C]{\small \thepage}
\renewcommand{\headrulewidth}{0.4pt}
% ==================================================================
% 梯形圖元件
% ==================================================================
\tikzset{
lad/.style={line width=0.75pt, color=railgray},
% ---- 常開接點 ----
pics/cno/.style={code={
\draw (-0.38,0) -- (-0.1,0) (0.1,0) -- (0.38,0);
\draw (-0.1,-0.18) -- (-0.1,0.18) (0.1,-0.18) -- (0.1,0.18);
\node[above, font=\tiny\ttfamily, text=black] at (0,0.2) {#1};
}},
% ---- 常閉接點 ----
pics/cnc/.style={code={
\draw (-0.38,0) -- (-0.1,0) (0.1,0) -- (0.38,0);
\draw (-0.1,-0.18) -- (-0.1,0.18) (0.1,-0.18) -- (0.1,0.18);
\draw (-0.17,-0.21) -- (0.17,0.21);
\node[above, font=\tiny\ttfamily, text=black] at (0,0.24) {#1};
}},
% ---- 上升緣接點 ----
pics/cpe/.style={code={
\draw (-0.38,0) -- (-0.1,0) (0.1,0) -- (0.38,0);
\draw (-0.1,-0.18) -- (-0.1,0.18) (0.1,-0.18) -- (0.1,0.18);
\node[font=\tiny\bfseries, text=black] at (0,0) {P};
\node[above, font=\tiny\ttfamily, text=black] at (0,0.2) {#1};
}},
% ---- 輸出線圈 ----
pics/coil/.style={code={
\draw (-0.38,0) -- (-0.16,0) (0.16,0) -- (0.38,0);
\draw (-0.08,0.17) .. controls (-0.24,0.06) and (-0.24,-0.06) .. (-0.08,-0.17);
\draw (0.08,0.17) .. controls (0.24,0.06) and (0.24,-0.06) .. (0.08,-0.17);
\node[above, font=\tiny\ttfamily, text=black] at (0,0.2) {#1};
}},
% ---- 設定(閂鎖)線圈 ----
pics/scoil/.style={code={
\draw (-0.38,0) -- (-0.16,0) (0.16,0) -- (0.38,0);
\draw (-0.08,0.17) .. controls (-0.24,0.06) and (-0.24,-0.06) .. (-0.08,-0.17);
\draw (0.08,0.17) .. controls (0.24,0.06) and (0.24,-0.06) .. (0.08,-0.17);
\node[font=\tiny\bfseries, text=black] at (0,0) {S};
\node[above, font=\tiny\ttfamily, text=black] at (0,0.2) {#1};
}},
% ---- 復歸(解閂)線圈 ----
pics/ucoil/.style={code={
\draw (-0.38,0) -- (-0.16,0) (0.16,0) -- (0.38,0);
\draw (-0.08,0.17) .. controls (-0.24,0.06) and (-0.24,-0.06) .. (-0.08,-0.17);
\draw (0.08,0.17) .. controls (0.24,0.06) and (0.24,-0.06) .. (0.08,-0.17);
\node[font=\tiny\bfseries, text=black] at (0,0) {U};
\node[above, font=\tiny\ttfamily, text=black] at (0,0.2) {#1};
}},
}
% ---- 比較方塊(EQU):\cmp{x}{y}{內容} ----
\newcommand{\cmp}[3]{%
\draw (#1-1.05,#2-0.4) rectangle (#1+1.05,#2+0.4);
\node[font=\tiny\bfseries, text=headgray] at (#1,#2+0.21) {EQU};
\node[font=\tiny\ttfamily, text=black] at (#1,#2-0.15) {#3};
\draw (#1-1.23,#2) -- (#1-1.05,#2);
\draw (#1+1.05,#2) -- (#1+1.23,#2);
}
% ---- 運算/傳送方塊:\opb{x}{y}{標題}{內容} ----
\newcommand{\opb}[4]{%
\draw (#1-1.15,#2-0.45) rectangle (#1+1.15,#2+0.45);
\node[font=\tiny\bfseries, text=headgray] at (#1,#2+0.24) {#3};
\node[font=\tiny\ttfamily, text=black] at (#1,#2-0.15) {#4};
\draw (#1-1.33,#2) -- (#1-1.15,#2);
\draw (#1+1.15,#2) -- (#1+1.33,#2);
}
\newcommand{\mov}[4]{\opb{#1}{#2}{MOV}{#3 $\to$ #4}}
% ---- 計時器方塊:\tonb{x}{y}{名稱}{PT} ----
\newcommand{\tonb}[4]{%
\draw (#1-1.05,#2-0.62) rectangle (#1+1.05,#2+0.62);
\node[font=\tiny\bfseries, text=headgray] at (#1,#2+0.4) {#3};
\node[font=\tiny, text=black] at (#1-0.82,#2+0.16) {IN};
\node[font=\tiny, text=black] at (#1+0.84,#2+0.16) {Q};
\node[font=\tiny\ttfamily, text=black] at (#1,#2-0.36) {PT: #4};
\draw (#1-1.23,#2) -- (#1-1.05,#2);
\draw (#1+1.05,#2) -- (#1+1.23,#2);
}
% ---- rung 說明列 ----
\newcommand{\rcapbad}[1]{\par\medskip\noindent\colorbox{critical}{\textcolor{white}{\scriptsize\bfseries\,現況\,}}\ {\small #1}\par\nopagebreak}
\newcommand{\rcapfix}[1]{\par\medskip\noindent\colorbox{good}{\textcolor{white}{\scriptsize\bfseries\,修正\,}}\ {\small #1}\par\nopagebreak}
\newcommand{\rcap}[2]{\par\medskip\noindent\colorbox{headgray}{\textcolor{white}{\scriptsize\bfseries\,#1\,}}\ {\small #2}\par\nopagebreak}
\newenvironment{ladder}
{\begin{center}\begin{tikzpicture}[lad]}
{\end{tikzpicture}\end{center}\vspace{-6pt}}
\begin{document}
% ================= 封面 =================
\begin{titlepage}
\centering
\vspace*{3cm}
{\color{headgray}\rule{\textwidth}{1.5pt}}\\[1.2cm]
{\Huge\bfseries PLC 審查問題對應階梯圖}\\[0.8cm]
{\Large 單車道雙向通行控制 —— 15 項問題的修正梯形圖與完整重構程式}\\[1.2cm]
{\color{headgray}\rule{\textwidth}{1.5pt}}\\[2cm]
{\large
\begin{tabular}{rl}
\textbf{對應文件:} & 《PLC 梯形圖程式設計審查報告》(2026-07-05)\\[4pt]
\textbf{內容範圍:} & 問題 1--11 與建議 12--15 之修正階梯圖\\[4pt]
\textbf{附錄:} & 修正後完整程式 Rung 1--23\\[4pt]
\textbf{文件日期:} & 2026 年 7 月 6 日\\
\end{tabular}
}
\vfill
{\small 圖中符號採 IEC 慣用之 NO/NC 接點、線圈與功能方塊表示法;\\
變數名稱沿用原程式,狀態常數與 I/O 對照見第 1 節。}
\end{titlepage}
\tableofcontents
\newpage
% ================= 1. 圖例 =================
\section{變數對照與圖例}
\subsection{狀態常數與變數}
\begin{center}
\small
\begin{tabular}{cl@{\qquad}ll}
\toprule
\textbf{值} & \textbf{狀態常數} & \textbf{變數} & \textbf{意義}\\
\midrule
0 & \texttt{INIT} & \texttt{INPUT1} / \texttt{INPUT2} & A 端/B 端光電感測器\\
1 & \texttt{IDLE} & \texttt{PB\_RESET} & 故障復歸按鈕\\
2 & \texttt{FWD} & \texttt{OUTPUT\_1} / \texttt{OUTPUT\_2} & 車道占用燈/故障燈\\
3 & \texttt{HOLD} & \texttt{STATE} & 狀態暫存器(INT)\\
4 & \texttt{REV} & \texttt{M\_INPUT1\_Rise} 等 & 邊緣旗標(單一掃描週期)\\
5 & \texttt{FAULT} & \texttt{FaultLatch} / \texttt{SensorStuck} & 故障閂鎖/感測器卡住\\
6 & \texttt{REV\_HOLD}(新增) & \texttt{TON\_1/2A/2B/3} & 10 s 駐留/5 min 卡住/60 s 逾時\\
\bottomrule
\end{tabular}
\end{center}
\subsection{梯形圖符號圖例}
\begin{ladder}
\pic at (0.9,0) {cno=VAR};
\node[right, font=\small, text=black] at (2.4,0) {NO 常開接點:變數為 1 時導通};
\pic at (0.9,-1.0) {cnc=VAR};
\node[right, font=\small, text=black] at (2.4,-1.0) {NC 常閉接點:變數為 0 時導通};
\pic at (0.9,-2.0) {cpe=VAR};
\node[right, font=\small, text=black] at (2.4,-2.0) {上升緣接點(OSR/R\_TRIG):0$\to$1 的那個掃描週期導通一次};
\pic at (0.9,-3.0) {coil=VAR};
\node[right, font=\small, text=black] at (2.4,-3.0) {輸出線圈:rung 導通時 ON,斷開時 OFF};
\pic at (0.9,-4.0) {scoil=VAR};
\node[right, font=\small, text=black] at (2.4,-4.0) {設定線圈(Latch):導通後保持 ON,需 U 復歸};
\pic at (0.9,-5.0) {ucoil=VAR};
\node[right, font=\small, text=black] at (2.4,-5.0) {復歸線圈(Unlatch):導通時將閂鎖變數復歸為 OFF};
\cmp{0.9}{-6.3}{STATE=FWD}
\node[right, font=\small, text=black] at (2.4,-6.3) {比較方塊:條件成立(相等)時導通,作為接點使用};
\mov{0.9}{-7.7}{IDLE}{STATE}
\node[right, font=\small, text=black] at (2.4,-7.7) {傳送方塊:rung 導通時將來源值寫入目的暫存器};
\tonb{0.9}{-9.3}{TON\_3}{T\#60s}
\node[right, font=\small, text=black] at (2.4,-9.3) {通電延遲計時器:IN 持續導通達 PT 後 Q = 1;IN 斷開立即復歸};
\end{ladder}
\subsection{問題與 rung 對照}
\begin{center}
\small
\begin{tabular}{clc}
\toprule
\textbf{問題} & \textbf{摘要} & \textbf{完整程式對應 rung(第 5 節)}\\
\midrule
問題 1 & INIT 無出口(上電死鎖) & R3\\
問題 2 & Reset 無條件回 IDLE & R21\\
問題 3 & REV 過早結束 & R13、R16、R18\\
問題 4 & 計時器 Q 未限定狀態 & R17、R18\\
問題 5 & 邊緣偵測標籤不一致 & R1、R2(改用內建邊緣)\\
問題 6 & 逾時應進 FAULT & R14、R15\\
問題 7 & REV 不點占用燈 & R22\\
問題 8 & 兩端同時來車死鎖 & R9--R11\\
問題 9 & 卡住偵測共用計時器 & R4--R6\\
問題 10 & 故障優先權與復歸耦合 & R8、R21\\
問題 11 & 多車跟進(車輛計數) & 選配(見 3.6 節)\\
建議 12--15 & 內建邊緣、集中化、命名、按鈕取緣 & R1、R2、R21 及全篇\\
\bottomrule
\end{tabular}
\end{center}
\newpage
% ================= 2. 嚴重問題 =================
\section{嚴重問題修正階梯圖(問題 1--5)}
\subsection{問題 1:INIT 狀態沒有出口 —— 上電死鎖}
原程式沒有任何 rung 處理 \texttt{STATE = INIT}(上電預設值 0)。
修正:新增一條初始化 rung,等待兩支感測器皆淨空後才進入 \texttt{IDLE};
若上電時感測器被遮斷,系統會停留在 \texttt{INIT} 直到車道淨空,不會誤動作。
\rcapfix{新增 rung:\texttt{INIT} 且 A、B 皆淨空 $\to$ \texttt{IDLE}}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=INIT}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cnc=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
若平台提供首次掃描旗標(如 \texttt{\_SYSVA\_FIRST\_SCAN}),亦可改以首次掃描觸發並在
感測器遮斷時直接閂鎖故障;上圖的「等待淨空」寫法較簡單且不需額外旗標。
\subsection{問題 2:Rung 24 —— PB\_RESET 無條件強制回 IDLE}
\rcapbad{原 Rung 24:按鈕電平直接寫入,任何狀態都會被覆寫}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=PB\_RESET};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{加上三重限定:按鈕取上升緣、僅在 \texttt{FAULT} 狀態、且故障已成功解閂}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=PB\_RESET};
\draw (1.68,0) -- (1.97,0);
\cmp{3.2}{0}{STATE=FAULT}
\draw (4.43,0) -- (5.02,0);
\pic at (5.4,0) {cnc=FaultLatch};
\draw (5.78,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
如此車輛通行中誤按復歸不再影響狀態機;故障未排除(\texttt{FaultLatch} 仍為 1)時
按住按鈕也不會造成 \texttt{STATE} 每週期震盪。
\subsection{問題 3:Rung 16 —— REV 的離開條件錯誤}
\rcapbad{原 Rung 16:B 下降緣即回 \texttt{IDLE},此時車輛仍在車道中間}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT2\_Fall};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
修正:\texttt{REV} 應在車輛\textbf{抵達 A 感測器}時才結束,並比照 \texttt{FWD} 增加
10 秒駐留緩衝狀態 \texttt{REV\_HOLD}(新增常數,值 6)。
\rcapfix{\texttt{REV} 且 A 上升緣 $\to$ \texttt{REV\_HOLD}}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT1\_Rise};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{REV\_HOLD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{駐留計時:\texttt{HOLD} 與 \texttt{REV\_HOLD} 共用 10 秒計時器 \texttt{TON\_1}}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=HOLD}
\draw (3.13,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_1}{T\#10s}
\draw (13.13,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.1);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=REV\_HOLD}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (3.35,-1.1) -- (3.35,0);
\end{ladder}
\rcapfix{\texttt{REV\_HOLD} 計時到 $\to$ \texttt{IDLE}(狀態限定,見問題 4)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV\_HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=TON\_1.Q};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\subsection{問題 4:計時器 Done 位元未限定狀態}
\rcapbad{原 Rung 12/14:\texttt{TON.Q} 一成立就無條件寫 \texttt{IDLE},可能覆寫 \texttt{FAULT} 等狀態}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=TON\_1.Q};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{每一條寫入 \texttt{STATE} 的 rung,第一個條件一律是「目前狀態」}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=TON\_1.Q};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
原 Rung 12(\texttt{TON\_3.Q} 逾時)除了加狀態限定外,目的地也應由 \texttt{IDLE} 改為
\texttt{FAULT},見問題 6 的階梯圖。
\subsection{問題 5:邊緣偵測標籤不一致}
\rcapbad{原 Rung 1:接點讀 \texttt{INPUT1\_Last},但 Rung 3 線圈寫的是 \texttt{M\_INPUT1\_Last} —— 若為兩個變數,邊緣偵測全失效}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=INPUT1};
\draw (1.68,0) -- (2.92,0);
\pic at (3.3,0) {cnc=};
\node[above, font=\tiny\ttfamily, text=critical] at (3.3,0.24) {INPUT1\_Last};
\draw (3.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Rise};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
修正後三條 rung 全部使用\textbf{同一個}變數 \texttt{M\_INPUT1\_Last},
且 \texttt{\_Last} 的更新 rung 必須排在最後(\texttt{INPUT2} 比照辦理):
\rcapfix{上升緣:本週期為 1、上週期為 0}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=INPUT1};
\draw (1.68,0) -- (2.92,0);
\pic at (3.3,0) {cnc=M\_INPUT1\_Last};
\draw (3.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Rise};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\rcapfix{下降緣:本週期為 0、上週期為 1}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cnc=INPUT1};
\draw (1.68,0) -- (2.92,0);
\pic at (3.3,0) {cno=M\_INPUT1\_Last};
\draw (3.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Fall};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\rcapfix{上週期值更新 —— 必須放在所有使用 \texttt{\_Last} 的 rung 之後}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=INPUT1};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Last};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
更好的做法是直接改用平台內建的上升緣接點(見建議 12 與第 5 節 R1、R2),
六條 rung 縮為兩條,並徹底消除此類命名錯誤。
\newpage
% ================= 3. 重要問題 =================
\section{重要問題修正階梯圖(問題 6--11)}
\subsection{問題 6:60 秒逾時應轉入 FAULT,而非回 IDLE}
車輛拋錨卡在車道內超過 60 秒屬於\textbf{異常};回 \texttt{IDLE} 會放行對向車輛。
修正:\texttt{FWD} 與 \texttt{REV} 共用通行逾時計時器,逾時即閂鎖故障並轉入 \texttt{FAULT}
(占用燈由輸出 rung 在 \texttt{FAULT} 狀態下保持點亮,見問題 7)。
\rcapfix{通行逾時計時:\texttt{FWD} 或 \texttt{REV} 期間累計 60 秒}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=FWD}
\draw (3.13,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_3}{T\#60s}
\draw (13.13,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.1);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=REV}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (3.35,-1.1) -- (3.35,0);
\end{ladder}
\rcapfix{逾時 $\to$ 進入 \texttt{FAULT} 並閂鎖,需人員確認車道淨空後復歸}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=TON\_3.Q};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{FAULT}{STATE}
\draw (13.43,0) -- (13.6,0);
\draw (10.5,0) -- (10.5,-1.1);
\draw (10.5,-1.1) -- (12.52,-1.1);
\pic at (12.9,-1.1) {scoil=FaultLatch};
\draw (13.28,-1.1) -- (13.6,-1.1);
\end{ladder}
\subsection{問題 7:REV 狀態不驅動占用指示}
原 Rung 17 只有 \texttt{FWD}/\texttt{HOLD} 點亮 \texttt{OUTPUT\_1}。
修正:\texttt{REV}、\texttt{REV\_HOLD} 也並聯進來;\texttt{FAULT} 期間同樣保持點亮
(車道狀況未知,必須封鎖)。
\rcapfix{占用燈 = 狀態的純函數,五個狀態並聯}
\begin{ladder}
\draw (0,0.85) -- (0,-4.9);
\draw (13.6,0.85) -- (13.6,-4.9);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=FWD}
\draw (3.13,0) -- (12.52,0);
\pic at (12.9,0) {coil=OUTPUT\_1};
\draw (13.28,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-4.4);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=HOLD}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (0.45,-2.2) -- (0.67,-2.2);
\cmp{1.9}{-2.2}{STATE=REV}
\draw (3.13,-2.2) -- (3.35,-2.2);
\draw (0.45,-3.3) -- (0.67,-3.3);
\cmp{1.9}{-3.3}{STATE=REV\_HOLD}
\draw (3.13,-3.3) -- (3.35,-3.3);
\draw (0.45,-4.4) -- (0.67,-4.4);
\cmp{1.9}{-4.4}{STATE=FAULT}
\draw (3.13,-4.4) -- (3.35,-4.4);
\draw (3.35,-4.4) -- (3.35,0);
\end{ladder}
\subsection{問題 8:兩端同時來車 $\to$ 雙方永久等待}
原程式以「上升緣 + 對側淨空」觸發,兩端幾乎同時遮斷時兩條 rung 都不成立,
且邊緣旗標一個週期後消失,永遠卡死。修正:進入條件改用\textbf{電平}
(車輛持續遮斷感測器即成立),並新增「兩側同時佔用」的固定優先權裁決 rung。
\rcapfix{\texttt{IDLE} $\to$ \texttt{FWD}:A 遮斷(電平)且 B 淨空}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{FWD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{\texttt{IDLE} $\to$ \texttt{REV}:B 遮斷(電平)且 A 淨空}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT2};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT1};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{REV}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{同時佔用的仲裁:固定 A 側優先(依現場規則亦可改為進入 \texttt{FAULT} 或輪流優先)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cno=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{FWD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
注意 rung 排列順序:兩條單側 rung 在前、仲裁 rung 在後;三條的條件互斥,
同一週期至多一條成立。
\subsection{問題 9:兩支感測器共用一顆卡住偵測計時器}
\rcapbad{原 Rung 19:\texttt{INPUT1 OR INPUT2} 餵同一顆 TON,計時跨感測器連續累積而誤報}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=INPUT1};
\draw (1.68,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_2}{T\#5m}
\draw (13.13,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.0);
\draw (0.45,-1.0) -- (0.92,-1.0);
\pic at (1.3,-1.0) {cno=INPUT2};
\draw (1.68,-1.0) -- (2.15,-1.0);
\draw (2.15,-1.0) -- (2.15,0);
\end{ladder}
修正:每支感測器各用一顆計時器,且僅在\textbf{與狀態矛盾}時計時
(\texttt{IDLE} 卻長時間遮斷才可疑;通行中的合法遮斷不計)。
\rcapfix{A 端獨立卡住偵測}
\begin{ladder}
\draw (0,0.85) -- (0,-0.8);
\draw (13.6,0.85) -- (13.6,-0.8);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_2A}{T\#5m}
\draw (13.13,0) -- (13.6,0);
\end{ladder}
\rcapfix{B 端獨立卡住偵測}
\begin{ladder}
\draw (0,0.85) -- (0,-0.8);
\draw (13.6,0.85) -- (13.6,-0.8);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT2};
\draw (4.08,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_2B}{T\#5m}
\draw (13.13,0) -- (13.6,0);
\end{ladder}
\rcapfix{任一計時到即判定感測器卡住}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=TON\_2A.Q};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=SensorStuck};
\draw (13.28,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.0);
\draw (0.45,-1.0) -- (0.92,-1.0);
\pic at (1.3,-1.0) {cno=TON\_2B.Q};
\draw (1.68,-1.0) -- (2.15,-1.0);
\draw (2.15,-1.0) -- (2.15,0);
\end{ladder}
\subsection{問題 10:故障優先權與復歸順序耦合}
修正有兩點:(1) 「\texttt{FaultLatch} $\to$ \texttt{FAULT}」rung 移到\textbf{狀態機之前},
故障成立的同一週期即接管狀態;(2) 解閂與回 \texttt{IDLE} 合併為\textbf{單一 rung},
不再依賴三條 rung 的掃描順序。
\rcapfix{故障接管 —— 置於所有狀態轉移 rung 之前}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=FaultLatch};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{FAULT}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{復歸整合:解閂與回 \texttt{IDLE} 同一 rung 完成}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=PB\_RESET};
\draw (1.68,0) -- (1.97,0);
\cmp{3.2}{0}{STATE=FAULT}
\draw (4.43,0) -- (5.02,0);
\pic at (5.4,0) {cnc=SensorStuck};
\draw (5.78,0) -- (12.52,0);
\pic at (12.9,0) {ucoil=FaultLatch};
\draw (13.28,0) -- (13.6,0);
\draw (10.5,0) -- (10.5,-1.1);
\draw (10.5,-1.1) -- (10.77,-1.1);
\mov{12.1}{-1.1}{IDLE}{STATE}
\draw (13.43,-1.1) -- (13.6,-1.1);
\end{ladder}
\subsection{問題 11:多車跟進 —— 車輛計數(選配)}
若場域允許多車同時在車道內,以「車道內車輛數」取代純計時判斷,
以下以 \texttt{FWD} 方向為例(\texttt{REV} 鏡像對稱):
\rcapfix{A 端進入一台,計數 $+1$(邊緣觸發,避免每週期累加)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=FWD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT1\_Rise};
\draw (4.08,0) -- (10.77,0);
\opb{12.1}{0}{ADD}{VehCnt+1 $\to$ VehCnt}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{B 端離開一台,計數 $-1$}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=FWD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT2\_Rise};
\draw (4.08,0) -- (10.77,0);
\opb{12.1}{0}{SUB}{VehCnt-1 $\to$ VehCnt}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcapfix{回 \texttt{IDLE} 的條件加上「車道內車輛數 = 0」}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=TON\_1.Q};
\draw (4.08,0) -- (4.77,0);
\cmp{6.0}{0}{VehCnt=0}
\draw (7.23,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
車輛計數屬功能擴充,第 5 節的完整程式未納入;導入時另需處理
\texttt{VehCnt} 的下限保護與 \texttt{FWD} 期間後車跟進重啟逾時計時等細節。
\newpage
% ================= 4. 建議 =================
\section{可維護性建議階梯圖(建議 12--15)}
\subsection{建議 12:改用內建邊緣接點}
手寫三段式邊緣偵測(6 條 rung、2 個中間變數)以內建上升緣接點(OSR/\texttt{R\_TRIG})
取代,每支感測器一條 rung 即可,並徹底避免問題 5 的命名斷裂:
\rcapfix{一條 rung 取代原 Rung 1--3}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=INPUT1};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Rise};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\subsection{建議 13:狀態機集中化}
梯形圖版本的落地原則(完整落實見第 5 節):
\begin{itemize}[nosep, leftmargin=2em]
\item 每個 \texttt{MOV $\to$ STATE} 一律先串 \texttt{EQU(STATE, 現態)};
\item 相同現態的多個轉移條件彼此互斥;
\item 故障接管 rung 放在所有轉移之前、輸出 rung 放在最後。
\end{itemize}
若平台支援,狀態轉移改用 ST 的 \texttt{CASE} 集中管理更佳(見審查報告第 3.2 節)。
\subsection{建議 14:計時器與變數命名語義化}
\begin{center}
\small
\begin{tabular}{llll}
\toprule
\textbf{原名} & \textbf{建議名} & \textbf{原名} & \textbf{建議名}\\
\midrule
\texttt{TON\_1} & \texttt{tHoldDwell}(10 s) & \texttt{OUTPUT\_1} & \texttt{LaneOccupiedLamp}\\
\texttt{TON\_2A/2B} & \texttt{tStuckA}/\texttt{tStuckB}(5 min) & \texttt{OUTPUT\_2} & \texttt{FaultLamp}\\
\texttt{TON\_3} & \texttt{tTransitTimeout}(60 s) & \texttt{INPUT1/2} & \texttt{SensorA}/\texttt{SensorB}\\
\bottomrule
\end{tabular}
\end{center}
\rcapfix{命名語義化後的同一條 rung,用途一目瞭然}
\begin{ladder}
\draw (0,0.85) -- (0,-0.8);
\draw (13.6,0.85) -- (13.6,-0.8);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=FWD}
\draw (2.73,0) -- (10.67,0);
\tonb{11.9}{0}{tTransitTimeout}{T\#60s}
\draw (13.13,0) -- (13.6,0);
\end{ladder}
\subsection{建議 15:手動按鈕一律取上升緣}
已落實於問題 2/問題 10 的復歸 rung(\texttt{PB\_RESET} 使用 P 接點):
按住不放只觸發一次,不會每個掃描週期重複執行 \texttt{MOV}。
\newpage
% ================= 5. 完整程式 =================
\section{修正後完整程式(Rung 1--23)}
以下為整合所有修正後的完整梯形圖程式。結構依「輸入處理 $\to$ 故障偵測 $\to$
狀態轉移 $\to$ 計時 $\to$ 復歸 $\to$ 輸出」排列,\texttt{STATE} 的每個寫入點
都以現態為第一條件,輸出為狀態的純函數。
\subsection{輸入處理與初始化(R1--R3)}
\rcap{R1}{INPUT1 上升緣(內建邊緣接點,取代原 Rung 1--3)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=INPUT1};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT1\_Rise};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\rcap{R2}{INPUT2 上升緣(取代原 Rung 4--6)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=INPUT2};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=M\_INPUT2\_Rise};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\rcap{R3}{初始化:INIT 且車道淨空 $\to$ IDLE(修正問題 1)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=INIT}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cnc=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\subsection{故障偵測與接管(R4--R8)}
\rcap{R4}{A 端卡住偵測:IDLE 卻持續遮斷 5 分鐘(修正問題 9)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.8);
\draw (13.6,0.85) -- (13.6,-0.8);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_2A}{T\#5m}
\draw (13.13,0) -- (13.6,0);
\end{ladder}
\rcap{R5}{B 端卡住偵測}
\begin{ladder}
\draw (0,0.85) -- (0,-0.8);
\draw (13.6,0.85) -- (13.6,-0.8);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT2};
\draw (4.08,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_2B}{T\#5m}
\draw (13.13,0) -- (13.6,0);
\end{ladder}
\rcap{R6}{任一計時到 $\to$ SensorStuck}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=TON\_2A.Q};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=SensorStuck};
\draw (13.28,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.0);
\draw (0.45,-1.0) -- (0.92,-1.0);
\pic at (1.3,-1.0) {cno=TON\_2B.Q};
\draw (1.68,-1.0) -- (2.15,-1.0);
\draw (2.15,-1.0) -- (2.15,0);
\end{ladder}
\rcap{R7}{卡住即閂鎖故障}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=SensorStuck};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {scoil=FaultLatch};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\rcap{R8}{故障接管 —— 置於狀態機之前(修正問題 10)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=FaultLatch};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{FAULT}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\subsection{狀態轉移(R9--R13)}
\rcap{R9}{IDLE $\to$ FWD:A 遮斷(電平)且 B 淨空(修正問題 8)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{FWD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R10}{IDLE $\to$ REV:B 遮斷(電平)且 A 淨空}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT2};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cnc=INPUT1};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{REV}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R11}{同時佔用仲裁:A 側優先(修正問題 8)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=IDLE}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=INPUT1};
\draw (4.08,0) -- (5.22,0);
\pic at (5.6,0) {cno=INPUT2};
\draw (5.98,0) -- (10.77,0);
\mov{12.1}{0}{FWD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R12}{FWD $\to$ HOLD:車輛通過 B}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=FWD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT2\_Rise};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{HOLD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R13}{REV $\to$ REV\_HOLD:車輛抵達 A(修正問題 3)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT1\_Rise};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{REV\_HOLD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\subsection{計時與逾時(R14--R20)}
\rcap{R14}{通行逾時計時:FWD 或 REV 共用 60 秒(修正問題 6、7 之計時部分)}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=FWD}
\draw (3.13,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_3}{T\#60s}
\draw (13.13,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.1);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=REV}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (3.35,-1.1) -- (3.35,0);
\end{ladder}
\rcap{R15}{逾時 $\to$ FAULT 並閂鎖(修正問題 4、6)}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=TON\_3.Q};
\draw (1.68,0) -- (10.77,0);
\mov{12.1}{0}{FAULT}{STATE}
\draw (13.43,0) -- (13.6,0);
\draw (10.5,0) -- (10.5,-1.1);
\draw (10.5,-1.1) -- (12.52,-1.1);
\pic at (12.9,-1.1) {scoil=FaultLatch};
\draw (13.28,-1.1) -- (13.6,-1.1);
\end{ladder}
\rcap{R16}{駐留計時:HOLD 或 REV\_HOLD 共用 10 秒}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=HOLD}
\draw (3.13,0) -- (10.67,0);
\tonb{11.9}{0}{TON\_1}{T\#10s}
\draw (13.13,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-1.1);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=REV\_HOLD}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (3.35,-1.1) -- (3.35,0);
\end{ladder}
\rcap{R17}{HOLD 駐留期滿 $\to$ IDLE(狀態限定,修正問題 4)}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=TON\_1.Q};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R18}{REV\_HOLD 駐留期滿 $\to$ IDLE}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV\_HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=TON\_1.Q};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{IDLE}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R19}{HOLD 期間後車自 A 跟進 $\to$ 回 FWD}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT1\_Rise};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{FWD}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\rcap{R20}{REV\_HOLD 期間後車自 B 跟進 $\to$ 回 REV}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.27,0);
\cmp{1.5}{0}{STATE=REV\_HOLD}
\draw (2.73,0) -- (3.32,0);
\pic at (3.7,0) {cno=M\_INPUT2\_Rise};
\draw (4.08,0) -- (10.77,0);
\mov{12.1}{0}{REV}{STATE}
\draw (13.43,0) -- (13.6,0);
\end{ladder}
\subsection{故障復歸與輸出(R21--R23)}
\rcap{R21}{復歸:按鈕上升緣、限 FAULT 狀態、故障已排除;解閂與回 IDLE 一次完成(修正問題 2、10、建議 15)}
\begin{ladder}
\draw (0,0.85) -- (0,-1.7);
\draw (13.6,0.85) -- (13.6,-1.7);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cpe=PB\_RESET};
\draw (1.68,0) -- (1.97,0);
\cmp{3.2}{0}{STATE=FAULT}
\draw (4.43,0) -- (5.02,0);
\pic at (5.4,0) {cnc=SensorStuck};
\draw (5.78,0) -- (12.52,0);
\pic at (12.9,0) {ucoil=FaultLatch};
\draw (13.28,0) -- (13.6,0);
\draw (10.5,0) -- (10.5,-1.1);
\draw (10.5,-1.1) -- (10.77,-1.1);
\mov{12.1}{-1.1}{IDLE}{STATE}
\draw (13.43,-1.1) -- (13.6,-1.1);
\end{ladder}
\rcap{R22}{占用燈:通行、駐留與故障期間皆點亮(修正問題 7)}
\begin{ladder}
\draw (0,0.85) -- (0,-4.9);
\draw (13.6,0.85) -- (13.6,-4.9);
\draw (0,0) -- (0.67,0);
\cmp{1.9}{0}{STATE=FWD}
\draw (3.13,0) -- (12.52,0);
\pic at (12.9,0) {coil=OUTPUT\_1};
\draw (13.28,0) -- (13.6,0);
\draw (0.45,0) -- (0.45,-4.4);
\draw (0.45,-1.1) -- (0.67,-1.1);
\cmp{1.9}{-1.1}{STATE=HOLD}
\draw (3.13,-1.1) -- (3.35,-1.1);
\draw (0.45,-2.2) -- (0.67,-2.2);
\cmp{1.9}{-2.2}{STATE=REV}
\draw (3.13,-2.2) -- (3.35,-2.2);
\draw (0.45,-3.3) -- (0.67,-3.3);
\cmp{1.9}{-3.3}{STATE=REV\_HOLD}
\draw (3.13,-3.3) -- (3.35,-3.3);
\draw (0.45,-4.4) -- (0.67,-4.4);
\cmp{1.9}{-4.4}{STATE=FAULT}
\draw (3.13,-4.4) -- (3.35,-4.4);
\draw (3.35,-4.4) -- (3.35,0);
\end{ladder}
\rcap{R23}{故障燈}
\begin{ladder}
\draw (0,0.85) -- (0,-0.55);
\draw (13.6,0.85) -- (13.6,-0.55);
\draw (0,0) -- (0.92,0);
\pic at (1.3,0) {cno=FaultLatch};
\draw (1.68,0) -- (12.52,0);
\pic at (12.9,0) {coil=OUTPUT\_2};
\draw (13.28,0) -- (13.6,0);
\end{ladder}
\subsection{設計要點備忘}
\begin{itemize}[leftmargin=2em]
\item \textbf{寫入點限定}:\texttt{STATE} 的寫入 rung(R3、R8--R13、R15、R17--R21)
除故障接管(R8)與逾時(R15,由狀態驅動的計時器保證)外,
全部以 \texttt{EQU(STATE, 現態)} 為第一條件,同一現態的轉移條件互斥。
\item \textbf{掃描順序}:邊緣旗標(R1--R2)最先產生;故障接管(R8)在所有轉移之前;
輸出(R22--R23)在最後,為狀態的純函數。
\item \textbf{計時器}:全部使用 TON(非保持型),IN 由狀態驅動,離開狀態即自動復歸;
R15、R17、R18 使用 \texttt{TON.Q} 時皆有狀態限定,即使日後搬動 rung 也不會誤寫。
\item \textbf{逾時即故障}:60 秒逾時不再放行對向車輛,一律閂鎖 \texttt{FAULT},
由人員確認車道淨空後以 R21 復歸。
\item \textbf{選配}:多車場域請加入第 3.6 節的車輛計數,
以「車數 = 0」取代純計時作為回 \texttt{IDLE} 的條件。
\end{itemize}
\end{document}