今天,正運(yùn)動(dòng)小助手給大家分享一下EtherCAT運(yùn)動(dòng)控制卡開發(fā)教程之Qt,主要介紹一下SCARA機(jī)械手正反解的建立。
?
?
ECI2828運(yùn)動(dòng)控制卡的硬件介紹
?
?
ECI2828系列控制卡支持最多達(dá)16軸直線插補(bǔ)、任意圓弧插補(bǔ)、空間圓弧、螺旋插補(bǔ)、電子凸輪、電子齒輪、同步跟隨、虛擬軸、機(jī)械手指令等;采用優(yōu)化的網(wǎng)絡(luò)通訊協(xié)議可以實(shí)現(xiàn)實(shí)時(shí)的運(yùn)動(dòng)控制。
?
ECI2828系列運(yùn)動(dòng)控制卡支持以太網(wǎng),232通訊接口和電腦相連,接收電腦的指令運(yùn)行,可以通過EtherCAT總線和CAN總線去連接各個(gè)擴(kuò)展模塊,從而擴(kuò)展輸入輸出點(diǎn)數(shù)或運(yùn)動(dòng)軸。
?
ECI2828系列運(yùn)動(dòng)控制卡的應(yīng)用程序可以使用VC、VB、VS、C++、C#等多種高級(jí)語言編程來開發(fā),程序運(yùn)行時(shí)需要?jiǎng)討B(tài)庫zmotion.dll。調(diào)試時(shí)可以把ZDevelop軟件同時(shí)連接到控制器,從而方便調(diào)試、方便觀察。
?
?
?
一、Qt進(jìn)行運(yùn)動(dòng)控制卡開發(fā)流程
1.新建Qt項(xiàng)目。
圖1:新建Qt項(xiàng)目
圖2:選擇項(xiàng)目路徑
圖3:選擇Qt編譯套件(kits)
圖4:選擇基類
2.將函數(shù)庫相關(guān)的文件復(fù)制到新建的項(xiàng)目中。
3.向新建的項(xiàng)目里面添加函數(shù)庫的靜態(tài)庫。(zmotion.lib)
第一步:添加函數(shù)庫1
第二步:添加函數(shù)庫2
第三步:添加函數(shù)庫3
4.添加函數(shù)庫相關(guān)的頭文件到項(xiàng)目中。
5.聲明相關(guān)頭文件,并定義連接句柄。
?
?
二、PC函數(shù)介紹
?
?
1.PC函數(shù)手冊也在光盤資料里面,具體路徑如下:“光盤資料\8.PC函數(shù)\函數(shù)庫2.1\ZMotion函數(shù)庫編程手冊 V2.1.pdf”。
2.PC編程,一般如果網(wǎng)口對控制器和工控機(jī)進(jìn)行鏈接。網(wǎng)口鏈接函數(shù)接口是ZAux_OpenEth();如果鏈接成功,該接口會(huì)返回一個(gè)鏈接句柄。通過操作這個(gè)鏈接句柄可以實(shí)現(xiàn)對控制器的控制。
ZAux_OpenEth()接口說明:
?
?
3.機(jī)械手逆解指令ZAux_Direct_Connframe介紹。
?
? ?4.機(jī)械手正解指令ZAux_Direct_Connreframe介紹。3.機(jī)械手逆解指令ZAux_Direct_Connframe介紹。
?
?
三、Qt開發(fā)實(shí)現(xiàn)Scara機(jī)械手的正逆解
?
?
1.SCARA機(jī)械手正逆解例程界面如下。
2.SCARA機(jī)械手模型如下。
?
3.在構(gòu)造函數(shù)里面調(diào)用鏈接控制器的接口ZAux_OpenEth(),與控制器進(jìn)行鏈接,鏈接成功后啟動(dòng)定時(shí)器監(jiān)控控制器的軸信息。
?
MainWindow::MainWindow(QWidget *parent) :
? ? QMainWindow(parent),
? ? ui(new Ui::MainWindow)
{
? ? int rint=0;
? ? //初始化窗體
? ? ui->setupUi(this);
? ? //定義按鈕組并進(jìn)行綁定
? ? btnGroup = new QButtonGroup(this);
? ? btnGroup->addButton(ui->ManualRev1,1);
? ? btnGroup->addButton(ui->ManualFwd1,2);
? ? btnGroup->addButton(ui->ManualRev2,3);
? ? btnGroup->addButton(ui->ManualFwd2,4);
? ? btnGroup->addButton(ui->ManualRev3,5);
? ? btnGroup->addButton(ui->ManualFwd3,6);
? ? btnGroup->addButton(ui->ManualRev4,7);
? ? btnGroup->addButton(ui->ManualFwd4,8);
? ? connect(btnGroup, SIGNAL(buttonPressed(int)), this, SLOT(ManualRev1_pressed(int)));
? ? connect(btnGroup, SIGNAL(buttonReleased(int)), this, SLOT(ManualRev1_released(int)));
? ? //系統(tǒng)啟動(dòng)自動(dòng)連接控制器
? ? rint = ZAux_OpenEth("127.0.0.1", &g_handle);
? ? //如果鏈接成功則啟動(dòng)定時(shí)器
? ? if(rint==0)
? ? {
? ? ? ? startTimer(50);
? ? }
}
?
4.通過定時(shí)器更新控制器各個(gè)軸的位置和速度信息。
//定時(shí)器事件
void MainWindow::timerEvent(QTimerEvent *event)
{
? ? QString Str;
? ? float TempData;
? ? //獲取J1的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ1->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposJ1->setText(Str);
? ? //獲取J2的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ2->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposJ2->setText(Str);
? ? //獲取Ju的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdJu->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposJu->setText(Str);
? ? //獲取Jz的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdJz->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposJz->setText(Str);
? ? //獲取x的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdX->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposX->setText(Str);
? ? //獲取y的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdY->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposY->setText(Str);
? ? //獲取U的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdU->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposU->setText(Str);
? ? //獲取Z的位置數(shù)據(jù)
? ? ZAux_Direct_GetMpos(g_handle, ui->AxisIdZ->text().toInt(), &TempData);
? ? Str = QString("%1").arg(TempData);
? ? ui->DposZ->setText(Str);
}
5.通過正逆解切換按鈕實(shí)現(xiàn)Scara機(jī)械手正逆解的切換。
?
?
//建立機(jī)械手模型
void MainWindow::on_ManipulModel_clicked()
{
? ? int JogAxislist[4]={ui->AxisIdJ1->text().toInt(),ui->AxisIdJ2->text().toInt(),ui->AxisIdJu->text().toInt(),ui->AxisIdJz->text().toInt()};
? ? int AxisList[4]={ui->AxisIdX->text().toInt(),ui->AxisIdY->text().toInt(),ui->AxisIdU->text().toInt(),ui->AxisIdZ->text().toInt()};
? ? int MtypeJ=0,MtypeX=0;
? ? //初始化機(jī)械手參數(shù)
? ? ManipulParaInit();
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);
? ? //停止軸運(yùn)動(dòng)
? ? ZAux_Direct_Rapidstop(g_handle,2);
? ? if(MtypeJ == 33)
? ? {
? ? ? ? ZAux_Direct_Base(g_handle,4,AxisList);
? ? ? ? ZAux_Direct_Connreframe(g_handle ,4 , AxisList, 1, 0, 4,JogAxislist);
? ? ? ? ui->ManipulModel->setText("正解模式");
? ? ? ? //修改手動(dòng)按鈕的文本信息
? ? ? ? ui->ManualRev1->setText("J1-");
? ? ? ? ui->ManualRev2->setText("J2-");
? ? ? ? ui->ManualRev3->setText("Ju-");
? ? ? ? ui->ManualRev4->setText("Jz-");
? ? ? ? ui->ManualFwd1->setText("J1+");
? ? ? ? ui->ManualFwd2->setText("J2+");
? ? ? ? ui->ManualFwd3->setText("Ju+");
? ? ? ? ui->ManualFwd4->setText("Jz+");
? ? }
? ? else
? ? {
? ? ? ? ZAux_Direct_Base(g_handle,4,JogAxislist);
? ? ? ? ZAux_Direct_Connframe(g_handle ,4 , JogAxislist, 1, 0, 4,AxisList);
? ? ? ? ui->ManipulModel->setText("逆解模式");
? ? ? ? ui->ManualRev1->setText("X-");
? ? ? ? ui->ManualRev2->setText("Y-");
? ? ? ? ui->ManualRev3->setText("U-");
? ? ? ? ui->ManualRev4->setText("Z-");
? ? ? ? ui->ManualFwd1->setText("X+");
? ? ? ? ui->ManualFwd2->setText("Y+");
? ? ? ? ui->ManualFwd3->setText("U+");
? ? ? ? ui->ManualFwd4->setText("Z+");
? ? }
}
?
6.通過手動(dòng)按鈕,根據(jù)當(dāng)前的機(jī)械手模式進(jìn)行手動(dòng)運(yùn)動(dòng)。
//按鈕1按下
void MainWindow::ManualRev1_pressed(int Id)
{
? ? int MtypeJ,MtypeX;
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);
? ? //如果是逆解
? ? if(MtypeJ == 33)
? ? {
? ? ? ? switch (Id)
? ? ? ? {
? ? ? ? ? ? case 1: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdX->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 2: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdX->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 3: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdY->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 4: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdY->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 5: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdU->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 6: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdU->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 7: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdZ->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 8: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdZ->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
? ? //如果是正解
? ? else if(MtypeX == 34)
? ? {
? ? ? ? switch (Id)
? ? ? ? {
? ? ? ? ? ? case 1: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ1->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 2: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ1->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 3: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ2->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 4: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJ2->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 5: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJu->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 6: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJu->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 7: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJz->text().toInt(),-1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case 8: ZAux_Direct_Single_Vmove(g_handle,ui->AxisIdJz->text().toInt(),1);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
//按鈕1松開
void MainWindow::ManualRev1_released(int Id)
{
? ? int MtypeJ,MtypeX;
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);
? ? ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);
? ? //如果是逆解
? ? if(MtypeJ == 33)
? ? {
? ? ? ?switch (Id)
? ? ? ?{
? ? ? ? ? ?case 1: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdX->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 2: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdX->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 3: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdY->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 4: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdY->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 5: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdU->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 6: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdU->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 7: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdZ->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 8: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdZ->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?default:
? ? ? ? ? ? ? ? ? ?break;
? ? ? ?}
? ? }
? ? //如果是正解
? ? else if(MtypeX == 34)
? ? {
? ? ? ?ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);
? ? ? ?switch (Id)
? ? ? ?{
? ? ? ? ? ?case 1: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 2: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ1->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 3: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ2->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 4: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJ2->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 5: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJu->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 6: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJu->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 7: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJz->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case 8: ZAux_Direct_Single_Cancel(g_handle,ui->AxisIdJz->text().toInt(),2);
? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?default:
? ? ? ? ? ? ? ? ? ?break;
? ? ? ?}
? ? }
}
?
?
?
四、例程移植到Linux設(shè)備上
?
?
1.Linux對應(yīng)架構(gòu)的庫復(fù)制到項(xiàng)目文件夾里面。
2.向新建的項(xiàng)目里面添加函數(shù)庫的靜態(tài)庫。(libzmotion.so)
添加函數(shù)庫1
添加函數(shù)庫2
添加函數(shù)庫3
?
3.重新編譯即可運(yùn)行。
效果運(yùn)行圖
?
?
五、調(diào)試與監(jiān)控
?
?
編譯運(yùn)行例程,同時(shí)連接ZDevelop軟件進(jìn)行調(diào)試,對運(yùn)動(dòng)控制的軸參數(shù)和運(yùn)動(dòng)情況進(jìn)行監(jiān)控。
同時(shí)可以通過機(jī)械手仿真工具ZRobotView,對機(jī)械手進(jìn)行仿真測試。
1.ZDevelop軟件監(jiān)控機(jī)械手參數(shù)。
(1)例程效果圖。
?
(2)關(guān)節(jié)軸Mtype=33,表示機(jī)械手為逆解模式。
?
(3)虛擬軸Mtype=34,表示機(jī)械手為正解模式。
2.ZRobotView的機(jī)械手仿真效果圖。
?
?
?
本次,正運(yùn)動(dòng)技術(shù)EtherCAT運(yùn)動(dòng)控制卡開發(fā)教程之Qt(下):SCARA機(jī)械手正反解的建立,就分享到這里。
?
審核編輯:湯梓紅
評論
查看更多