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