The value of Zmotion is to bring customers more success!
今天,正运动小助手给大家分享一下
EtherCAT运动控制卡开发教程之Qt,主要介绍一下SCARA机械手正反解的建立。
ECI2828运动控制卡的硬件介绍
ECI2828系列控制卡支持最多达16轴直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴、机械手指令等;采用优化的网络通讯协议可以实现实时的运动控制。
ECI2828系列运动控制卡支持以太网,232通讯接口和电脑相连,接收电脑的指令运行,可以通过EtherCAT总线和CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。
ECI2828系列运动控制卡的应用程序可以使用VC、VB、VS、C++、C#等多种高级语言编程来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试、方便观察。
一、Qt进行运动控制卡开发流程
1.新建Qt项目。
图1:新建Qt项目
图2: 选择项目路径
图3: 选择Qt编译套件(kits)
图4: 选择基类
2.将函数库相关的文件复制到新建的项目中。
3.向新建的项目里面添加函数库的静态库。(zmotion.lib)
4.添加函数库相关的头文件到项目中。
5.声明相关头文件,并定义连接句柄。
二、PC函数介绍
2.PC编程,一般如果网口对控制器和工控机进行链接。网口链接函数接口是ZAux_OpenEth();如果链接成功,该接口会返回一个链接句柄。通过操作这个链接句柄可以实现对控制器的控制。
3.机械手逆解指令ZAux_Direct_Connframe介绍。
4.机械手正解指令ZAux_Direct_Connreframe介绍。3.机械手逆解指令ZAux_Direct_Connframe介绍。
三、 Qt 开发实现 Scara机械手的正逆解
1. S CARA机械手正逆解例程界面如下。
2.SCARA机械手模型如下。
3.在构造函数里面调用链接控制器的接口ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器监控控制器的轴信息。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
int rint=0;
//初始化窗体
ui->setupUi(this);
//定义按钮组并进行绑定
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)));
//系统启动自动连接控制器
rint = ZAux_OpenEth("127.0.0.1", &g_handle);
//如果链接成功则启动定时器
if(rint==0)
{
startTimer(50);
}
}
//定时器事件
void MainWindow::timerEvent(QTimerEvent *event)
{
QString Str;
float TempData;
//获取J1的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ1->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposJ1->setText(Str);
//获取J2的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdJ2->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposJ2->setText(Str);
//获取Ju的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdJu->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposJu->setText(Str);
//获取Jz的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdJz->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposJz->setText(Str);
//获取x的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdX->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposX->setText(Str);
//获取y的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdY->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposY->setText(Str);
//获取U的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdU->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposU->setText(Str);
//获取Z的位置数据
ZAux_Direct_GetMpos(g_handle, ui->AxisIdZ->text().toInt(), &TempData);
Str = QString("%1").arg(TempData);
ui->DposZ->setText(Str);
}
//建立机械手模型
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;
//初始化机械手参数
ManipulParaInit();
ZAux_Direct_GetMtype(g_handle,ui->AxisIdJ1->text().toInt(),&MtypeJ);
ZAux_Direct_GetMtype(g_handle,ui->AxisIdX->text().toInt(),&MtypeX);
//停止轴运动
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("正解模式");
//修改手动按钮的文本信息
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+");
}
}
//按钮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设备上
1.Linux对应架构的库复制到项目文件夹里面。
2.向新建的项目里面添加函数库的静态库。(libzmotion.so)
添加函数库1
添加函数库2
添加
函数库3
3.重新编译即可运行。
效果运行图
五、调试与监控
编译运行例程,同时连接ZDevelop软件进行调试,对运动控制的轴参数和运动情况进行监控。
同时可以通过机械手仿真工具ZRobotView,对机械手进行仿真测试。
1.ZDevelop软件监控机械手参数。
(1)例程效果图。
(2)关节轴Mtype=33,表示机械手为逆解模式。
2.ZRobotView的机械手仿真效果图。
本次,正运动技术EtherCAT运动控制卡开发教程之Qt(下): SCARA机械手正反解的建立,就分享到这里。
本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。