水能載舟亦能覆舟
「多工」是運動控制的一項利器,但如果使用不當是可能替程序埋下一顆未爆彈
再者,多工所衍生的錯誤往往不好偵錯也不易重現,因此如何提升程序穩健性? 以正確的多工觀念來開發是大家必精進的課題
本文以ServoMotion的多工機制為基礎,演示一些容易衍生錯誤的多工手法,盼讀者能以之為借鏡,避免重蹈覆測。
幾種類型如下:
1. 拐彎抹角
由於Cyclic & Default Task不能執行POU含有等待系列的指令(ex : Delay, WT_MCOK, WT_PFILE … etc.),所以我們往往會委派Trigger Task來執行該POU
上述是個合理且常見的操作,但我們應該避免類似如下操作
TaskB 偵測到事件發生進而先舉起一旗標(flag)欲通知Task0,待Task0發現該旗標為ON時再委派Task1來執行該POU
上述拐彎抹角的手法(經兩手後才委派給Task1),是有可能在某些情境下埋下不易重現的錯誤,如下
TaskB再發現Servo ON時先舉起旗標(LUN_FLG ON),後續由Task0檢查旗標(LUN_FLG)是否為ON,是,再委派Task1執行POU_P2P,但若不幸的在Slot0期間Servo OFF,即導致後續無法進行預期操作或甚至引發AL。
這類手法大部分時間(運氣好)也許皆能正常運作,但會偶而有發生不符合預期的錯誤,事實上要釐清這類型的錯誤往往並不容易。
2. 堅貞不渝
在ServoMotion預設的5個Task中 1, 2, 3皆為Trigger類型,那當有需要時到底要選擇哪個Trigger Task優先?
在大部分的案例下選擇哪個優先並沒有太大差異,但重點是部分應用情境下就不適合堅貞不渝的僅選擇其一來委派
如下圖情境,所有委派都交由 Task1,保留Task2 & Task3不用。這樣的作法須確保有沒有機會造成POU被覆蓋的現象,一旦發生可能導致結果不符預期。
堅貞不渝的情境2也是都習慣把委派全數交由Task1,但這次並非立即覆蓋,而是Task1在執行綠色POU遇到等待系列的指令(ex : DELAY, WT_MCOK, WT_PFILE … etc.),在這段等待的期間內因TaskB忽然又委派新的POU(橘色)給Task1,將造成原執行的POU的後半段代碼(淺綠色)都沒有被執行。
嚴格來說堅貞不渝類型的多工手法,由於有可能造成一序列的預期的動作整個或中途沒有被執行,嚴重將導致整個程序狀態的不穩定,須特別小心注意。