← 所有文章

斜坡升降速計算如何處理週期不固定

· 站長

以0→10、2 units/s與dt 0.1/0.25/0.15的案例,說明實際週期、固定週期、長停頓與時間倒退處理。

一 週期不固定時先保存 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指令。

延伸閱讀


使用 PLC 工具箱 →