自動化量測程式問題

大家好:

我現在想要同時控制旋轉平台與示波器 目前有用狀態機分別控制各個功能
但目前希望能夠讓整個量測過程完全自動化 量測過程是這樣:
一開始會給使用者輸入一個角度範圍及一個小角度
示波器會在每個角度紀錄波形後旋轉平台才轉到下個角度然後再記錄,依此類推
最後輸出一個文件檔 裡面有各位置所擷取的data
請問我整個程式架構大概要怎麼寫比較好 謝謝

[QUOTE=superKD] 大家好:

我現在想要同時控制旋轉平台與示波器 目前有用

狀態機分別控制各個功能
但目前希望能夠讓整個量測過程完全自動化 量

測過程是這樣:
一開始會給使用者輸入一個角度範圍及一個小角度


示波器會在每個角度紀錄波形後旋轉平台才轉到下個角度然後再記錄,依此類

最後輸出一個文件檔 裡面有各位置所擷取的data
請問我整個

程式架構大概要怎麼寫比較好 謝謝
[/QUOTE]



一個While loop加上一個State machine架構應該足夠。參考流程如下:

Case 1. 輸入角度與範圍

Case 2. 轉角度

Case 3. 到達指定角度

Case 4. 記錄波形

Case 5. 判斷是否完成所有角度 是:至Case 6, 否:至Case 2.

Case 6. 輸出文件

Case 7. 結束

謝謝答覆~

另外我想請問一下 假如用狀態機寫的話
能不能立刻在執行中停止? 怕有緊急狀況發生

狀態機(State Machine)的程式架構設計, 主要的好處之一, 就是可任意給定執行下一狀態的條件, 或是觸發條件. 只要流程與條件定義清楚, 程式開發的彈性很高.

你說的情況, 不管是緊急停止, 暫停, 中斷, 流程忽略…等,都可以實現.

能否請教您大概怎麼寫會比較好?

目前狀態機已經完成馬達控制部分的程式
一開始會停在stand by狀態
輸入完參數 按鍵按下就執行rotation的狀態 馬達開始運動
我想要在運動過程中給指令讓馬達停止 不知道這部分要怎麼達成?
有嘗試過再設一個緊急停止的狀態,但測試完發現似乎還是要等rotation的狀態跑完才會開始執行
 

先記住基礎要件一:「緊急檢測」最好落在「最內層的迴圈」,或獨立的迴圈
再討論基礎要件二:狀態機的流程規劃,決定後面會不會有嚴重的麻煩發生

狀態機的好處,如果你還在規劃階段,那麼就應該用流程圖規劃出來,並且決定「用什麼方式進行緊急檢測」
那麼整件事都會很好,所以要在流程規劃階段就先討論清楚。

狀態機的麻煩,在於如果一開始沒有規劃好,那麼事後才要加入的時候,就會碰到困難
大部分時候,等到發現意料之外的問題,就會處在很窘的情況

[QUOTE=superKD]能否請教您大概怎麼寫會比較好?
目前狀態機已經完成馬達控制部分的程式
一開始會停在stand by狀態
輸入完參數 按鍵按下就執行rotation的狀態 馬達開始運動
我想要在運動過程中給指令讓馬達停止 不知道這部分要怎麼達成?
有嘗試過再設一個緊急停止的狀態,但測試完發現似乎還是要等rotation的狀態跑完才會開始執行
 
[/QUOTE]

「用什麼方式進行緊急檢測」這個議題,有下列三大發展方向,例如:

[1] 每隔10ms會進入一次緊急檢查階段,然後進行單步最小化的移動階段,然後再進入一般檢查與顯示當前狀態階段,三個階段循環。

由於緊急檢測最好落在「最內層的迴圈」,上述例子中,是利用狀態機本身的大迴圈進行緊急檢測,
所以其他的單步最小化移動階段,跟一般檢查與顯示當前狀態階段,都要嚴禁使用Flat/Stacked Sequence Structure,以及各式迴圈。

這種做法稍微適合狀態機預先規劃流程下,控制步進馬達。但你永遠不容易預先知道這台機器的單步最小化移動階段到底是多小步。


[2] 另一個最糟但也最常被用的補救辦法,就是在任何可能需要檢查的「最內層迴圈」(最常陷在裡面的那幾個迴圈)增加Local Variable。然後每圈結束時都會檢查緊急停止為True。

這種情況之所以被稱為最糟,第一個糟點是因為,選擇這個選項的Programmer,通常還是都正好還很愛用Flat/Stacked Sequence Structure。我們可以在迴圈每圈結束時緊急檢查Local Variable,但是不容易在Sequence Structure的每一幀都再加上Case Sturcture加入緊急檢查。

第二個糟點是任一處「較內層的迴圈」,沒有被單步最小化,或根本不適宜被單步最小化。只要沒有被單步最小化,你就有可能要面對一些最大公因數的處理。所謂最大公因數的處理,是指不適合用Elapsed Time需要週期進行固定行為時,如你需要每2ms做一次緊急檢查,需要每3ms動一步,但卻需要每5ms做一次一般檢查與顯示當前狀態。這時候最大公因數的處理就使得迴圈得用Delay 1ms去跑。所謂不適宜被單步最小化,就是說我放了個Delay 1ms去決定了迴圈運作時間的下限,但是這個迴圈隨著Windows分配CPU資源可能會跑[12ms, 17ms, 1ms, 7ms, 1ms, ....],使得時間難以控制,完全打亂了上層的頻度需求。

這個問題常在新手挑戰CLD的時候,寫到跑步機與溫控器的時候發生。
這也是為什麼有人會說「含事件結構的狀態機」可以打遍CLD,但也有新手尋著這條路走卻會碰到問題。


[3]
第三個處理方法,就是理解[2]的困難核心到底在說什麼,然後在確認一定會碰到問題的情形下,毅然決然打掉重練 (而不是看到什麼都得打掉重練)。

一、把你的單步最小化是什麼東西定義清楚,每次單步最小化都要檢查緊急停止。不論是在狀態機層級,還是任何迴圈。狀態機正是一層超大層的do-loop迴圈。

二、而你的緊急停止則使用另一個含事件結構的迴圈去偵測使用者按鍵,初學的時候,多迴圈的溝通先使用Local Variable即可。對初學者的小優勢是,這可以有助於簡易地處理任何「User在下一次緊急停止前快速連按」的情況。單純使用Local Variable不使用Event Structure的情況下,User在200ms跟10ms delay的迴圈內進行快速連按,會產生不同的使用者體驗。
(200ms連按兩下Switched when released,可能什麼事都沒發生,而事件結構可以統一把False->True視為要的,把Ture->False視為不需要的)。

MingYen43095.5933101852
我提供一個跟架構已經被決定後,才想要增加緊急停止有關的情境。
*******************************************************************************************************
下面是360板友的人行道小綠人程式(抱歉意外沒記錄到作者)
我們當時把程式整形成如下,他還不是個狀態機,有[1]迴圈,有[2]Yes/No Select的Case,但沒有[3]Shift Register與 Enum紀錄當前狀態。

[1] 試想程式運行過程中,如果User在50ms內連點兩次Force to Stop,無法正確Force to Stop。這是小議題,用獨立含事件結構迴圈,讓介面的迴圈負責介面。

[2] 這背後原因指向Wait Until Next ms Multiple (或Wait)把整個迴圈hang住了。事實上不只是Force to Stop,所有的動作都卡在這個含Wait的迴圈。
只要大家都卡在這裡,雖然可以保證在進入下一個狀態(下一圈)的時候停止,但你就無法做到最即時的停止。只要小綠人沒爽完這一輪,你就不能在50ms內阻止他。

[3] 如果你想要每10ms就有機會阻止小綠人一次,你可以把迴圈的Wait變成10ms繞一次,並計數繞了幾次10ms。
條件未達時,繞10ms*10次才更新一次小綠人與Time(s)
條件到達後,繞10ms*5次就更新一次小綠人與Time(s)
在絕大部分的控制例子中,只要做到這裡,並了解10ms以下迴圈天生有不精準的風險(CPU resource)。可以想想再放進Sequence Structure會發生什麼。

[4] Loop判斷受限於Wait ms的缺點(只能保證Delay下限),與Case判斷受限於Elapsed Time的缺點(只能在超過上限後發現)
這個迴圈是不易精準的。不容易精準是一回事,數學上或控制上,如果誤差穩定,一切都好說。但如果這迴圈未來被增加更多顯示與計算,CPU Resource不足而導致誤差不穩定呢? 這個問題,常在Programmer替User增加了一組History Length很長的Waveform Chart後發生。
基於這個原因,我們未來會學習從程式架構面進化,讓計時的迴圈就負責計時,好好地數他的10ms*5與10ms*10,讓顯示與計算存檔的迴圈就負責顯示與計算存檔。也因此會有進階的多迴圈程式架構。
2017-7-20 小綠人與秒數 (LabVIEW360).viMingYen43095.6288194444