吳文超,王鵬飛,陳一凡,王 瑞,葉 敏,瞿 寧
(上海無線電設備研究所,上海 200090)
目前,信息技術在醫療衛生領域已經得到了較普遍的應用[1-3],各種規模的醫院一般部署了HIS(醫院信息系統),這使得醫院中對各類信息的管理效率得到了大大的提高。發藥環節是影響工作效率提高的一個瓶頸環節,多數醫院目前還是使用手工方式進行發藥操作,速度慢、工作強度大并且易產生錯誤[4-7]。具有高度自動化的智能藥房系統[8-10]較好地彌補了這方面的不足, 它將處方發藥操作由軟件系統控制,由基于嵌入式平臺的自動化機件系統完成操作, 速度快、準確率高并且容易維護。智能藥房系統大大提高醫療機構的工作效率,是構建現代醫療機構的一個必然的發展方向[11-12]。
目前智能藥房自動化設備形式主要有機械手式、存儲藥槽式、散裝藥品式、回轉柜式等方式[13- 17],主要通過運動控制卡,PLC,CPLD,數控系統等傳統控制方式[18-19],系統存在功能較為簡單,拓展性不足、智能化程度不夠的缺點。本文提出一種模塊化多線程消息機制軟件框架[20-21],基于Windows進行控制系統設計,以解決智能藥房控制系統上訴不足。
智能藥房系統包含的主要硬件有機架機構,工控機,發藥控制模塊,一體式步進電機,可編程伺服電機,IO控制板及相應的傳感器、執行器。智能藥房系統由3大模塊組成:發藥模塊、上藥模塊和左、右出藥模塊,通過工控機實現對藥房各個模塊的控制。系統硬件模塊組成如圖1所示。

圖1 系統硬件模塊組成
發藥模塊實現藥品的發出功能,主要由發藥電控模塊,傳輸皮帶和安全門電機構成,其中,發藥電控模塊通過CAN總線與工控機通信,接收工控機的指令實現發藥動作,使得藥品從藥槽中滑出,并掉落在皮帶上方,此時通過控制皮帶運轉將藥品傳輸到出藥模塊。上藥模塊實現藥品入庫功能,主要由上藥臺、龍門和機械手組成,機械手整體位于龍門移動軸上,通過龍門X,Z軸的運動,帶動機械手運動到指定的上藥槽或儲藥槽。上藥平臺、龍門和機械手采用電機進行驅動,通過RS485總線與工控機實現通信。出藥模塊由左右兩個提升機及傳輸皮帶組成,將藥品最后輸送到指定的窗口,并提示用戶取藥。
智能藥房控制系統采用Labview開發平臺進行開發[21],其采用G編程語言結合圖形化界面,提供豐富的對外通信接口和工具,能夠一定程度降低系統的開發難度,大大加快軟件系統的開發進展。
智能藥房控制系統主要有外部接口通信,上藥功能,發藥功能,出藥功能,其中外部接口通信為背景后臺運行,負責響應外部系統的任務指令。出于軟件模塊化以及開發調試簡化的考慮,上藥功能,發藥功能,出藥功能設計為獨立并行運行模塊,以保證在進行外部發藥任務時,藥房控制系統仍然有能力響應上藥指令動作以及實現左右兩個出藥機構的同時運行,增加智能藥房系統的運行效率。
根據智能藥房的模塊與功能組成,并考慮到各模塊之間的并發和開發調試方面的獨立性,軟件采用模塊化的設計方法,將智能藥房控制系統分為TCP通信模塊、藥倉模塊、左提籃機模塊、右提籃機模塊、上藥綜合模塊、配置數據管理模塊以及主程序。系統運行時各模塊均嵌入到主程序模塊,主程序模塊不實現具體的功能,完成對各子模塊的綜合調度,各子模塊均可獨立運行和調試,單獨實現各子模塊特有的功能,軟件開發時,可對各子模塊進行同步開發,節約開發時間。
子模塊和主模塊均采用生產者-消費者模式多線程消息架構,各模塊之間可實現靈活的功能調用,便于實現復雜的流程設計。
根據2.2節進行的任務劃分,智能藥房控制系統包含有TCP通信模塊,上藥模塊,發藥模塊,左出藥模塊,右出藥模塊,主程序模塊以及配置數據管理。
模塊框架如圖2所示,TCP通信模塊接收藥房數據管理系統(上位機)下發的指令后,將指令解析后傳送到下位機主程序,主程序根據指令內容按照順序進行進一步解析,將解析后的動作序發送到向上藥模塊、發藥模塊、左出藥模塊、右出藥模塊,進而通過相關機構進行藥品的進出操作,在完成藥品進出操作后,再向TCP通信模塊發出調用指令,通過TCP通信模塊向上位機回饋指令的執行情況。系統各模塊均為獨立運行的狀態,上藥、發藥動作可同步進行動作。

圖2 模塊關系框架
2.3.1 TCP通信模塊
如圖3所示,TCP通信模塊包含界面事件線程、TCP通信線程、指令執行線程3個線程。其中界面事件線程用于調試使用,通過界面事件觸發執行特定的指令發送。界面事件線程用于調試,發出TCP發送指令的指令以及向外部系統發送TCP指令;TCP接收與解析線程用于接收TCP指令,并將TCP指令解析成對應的系統指令,通過隊列消息傳送到指令執行線程,最后指令執行線程執行指令將指令通過隊列消息發送到主程序。

圖3 TCP通信模塊設計
2.3.2 主程序模塊
如圖4所示,主程序模塊包含界面事件線程、指令執行線程以及后臺監控線程3個線程。其中界面事件線程用于調試使用,用于進行上藥、發藥、出藥、盤點等指令的手動調試以及作為控制系統其它模塊的啟動接口,便于實現多模塊的聯合調試。指令執行線程執行對應的程序指令,將相應的模塊指令通過隊列消息下發到各個模塊,模塊指令的內容從文件讀取,需要執行的指令來自主程序調試界面或者TCP通信模塊的消息。后臺監控線程執行外部門開傳感器監控,模塊報警監控,并執行監控到異常后的相應動作功能。

圖4 主控模塊設計
2.3.3 上藥、發藥、左右出藥模塊
模塊軟件架構與前文所訴主控模塊、TCP通信模塊相同,上藥模塊、發藥模塊、左出藥模塊、右出藥模塊均包含界面事件線程,指令執行線程以及后臺監控線程3個線程。其中界面事件線程用于調試使用,用于進行上藥、發藥、出藥、盤點、單步動作等指令的手動調試。指令執行線程執行對應的程序指令,將相應的動作指令進行進一步解析為硬件控制命令序列,控制電機、繼電器等電控單元。模塊指令的內容從配置文件讀取,需要執行的指令來自主程序消息或者下位機人機交互界面。后臺監控線程執行外檢測傳感器,電機控制器監控,并將監控到的狀態顯示到界面上。
2.3.4 配置數據管理模塊
配置數據管理模塊包含界面事件線程,指令執行線程兩個線程。其中界面事件線程用于調試使用,用于文件讀取或寫入時的手動調試。指令執行線程執行對應的程序指令,從磁盤讀或者寫相應的配置文件,并將結果顯示到界面上,需要執行的指令來自主程序消息或者配置數據管理界面。配置數據管理相關的文件主要有程序運行的配置文件以及生成的日志文件兩大類。
上位機接口屬于通信協議,通常采用的通信指令采用XML進行表達[16],協議具有較強的可讀性和拓展性,可以實現基本類型和自定義類型及其類型數組的表征,并且自帶語義及結構,解析相對簡單。
以藥倉發藥指令為例,其指令設計如表1所示。

表1 指令設計說明(機械手上藥)
指令示例如下:
…
控制系統按照模塊設計開發,運行過程中各模塊通過消息機制進行通信,并根據消息內容執行響應的指令。消息傳遞的過程如圖5所示。首先TCP通信線程后臺接收上位機TCP信息,解析指令后,發送消息到TCP執行指令線程,TCP執行指令線程收到消息后,關聯主程序指令,發送消息到主程序動作調度線程,主程序動作調度線程接收到消息后,進一步解析為相應的子模塊動作線程指令,并通過消息發送到子模塊消息隊列,由子模塊執行相應的動作序列。

圖5 消息傳遞過程
模塊運行過程如圖6所示。TCP通信線程過程為:線程創建后,完成通信連接建立,初始化相關的狀態變量。其后線程切換到監控TCP端口,當接收到TCP信息后,對指令進行解析,并根據指令內容向執行指令線程發送消息,通知執行指令線程執行具體的動作;當接收到停止指令時,將進行結束線程的動作,并向執行指令線程發送結束指令,最終結束整個系統。

圖6 TCP通信線程和TCP指令執行線程工作流程
為了盡可能實現功能上的解耦,并沒有直接通過TCP通信線程向主程序線程發送消息,而是通過TCP指令執行線程進行發送,主要目的將TCP消息接收和向主程序發送任務消息的動作解耦,便于通過界面事件(第三方)向指令執行線程發送消息,達到執行相應主程序指令的目的。同時,確保了TCP通信線線程和指令執行線程代碼結構的簡單,便于維護和拓展新功能。
TCP通信模塊的主要功能包括將接收到的通信數據顯示在界面上以及手動將特定的指令向外發送。單步執行界面為執行通信協議所定義的指令,即在上位機未參與的情況下,實現向外發布協議中相應的指令,主要為了實現模塊的獨立調試。調試步驟類似于日志功能,用于記錄調試過程中產生的所有步驟的信息,用于對動作流程以及時序進行分析和優化,以及排查有可能出現的異常。
主程序模塊包括界面線程、主程序動作調度線程和后臺監控共3個線程,其中主程序動作調度線程的運行過程如圖7所示。

圖7 TCP指令執行線程和主程序調度線程工作流程
首先,主程序初始化,啟動所有子模塊線程,并初始化相關的程序內部變量,啟動完成后,主程序動作調度線程監控消息隊列中是否接收外部消息。當接收到外部消息后,若非停止消息并且消息相關的子模塊處于就緒狀態,則向子模塊發送動作執行消息,并重新監控是否收到外部消息;若為停止消息,則向子模塊發送停止消息,并停止本模塊;若相關的子模塊處于非就緒狀態,主程序動作調度線程將進行等待,直到子模塊就緒,再向子模塊發送動作執行消息。
主程序的主要功能有:彈出子模塊,方便進行子模塊的調試工作,直接通過界面對智能藥房功能動作進行調試,而不依賴于上位機系統,提高調試效率。
上藥、出藥、發藥模塊為智能藥房控制系統的底層模塊,實現對系統硬件進行直接操作,完成相應的動作功能。執行過程如圖8所示。軟件啟動時,子模塊動作線程啟動,并進行初始化,隨即監控相關的消息隊列,當收到消息后,子模塊執行相應動作,執行完成后,從消息隊列按順序拉取下一條指令,直到全部指令執行結束。當子模塊接收到停止消息時,將直接退出線程,并關閉子模塊。
各模塊實現均按照相同的框架完成,上藥模塊、出藥模塊、發藥模塊界面設計如圖8所示。

圖8 主程序調度線程和子模塊執行線程工作流程
上藥模塊由上藥平臺、龍門以及機械手組成,實現對模塊相關的電機控制、傳感器數據采集。主要功能有電機調試、傳感器調試、標定功能調試、單步調試等。調試時以界面事件為載體,向子模塊動作線程(上藥龍門機械手執行線程)發送消息,實現對每一個步驟的調試過程。
出藥模塊包括左提籃機和右提籃機,由于左右出藥模塊同步出藥的需求,將該功能分為左提籃機和右提籃機兩個模塊。出藥模塊僅由電機組成,主要功能為電機調試。調試時以界面事件為載體,向子模塊動作線程(例如右提籃機動作執行線程)發送消息,實現對電機相關功能的調試過程。
發藥模塊主要實現藥倉的參數設置與保存,硬件相關動作(復位、發藥、老練等)的調試。
軟件設計上為了隔離開發和調試的過程,將智能藥房位置相關、動作相關、軟件設定相關的參數均做成了可配置的形式,配置數據管理模塊對程序所有的配置數據進行了匯總,并予以顯示。
智能藥房控制系統基于消息對子模塊系統進行控制,消息內容通過參數配置調試界面輸出,可詳細的顯示智能藥房控制系統的運行狀態,例如實際運行步驟順序和耗時等相關信息。調試過程可根據相關信息,分析故障原因,并優化智能藥房控制參數,提高系統效能。
為驗證智能藥房控制系統實際效能,對智能藥房控制系統做了單藥單發藥實驗,多藥單發藥實驗和上藥實驗,測試結果如表2~4所示。智能藥房發藥綜合時間與藥品發藥頻次和藥品位置有關。本文描述的智能藥房具體情況如下:1)包含3個模塊化的藥倉,每個藥倉有16層,每層包含13~15個藥槽編號;2)上藥模塊包含2條上藥軌道和2個緩存軌道,可一次性完成8盒藥品的上藥動作;3)包含6個出藥口。實際控制發藥時,根據被發藥品的位置,會自動選擇藥品的出藥位置,以減少發藥時間。
對于單個藥單進行發藥,發藥實驗取最高層藥槽、最底層藥槽、最左藥倉、最右藥倉、單盒、多盒、單藥單、多藥單等情況進行測試,發藥時間介于4.5~11.6 s之間,單種藥品數量越多,發藥位置越高,發藥位置距離藥籃越遠,發藥時間越長。單個藥單的平均發藥時間為8 s左右。
對于多個藥單進行發藥,由于發藥時左右出藥口出藥過程是并行的,平均單個藥單的發藥時間為7 s左右。
上藥耗時和藥品目標槽位與上藥模塊的距離相關,距離越近,上藥時間越短,單次上藥平均時間為7.6 s,即0.95 s/盒。

表2 單藥單發藥過程測試結果

表3 多藥單發藥過程測試結果

表4 上藥過程測試結果
本文介紹了智能藥房控制系統的軟件設計和實現,提出了一種基于消息的模塊化、多線程控制軟件設計架構,在自動化設備控制系統開發有較好的可復用性。
根據本智能藥房在醫院的使用情況來看,智能藥房控制系統的模塊性強,安裝維護簡單,運行穩定可靠,對醫院藥房工作人員的工作效率提升明顯,具有較大的應用前景。