0 引言
開放式數控系統已經成為當前CNC技術發展的必然趨勢,而基于/PC+運動控制器0結構體系的開放式數控系統也已成為自動化領域備受關注的數控裝置之一。含有DSP處理器的運動控制器,實現復雜的控制算法和功能,完成數控系統中補償處理、速度控制、位置控制等實時性任務; PC機利用其豐富的軟件資源,在Windows環境下開發相應的應用程序模塊,專注于人機界面、輸入輸出、預處理、發送指令等弱實時和非實時性任務的實現。人機界面是集成各種應用程序模塊的平臺,設計一個界面簡潔,操控方便的人機界面,是構建開放式數控系統的重要內容。本文介紹采用C++Builder編程語言構建基于固高GT400-SV型運動控制器的開放式數控系統人機界面的實現方法。
1 界面顯示方案選擇
在界面的設計初期,擬訂了兩種界面顯示方案:多窗口模式和窗口分頁顯示模式。
在多窗口模式下,將每一個功能模塊設計在一個功能子窗口上。即先設計一個主窗口,在主窗口下分設多個子窗口來作為各個功能模塊的接口。但這種模式的界面整體性不夠好,每需要一種功能時必須得激活相應窗口,其他窗口會被隱藏起來,而這種隱藏會使各個功能窗口混到一起,當需要激活某一特定功能時,無法確認所要打開的窗口。
單一窗口分頁顯示模式是在一個主窗口上設計出多個分頁,將特定的功能模塊設計在相應的分頁上,這樣每個分頁在主窗口上都有確定的位置。這種顯示方式能夠很方便地在各個功能之間進行切換。通過兩種方案的對比,決定采用第二種方案。
2 界面設計與文件銜接
界面設計與文件的銜接是界面設計的重點。下面針對具有代表性的模塊論述銜接過程。在同一類功能當中,設計思想是一樣的,不同的只是所響應的事件不同而已。
2.1 主程序文件與程序編輯器
設計程序編輯器是為了讓主程序文件當中的函數能夠讀取和編輯程序編輯器當中的代碼。通過以下函數來實現其銜接:
(1)Dword CallbackThreadFunc(void* ptr)
這個函數是一個線程回調函數,函數體實現的功能跟一般的函數類似,唯一不同的是這種函數只能夠用于多線程,只能由某一線程調用。當一個線程建立起來后,它必須調用某一個線程函數才能夠完成某一特定功能。例如在程序設計中,通過建立一個線程來執行G代碼轉換,這個線程的作用是從編輯器讀取G代碼,經過相應的轉換,再調用GT400基本功能函數。由于C++Builder中的RichEdit編輯器控件本身的功能就很完善,所以只要一條原代碼,就完成了從編輯器中讀取G代碼的功能。原代碼是: pedit=Form1->RichEdit1->Lines->GetText();
(2)void _fastcallTForm1:: SetFileName(constAn-siString FileName)
這個函數完成的功能是為編輯器當中所編輯的未命名或重命名文件設定文件名并在標題欄顯示出來。這個函數與界面的關系,可以從整條語句看出:TForm1是一個窗體類,而Form1為控制界面的主窗體,因而它屬于主窗體文件,要連接到界面還須配合界面的相應功能按鈕。
(3)void _fastcallTForm1::CheckFileSave(void)
這個函數檢查G代碼是否被修改過,如果被修改過則在文件關閉或進行一些其他操作時,提示是否要對當前文件進行存儲。這個函數可以由其它函數調用,也可以響應界面編輯按鈕來完成對G代碼文件的檢驗。
(4)TTextAttributes* _ fastcall TForm1:: CurrText(void)
這個函數從編輯器中返回所選擇字體的屬性。這些函數完成了編輯器與主程序的連接,是界面和G代碼轉換的橋梁。
2.2 界面功能按鈕與響應事件的銜接
在控制界面當中,功能按鈕大致可以分為三類:第一類是主菜單底下的子菜單按鈕;第二類是工具欄中的快捷按鈕;第三類是界面上的其它功能按鈕。這三類按鈕是程序與界面銜接的重要部分,現以第一類按鈕當中存儲子菜單為例說明銜接過程:
在完成菜單項的界面設計之后,先在集成開發環境當中單擊存儲子菜單按鈕,則在主程序文件當中會自動生成這樣一個函數:
void __fastcallTForm1::N7Click(TObject* Sender) { }
由于沒有響應事件,在編譯運行后點擊該子菜單時,系統不做任何響應。然后在響應函數當中添加如下實體,以便完成存儲功能:
void __fastcallTForm1::N7Click(TObject* Sender) { if(! strcmp(FFileName. c_str(), "未命名")); //判斷G 代碼文件是否命名 { if(SaveDialog1->Execute()); //沒有命名,打開存儲 文件對話框 { RichEdit1->Lines->SaveToFile(SaveDialog1-> FileName); //存儲文件 SetFileName(SaveDialog1->FileName); //在文件標題上顯示 RichEdit1->Modified=false; //復位文件修改標志 } } else //如果文件已命名則直接存儲 { RichEdit1->Lines->SaveToFile(FFileName); RichEdit1->Modified=false; } }
這樣,程序運行之后點擊存儲按鈕,就可完成將編輯器當中的G代碼存儲起來。
第二類是工具欄上的快捷工具按鈕,而在子菜單當中又都能夠找到它們的響應按鈕,所以可以直接將它們與各個相應子菜單按鈕銜接,這樣就不用在它們的函數當中添加同樣的函數體以省去寫原代碼的麻煩。仍以存儲按鈕為例,通過兩種方法來實現兩個按鈕的銜接:
(1)在集成開發環境當中的界面工具欄上選中存儲按鈕(假設界面已設計好),在左邊控件屬性欄中點擊even,t再點擊Onclick右邊的框子,在下拉菜單中選相應按鈕名稱即可完成銜接。
(2)在集成開發環境當中的界面工具欄上雙擊存儲按鈕,在主程序文件當中會自動生成如下響應函數:
void __fastcallTForm1::ToolButton1Click(TObject* Sender) { } 在函數體中添加如下代碼即可完成兩個按鈕之間的銜接:
void __fastcallTForm1::ToolButton1Click(TObject* Sender) { N7Click(Sender); }
由于設計思路一樣,對其他按鈕的銜接問題不再贅述。
2.3 界面參數的讀入
在控制界面上讀入各種控制參數,才能建立起系統的運行環境。界面參數輸入一般通過Edit和Com-boBox等控件來實現。
如圖1所示為設定系統周期的輸入框,通過下面函數,可將輸入框中的各個參數輸入系統:
void ZhouqiSet() { short rtn; tm=StrToFloat(Form1->cbotm->Text); lmt=StrToFloat(Form1->cbolmt->Text); enc=StrToFloat(Form1->cboenc->Text); . }
圖中三個輸入框都是ComboBox控件,從上到下被命名為cbotm、cbolmt、cboenc。系統伺服周期通過Form1->cbotm->Text語句讀入,此語句在功能上相當于一個指針,對應地址當中的內容就是向輸入框當中輸入的數字,這時參數的類型為String而不是整形或浮點型,因而需要進行轉換后再賦予相應變量,以便系統函數調用。轉換的數據類型通過這樣的語句實現: tm=StrToFloat(Form1->cbotm->Text),這句將周期輸入框中的輸入參數轉換成浮點型,再賦予周期變量。
Edit控件的讀入原理跟ComboBox一樣。
2.4 界面參數的輸出
在程序設計中,用到的數據輸出控件主要有Lable控件、PaintBox控件及狀態條StatusBar控件。PaintBox控件的使用與圖形顯示有關,而Lable控件是一個標簽控件,它可以用于在界面上標示各種輸入輸出框的作用,也可以直接用于輸出某一數據,在設計中,除了利用這個控件來標示各種輸入框外,還用于輸出X軸和Y軸的位置坐標。以顯示運行軌跡界面X、Y位置坐標為例,論述其輸出過程。
首先,訪問GT400運動控制器的位置寄存器。訪問函數為: shortGT_GetAtlPos(long* Apos);這個函數返回各坐標的位置數據,以便實現必要的位置數據輸出和圖形顯示。位置坐標的讀回代碼為:
EnterCriticalSection(&Sect1); //多線程中初始化臨界區域 rtn=GT_Axis(1); error(rtn); rtn=GT_GetAtlPos(&actl_xpos); error(rtn); //讀回X位置值,放到變量actl_xpos中 rtn=GT_Axis(3); error(rtn); rtn=GT_GetAtlPos(&actl_ypos); error(rtn); //讀回Y位置值,放到變量actl_ypos中 LeaveCriticalSection(&Sect1); //釋放臨界區然后,在界面上顯示坐標位置: Form1->xpos->Caption=" " +IntToStr(actl_xpos); // 將X軸的位置值向運行軌跡分頁的X軸標簽處輸出 Form1->StatusBar1->Panels->Items[1] ->Text=" X: "+IntToStr(actl_xpos); //將X位置值向控制界面的狀態欄輸出 Form1->ypos->Caption=" " + IntToStr( actl_ypos); //將Y軸的位置值向運行軌跡分頁的Y軸標簽處輸出 Form1->StatusBar1->Panels->Items[2] ->Text=" Y: "+IntToStr(actl_ypos); //將Y位置值向控制界面的狀態欄輸出
第一句涉及到多線程當中對公共變量的訪問問題。為了避免在多線程中因為同時訪問公共數據塊而造成不良后果,需要對公共數據塊進行保護,直到一個線程對它的訪問結束為止,在設計中調用的是W in32的API函數進行臨界區域的劃定,即EnterCriticalSec-tion(&Sect1)和LeaveCriticalSection(&Sect1)。設定臨界區域后就可以保證一次只有一個線程對該區域進行訪問,而不會引起數據訪問的沖突。
3 軌跡顯示設計過程
分的執行代碼包含在Display. cpp程序文件當中。運行軌跡界面設計成其被激活時才顯示軌跡,其它界面被激活時不顯示。運動軌跡顯示的坐標軸采用紅色,運行G00時運動軌跡采用黃色,其它軌跡采用藍色。設計中用到C++Builder中的兩個控件:一個是Standard組件當中的GroupBox控件,它用來標記出軌跡顯示的邊界;另一個是System組件當中的PaintBox控件,即圖形顯示控件,它能夠在窗體上指定形成一個Canvas對象的繪圖區域,通過這個繪圖區域可以實現運動軌跡的實時顯示。實現步驟分為兩步:
(1)在窗體初始化時先畫出坐標軸,它通過Dis-play. cpp程序文件當中的void Coordinate()函數實現;
(2)當程序運行時,通過位置讀回函數GT_GetAt-lPos(double)不斷讀回坐標位置值,并將其映射到坐標軸中去,再利用定時器快速刷新坐標值,而每一個坐標值勾畫一段小直線,這樣無數段小直線便勾畫出各種運動軌跡。該部分的功能通過Display. cpp程序文件當中的void Display ()函數來實現。
4 結束語
初步完成了以固高GT400-SV運動控制器構建的開放式數控系統人機界面部分的設計。通過調試證明,所設計的人機界面滿足兩坐標數控系統的要求。此界面包括了常用的菜單欄、工具欄、界面顯示欄等。設計方法和過程對構建基于運動控制器的開放式數控系統人機界面具有一定的通用性。設計中對界面作了相應地優化,去掉了那些具有重復功能的按鈕,并使菜單欄和工具欄中的按鈕只有在編程界面上有效,而在其它界面上無效,提高了系統的可靠性。
(審核編輯: 智匯張瑜)
分享