圖一
大多數的 LabVIEW 使用者對於延時元件 Wait (ms) 與 Wait Until Next ms Multiple 都不陌生,但對於這兩者的差別往往說不清楚,甚至有錯誤的理解。讓我們先來看以下的例子:
圖二
在上圖的程式中,註解1標示的區域是模擬一個執行時間為 50 ms 的主程式功能,註解2標示的是延時元件,此處以Wait (ms)等待200 ms。註解3的程式則是利用 Tick Count (ms) 實測每次迴圈執行所費的時間。由於在上圖中,Wait 等待的時間為 200 ms 大於主程式的 50 ms,for 迴圈每次執行完主程式的 50 ms後,都要等待額外的150 ms,補足到 200 ms 才會執行下一次迴圈運算。因此Wait元件的功能,顧名思義就是「等待」,等到一定的時間後,才進行下一次迴圈運算。實際的運算結果如下圖所示,每次都是不多不少正好是 200 ms。
圖三,迴圈單次的時間(Elapsed Time)被 Wait 控制
那麼當主程式的長度大於 Wait 指定的長度時會怎麼樣呢?
圖四
如圖四所示,此時主程式的時間長度為 250 ms,大於Wait所等待的 200 ms,這個時候Wait不會有任何作用,單次迴圈運算的執行時間完全受主程式控制。實測結果如圖五,每次迴圈運算的時間長度都變成 250 ms。
圖五,迴圈單次的時間(Elapsed Time)被主程式控制,Wait 無作用
到此為止,相信大部分的使用者之前都是照上述的邏輯正確理解的。現在讓我們來看另一個延時元件Wait Until Next ms Multiple。
圖六,區塊2中的Wait替換為Wait Until
上圖區塊2中不再使用 Wait,而換成了 Wait Until。這時請問您覺得單次的迴圈運算會需要多久的時間呢?網路上盛傳的解釋是:「如果主程式的時間長度超過了 Wait Until 的指定時間,那麼就會等待到指定時間的下一個整數倍(multiple),或是下下一個整數倍,依此類推」。照這樣推斷,執行時間是 200 + 200 = 400 ms。但這是錯誤的!請讀者下載文末的程式實際操作一次,觀察 Elapsed Time 記錄的時間便可以驗證。實測結果如圖七所示,每次迴圈的執行時間仍然是250 ms。
圖七,使用 Wait Until 的實測結果仍然是 250 ms
差異在於回傳值
要了解箇中原因,就要先知道 Wait (ms) 與 Wait Until Next ms Multiple 在進行計時的時候,都是以CPU時間為基準的毫秒計時器(millisecond timer)在進行時間控制。Wait在執行時,會等待特定長度的時間,然後再回傳計時器時間。舉例來說:若剛開始一次迴圈運算時,計時器的值是 275,380,340,Wait須等待的時間是 25 ms,那麼等到計時器的值成為 275, 380, 365 時,Wait 就會將數值回傳以結束自身函式的運算,只是一般使用上我們甚少使用到這個回傳值。此時如果當次迴圈內已沒有要運算的程式,那麼該次迴圈就會結束;如果還有其他程式要運算,迴圈就必須等待直到運算結束。因此各位可以發現,對於 Wait 自己來說,它不是在等待其它程式區塊,它等的是毫秒計時器,其它程式區塊是否計算完畢跟它毫無關係。
Wait Until 也是要依賴毫秒計時器,只是它在意的是計時器是否到達指定時間的整數倍(multiple),一開始計數器的值是多少並無所謂。也就是說,當指定的時間是 30 ms 時,整個計時器的倍數只要是30的倍數,Wait Until 就會回傳。這樣會衍伸出一個問題,就是 Wait Until 第一次運行時,它等待的時間可能少於指定的時間。例如一開始計時器的數值是275,380,340,但只要經過 10 ms,成為275,380,350就變成30 ms的倍數,這時數值便會立刻回傳,然而時間才過了 10 ms 而已(如圖八),不足指定的時間長度,這是使用者要注意的地方。這一點在LabVIEW Help內關於Wait Until Next ms Multiple 有特別說明。
圖八,使用Wait Until進行第一次迴圈的長度可能小於指定時間200 ms
Wait 與 Wait Until的使用場合
一般最常使用延時元件的場合是放在迴圈中釋放CPU資源,這時使用Wait與Wait Until都可以,因為與程式同步執行無關,只要迴圈不要以CPU全速執行占據所有運算資源即可。而在這樣的場合下,我個人的習慣是只會使用 Wait (ms),避免第一個迴圈執行時間不足指定長度的現象。
值得一提的是,Wait Until 有一個獨特的使用場合,就是達到上文說的「如果主程式的時間長度超過了 Wait Until 的指定時間,那麼就會等待到指定時間的下一個整數倍(multiple),或是下下一個整數倍,依此類推」。但就像前面提的,光靠Wait Until 是無法達到的,解決辦法是搭配 Sequence Structure,請參考圖九:
圖九,Wait Until 搭配 Sequence Structure才能達到等待指定時間整數倍的功能
這個概念是,第 i+1 次迴圈內的主程式開始運算前,先利用Wait Until 檢查是否離第 i 次運算已過了指定的時間長度或其倍數。由於使用了 Sequence ,因此可以確定一定要等 Wait Until 執行完畢丟出回傳值才會進行主程式運算。實際的測試結果請參考圖十,除了第一次迴圈運算的時間以外,其他每次都是200 + 200 = 400 ms。
圖十,Wait Until 搭配 Sequence Structure的實測結果,主程式250 ms、指定時間 200 ms
希望讀畢本文後,各位讀者能更了解 Wait (ms) 與 Wait Until Next ms Multiple 兩者之間具體而微的差異。若有任何建議也請不吝留言,謝謝。
範例程式載點
Wait & WaitUntil comparison ver12.zip (LabVIEW 2012版本)
Wait & WaitUntil comparison ver80.zip (LabVIEW 8.0版本)
延伸閱讀
[NI White Paper] Software Timed Loops using Wait (ms) and Wait Until Next ms Multiple
沒有留言:
張貼留言