段從武,李亭亭,趙世平
(四川大學(xué) 制造科學(xué)與工程學(xué)院,四川 成都 610065)
數(shù)據(jù)采集系統(tǒng)(dataacquisitionsystem,DAS)是允許被測對象經(jīng)過傳感器采集和調(diào)理,轉(zhuǎn)變?yōu)橹T如電壓、電流、脈沖或其他易被采集的信號之后,再通過特定的方式送入計(jì)算機(jī)或者微處理器供處理或存儲的測量系統(tǒng)。數(shù)據(jù)采集是工業(yè)自動(dòng)化技術(shù)的前提,在工業(yè)控制和科學(xué)研究中具有舉足輕重的作用,而數(shù)據(jù)采集系統(tǒng)的軟件模塊是保證試驗(yàn)臺自動(dòng)、可靠、高效運(yùn)行的關(guān)鍵。
根據(jù)四川某軍工單位的某型飛機(jī)特殊零件的測試需求,研制了一套機(jī)電液一體化的測控系統(tǒng)。該測控系統(tǒng)中,根據(jù)試驗(yàn)要求,存在多種需要采集的信號,包括模擬信號、數(shù)字信號、脈沖信號等,根據(jù)其采集信號的不同采用不同采集標(biāo)準(zhǔn)的采集卡獲取數(shù)據(jù)是設(shè)計(jì)該系統(tǒng)的關(guān)鍵所在。本文根據(jù)相應(yīng)的技術(shù)協(xié)議書的要求,對數(shù)據(jù)采集系統(tǒng)的軟件模塊進(jìn)行了分析,然后采用適配器模式、裝飾者模式和單例模式對其進(jìn)行具體實(shí)現(xiàn),通過這3種設(shè)計(jì)模式的實(shí)際應(yīng)用效果表明數(shù)據(jù)采集系統(tǒng)軟件模塊除擁有較高的可拓展性外,其可靠性、靈活性與復(fù)用性也得到了極大的提高。
設(shè)計(jì)模式是軟件設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),它允許直接復(fù)用他人已經(jīng)成功使用過的設(shè)計(jì)和體系結(jié)構(gòu),并能快速做出有利于系統(tǒng)復(fù)用、擴(kuò)展的選擇[1]。
適配器模式屬于結(jié)構(gòu)型模式,它將一個(gè)類的接口轉(zhuǎn)換成用戶需要的接口[2],并讓原本接口不兼容的類協(xié)同工作[3]。適配器模式可以分為對象適配器和類適配器,由于類適配器需要適配器繼承目標(biāo)類與適配者類,而對象適配器對適配者類應(yīng)用動(dòng)態(tài)組合的方式使代碼具備了更大的靈活性,因此在Java、C#等不能支持多重繼承的靜態(tài)語言中主要使用對象適配器。
適配器模式由Target(目標(biāo)抽象類)、Adapter(適配器類)和Adaptee(適配者類)三部分組成,其中,Target類中定義了客戶所需的接口[4];Adaptee定義了一個(gè)已經(jīng)存在的接口,它包含了客戶希望使用的業(yè)務(wù)方法,此接口需要適配;而Adapter是此模式的核心,它將對Adaptee和Target進(jìn)行適配。
裝飾者模式屬于結(jié)構(gòu)型模式,它可以動(dòng)態(tài)地給一個(gè)對象增加一些額外的職責(zé)[5]。裝飾者模式是繼承方式的替代手段之一,它使得需要裝飾的類和用于裝飾的類均可獨(dú)立變化,增加新的構(gòu)建類和具體裝飾者類都非常方便,較好地遵循面向?qū)ο笤O(shè)計(jì)的開閉原則[4]。
裝飾者模式包含Component(抽象構(gòu)建)、ConcreteComponent(具體構(gòu)建)、Decorator(抽象裝飾類)和ConcreteDecorator(具體裝飾類)。Component是ConcreteComponent和Decorator的共同基類,借助它可以使客戶端以一致的方式處理裝飾前后的對象;ConcreteComponent是Component的子類;Decorator是Component的子類,用于給具體構(gòu)建類增加職責(zé),同時(shí)它維護(hù)一個(gè)指向Component的引用,通過該引用可以調(diào)用裝飾之前構(gòu)件對象的方法,并通過子類擴(kuò)展該方法,以達(dá)到裝飾的目的;ConcreteDecorator是Decorator的子類,負(fù)責(zé)向構(gòu)建添加新的職責(zé)。
單例模式屬于創(chuàng)建型模式,它確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)來訪問這個(gè)唯一實(shí)例[6]。借助此模式,不但可以方便對實(shí)例個(gè)數(shù)進(jìn)行控制,而且可避免系統(tǒng)同一時(shí)刻存在多個(gè)狀態(tài)。單例模式按其實(shí)現(xiàn)形式可以分為“餓漢式”單例模式和“懶漢式”單例模式兩類,其中,“餓漢式”單例模式在類加載時(shí)就實(shí)例化單例類,而“懶漢式”單例模式則在第一次調(diào)用時(shí)才實(shí)例化單例類[7]。因此,對系統(tǒng)初始化時(shí)就需要的資源而言一般采用“餓漢式”單例模式[6]。
單例模式僅由一個(gè)類組成。它能夠自行創(chuàng)建程序中唯一的實(shí)例,并讓客戶端通過一個(gè)共有的靜態(tài)方法使用這個(gè)唯一的實(shí)例[8]。
在某試驗(yàn)臺的DAS系統(tǒng)中需要采集多種不同類型的信號,且同一類型的信號還有不同的采集速率的要求,因此采用了多個(gè)生產(chǎn)廠家的采集卡構(gòu)建了此系統(tǒng)。不同的采集卡廠商提供了各式各樣的API讓用戶通過編程操作設(shè)備,但是,如果讓測控軟件直接調(diào)用API函數(shù),則程序會(huì)依賴于底層的采集模塊,如果出現(xiàn)采集信號頻率發(fā)生變化等原因?qū)е滦枨蟾淖冞M(jìn)而更換相應(yīng)的采集卡時(shí),則程序有大量代碼需要重新編寫,不利于保證程序的可維護(hù)性和擴(kuò)展性,也不符合面向?qū)ο蟮囊蕾嚨怪迷瓌t。因此,設(shè)計(jì)中采用了適配器模式對廠家提供的API函數(shù)進(jìn)行封裝,以便軟件的其他模塊進(jìn)行調(diào)用,并讓程序其他模塊依賴于抽象接口。
基于適配器模式的采集模塊類圖如圖1所示,在此僅以HSLAI16AO2為例進(jìn)行說明。HSL類是凌華公司提供的操控采集設(shè)備的API,屬于Adaptee;AbstractDevice類為Target,高層模塊通過操作該抽象類提供的接口來操作底層的采集設(shè)備。在AbstractDevice類中定義了Open、IsReady、Read等5種虛方法作為高層模塊操作底層采集設(shè)備的接口,其中,Open方法中封裝了采集卡的初始化、參數(shù)配置等方法,通過調(diào)用此方法可以完成采集設(shè)備的啟動(dòng)工作;IsReady方法用于判斷采集卡是否可以開始工作;Read方法用于獲取采集卡的數(shù)據(jù),其中,data用于存放讀到的數(shù)據(jù),length用來表示需要獲取數(shù)據(jù)的長度;Write方法用于向采集卡輸出數(shù)據(jù)進(jìn)而控制外接設(shè)備;Close方法
圖1 基于適配器模式的采集模塊類圖
中封裝了停止采集和關(guān)閉采集設(shè)備等方法,用于程序退出之前關(guān)閉采集卡。DeviceHSLAI16AO2類為Adapter,它繼承自AbstractDevice并持有一個(gè)對HSL類的引用,通過調(diào)用HSL中的相應(yīng)方法來重寫AbstractDevice中的5種方法,進(jìn)而實(shí)現(xiàn)操作采集卡的最終目的。若DAS中需要加入新的采集卡,則只需添加一個(gè)新類,讓其繼承AbstractDevice并引用廠家提供的庫函數(shù)來重寫以上5種虛方法即可,無需對上層軟件代碼進(jìn)行修改。
通過采用適配器模式對采集模塊進(jìn)行封裝設(shè)計(jì)之后,首先,避免了該測控系統(tǒng)的高層模塊直接依賴于采集卡廠商提供的庫函數(shù),當(dāng)需要更換采集卡或增加新的采集卡時(shí),不需要對代碼進(jìn)行大范圍的修改,從而增強(qiáng)了此試驗(yàn)臺測控系統(tǒng)軟件的靈活性和維護(hù)性;其次,可以同時(shí)對上層軟件和底層適配器進(jìn)行編寫,極大提高了軟件的開發(fā)效率。
試驗(yàn)臺的采集卡采集到數(shù)據(jù)之后需要對其按照一定的換算關(guān)系式進(jìn)行運(yùn)算處理;與此同時(shí),在工廠環(huán)境中模擬信號采集卡采集到的數(shù)據(jù)含有噪聲信號,為減少噪聲信號對試驗(yàn)臺控制的影響,不僅需要從硬件上對其進(jìn)行隔離,而且軟件上也需要使用相應(yīng)的濾波算法進(jìn)行處理;此外,隨著新的需求出現(xiàn),今后可能需要對采集卡采集到的數(shù)據(jù)進(jìn)行校準(zhǔn)等操作。因此,DAS的軟件模塊應(yīng)該具備在不影響整個(gè)程序結(jié)構(gòu)的前提下應(yīng)對今后新需求的能力。
采用裝飾者模式的類圖如圖2所示,其中DeviceHSLAI16AO2與DeviceDataProcess均繼承自AbstractDevice類,DeviceDataProcess類中的dataProcessObject持有一個(gè)AbstractDevice的引用,F(xiàn)ilter類則繼承自DeviceDataProcess并重寫基類中的ReadData方法,程序運(yùn)行時(shí)當(dāng)需要對數(shù)據(jù)進(jìn)行濾波處理時(shí)則用Filter類包裝DeviceHSLAI16AO2類的數(shù)據(jù),然后調(diào)用ReadData方法即可。若以后需要添加新的數(shù)據(jù)處理功能時(shí)只需要添加一個(gè)新類,并讓其繼承DeviceDataProcess并重寫ReadData方法即可。
通過采用裝飾者模式對采集模塊進(jìn)行設(shè)計(jì)之后,可以較靈活地對采集到的數(shù)據(jù)進(jìn)行必要的處理;同時(shí),在不改變原有代碼結(jié)構(gòu)體系的情況下,允許今后對數(shù)據(jù)進(jìn)行進(jìn)一步的運(yùn)算處理和改變數(shù)據(jù)處理方法的調(diào)用順序,符合了面向?qū)ο蟮摹伴_閉原則”。
圖2 基于裝飾者模式的數(shù)據(jù)處理方法類圖
試驗(yàn)臺的測控系統(tǒng)中每一塊采集卡的實(shí)例應(yīng)該只有一個(gè),否則,如果測控系統(tǒng)中存在多個(gè)獨(dú)立的對象,則會(huì)造成采集設(shè)備的誤操作和數(shù)據(jù)采集、設(shè)備管理的混亂,進(jìn)而影響試驗(yàn)臺的正常運(yùn)行。因此,為了避免此類問題,采用單例模式是最佳的選擇。
在DAS模塊中,設(shè)計(jì)了一個(gè)DeviceManager類對所有采集設(shè)備進(jìn)行管理,由于設(shè)備管理一直貫穿整個(gè)測控軟件的整個(gè)生命周期,所以采用餓漢單例模式進(jìn)行設(shè)計(jì),使其在DeviceManager類加載時(shí)就實(shí)例化唯一的一個(gè)對象。按單例模式設(shè)計(jì)的類圖如圖3所示。當(dāng)高層模塊需要對采集卡進(jìn)行讀寫操作時(shí),可以通過調(diào)用GetInstance方法直接使用DeviceMangaer的實(shí)例對采集設(shè)備進(jìn)行間接操作,該類包含了一個(gè)私有容器類(deviceIndex)用于存儲實(shí)例化的設(shè)備,將其類型聲明為ImmutableDictionary
通過采用單例模式對數(shù)據(jù)采集系統(tǒng)軟件模塊進(jìn)行設(shè)計(jì)之后,可以保證采集卡的對象只有開始時(shí)實(shí)例化一次并容易對它們進(jìn)行統(tǒng)一管理,同時(shí)又方便高層組件獲取設(shè)備對象進(jìn)行相應(yīng)操作[9]。
最終數(shù)據(jù)采集系統(tǒng)軟件模塊的類圖如圖4所示,此DAS軟件模塊充當(dāng)?shù)蛯咏M件,高層軟件模塊持有一個(gè)對DeviceManager的引用,通過此引用可以調(diào)用相應(yīng)采集卡對象進(jìn)行對應(yīng)的數(shù)據(jù)讀取操作,其關(guān)鍵偽代碼如下:
doubledata=0;
AbstractDeviceai16AO2=newDeviceHSLAI16AO2(); //實(shí)例化采集卡
ai16AO2.Open(null); //null表示使用默認(rèn)參數(shù)啟動(dòng)采集卡
AbstractDevicefilter=newFilter(ai16AO2); //用濾波算法來裝飾采集卡采集的數(shù)據(jù)
filter.Type=EnumDevice.AI16AO2;
DeviceManager.GetInstance().Add(filter); //添加采集設(shè)備
DeviceManager.GetInstance().DeviceAtIndex(EnumDevice.AI16AO2).ReadData(refdata,1); //設(shè)備調(diào)用,獲得經(jīng)過濾波處理的數(shù)據(jù)
圖3 基于單例模式的設(shè)備管理類圖
圖4 DAS軟件模塊最終類圖
設(shè)計(jì)模式是解決軟件開發(fā)過程中常見問題的有效手段,開發(fā)人員可以直接借鑒已有的成熟解決方案來解決實(shí)際編程問題。通過軟件的開發(fā)和實(shí)際使用效果表明對DAQ系統(tǒng)軟件模塊采用適配器模式、裝飾者模式和單例模式進(jìn)行綜合設(shè)計(jì)。首先,成功解決了系統(tǒng)上層軟件模塊對采集設(shè)備對應(yīng)的庫函數(shù)耦合度高、使用復(fù)雜、管理混亂的問題,為構(gòu)建高可靠、易維護(hù)、可擴(kuò)展的測控系統(tǒng)軟件夯實(shí)了基礎(chǔ);其次,為今后數(shù)據(jù)處理留下了較大的擴(kuò)展空間,方便添加新的數(shù)據(jù)處理功能;最后,若今后的測控系統(tǒng)開發(fā)中采用相同的采集設(shè)備,則可直接使用此模塊,實(shí)現(xiàn)了代碼的有效復(fù)用。