一 週期不固定時先保存 dt
不固定週期的斜坡計算,核心不是每次加一個固定數,而是依實際經過時間更新。本篇案例 設定 target=10、current=0、rate=2 units/s,三次實際 dt 依序為 0.10、0.25、0.15 s。每輪增量是 rate×dt,累計時間 0.50 s,理想輸出為 1.0。
介面至少分開 current、target、rate、now、last_time、dt、valid_time 和 state。dt=(now-last_time) 必須使用單調時間或明確處理時鐘回撥;不能把牆上日期時間當作永遠遞增。第一次呼叫沒有 last_time 時,應建立基準並決定輸出保持 0,而不是猜測一個週期。
斜坡速度是每秒的輸出變化率,不是加速度,也不是 jerk。它只產生一個數值設定值;若輸出連接運動軸或壓力設備,仍需另外核對控制器、回授、限位和安全條件。
| 輪次 | dt(s) | rate(units/s) | 增量 | current後 |
|---|---|---|---|---|
| 1 | 0.10 | 2 | 0.20 | 0.20 |
| 2 | 0.25 | 2 | 0.50 | 0.70 |
| 3 | 0.15 | 2 | 0.30 | 1.00 |
| 合計 | 0.50 | 2 | 1.00 | 1.00 |
時間計算的單位要在資料契約中只保留一種權威表示,例如以毫秒整數保存 elapsed_ms,再轉成秒供 rate 計算。若 now 和 last_time 一個是秒、一個是毫秒,0.25 秒可能被誤算成 249.75 秒。每筆 本篇案例 紀錄都應列出原始時間值、換算單位與 dt。
驗收要記錄 now、last_time、dt、delta、current_before、current_after,而不是只記錄最後的 1.0。若只保存輸出,無法知道第二輪是實際等了 0.25 秒,還是程式漏跑兩次後一次補加。
二 實際 dt 與固定 dt 的差異
若錯誤地固定使用 dt=0.1,三輪輸出會是 0.2、0.4、0.6,而實際時間已過 0.5 秒,應為 1.0。這不是小數誤差,而是時間模型不同。固定 dt 只有在任務週期有明確上限且工程允許以名目週期估算時才可使用。
本篇案例 可設一個比較案例:程式在 0.10 秒、0.25 秒、0.15 秒後被呼叫。實際 dt 產生 0.2、0.5、0.3;固定 dt 則每次 0.2。把兩組結果並排,能在離線測試中直接抓到把 scan period 當實際經過時間的錯誤。
| 策略 | 第1輪 | 第2輪 | 第3輪 | 總輸出 |
|---|---|---|---|---|
| 實際dt | 0.20 | 0.50 | 0.30 | 1.00 |
| 固定0.1 | 0.20 | 0.20 | 0.20 | 0.60 |
| dt=0依政策保持 | 0.00 | 依規格 | 依規格 | 需標記 |
| 倒退時間拒收 | 0.00 | 不更新 | 恢復後重建基準 | 待同步 |
dt 應設定上限。若程式停頓 5 秒,直接計算 2×5=10 可能一次追到 target;若目標是模擬實際經過時間,這可能合理,若目標是避免長停頓造成大步進,則要把 dt cap、Catchup 或 Hold 策略寫進規格,不能在程式中隨意選一個。
固定週期只有在調度器保證週期且工程允許時才可用。即使名目週期為 100 ms,通訊阻塞、優先級搶占或程式停頓仍可能令實際間隔改變。可把 cycle_jitter 和 elapsed_dt 一起記錄,先用離線資料確認誤差是否足以影響輸出,再決定是否簡化。
時間戳來源也要保存。若 now 來自可調整系統時鐘,校時可能造成 dt 負值;應改用單調計時來源,或檢查倒退後進入 TimeReset 狀態。不同平台的時鐘精度與型別需由手冊核對。
三 長暫停與 catch-up 策略
長暫停是週期不固定最需要先定義的分支。本文 本篇案例 採 HoldOnLongGap:若 dt>0.5 s,先保存 gap_duration,輸出保持 current,重新建立 last_time,下一次有效呼叫才恢復。這個策略會讓輸出落後 target,但不會把未知期間一次補成大步。
另一種策略是 BoundedCatchup:只接受 dt_cap=0.5,delta=rate×min(dt,dt_cap),並把 skipped_time 記錄為診斷。此例捨棄超過上限的時間,不保留待補時間債;往後只按新dt前進,直到到達目前目標,並非追補完整歷史時間。兩者都必須顯示策略名稱,不能用「逾時照常」這種含糊描述讓維護人員猜。
| 情境 | 實際dt | 本案例策略 | 輸出 | 診斷 |
|---|---|---|---|---|
| 正常 | 0.10 | 實際dt | +0.20 | None |
| 短延遲 | 0.25 | 實際dt | +0.50 | None |
| 長停頓 | 5.00 | HoldOnLongGap | 保持 | Gap=5.00 |
| 長停頓 | 5.00 | BoundedCatchup cap0.5 | +1.00 | Skipped=4.50 |
| 時間倒退 | -0.10 | TimeReset | 保持 | 重建基準 |
若 target 在長停頓期間改變,恢復時仍要以當下 target 計算,不能把舊 target 的多個歷史步驟補播。輸出應保留 current_before、target_at_resume 和 recovery_policy,這樣才能知道落後是策略造成,還是資料遺失。
本篇HoldOnLongGap在偵測長間隔的當輪保持並重設last_time;下一輪若dt正常才繼續。若選另一種恢復策略,需另立版本與預期結果,不能在同一測試中混用。測試案例應包含 target 在停頓中改為 6 的情況,確認恢復時使用新 target,而不是把停頓前的 10 步歷史補播。
對長停頓的選擇應由需求決定:流程設定值通常需要限制追趕速度,模擬時間積分則可能要保留實際經過時間。報告中固定寫出 Hold 或 BoundedCatchup,並以同一筆 本篇案例 資料重跑,避免不同工程師採不同解讀。
長停頓驗收要特別檢查首次恢復呼叫:它是否只建立時間基準、是否有限幅、是否留下 gap 診斷。很多錯誤只在第一次恢復發生,連續正常週期測試不會發現。
本例把dt=0定為ZeroElapsed,當輪保持輸出且不改last_time;因now與last_time相同,下一個正dt仍從同一基準計算。倒退時間則保持並以新的可信時間重建基準,不能把負dt帶進斜坡。
四 方向 邊界與工程限制
當 target>current 使用 rise_rate,當 target<current 使用 fall_rate;兩者可以不同。若 target=10、current=9.9、fall/rise 都足夠,本輪應直接到 10 並停止,不能因浮點誤差越過目標。若 target 在每輪來回變化,斜坡器會依每輪方向限幅,需另評估是否造成追蹤遲滯。
rate=0 表示保持,不是錯誤;rate<0、dt<0、非有限數值則應拒收。輸入有效性與斜坡結果分開保存,避免把「輸出沒有變」誤讀成「目標沒有變」。
本方法不計算加速度或 jerk。若設備要求平滑運動,需使用已核准的運動功能或專用控制器,並由工程師定義加速度、限位、互鎖和停機條件。離線公式不能證明現場動作安全。
數值計算可用 REAL 或更寬型別,但實際 PLC 的資料格式、轉換與時間函式不可由其他平台推定。IEC 61131-3 說明語言與型別範圍,並不保證每個控制器對時間資料或浮點例外採相同實作。
若斜坡輸出被多個使用者共用,週期不固定還會造成資料競爭。應指定單一寫入者,將 current_after 作為下一輪唯一來源;其他畫面或通訊只讀取快照。否則每個來源都可能以自己的 dt 再加一次,產生超速。
可變 dt 的驗收不可只用三個正常值,還要加 dt=0、dt 倒退、長停頓和 target 在停頓中改變的資料列。每一列都要有策略結果與診斷欄位,才能證明實際時間模型已被固定。
若 dt 太小而 rate×dt 低於資料解析度,輸出可能暫時不變;需保留小數餘量或使用更寬型別,不能把零變化誤判成目標已到達。
完成測試後輸出報告要列出每輪 dt、策略、輸出、狀態和未處理 gap。若報告只寫「斜坡正常」,無法審核週期不固定時是否仍符合需求。
五 驗收 FAQ與來源
本篇案例 通過條件是:dt=0.1、0.25、0.15 時輸出依序 0.2、0.7、1.0;固定 dt 的錯誤結果 0.6 能被測試抓出;長停頓依明確策略處理;倒退時間不產生負增量;target 反向時使用對應 rise/fall rate。
FAQ1:為何三輪總輸出是 1.0?答:實際時間是 0.5 秒,2 units/s×0.5 s=1.0;每輪則為 0.2、0.5、0.3。
FAQ2:長停頓一定要 catch-up 嗎?答:本例固定採HoldOnLongGap:當輪保持並重建基準,下一輪正確dt才繼續。有上限的catch-up只是另一版比較策略。
FAQ3:斜坡速率是不是加速度?答:不是。它是輸出值每秒的變化率,不描述運動軸的加速度或 jerk。
FAQ4:系統時鐘被校回去怎麼辦?答:將負 dt 視為 TimeReset,保持或按工程策略處理,重新建立時間基準,不把負時間直接乘入公式。
參考:Python官方time.monotonic:單調時間概念,僅作計時設計參考,非PLC API。
參考:MathWorks Rate Limiter官方文件:依經過時間限制上升與下降速率的模型,非PLC指令。