今天,正運(yùn)動(dòng)小助手為大家分享一下應(yīng)用C++開發(fā)一個(gè)硬件比較輸出例程。
我們主要從新建MFC項(xiàng)目,添加函數(shù)庫講起,再了解PC函數(shù)用,最后通過項(xiàng)目實(shí)戰(zhàn)——硬件比較輸出例程講解,來讓大家熟悉運(yùn)動(dòng)控制卡的PC開發(fā)。
在正式學(xué)習(xí)之前,我們先了解一下正運(yùn)動(dòng)技術(shù)的運(yùn)動(dòng)控制卡ECI2828。這款產(chǎn)品是8軸運(yùn)動(dòng)控制卡。
正運(yùn)動(dòng)技術(shù)ECI2828 EtherCAT總線型運(yùn)動(dòng)控制卡,相對(duì)之前發(fā)布的ECI2618,新增了EtherCAT總線接口,電機(jī)軸數(shù)增加到8個(gè),板載24+16點(diǎn)輸入,16+16點(diǎn)輸出(每個(gè)軸接口含2路通用輸入和2路通用輸出,可以做伺服使能、報(bào)警清除、到位信號(hào)、報(bào)警信號(hào)等控制);每軸輸出脈沖頻率可達(dá)10MHz;通過 CAN 總線,可擴(kuò)展到512 個(gè)隔離輸入或輸出口。ECI2828支持硬件比較輸出、精準(zhǔn)輸出、飛拍等功能。
運(yùn)動(dòng)控制卡ECI2828,支持C++、C#、LabVIEW、VB、Delphi、Linux、.Net平臺(tái)、iMac、Python、Matlab等,統(tǒng)一的上位機(jī)API函數(shù)接口,具有開放、兼容、簡(jiǎn)單、易用等功能特性。
一 新建MFC項(xiàng)目 添加函數(shù)庫
1.在VS2015菜單“文件”→“新建”→ “項(xiàng)目”,啟動(dòng)創(chuàng)建項(xiàng)目向?qū)А?/p>
2.選擇開發(fā)語言為“Visual C++”和程序類型“MFC應(yīng)用程序”。
3.下一步即可。
4.選擇類型為“基于對(duì)話框”,下一步或者完成。下一步則往后繼續(xù)配置,完成就直接完成即可。這里就不需要再配置了,無關(guān)緊要的,只要這個(gè)類型選好就行,其他的可以在項(xiàng)目中編輯。
5.找到正運(yùn)動(dòng)技術(shù)廠家提供的光盤資料,路徑如下(64位庫為例):
(1)進(jìn)入光盤資料找到PC函數(shù)文件夾。
(2)選擇函數(shù)庫2.1。
(3)Windows平臺(tái)。
(4)根據(jù)需要選擇對(duì)應(yīng)的函數(shù)庫這里選擇64位庫。
(5)解壓C++的壓縮包,里面有C++對(duì)應(yīng)的函數(shù)庫。
(6)函數(shù)庫具體路徑如下。
6.將廠商提供的C++的庫文件和相關(guān)頭文件復(fù)制到新建的項(xiàng)目里面。
7.在項(xiàng)目中添加靜態(tài)庫和相關(guān)頭文件。
靜態(tài)庫:zauxdll.lib, zmotion.lib
相關(guān)頭文件:zauxdll2.h, zmotion.h
(1)先右擊頭文件,接著依次選擇:“添加”→“現(xiàn)有項(xiàng)”。
(2)在彈出的窗口中依次添加靜態(tài)庫和相關(guān)頭文件。
8.聲明用到的頭文件和定義控制器連接句柄。
至此項(xiàng)目新建完成。
二 查看PC函數(shù)手冊(cè) 了解PC函數(shù)用法
1.PC函數(shù)手冊(cè)也在光盤資料里面,具體路徑如下:
2.PC編程,一般先根據(jù)控制器連接方式選擇對(duì)應(yīng)的連接函數(shù)連接控制器,返回控制器句柄。接著用返回的控制器句柄,實(shí)現(xiàn)對(duì)控制器的控制。
3.比如通過網(wǎng)口連接控制器,先使用ZAux_OpenEth()鏈接控制器,獲取控制器句柄handle。
4.通過獲取到的控制器句柄,使用ZAux_Direct_SetTable,來設(shè)置控制器的TABLE寄存器的數(shù)值。
5.通過獲取到的控制器句柄,使用ZAux_Direct_HwPswitch2,來啟動(dòng)并設(shè)置控制器的硬件比較輸出的模式。
6.通過獲取到的控制器句柄,使用ZAux_Direct_Regist()來啟動(dòng)并設(shè)置控制器的鎖存方式。
三 項(xiàng)目實(shí)戰(zhàn)之硬件比較輸出例程講解
1.硬件比較輸出
運(yùn)動(dòng)控制器內(nèi)有位置比較單元,硬件比較輸出是通過比較軸是否到達(dá)設(shè)定位置,來操作輸出口動(dòng)作,一般使用時(shí)將編碼器位置與設(shè)定位置比較,當(dāng)編碼器的位置到達(dá)一個(gè)設(shè)定比較位置時(shí),觸發(fā)相應(yīng)輸出口電平翻轉(zhuǎn)一次。
如下圖所示,到達(dá)設(shè)置的位置1,電平翻轉(zhuǎn),到達(dá)位置2電平再次翻轉(zhuǎn),到達(dá)位置3電平再翻轉(zhuǎn),直達(dá)比較完所有的點(diǎn)后,電平維持最后一次翻轉(zhuǎn)后的狀態(tài)。
2.例程以建立板卡的連接,然后設(shè)置并開啟硬件比較輸出,將硬件比較輸出的輸出口和鎖存的輸入口進(jìn)行連接,從而通過鎖存記錄硬件比較輸出的位置。
(1)為了實(shí)驗(yàn)室測(cè)試方便,采用自發(fā)脈沖,同一軸編碼器接收脈沖模式測(cè)試。同一個(gè)DB26軸接口的脈沖軸和編碼器軸的連接方式(用于鎖存硬件比較輸出的位置),PUL+接EA+、PUL-接EA-、DIR+接EB+、DIR-接EB-。(或者直接通過脈沖型伺服電機(jī)進(jìn)行位置反饋。)
(2)例程界面。
3.例程簡(jiǎn)易流程圖。
4.通過網(wǎng)口連接控制器,獲取控制器連接句柄。
//連接控制器
void Ctest_PswitchDlg::OnBnClickedOpen()
{
char buffer[256];
int32 iresult;
//從下拉框中獲取IP地址
GetDlgItemText(IDC_IPLIST,buffer,255);
buffer[255] = '\0';
//通過網(wǎng)口連接控制器
iresult = ZAux_OpenEth(buffer, &g_handle);
if(ERR_SUCCESS != iresult)
{
g_handle = NULL;
MessageBox(_T("鏈接失敗"));
SetWindowText("未鏈接");
return;
}
SetWindowText("已鏈接");
SetTimer(0,100,NULL);
}
5.通過運(yùn)動(dòng)按鈕的事件處理函數(shù)去設(shè)置硬件比較輸出的模式,并開始軸運(yùn)動(dòng)。
(1)通過對(duì)UI界面的控件添加對(duì)應(yīng)的變量,實(shí)現(xiàn)硬件比較輸出的模式的參數(shù)輸入。
(2)運(yùn)動(dòng)按鈕事件處理函數(shù)。
//運(yùn)動(dòng)
void Ctest_PswitchDlg::OnBnClickedStartmove()
{
m_RegistCount = 0;
ShowRegistList();
UpdateData(TRUE);
//設(shè)置軸參數(shù)
ZAux_Direct_SetAtype(g_handle, m_AxisNum, 1);
ZAux_Direct_SetUnits(g_handle, m_AxisNum, 1000);
ZAux_Direct_SetSpeed(g_handle, m_AxisNum, 200);
ZAux_Direct_SetAccel(g_handle, m_AxisNum, 2000);
ZAux_Direct_SetDecel(g_handle, m_AxisNum, 2000);
//關(guān)閉硬件比較輸出(停止并刪除沒有完成的比較點(diǎn))
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0);
//開啟硬件比較輸出 MODE:1
if (m_POS_IfOpen == false) //比較完成一次后需要重新調(diào)用HwPswitch
{
//將比較點(diǎn)填入TABLE
ZAux_Direct_SetTable(g_handle, m_POS_StartTable, m_POS_EndTable- m_POS_StartTable+1, fPointPos);
//開啟硬件比較輸出
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 1, m_POS_out, m_POS_OutStatus, m_POS_StartTable, m_POS_EndTable, m_POS_dir, 0);
}
else
{
//關(guān)閉硬件比較輸出
ZAux_Direct_HwPswitch2(g_handle, m_AxisNum, 2, 0, 0, 0, 0, 0, 0);
}
//打開示波器
ZAux_Trigger(g_handle);
ZAux_Direct_SetDpos(g_handle, m_AxisNum, 0);
//開始軸運(yùn)動(dòng)(絕對(duì)位置)
ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_Start_Pos);
ZAux_Direct_Single_MoveAbs(g_handle, m_AxisNum, m_End_Pos);
}
6.根據(jù)設(shè)置情況判斷是否開啟鎖存,并設(shè)置鎖存模式。
//啟動(dòng)或停止鎖存
void Ctest_PswitchDlg::OnBnClickedRegistStart()
{
int iret = 0;
UpdateData(TRUE);
if(m_Regist_IfOpen == FALSE)
{
m_RegistCount = 0;
//必須是編碼器軸才可以鎖存
iret = ZAux_Direct_SetAtype(g_handle,m_RegistAxis,6);
//設(shè)置鎖存模式
int ReglistListSel = ((CComboBox *) GetDlgItem(IDC_REGIST_MODE))->GetCurSel() ;
if(ReglistListSel >= 0 && ReglistListSel <=3)
{
RegistMode = ReglistListSel +1;
}
else if(ReglistListSel == 4 || ReglistListSel ==5)
{
RegistMode = 10 + ReglistListSel;
}
else if(ReglistListSel > 5 || ReglistListSel < 9)
{
RegistMode = 12 + ReglistListSel;
}
//開啟鎖存
iret = ZAux_Direct_Regist(g_handle,m_RegistAxis,RegistMode);
SetTimer(1,5,NULL);
m_Regist_IfOpen = TRUE;
SetDlgItemTextA(IDC_REGIST_START,_T("停止鎖存"));
((CComboBox *)GetDlgItem(IDC_REGIST_MODE))->EnableWindow(FALSE);
ShowRegistList();
}
else
{
KillTimer(1);
m_Regist_IfOpen = FALSE;
SetDlgItemTextA(IDC_REGIST_START,_T("啟動(dòng)鎖存"));
((CComboBox *)GetDlgItem(IDC_REGIST_MODE))->EnableWindow(TRUE);
}
}
7.通過定時(shí)器1,更新鎖存信息。
void Ctest_PswitchDlg::OnTimer(UINT_PTR nIDEvent) //定時(shí)器刷新
{
if(NULL != g_handle)
{
CString str;
if(nIDEvent == 1)
{
int iret = 0;
int MarkStatus = 0;
float RegistPos;
//判斷鎖存是否觸發(fā)
if(RegistMode >= 0 && RegistMode < 4)
{
iret = ZAux_Direct_GetMark(g_handle,m_RegistAxis,&MarkStatus);
}
else if(RegistMode >= 14 || RegistMode < 16)
{
iret = ZAux_Direct_GetMarkB(g_handle,m_RegistAxis,&MarkStatus);
}
else if(RegistMode >= 18 || RegistMode < 20)
{
float tempc;
iret = ZAux_Direct_GetParam(g_handle,"MARKC",m_RegistAxis,&tempc);
MarkStatus = (int)tempc;
}
else if(RegistMode >= 20 || RegistMode < 22)
{
float tempd;
iret = ZAux_Direct_GetParam(g_handle,"MARKD",m_RegistAxis,&tempd);
MarkStatus = (int)tempd;
}
//讀取鎖存的位置
if(MarkStatus == -1)
{
if(RegistMode >= 0 && RegistMode < =4)
{
iret = ZAux_Direct_GetRegPos(g_handle,m_RegistAxis,&RegistPos);
}
else if(RegistMode >= 14 || RegistMode < 16)
{
iret = ZAux_Direct_GetRegPosB(g_handle,m_RegistAxis,&RegistPos);
}
else if(RegistMode >= 18 || RegistMode < 20)
{
iret = ZAux_Direct_GetParam(g_handle,"REG_POSC",m_RegistAxis,&RegistPos);
}
else if(RegistMode >= 20 || RegistMode < 22)
{
iret = ZAux_Direct_GetParam(g_handle,"REG_POSD",m_RegistAxis,&RegistPos); }
m_RegistList.InsertItem(m_RegistCount,"");
str.Format(_T("%d"), m_RegistCount);
m_RegistList.SetItemText(m_RegistCount,0,str);
str.Format(_T("%.3f"), RegistPos);
m_RegistList.SetItemText(m_RegistCount,1,str);
m_RegistCount++;
//重新觸發(fā)鎖存
iret = ZAux_Direct_Regist(g_handle,m_RegistAxis,RegistMode);
}
str.Format(_T("鎖存觸發(fā)狀態(tài):%d 次數(shù):%d"), MarkStatus,m_RegistCount);
SetDlgItemTextA(IDC_STATUS_REGIST,str);
}
}
CDialogEx::OnTimer(nIDEvent);
}
8.通過停止按鈕的事件處理函數(shù)來停止運(yùn)動(dòng)。
//停止
void Ctest_PswitchDlg::OnBnClickedStopmove()
{
int iret = ZAux_Direct_Single_Cancel(g_handle, m_AxisNum, 2);
}
9.編譯運(yùn)行演示。
(1)將硬件比較輸出的輸出口(out0)和鎖存的輸入口(in0)用導(dǎo)線進(jìn)行連接,將軸0的DB26接口上的脈沖軸和編碼器軸進(jìn)行連接。
(2)編譯并運(yùn)行例程。
(3)同時(shí)通過ZDevelop軟件連接同一個(gè)控制器,通過示波器對(duì)運(yùn)動(dòng)過程進(jìn)行監(jiān)控。
-
工控
+關(guān)注
關(guān)注
6文章
239瀏覽量
28251 -
運(yùn)動(dòng)控制
+關(guān)注
關(guān)注
4文章
585瀏覽量
32915 -
運(yùn)動(dòng)控制卡
+關(guān)注
關(guān)注
7文章
114瀏覽量
15488 -
工廠自動(dòng)化
+關(guān)注
關(guān)注
1文章
47瀏覽量
17261 -
正運(yùn)動(dòng)技術(shù)
+關(guān)注
關(guān)注
0文章
103瀏覽量
442
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論