运动控制卡应用开发教程之Linux
今天,正运动技术为大家分享一下运动控制卡应用开发教程之Linux。我们将从新建Qt项目,添加函数库讲起,再详细讲解函数的用法,最后通过一个连续插补例程讲解来了解项目实操。
在正式学习之前,我们先了解一下正运动技术的运动控制卡ECI2418和ECI2618。这两款产品分别是4轴,6轴运动控制卡。
ECI2418,ECI2618均使用同一套API函数,均支持C、C++、C#、LabVIEW、Python、Delphi等开发语言,支持VC6.0、VB6.0、Qt、.Net等平台,支持Windows、Linux、WinCE、iMac等操作系统。
一
新建Qt项目 添加函数库
1.新建Qt项目:点击“New Project”→“Qt Widgets Application”→“Choose”。
2.找到正运动技术光盘资料里面的Linux系统的函数库。
图2 Linux系统64位库路径
3.将上面路径下的所有文件通过共享文件夹复制到刚刚新建的Qt项目中。
图3 复制函数库相关文件
4.在Qt项目中添加函数库。
A.右键项目,接着点击添加库。
图4 添加库1
B.选择外部库,接着点击下一步。
图5 添加库2
C.点击浏览,找到刚刚复制到项目中的库文件libzmotio.so,然后点击下一步直到完成。
图6 添加库3
5.在Qt项目中添加相关头文件和源文件(zmotion.h、zmcaux.h、zmcaux.cpp)。
A.右键Headers/Sources文件夹,点击添加现有文件。
图7 添加头文件
B.在弹出的界面中找到相关文件,并依次添加。
图8 选择文件
6.在mainwindow.h中添加 #include “zmotion.h”、 #include “zmcux.h”和定义控制器的连接句柄g_handle,至此,项目新进完成。
图9 声明头文件
二
查看PC函数手册 了解其用法
我们在PC项目开发的过程中,经常用到PC函数库,因此,需要查看PC函数手册来了解新函数的用法。
比如在接下来的项目实战中,会用到一些新的函数接口。我们先来看一下这些函数接口的用法。
1.连续连续插补指令的用法。
2.拐角模式设置指令的用法。
注意:这里的拐角模式设置,只是设置了一个模式。像拐角减速设置,还需要设置开始减速角度和结束减速角度等具体使用方法请参考下面的例程讲解。
图11 拐角模式设置指令用法
3.获取控制器缓冲区剩余的缓冲数量指令的用法。
注意:在发送插补指令前,需要先判断缓冲区是否有剩余,这样才能保证运动指令发送成功。
图12 拐角模式设置指令用法
三
项目实操连续插补例程
1.例程以建立板卡的连接,执行运动距离数组“destdis[120][5]”里面的120段点位运动为加工目标。
图13 连续插补例程
图14 destdis数组
2.例程流程图。
图15 例程流程图
3.通过连接按钮的槽函数去调用“ZAux_OpenEth()”连接控制器,获取控制器连接句柄,连接成功后并对轴参数初始化。
//链接按钮槽函数
void MainWindow::on_Open_clicked()
{
int32 iresult;
char * tmp_buff = new char[16];
QString str;
QString str_title;
//从下拉框中获取IP地址
str = ui->comboBox_IP->currentText();
QByteArray ba = str.toLatin1();
tmp_buff = ba.data();
//链接控制器
iresult = ZAux_OpenEth(tmp_buff,&g_handle);
if(0 == iresult)
{
str_title += tmp_buff;
setWindowTitle(str_title);
}
else
{
setWindowTitle('no link!');
return ;
}
//开起定时器
id1=startTimer(100);
id2=startTimer(50);
//初始化轴参数
for(int i=0 ;i<4;i++)
{
ZAux_Direct_SetAtype(g_handle,i,1); //轴类型
ZAux_Direct_SetUnits(g_handle,i,1000); //脉冲当量
ZAux_Direct_SetSpeed(g_handle,i,100); //速度
ZAux_Direct_SetAccel(g_handle,i,1000); //加速度
ZAux_Direct_SetDecel(g_handle,i,1000); //减速度
}
}
4.通过定时器1和2更新控制器轴信息和运动状态。
//定时器
void MainWindow::timerEvent(QTimerEvent *event)
{
//定时器1:获取并更新轴位置信息
if(event->timerId() == id1)
{
QString Xpos1,Ypos1,Zpos1,Upos1;
QString Curspeed;
float showpos[4] ={0};
float curspeed =0;
ZAux_Direct_GetDpos( g_handle,0,&showpos[0]);
ZAux_Direct_GetDpos( g_handle,1,&showpos[1]);
ZAux_Direct_GetDpos( g_handle,2,&showpos[2]);
ZAux_Direct_GetDpos( g_handle,3,&showpos[3]);
ZAux_Direct_GetVpSpeed( g_handle,0,&curspeed);
Xpos1=Xpos1.sprintf('X:%.2f',showpos[0]);
Ypos1=Ypos1.sprintf('Y:%.2f',showpos[1]);
Zpos1=Zpos1.sprintf('Z:%.2f',showpos[2]);
Upos1=Upos1.sprintf('U:%.2f',showpos[3]);
Curspeed=Curspeed.sprintf('%.2f',curspeed);
ui->Xpos->setText(Xpos1);
ui->Ypos->setText(Ypos1);
ui->Zpos->setText(Zpos1);
ui->Upos->setText(Upos1);
ui->Curspeed->setText(Curspeed);
}
//定时器2:获取并更新轴运动信息
if(event->timerId() == id2)
{
int status=0, rembuff=0, curmark=0;
//判断主轴状态(即BASE的第一个轴)
ZAux_Direct_GetIfIdle(g_handle,0,&status);
if (status == -1)
{
ui->motion_state->setText('停止中' );
}
else
{
ui->motion_state->setText('运动中' );
}
QString str='';
//判断存放直线的剩余缓冲
ZAux_Direct_GetRemain_LineBuffer(g_handle,0,&rembuff);
str=str.sprintf('%d',rembuff);
ui->rem_buff->setText(str);
//判断当前运动到第几条运动,
ZAux_Direct_GetMoveCurmark(g_handle,0,&curmark);
str=str.sprintf('%d',curmark);
ui->current_mark->setText(str);
}
}
5.通过启动按钮的槽函数来设置拐角模式及拐角参数,设置插补运动参数,并启动定时器3来发送连续插补指令。
//启动按钮槽函数
void MainWindow::on_Onstart_clicked()
{
int corner_mode = 0;
int axislist[4] = {0,1,2,3};//运动BASE轴列表
QString str;
//选择参与运动的轴,第一个轴为主轴,插补参数全用主轴参数
ZAux_Direct_Base(g_handle,4,axislist);
str = ui->m_speed->text();
m_speed = str.toFloat();
ZAux_Direct_SetSpeed(g_handle,axislist[0],m_speed); //速度
str = ui->m_acc->text();
m_acc = str.toFloat();
ZAux_Direct_SetAccel(g_handle,axislist[0],m_acc); //加速度
str = ui->m_dec->text();
m_dec = str.toFloat();
ZAux_Direct_SetDecel(g_handle,axislist[0],m_dec); //减速度
//拐角模式设置
if(m_mode1 == 1)corner_mode = corner_mode + 2;
if(m_mode2 == 1)corner_mode = corner_mode + 8;
if(m_mode3 == 1)corner_mode = corner_mode + 32;
ZAux_Direct_SetCornerMode(g_handle,axislist[0],corner_mode);
//打开连续插补开关
ZAux_Direct_SetMerge(g_handle,axislist[0],1);
//设置起始速度 ,拐角减速由 运动速度-起始速度 线性减速的
str = ui->m_lspeed->text();
m_lspeed = str.toFloat();
ZAux_Direct_SetLspeed(g_handle,axislist[0],m_lspeed);
//开始减速角度和结束减速角度,转换为弧度
str = ui->m_startang->text();
m_startang = str.toFloat();
ZAux_Direct_SetDecelAngle(g_handle,axislist[0],m_startang*3.14/180);
str = ui->m_stopang->text();
m_stopang = str.toFloat();
ZAux_Direct_SetStopAngle(g_handle,axislist[0],m_stopang*3.14/180);
//设置小圆限速最小半径
str = ui->m_fullradius->text();
m_fullradius = str.toFloat();
ZAux_Direct_SetFullSpRadius(g_handle,axislist[0],m_fullradius);
//设置拐角半径
str = ui->m_zsmooth->text();
m_zsmooth = str.toFloat();
ZAux_Direct_SetZsmooth(g_handle,axislist[0],m_zsmooth);
//设置MARK = 0 ,来通过读取CURMARK实现判断当前执行到那里
ZAux_Direct_SetMovemark(g_handle,axislist[0],0);
g_curseges = 0;
//打开示波器
ZAux_Trigger(g_handle);
id3=startTimer(100);
}
6.通过定时器3来发送连续插补指令。
//定时器3
void MainWindow::timerEvent(QTimerEvent *event)
{
if(event->timerId() == id3)
{
int iresult = 0;
int iremain = 2;
for (int i = 0 ; i < 5; i++)
{
if(g_curseges >= LEGS_MAX) //是否发送完所有指令
{
killTimer(id3);
return;
}
iresult = ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, &iremain);
if(iremain > 2)
{
//加入一段,每段可以有自己的ForceSpeed
ZAux_Direct_SetForceSpeed(g_handle, 0, destdis[g_curseges][4]);
ZAux_Direct_MoveAbsSp(g_handle, 4, destdis[g_curseges]);
g_curseges++;
}
}
}
}
7.通过停止按钮的槽函数来停止轴运动,并停止定时器3。
//停止按钮插函数
void MainWindow::on_stop_clicked()
{
if(NULL == g_handle)
{
setWindowTitle('链接断开');
return ;
}
killTimer(id3);
ZAux_Direct_Singl_Cancel(g_handle,0,2); //停止主轴 BASE的一个轴
}
8.通过清零按钮的槽函数来对各个轴的坐标进行清零。
//清零按钮槽函数
void MainWindow::on_pushButton_5_clicked()
{
for (int i=0;i<4;i++)
{
ZAux_Direct_SetDpos(g_handle,i,0);//设置为零点
}
}
9.最后编译运行查看效果。
A.修改运动距离数组“destdis[120][5]”的前面4段运动参数,打开自动倒角,通过ZDevelop软件的示波器查看效果。
B.修改运动距离数组“destdis[120][5]”的前面4段运动参数,通过示波器查看连续插补加合适的拐角减速的速度波形。