PLC中的常量,同樣是我所不喜歡用的。
因為與我抨擊過多次的全局變量和UDT一樣,它們都是一種全局資源。
然而, 因為這個觀點又是在整個PLC行業中獨一無二的首發,以前未見到其他人發表過,所以勢必又會驚掉一大堆人的下巴,所以需要先把這其中的道理掰扯清楚。
以往我發表的很多類似技術觀點的文章發表后, 總會出現各種不同的聲音。
其中一種是指責我故意制造爭論,嘩眾取寵。
嘩眾取寵這種罪責從來都是完全沒有邏輯的。技術的問題, 要么對, 要么錯。如果你不能證明錯誤,而只是因為自己沒有相關的認知那么至少暫時你也應該暫時擱置,給自己留個學習認證的時間,而不是第一時間就加以否定, 甚至還什么我的目的是要取寵你。
讀者有什么好取寵的呢?除非我能帶給讀者真正的知識,讓他有思考有收獲,他會感激我。初次之外,我僅僅驚嚇了他們一跳,他憑啥就要寵我,我還取寵呢!
還有一種觀點是倒過來質疑我不會用我文章提到的這個技術點。我講不用UDT的時候懷疑我不會用UDT,我講不用循環的時候懷疑我不會用循環,我講不用IO映射的時候懷疑我不會用IO映射,我講不用全局變量的時候懷疑我不會用全局變量。總之,我不用啥都不是因為這個方法有啥缺點,而是因為我不會用。然后我寫出文章來正好撞到了會用的他。
就不想想,我不會的東西可多了去了。天文地理軍事體育,天底下的知識技能包羅萬象,其中的大部分都是我不懂的。那么多我不懂的內容我為啥不去寫挨著寫文章發表觀點, 憑啥就撞到了你特長的槍口上發表觀點呢?
真實的情況應該是, 那些我不懂的東西我應該是它們的名字都叫不上來,甚至都不了解它們的存在。我既然能拿這些作為題目寫出一篇小作文來,而且能準確地踩到一大批人的脈搏,大概率當然應該是我會的。就因為我會,我才有能力拿它們開刀開涮。而且所理解的深度比剛剛讀到這個觀點的你更深刻。 ? ?
亦或是, 如果你覺得你也可以憑自己不懂,就可以寫文章, 那不妨寫一兩篇出來試試。我相信你如果愿意寫,很快就能寫上幾萬篇文章,積累成專輯出版傳世后人。
而且,咱說的這些問題,普遍都是需要掌握的非常低的技能,斷然連門檻都算不上。比如全局變量, 你說會用全局變量還需要什么技能?相反,會不用, 能不用才是技能!
當然,還有一些人,在用上述觀點跟我周旋良久占不到便宜后,還會使出最后的絕技:人家西門子, CODESYS ,? 三菱等系統平臺,既然設計了此功能, 你為啥不讓我用呢?
這種通常就是屬于沒有邏輯的人群中的下下限,通常到此為止我就沒必要再與這樣的人進行技術話題的探討了。
就好比,我在分享工程師如何做到出差不帶編程電纜萬用表的經驗知識,他來抬杠我家里有,憑什么就不能帶?我講可以出差不帶電腦,他來杠不帶電腦拿什么干活?講如何做到乘坐商務倉而不去擠經濟艙,他來杠飛機上有經濟艙你憑啥不讓人坐?要不要你去建議飛機制造商把經濟艙座位全部取消了!
所以一定要注意,我在講到不使用這個不使用那個的時候,我說的是我自己做到了不用,我從來沒有卡住別人的脖子不許別人使用。甚至連對煙臺方法的學員,我都沒有這個權力。其次,我在講這些觀點的時候,都是有前提條件的,就是在做標準化架構的模塊的時候的最優解。如果不求最優,或者根本不在模塊化范圍內,那也是無關的。?
要說卡脖子,我也只是卡住了我自己的脖子,并且還秀給別人看:我不用這個材料,也不用那個材料,卻仍然做出了標準化架構煙臺方法(6年前)。圍觀群眾縱然沒有機會親自領略其神奇,但可以通過排除法逐漸逼近真相。因為首先一個前提是可以保證的:真實。 ? ?
因為但凡我有丁點撒謊, 比如如果我明明在自己的項目程序中使用了全局變量或者常量,卻還寫文章來探討這個不用那個不用,那就等于把命門暴露給了別人,分分鐘等待被學員給揭發,扒掉了底褲。
而從利益的角度,如果我在用的東西,我也完全沒必要編瞎話再給自己無端增加事端,我就保持我既有的技術架構,繼續出售我的技能知識,都足夠。所以我寫這些文章更多的意義在于啟發已有的煙臺方法的學員,從我交付的資料中發現這些細節的閃光點。我只是在對自己已經做到的技術方法持續做出總結而已。比如在我寫本文發表本文的觀點之前, 那些學習了3-5年的煙臺方法學員,恐怕未必自己能從煙臺方法的案例中總結歸納到。
當然,未來的學員提前有了這方面的準備預期,真正入手之后方向也會更明確。
回到文章的開始我把常量和全局變量都比作全局資源,一定有人不能理解。全局變量M是有地址范圍的,有可能會用光,不同的CPU,其M空間不一樣多。而常量是不需要地址的,怎么也算全局資源呢?
其實,我在最早的講不用全局變量的文章中,就已經提到過了,比方AB PLC,它是沒有M的概念的。所有的全局變量沒有地址,你聲明一批BOOL或者INT等數據類型的變量名,然后就全局使用了。我們指的是它們,符號化的全局變量。而平常用M來泛指,只是為了表達方便。
所以,即便是符號命名的變量或者常量,或者UDT,它們的名字也是全局資源,也是可能發生沖突,而只要有發生沖突的可能, 那么不管這個可能性的概率有多低,在制作標準的模塊庫時都應該盡量避免。比如我自己,就從來不用。當然讀者可以質疑我經歷過的項目都還不夠復雜, 也確實我目前也遇到的一些功能使用了常量,而我還沒找到更好的避免的方法,也仍然在探索中。文章的最后會提及。 ? ?
有的人搞不懂我為啥要對沖突如此敏感,尤其是這種可能性極小的沖突。做一個約定,事先規定一個規則,把所有的功能模塊都約定在規則之下,不就好了嘛!
比如我在講不用M的時候,就有博主表示不以為然,并大秀智商給了一個高級解決方案:提前規劃。即針對不同的應用和功能,預先分配好不同的M地址區域, 不就好了嘛!
然而,有沒有想過,如果你通過規劃的約束,不管是一個工程項目,還是一套架構方案,那么在規劃誕生之前所做的技術儲備就全部不能直接拿來使用了。即便不會被作廢,也需要在使用之前做沖突檢查。那所謂的封裝和復用的模塊化的效果就大打了折扣。
而且,這種規劃并沒有一個天然的核心,并不是你或者我提出了這種規劃大法,我或者你就擁有了天然的主持規劃的話語權, 而是所有人都可以主持規劃, 那么導致的結果是人人都可以做規劃主任, 每個人的規劃方案當然會有差異, 那么即便假設有人甘心做小弟,不謀求做規劃主任,而只是被動執行規劃,也會因為有多個不同的主心骨而無所適從。比如A主導了一個平臺架構, B主導了另一個平臺架構,而C作為小弟,想貢獻一套自己做的算法模塊的時候,還需要分別調整,根據AB各自的規則調整之后,才可以投稿。除非他在做這套算法模塊的時候沒有使用到任何全局資源,模塊是完全內聚的,對資源沒有任何要求和約定。如我一直在號召并踐行的。這就是為什么在GITHUB上面關于PLC的庫分享還完全不成氣候的原因。連規則方法都還沒達成一致的行業,怎么可能有共享的生態環境呢? ? ?
下面我們在TIA PORTAL中演示下使用CONST常量會帶來的危害。當然順便也演示使用了UDT, 用戶數據類型。
新建一個S7-1200的項目, 在其中建立用戶數據類型,就缺省的名字“用戶數據類型_1”好了。建立了2條數據DATA1和DATA2,分別為BOOL,假設算法需要。
然后PLC變量表中的用戶常量的頁,建立一個INT類型的常量,名字為MAX, 數值等于99。通常使用常量的目的就是為了數值可以統一修改。將來需要的時候可以從99改為別的數值。
然后建立FB塊, 在其靜態變量中建立變量,一個數組,數組的上限是MAX, 數據類型即為建立的UDT。 ? ?
這不就是你們使用常數的最大目的嘛!需要建立數組做循環,然而循環的上限提前不能確定,導致數組的上限也不能確定,然而幾乎所有的編程語言都不允許數組的上限值不確定,不允許變化的變量, 只接受常量。所以就只好用常量來實現了。
后面的程序邏輯就不具體做了。反正就是有了這樣的數據接口和結構,最終在FB內實現了特定的算法功能,然后以為可以封裝成一個固化的FB了,可以無限重復使用了。
然后把整個PLC復制一份,并修改自定義數據的結構,比如數據類型改為2個INT,而UDT的名稱不變。
同樣也建立FB, 定義數據,為了實現另外其它的算法功能。其中MAX常量的數值做了修改,比如10 ? ?
好啦!我們現在假設手里有2套完全不同的庫函數,分別實現了不同的控制算法功能。唯獨它們之間好巧不巧使用了相同的名稱,FB的名稱、自定義數據名稱以及常量名稱。當然這個巧合是我人為造出來的, 但你不可否認這種巧合當然存在。
現在,我們假設有第三個項目,需要用到上述的2個功能庫, 所以需要把它們復制到同一個PLC中。
FB名稱的重復很容易發現,也很容易處理。復制的時候另外取個名字,也另外分配個FB編號即可。當然CODESYS等環境下的FB沒有編號,不需要。
然而如果重復使用這2個FB的不是原作者本人, 必然對數據結構和邏輯不夠熟悉。復制之后再編譯的時候,發現提示UDT和常數缺失,然后按照提示去源程序中復制。對于FB1,沒有問題,而對FB2,則會發現出了問題。UDT結構定義變化了, 編譯沖突,通不過了。
解決辦法是,可以在復制之前,先將UDT的名稱改掉,改為不重復,然后再復制,就可以不沖突了。
而常量,則并不會有提示,所以,如果你不曉得代碼邏輯中有沖突使用的常量,就不會發現其中的數值被偷偷的改掉了,而你一無所知。----------這樣,必然就留下了BUG隱患。
這就是我反對我自己使用全局常量的原因所在。因為它破壞了封裝的獨立性和完整性,給原本調試完成的代碼留下了一個缺口,有可能隨時被干擾,而產生功能的不完整。
假設我是有償庫函數的提供者, 那么我自然要對庫的功能完整負有服務義務,而這種因為常量數值變化導致的功能失效,我是沒有臉面來指責用戶使用不當的。比如我咋樣給自己找理由擺脫責任呢?你們對我的庫不熟悉, 你們系統里使用了不該用的常量?對方會回答:我們當然不熟悉,我們從頭就不打算熟悉,而只想簡單使用。我們如果熟悉了就自己做了,誰稀罕用你的庫! ? ?
這還是在庫函數并沒有被加密的情況下。如果指望把庫函數加密,然后不給用戶看到源代碼,用戶只能使用而不能盜用專利技術,那么使用了上述UDT和常量的庫函數都是幾乎不可能的。因為用戶隨時需要編譯,需要使用密碼打開程序塊。
所以總結:如果這個行業普遍習慣于大量使用全局常量數據來做所謂的標準化封裝模塊, 那就永遠不會有成熟穩定的庫函數交易市場。那么所有人,都只能永遠自己閉門造車,自己做庫自己用。分工與專業化提高效率就永遠沒有可能。
有沒有人注意到我在建立FB的時候,圖中,在FB的常量區還順手建立了一個MAXX的常量?
如果你要使用的常量在這里,我們稱之為局部常量數據的話,那是沒有問題的。因為FB和FB之間不會發生沖突,隨便使用都可以。我本文針對的內容是全局常量, 而非局部。
然而,恐怕這又是那些習慣于使用全局常量的同行們所不能接受的。因為你大概率的是會在多個FB中公用這一個常量。即,你本來使用常量的目的也是為了在不同模塊之間分享信息。而這恰恰是我著本文提醒你需要更改提升方法的所在。
我當然清楚你們的習慣,以及技能方法。并不是我不知道這種用法,而恰恰是我更清楚這種用法,并非常知曉這種用法的弊端,所以才會提出來主張。
這里也引申出來另一個道理,即一個人, 遇到對自己固有觀念和習慣有沖擊力的理論和方法的時候,應該持有怎樣的態度。 ? ?
是承認自己的未知狀態,遇到的理論方法,哪怕暫時自己還不能接受不能實現,暫時做下記號,留待自己以后有機會時再圖謀深入了解, 還是第一時間先否定,先找各種理由為自己做法的合理性做辯解,不管是發出聲來還是自己默默內心給自己辯護?這都體現了一個人的學習能力和創新思維能力。對未知事物的拒絕保守態度,本質上是井底之蛙的邏輯。
我曾經研究實現了將LBP庫函數從S7-1500移植到S7-1200,對其中大量使用的UDT頭痛不已。其整個系統中用到了UDT 共有130多個,而且是互相耦合的,即要使用哪怕只有1個FB, 所有的其它的UDT也必須復制過來,少一個都不行。所以為了解耦它們,花費了許多的精力。
而在LBP中,常量的使用則比較少,只有一個:PANELS_NO=2 。
代表的是這臺PLC通訊的觸摸屏的數量等于2 。如果下一個項目,觸摸屏數量為3,則需要把這里的數值改為3。而在整套庫函數中, 這個常量到處用到,不管是循環語句還是數組定義的上限值,因為每一個對象的FB都需要處理觸摸屏通訊數據,并對觸摸屏之間的操作指令做出互鎖保護。所以是幾乎沒辦法避免。
我能想到的是,如果真的需要封裝這批函數,就為每一個數量值分別打包,比如2的時候一個包, 3的時候另一個包。哪怕觸摸屏數量最多到10, 那也頂多10套。 ? ?
但畢竟,在真實的行業應用中,觸摸屏的數量并不會如此多變, 所以暫時,也還只沿用其原有的使用常數的方法了。
最后再補充一點, 在PLC變量表中還有一頁“系統常量”,通常系統會自動生成一大批,程序中可以使用
有可能會有人誤解到我反對用系統常量。關于系統常量的使用是,你只要不在FB內部使用即可。即,你可以使用,但只能把它們當作實參掛到FB實例的管腳上,但不可以封裝在邏輯內部。
其實我們全文所反對的,也是把全局常量用到FB邏輯內部。
審核編輯:黃飛
評論
查看更多