一直以來我都不相信在XP系統下可以做即時控制,我個人始終認為決定一個程式的根本特徵的東西,就是它的程式架構,那些國外的RTOS供應商們宣稱他們可以在XP下做到100us,我認為簡直就是天方夜談一樣,因為XP作業系統的架構就在那擺著,你不可能指望把一輛牛車開出平治的速度,可是我TMD又錯了,事實上又證明了經驗害死人的主觀錯誤,我錯了,我真的錯了。因為我做出來了,連我自己都不相信。我不知道是否有人能理解出我此時因為感覺自己失敗而痛苦的心情。
要想說明白XP系統下開發運動控制的痛點在哪裡,需要從一個標準說起,這個標準的名稱叫做IEC 1131-3,幾乎所有的RTOS廠商都支援這個運動控制上的編程標準,最著名的廠家我個人認為有兩個一個是CODESYS一個是德國的倍福,雖然德國的倍福用的也是CODESYS的平台,但是經過我認真的分析它的特點發現倍福有很多都是自己的東西。其實根本就不用管什麼ST FBD LD SFC IL那些並不是決定一個系統是否即時的痛點,實現這些語言中國很多廠商都能做到。在這個標準下實現即時性的痛點是IEC 1131-3的資料定義標準,下面是一個例子:
L1_green AT %QB0.1:BOOL;(*定義一個bool型的變數*)
anlog_1 AT%Q*:DINT;(*定義一個雙整形的變數*)
以及和以上類似的各種類型的資料定義。如果沒有研究過即時庫的人,你是不太可能明白,在這種資料結構下,如何重新整理這些變數,以及為什麼想提高即時性,這麼困難,因為變數的重新整理周期就決定了這個系統即時性的效能,而+,-,*,/這些類似的運算,大家如果使用同樣的CPU的話,同樣的編譯最佳化技術(已經很成熟了,發揮空間很小了),想在計算上獲得優勢想都不要想,決定了你系統即時效能的,就是變數的重新整理周期,可是所有的變數名字都是字串,涉及到一個尋找,系統是並發的,又涉及到互鎖,資料維護,因為IEC 1131-3的標準並不單單是下位的標準,和其他系統如上位的互動標準也是這個,你可以瞭解一下倍福的ADS協議和RTIO協議。從我查的國外文獻當中看,大部分論述的都是這個問題,即如何解決變數的搜尋問題,可惜想通過文獻得到答案,比我不想做家務還要困難。
我這裡不能說我是如何做的,因為我想把這個成果應用到我們公司現有的項目上,但是我有權力在這裡展示一下我確實是做到了,畢竟這是我自己私底下努力了將近一年的勞動成果。
下面是My Code,和倍福的ADS協議介面是一樣的。
int main(int argc, char* argv[])<br />{<br />char sText[256];<br />int i =0;<br />int iCount=0;<br />int iErrorCode=0;<br />double iData=0;<br />char sTextArr[1024][256];<br />long lHndVarArr[1024];<br />DWORD dStart,dEnd;</p><p>InitHtsSystem(5);<br />RegisterHts(NULL,"io_timer_counter");//這個倍福的介面函數裡沒有,相當於開闢一個倍福的main資料區<br />srand((unsigned)time( NULL ) );<br />for (i =0;i<1024;i++)<br />{<br />sprintf(sText,"io%d",rand());//變數名字是我隨機產生的,共1024個變數,注意所有的變數名稱都是字串<br />iErrorCode=RegisterData(NULL,"io_timer_counter",sText,sizeof(double),T_DOUBLE);//相當於聲明一個anlog_1 AT%Q*:DINT;IEC 1131-3標準的變數<br />if (iErrorCode!=0)<br />{<br />//printf("資料註冊失敗%d:Errcode=%d/n",i,iErrorCode);<br />}<br />else<br />{<br />strcpy(sTextArr[i],sText);<br />}<br />}</p><p>printf("/n");<br />for (i=0;i<1024;i++)<br />{<br />ReadWriteReqByHND(NULL,"io_timer_counter",sTextArr[i],&lHndVarArr[i]);//這個相當於倍福的AdsSyncReadWriteReq函數<br />}<br />//下面是對這個1024個變數,已讀寫一次為周期,測1000個周期,所得出的時間<br />do<br />{<br />dStart = GetTickCount();<br />iCount=1000;<br />do<br />{<br />iData = 1024;<br />for (i=0;i<1024;i++)//對這1024個變數進行一次寫<br />{<br />iErrorCode = WriteRequestByHND(NULL,lHndVarArr[i],&iData,sizeof(double));//相當於倍福的AdsSyncWriteReq函數<br />}<br />for (i=0;i<1024;i++)//對這1024個變數進行一次讀<br />{<br />iData = 0;<br />iErrorCode = ReadRequestByHND(NULL,lHndVarArr[i],&iData,sizeof(double));//相當於倍福的AdsSyncReadReq函數<br />}<br />iCount--;<br />} while(iCount>0);<br />//100us的計算得來方法 讀寫1024個double型資料,1000次的總時間是100ms+-3ms 100/1000=0.11ms約110us<br />dEnd = GetTickCount();<br />printf("%dms/n",dEnd-dStart);//輸出1000個周期的時間<br />Sleep(5);</p><p>} while(1);</p><p>getchar();<br />return 0;<br />}
下面是運行時,顯示各個1000個周期的時間
把這些時間/1000 之後求平均值,正好是100us左右,再次證明了國外的人比中國人誠信,一點噱頭都沒有加,確實能做到100us。這個在宏觀上看起來好像不太穩定差了20~30ms,但是在單獨的一個us周期上你是根本就看不出來差別的,倍福說它的PLC重新整理周期可以1個ms,我認為簡直就和玩一樣,因為即使是機器手的插補控制周期做到8ms就非常滿足要求了。另外請注意1024個double型資料的查詢,據我所知這比很多PLC程式占的記憶體都要多,因為PLC程式大部分都是bool型的資料,我們最複雜的項目也沒有這麼多的資料。
說起來這個東西真輕鬆,幾句話就說完了。如果我不是弄明白了倍福軟體的記憶體管理方式,有可能再給我幾年時間我都捉摸不明白這個東西到底怎麼做,我對德國人的實現方式佩服的簡直五體投地,同時我也發自真心的感謝德國鬼子,他們在開發軟體的時候,肯定沒有想到擅長山寨的中國人會捉摸他的實現方式。
首先說實現痛點,如果你想在XP系統下做即時控制,那麼就必須脫離開XP的系統架構,如何脫離,記憶體要你自己去管,自己去維護。我想說到這裡很多牛人已經知道了我是怎麼做的了。彙編和C語言都可以做到這一點,當然你要很牛叉才行。另外一個就是搜尋和維護的痛點了。本質上來說這種即時引擎就是在作業系統上開了一個洞,你所需要的就是除了利用作業系統的保護機制以外,其他的工作都由你自己來完成,這樣一半的痛點你就解決了。
另外一半的痛點我即使說出來也白說,因為涉及到太多的理論了,但是我保證所有的理論在大學的教科書上都講到了,你所需要的就是把這些知識點都好好的深入下去,學好C語言和彙編,如果你能把這個東西做出來,你就知道C#和JAVA語言是非常容易被取代的。這一年來我沒少看虛擬機器,編譯原理方面的書。C為什麼這些年,越來越流行,也有其根本原因,物件導向其實沒有什麼,其實現的根本還是結構化編程。
彙編的重要性,並不是你要學會了用它,而是學會它,瞭解它,對你電腦理論方面的學習有很大的好處,你可以看看我的這篇文章
,沒事拿個小程式,反組譯碼之後好好的分析分析為什麼是這樣的。
另外我想說的是雖然我弄明了這個即時引擎的資料結構怎麼設計,架構怎麼寫。但是與國外的發展水平比,它在天上我還在地上呢。
最後送給大家一句話,應用永遠不能為王,理論才是王道。什麼是道,這裡附上唐駿的一句話:“萬事萬物的運轉,大到宇宙,小至一花一果,其實都遵循若干非常簡明的規則。語言也是如此。只要掌握這些規則,就可以不斷複製,創造出紛繁複雜的內容”
,說的太好了。這個即時引擎我用C語言寫的,核心代碼總共才有395+28=423行,你信嗎?從我昨天晚上寫出來(當然花了N個晚上,N個周末,改了N次),今天都冷靜了一天了,我還不信呢!而我相信國外的軟體這裡大部分代碼都會直接用彙編寫,能不快嘛,想不快都難,我也明白了為啥倍福那麼牛叉,那麼牛叉的一個系統ADS介面的API只有十幾個(核心的只有4~5個),自卑啊,我TMD太自卑了,自卑的我想哭。
剩下還有很多路要走,我認為運動控制的下一個黃金時代是平行處理技術,因為現在大部分嵌入式系統CPU都是單核的,即使XP類系統,並發庫也剛剛出來,一兩年以後現有的即時引擎技術就不適用了,無論是哪家企業都必須重新設計它們的演算法了,也就是說我剛摸到一點門,這個技術就要過時了哈哈,自虐啊。我祝諸位仁君好運。
我要整理文檔,再好好的分析一下,整理一下,繼續往下走。