李菊葉
(陜西理工學(xué)院計(jì)算機(jī)科學(xué)與技術(shù)系,漢中723003)
在藥品生產(chǎn)工藝流程中,將藥物原料加工制成具有一定規(guī)格的藥物制品,其中溫度是影響藥品質(zhì)量的一個(gè)重要因素.為避免藥品有效成分損失或破壞,在藥物加工過程中,我們需要對反應(yīng)罐的溫度進(jìn)行實(shí)時(shí)監(jiān)測.本文實(shí)現(xiàn)了對陜西漢江藥業(yè)公司化學(xué)車間生產(chǎn)過程中的化學(xué)反應(yīng)罐溫度的實(shí)時(shí)監(jiān)測.
在Windows平臺下搭建以IPC為核心的多通道實(shí)時(shí)數(shù)據(jù)采集系統(tǒng),硬件上選用高速數(shù)據(jù)采集卡,軟件上采用多線程編程技術(shù)及數(shù)字濾波技術(shù),以滿足高速度、高精度的數(shù)據(jù)采集、處理、顯示等多任務(wù)要求.
系統(tǒng)硬件由工控機(jī)系統(tǒng)、多功能數(shù)據(jù)采集卡,信號調(diào)理電路組成.采集卡選用研華科技生產(chǎn)的PCI-9113A.每片 PCI-9113A具有 32位 PCI總線,32通道單端或16通道差動(dòng)輸入;卡上帶有可存儲1024個(gè)數(shù)據(jù)的FIFO,即插即用 .
硬件結(jié)構(gòu)上由溫度采集模塊和數(shù)據(jù)處理模塊兩部分組成.采集模塊通過溫度傳感器將實(shí)時(shí)溫度物理量轉(zhuǎn)換成模擬信號,再由A/D轉(zhuǎn)換器轉(zhuǎn)換為數(shù)字信號并傳至計(jì)算機(jī),由計(jì)算機(jī)進(jìn)行溫度連續(xù)采集.一個(gè)采集模塊可以控制29個(gè)溫度傳感器,為了是采樣數(shù)據(jù)更準(zhǔn)確,在每個(gè)檢測單元中設(shè)置多個(gè)采樣傳感器,并將其放置在制藥罐內(nèi)部不同位置上.硬件原理框圖如圖1所示.
圖1 硬件原理框圖
溫度采集系統(tǒng)的軟件設(shè)計(jì)包括參數(shù)設(shè)置、采集、處理、顯示等模塊.參數(shù)設(shè)置模塊主要負(fù)責(zé)對數(shù)據(jù)采集系統(tǒng)的運(yùn)行參數(shù)進(jìn)行設(shè)置.運(yùn)行的參數(shù)有:采樣通道號、采樣點(diǎn)數(shù)、采樣周期及各路的上下限報(bào)警參數(shù)等;采集模塊負(fù)責(zé)從數(shù)據(jù)采集卡上連續(xù)不斷地讀取采樣數(shù)據(jù);顯示模塊實(shí)時(shí)溫度、溫度曲線等數(shù)據(jù)的實(shí)時(shí)變化.基于實(shí)時(shí)性的要求,采樣需要不間斷運(yùn)行,顯示也同樣需要連續(xù)不間斷,而且顯示模塊所需要的數(shù)據(jù)必須來源于采樣模塊.因此,兩個(gè)模塊不僅需要各自同時(shí)獨(dú)立運(yùn)行,還要互相協(xié)作,并能實(shí)時(shí)響應(yīng)用戶發(fā)來的指令,為了滿足這種采樣需求,我們需要運(yùn)用多線程技術(shù).
PCI-9113A數(shù)據(jù)采集卡具有很完善的軟件支持.在各種軟件環(huán)境下均可使用,本系統(tǒng)所使用的軟件開發(fā)工具C++Builder,其具備功能強(qiáng)大、高效及界面友好等特點(diǎn),但并不具備直接對硬件I/O地址進(jìn)行訪問的能力,需要調(diào)用DLL函數(shù)實(shí)現(xiàn)對I/O口的訪問和控制.PCI-9113A的開發(fā)商為該卡提供了標(biāo)準(zhǔn)動(dòng)態(tài)連接庫文件,通過調(diào)用動(dòng)態(tài)連接庫中的函數(shù)很容易對硬件設(shè)備進(jìn)行底層的操作.
bool__fastcall TMainForm::StartSample(void)//啟動(dòng)數(shù)據(jù)采集卡
{
if(DemoFlag)return true;//測試
Card_9113=Register_Card(PCI_9113,0);
if(Card_9113<0)
return false;
else
{
AI_9113_Config(Card_9113,TRIG_INT_PACER);
AI_AsyncDblBufferMode(Card_9113,FALSE);
return true;
}
}
在Windows NT和Window s 9x中,多線程的編程實(shí)現(xiàn)需要調(diào)用一系列的 API函數(shù),如 CreateThread、ResumeThread等,比較麻煩且容易出錯(cuò).我們使用Inprise公司的新一代RAD開發(fā)工具C++Builder,可以方便地實(shí)現(xiàn)多線程的編程.我們利用C++Builder提供的TThread對象,多線程的編程變得非常簡便易用.具體實(shí)現(xiàn)方法如下:
在C++Builder IDE環(huán)境下選擇菜單File New,在New 欄中選中Thread Object,按OK,接下來彈出輸入框,輸入 TThread對象子類的名字My Thread,這樣C++Builder自動(dòng)為你創(chuàng)建了一個(gè)名為TMy Thread的 TThread子類.同時(shí)編輯器中多了一個(gè)名為Unit2.cpp的單元,這就是我們創(chuàng)建的TMy Thread子類的原碼.
制藥罐溫度檢測系統(tǒng)的應(yīng)用程序設(shè)計(jì)中的三大部分即(數(shù)據(jù)采集模塊、數(shù)據(jù)處理模塊及顯示模塊)作以介紹,其它部分從略.
2.2.1 采集子線程
在C++Builder環(huán)境下,利用 GlobalAllocPtr函數(shù)來獲得一段內(nèi)存空間,主要用來存放采樣來的數(shù)據(jù).但Windows操作系統(tǒng)中采用的是虛擬存儲的管理機(jī)制,通過GlobalAllocPtr函數(shù)獲得的這段內(nèi)存空間隨時(shí)都有可能被置換到硬盤上,在讀寫硬盤時(shí)所耗費(fèi)的時(shí)間,會導(dǎo)致采樣的不連續(xù)性.為了消除這種不利因素,可以在將緩沖區(qū)的數(shù)據(jù)送往輸入設(shè)備之前,首先調(diào)用GlobalAllocPtr函數(shù)以確保緩沖區(qū)的數(shù)據(jù)不會直接被置換到硬盤上.但是,如果僅僅只為輸入設(shè)備開辟一個(gè)新的緩沖區(qū),則當(dāng)該緩沖區(qū)的空間被采樣的數(shù)據(jù)填充滿后,輸入設(shè)備就沒有緩沖區(qū)可以利用,結(jié)果導(dǎo)致采樣的停止,從而造成了采樣的不連續(xù),所以在實(shí)際應(yīng)用中 ,至少要為輸入設(shè)備準(zhǔn)備兩個(gè)緩沖區(qū)才是合理的.采集模塊的流程圖見圖2.
圖2 采集子線程的流程圖
void__fastcall My Thread::Execute()
PCI-9113A數(shù)據(jù)采集卡提供了非常豐富的采集函數(shù),通過直接調(diào)用其自身攜帶的驅(qū)動(dòng)程序來啟動(dòng)數(shù)據(jù)采集卡,并控制其工作.采集過程中,函數(shù)調(diào)用過程如下:調(diào)用PCI-9113A_CreateDevice函數(shù)創(chuàng)建設(shè)備對象,采集卡進(jìn)入待機(jī)狀態(tài),監(jiān)視溫度的變化并同時(shí)等待用戶的指令;當(dāng)用戶發(fā)出開始采集的命令后,采集、顯示子線程創(chuàng)建并啟動(dòng),采集子線程調(diào)用PCI22300_Read DevBulk AD,批量讀取數(shù)據(jù),一輪采集完成后調(diào)用SetEvent函數(shù)向顯示子線程發(fā)出指令,并開始下一輪的采集.
2.2.2 信號處理子線程
因?yàn)樵跈z測現(xiàn)場傳感器所測到的模擬信號無法完全避免要混雜一些干擾信號,采用數(shù)字濾波來減弱或消除干擾的影響,提高測量的精度和可靠性.以及對分廠32個(gè)點(diǎn)的溫度、濕度(實(shí)際使用29個(gè)點(diǎn))進(jìn)行實(shí)時(shí)監(jiān)測、定期巡檢并可以對任意采集點(diǎn)設(shè)置不同的報(bào)警上下限,使其超限報(bào)警.采集系統(tǒng)應(yīng)可以周期(周期應(yīng)小于等于5 min)自動(dòng)采集、存儲數(shù)據(jù).并具有采集點(diǎn)方便擴(kuò)充能力.32個(gè)點(diǎn)的溫度、濕度誤差應(yīng)≤±0.2℃(-25~175℃).采集速度應(yīng)大于32個(gè)點(diǎn)/min.所選擇的計(jì)算機(jī)應(yīng)具有足夠大的空間,以存儲龐大的溫度數(shù)據(jù).部分代碼如下:
AI_ContScanChannels(Card_9113,31,AD_U_10_V,AI_Buf,512*32,(F64)80000,SYNCH_OP);//均值濾波后換算為溫度保存
for(int i=0;i<32;i++)Sum[i]=0;
for(int k=0;k<16384;)
{
for(int i=0;i<32;i++,k++)
{
Sum[i]=Sum[i]+(AI_Buf[k*2]&0x0fff);//************
}
}
for(int i=0;i<32;i++)//采樣、保存、顯示全部通道,存入數(shù)據(jù)庫時(shí)只存入已經(jīng)開始批號的通道
{
//temp=Sum[i]/512.0*200/4095-25;
//str=str.FormatFloat("0.00",temp);
//RealTimeArray[i].TempData[RealTime-Array[i].SampleCount]=str.ToDouble();
//Temp Val[i]=Sum[i]/512.0*10/4095*19.858721-24.761047;
Temp Val[i]=(Sum[i]/512.0/4095*200-25)*k[i]+b[i];
if(TimerCount==0)
{
if(RealTimeArray[i].SampleCount==Max-Count)RealTimeArray[i].SampleCount=0;//數(shù)組中最多保存Max Count個(gè)數(shù),超過則從頭開始存儲
2.2.3 顯示子線程
數(shù)據(jù)實(shí)時(shí)顯示模塊主要是為現(xiàn)場工作人員提供很大的方便,他們可以實(shí)時(shí)觀察各個(gè)參數(shù)之間的關(guān)系,為了將數(shù)據(jù)實(shí)時(shí)的用曲線圖顯示出來,同時(shí)又不能影響到數(shù)據(jù)采集的連續(xù)不間斷性,因此顯示模塊就需要作為一個(gè)獨(dú)立運(yùn)行的子線程.然而繪圖所必須的數(shù)據(jù)信息完全依附于采集子線程,即顯示模塊必須等待采集子線程的一次數(shù)據(jù)采集任務(wù)完成之后,才能執(zhí)行一次繪圖任務(wù).為了實(shí)現(xiàn)這一功能則需要顯示模塊和采集模塊運(yùn)行時(shí),在兩者之間進(jìn)行協(xié)調(diào),我們可以通過調(diào)用多線程函數(shù) WaitForSingleObject(hEv2ent,IN FIN I T E)函數(shù)實(shí)現(xiàn),IN FIN I T E表示永遠(yuǎn)等待,即顯示線程永遠(yuǎn)等待采集線程的繪圖指令.顯示模塊流程如圖3所示.
圖3 顯示模塊流程圖
部分代碼如下:
void__fastcall TMainForm::Show ChannelData(bool Draw,bool All)//顯示該實(shí)時(shí)通道或查詢結(jié)果溫度數(shù)據(jù)及曲線
{
int x,y,num;
float high,low,MaxVal,MinVal,DiffVal;
TColor PenColor;
String str,str1;
TDateTime time1,time2;
long difftime;
if(!Draw)return;
bit1->Canvas->Brush->Color=clWhite;//clMoneyGreen;////clBlack;//clInfoBk;
bit1->Canvas->Fill Rect(Rect(0,0,bit1->W(wǎng)idth-1,bit1->Height-1));//清除原圖形
Label49->Caption="";
Label48->Caption="";
Label53->Caption="";
bit1->Canvas->Pen->W(wǎng)idth=1;//繪上、下限曲線
bit1->Canvas->Pen->Mode=pmCopy;//pmXor
……….}
程序中多個(gè)線程同時(shí)運(yùn)行,難免要遇到使用同一系統(tǒng)資源,或者一個(gè)線程的運(yùn)行要依賴另一個(gè)線程的完成等,這樣需要在線程間進(jìn)行同步的問題.在C++Builder中,為我們提供了用于創(chuàng)建Event的TEvent對象供我們使用.首先創(chuàng)建一個(gè)全局的TEvent對象作為所有線程可監(jiān)測的標(biāo)志.當(dāng)一個(gè)線程完成某項(xiàng)特定的操作時(shí),調(diào)用 TEvent對象的SetEvent()方法,這樣將設(shè)置這個(gè)標(biāo)志,其他的線程可以通過監(jiān)測這個(gè)標(biāo)志獲知操作的完成.相反,要取消這個(gè)標(biāo)志,可以調(diào)用ResetEvent()方法.在需要等待操作完成的線程中使用WaitFor()方法,將一直等待這個(gè)標(biāo)志被設(shè)置為止.部分事件同步代碼如下:
hEvent=CreateEvent(NULL,FAUSE,TRUE,NULL);
//采集線程請求事件的對象
WaitForSingleObject(hEvent,INFINITE);
//處理采集任務(wù)
SetEvent(hEvent);//重置事件對象
系統(tǒng)以工業(yè)控制計(jì)算機(jī)為核心,采用具有多功能數(shù)據(jù)采集卡PCI-9113A,利用C++Builder的多線程編程技術(shù)實(shí)現(xiàn)了多通道實(shí)時(shí)任務(wù)數(shù)據(jù)采集.系統(tǒng)已經(jīng)投入使用,運(yùn)行穩(wěn)定,可靠性高.
[1]馬建明.數(shù)據(jù)采集與處理技術(shù)[M].西安交通大學(xué)出版社,2005:15-20.
[2]張旭東,付 強(qiáng),何松華,等.基于PCI接口的多通道高速數(shù)據(jù)采集系統(tǒng)數(shù)據(jù)采集與處理[J].系統(tǒng)工程與電子技術(shù),2000,(6):240-244.
[3]張?zhí)N玉,宋宇明,胡修林,等.多通道高速數(shù)據(jù)采集系統(tǒng)PCI接口的結(jié)構(gòu)設(shè)計(jì)[J].華中科技大學(xué)學(xué)報(bào)(自然科學(xué)版),2004,32(8):73-75.
[4]王常力.工業(yè)控制計(jì)算機(jī)系統(tǒng)[J].電子工業(yè)出版社,1993.
[5]陳寬達(dá).C++Builder深度歷險(xiǎn)[M].武漢:華中科技大學(xué)出版社,2002.
[6]石學(xué)文,陳 梅,武玉強(qiáng),等.基于C++Builder的過程控制系統(tǒng)設(shè)計(jì)[D].華中科技大學(xué)碩士論文,2002.
[7]喬宗立.一種在C++Builder環(huán)境中調(diào)用Matlab數(shù)據(jù)的方法[J].湖北汽車工業(yè)學(xué)院學(xué)報(bào),2002,15(4):30-33.
[8]劉森林 ,寇光杰.一種基于C++Builder的過程控制系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[J].東南大學(xué)學(xué)報(bào),2003,33(9):158-161.