点位运动即点到点的运动,只要给定目标位置,设置好相关的速度加速度等参数即可实现。下面我们来用C#实现下图所示的一个GTS点位运动demo。
界面可以设置参数和做一些相关的操作,显示状态和指令返回值。如果你对界面上使用到的控件使用不熟悉,请自行学习相关内容,下面直接说怎么调指令实现功能。
1. 控制卡初始化
我们使用多卡库,并且要实现可以切换卡号和轴号,先定义两个变量来存放卡号和轴号。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WinFormControls.YDControls;
using WinFormControls;
using System.Threading;
namespace GTS_TrapDemo
{
public partial class Form1 : Form
{
public short cardNum = 0;//用于存卡号的变量,默认卡号为0
public short axisNum = 1;//用于存放轴号的变量,默认轴号为1
public Form1()
{
InitializeComponent();
cbCardNum.SelectedIndex = 0;
cbAxisNum.SelectedIndex=0;
cbLdm.SelectedIndex = 0;
}
......
初始化运动控制卡:
private void btnInitCard_Click(object sender, EventArgs e)
{
short sRtn = 0;
// 打开运动控制器
sRtn = gts.mc.GT_Open(cardNum,0,1);
// 指令返回值检测
commandhandler("GT_Open", sRtn);
// 复位运动控制器
sRtn = gts.mc.GT_Reset(cardNum);
commandhandler("GT_Reset", sRtn);
// 配置运动控制器,配置文件要先通过调试软件mct2008生成
sRtn = gts.mc.GT_LoadConfig(cardNum,"test.cfg");
commandhandler("GT_LoadConfig", sRtn);
// 清除各轴的报警和限位
sRtn = gts.mc.GT_ClrSts(cardNum,1, 8);
commandhandler("GT_ClrSts", sRtn);
timer1.Start(); //启动定时器刷新界面控件
}
2. 伺服使能
伺服使能的按钮我们点击使能伺服后,按钮显示文字可以更改为“伺服关闭”,反之点击按钮伺服关闭后,按钮显示文字更改为“伺服使能”。
private void btnEnable_Click(object sender, EventArgs e)
{
short sRtn = 0;
if (btnEnable.Text=="伺服使能")
{
// 伺服使能
sRtn = gts.mc.GT_AxisOn(cardNum, axisNum);
commandhandler("GT_AxisOn", sRtn);
if(sRtn==0)
{
btnEnable.Text = "伺服关闭";
}
}
else
{
sRtn = gts.mc.GT_AxisOff(cardNum, axisNum);
commandhandler("GT_AxisOff", sRtn);
btnEnable.Text = "伺服使能";
}
}
3. 位置清零
private void btnZeroPos_Click(object sender, EventArgs e)
{
short sRtn = 0;
// 位置清零
sRtn = gts.mc.GT_ZeroPos(cardNum, axisNum,1);
commandhandler("GT_ZeroPos", sRtn);
}
4. 启动点位运动
点位运动我们可以写一个方法来实现绝对运动或者相对运动以及循环往复运动。
bool runFlag = true;
public void TrapMove()
{
short sRtn = 0;
gts.mc.TTrapPrm setTrapPrm = new gts.mc.TTrapPrm();
float Acc;
float Dec;
float Vel;
int pos;
short Smooth;
short loopNum;
short delayTime;
float.TryParse(tBVel.Text, out Vel);
float.TryParse(tBVel.Text, out Acc);
float.TryParse(tBDec.Text, out Dec);
short.TryParse(tBSmooth.Text, out Smooth);
short.TryParse(tBLoopNum.Text, out loopNum);
short.TryParse(tBDelayTime.Text, out delayTime);
int.TryParse(tBStep.Text, out pos);
double odlPrfPos = 0.0;
int lAxisStatus;
uint pClock;
double prfpos, encpos;
short i = 1;
//判断是否是相对运动
if (PosDcmoth==0)
{
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
//commandhandler("GT_SetPrfPos", sRtn);
sRtn = gts.mc.GT_GetPrfPos(cardNum, axisNum, out odlPrfPos, 1,out pClock);
commandhandler("GT_SetPrfPos", sRtn);
pos = (int)(odlPrfPos )+ pos;
}
// 清除各轴的报警和限位
sRtn = gts.mc.GT_ClrSts(cardNum, axisNum, 1);
// 将 AXIS 轴设为 Jog 模式
sRtn = gts.mc.GT_PrfTrap(cardNum, axisNum);
commandhandler("GT_PrfTrap", sRtn);
// 读取 Jog 运动参数(需要读取全部运动参数到上位机变量)
sRtn = gts.mc.GT_GetTrapPrm(cardNum, axisNum, out setTrapPrm);
commandhandler("GT_GetTrapPrm", sRtn);
//设置需要修改的运动参数
setTrapPrm.acc = Acc;
setTrapPrm.dec = Dec;
setTrapPrm.smoothTime = Smooth;
setTrapPrm.velStart = 0;
// 设置 Jog 运动参数
sRtn = gts.mc.GT_SetTrapPrm(cardNum, axisNum, ref setTrapPrm);
commandhandler("GT_SetTrapPrm", sRtn);
// 设置 AXIS 轴的目标位置
sRtn = gts.mc.GT_SetPos(cardNum, axisNum, pos);
commandhandler("GT_SetPos", sRtn);
// 设置 AXIS 轴的目标速度
sRtn = gts.mc.GT_SetVel(cardNum, axisNum, Vel);
commandhandler("GT_SetVel", sRtn);
// 启动 AXIS 轴的运动
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1));
commandhandler("GT_Update", sRtn);
//实现循环运动
if ((PosDcmoth == 0) && (loopNum > 0))
{
while (runFlag)
{
sRtn = gts.mc.GT_GetSts(cardNum, axisNum, out lAxisStatus, 1, out pClock);
gts.mc.GT_GetPrfPos(cardNum, axisNum, out prfpos, 1, out pClock);//读取轴的规划位置
gts.mc.GT_GetEncPos(cardNum, axisNum, out encpos, 1, out pClock);//读取轴编码器位置
if (i <= loopNum)
{
if ((lAxisStatus & 0x400) != 0x400)
{
if ((int)(prfpos) == odlPrfPos)
{
Thread.Sleep(delayTime);
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
sRtn = gts.mc.GT_SetPos(cardNum, axisNum,pos);//设置轴的目标位置
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1)); //启动轴的运动
i++;
}
else if (prfpos == pos)
{
Thread.Sleep(delayTime);
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
sRtn = gts.mc.GT_SetPos(cardNum, axisNum, (int)(odlPrfPos));
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1)); //启动轴的运动
i++;
}
}
}
}
}
}
由于点位运动中有循环,直接放在界面线程会导致界面卡死,我们放到一个线程来执行点位运动。
private void btnNmove_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(new ThreadStart(TrapMove));
th1.IsBackground = true;
th1.Start();
}
5. 停止运动
private void btnPMove_Click(object sender, EventArgs e)
{
short sRtn;
sRtn = gts.mc.GT_Stop(cardNum, 1<<(axisNum-1), 0);
commandhandler("GT_Stop", sRtn);
runFlag = false;
}
6.刷新状态
获取轴的状态和运动位置,速度等是必要的。我们还是放到一个timer里面定时刷新。
int sts;
uint pClock;
double prfPos=0.000;
double encPos=0.000;
double prfVel = 0.000;
double encVel = 0.000;
private void timer1_Tick(object sender, EventArgs e)
{
gts.mc.GT_GetSts(cardNum, axisNum,out sts,1,out pClock);
// 伺服使能标志
if ((sts & 0x200)==0x200)
{
ledEnable.Checked = true;
}
else
{
ledEnable.Checked = false;
}
// 正向限位
if ((sts& 0x20)==0x20)
{
ledLimitP.Checked = true;
}
else
{
ledLimitP.Checked = false;
}
// 负向限位
if ((sts& 0x40)==0x40)
{
ledLimitN.Checked = true;
}
else
{
ledLimitN.Checked = false;
}
// 伺服报警标志
if ((sts & 0x2)==0x2)
{
ledAlarm.Checked = true;
}
else
{
ledAlarm.Checked = false;
}
// 跟随误差越限标志
if ( (sts & 0x10)==0x10)
{
ledMvErr.Checked = true;
}
else
{
ledMvErr.Checked = false;
}
// 规划器正在运动标志
if ((sts & 0x400)==0x400)
{
ledRun.Checked = true;
}
else
{
ledRun.Checked = false;
}
// 平滑停止
if ((sts & 0x80)==0x80)
{
ledsthStop.Checked = true;
}
else
{
ledsthStop.Checked = false;
}
// 急停标志
if ((sts & 0x100)==0x100)
{
ledAbruptStop.Checked = true;
}
else
{
ledAbruptStop.Checked = false;
}
gts.mc.GT_GetPrfPos(cardNum, axisNum, out prfPos, 1, out pClock);
lbPrfPos.Text = prfPos.ToString("0.000");
gts.mc.GT_GetEncPos(cardNum, axisNum, out encPos, 1, out pClock);
lbEncPos.Text = encPos.ToString("0.000");
gts.mc.GT_GetPrfVel(cardNum, axisNum, out prfVel, 1, out pClock);
lbPrfVel.Text = prfVel.ToString("0.000");
gts.mc.GT_GetEncVel(cardNum, axisNum, out encVel, 1, out pClock);
lbEncVel.Text = encVel.ToString("0.000");
}
完整的代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WinFormControls.YDControls;
using WinFormControls;
using System.Threading;
namespace GTS_TrapDemo
{
public partial class Form1 : Form
{
public short cardNum = 0;
public short axisNum = 1;
public Form1()
{
InitializeComponent();
cbCardNum.SelectedIndex = 0;
cbAxisNum.SelectedIndex=0;
cbLdm.SelectedIndex = 0;
}
private void updatetBLog(string text)
{
this.tBLog.AppendText(text);
}
public void commandhandler(string command, short err)
{
string log = DateTime.Now.ToString("HH:mm:ss ") + command + " = " + err.ToString() + "\r\n";
// tBLog.AppendText(DateTime.Now.ToString("HH:mm:ss ") + command + " = " + err.ToString() + "\r\n");
if (this.tBLog.InvokeRequired)
{
// 使用Invoke安全地在主线程上调用
this.tBLog.Invoke(new Action<string>(updatetBLog), log);
}
else
{
// 已在主线程上,直接更新
this.tBLog.AppendText(log);
}
WriteLog.Write(command + "=" + err.ToString());
}
private void cbCardNum_SelectedIndexChanged(object sender, EventArgs e)
{
cardNum = (short)cbCardNum.SelectedIndex;
}
private void cbAxisNum_SelectedIndexChanged(object sender, EventArgs e)
{
axisNum = (short)(cbAxisNum.SelectedIndex+1);
}
short PosDcmoth;
private void cbLdm_SelectedIndexChanged(object sender, EventArgs e)
{
PosDcmoth=(short)cbLdm.SelectedIndex;//0:相对运动 1:绝对运动
if(cbLdm.SelectedIndex==1)
{
tBLoopNum.Enabled = false;
tBDelayTime.Enabled = false;
}
else
{
tBLoopNum.Enabled = true;
tBDelayTime.Enabled = true;
}
}
bool runFlag = true;
public void TrapMove()
{
short sRtn = 0;
gts.mc.TTrapPrm setTrapPrm = new gts.mc.TTrapPrm();
float Acc;
float Dec;
float Vel;
int pos;
short Smooth;
short loopNum;
short delayTime;
float.TryParse(tBVel.Text, out Vel);
float.TryParse(tBVel.Text, out Acc);
float.TryParse(tBDec.Text, out Dec);
short.TryParse(tBSmooth.Text, out Smooth);
short.TryParse(tBLoopNum.Text, out loopNum);
short.TryParse(tBDelayTime.Text, out delayTime);
int.TryParse(tBStep.Text, out pos);
double odlPrfPos = 0.0;
int lAxisStatus;
uint pClock;
double prfpos, encpos;
short i = 1;
if (PosDcmoth==0)
{
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
//commandhandler("GT_SetPrfPos", sRtn);
sRtn = gts.mc.GT_GetPrfPos(cardNum, axisNum, out odlPrfPos, 1,out pClock);
commandhandler("GT_SetPrfPos", sRtn);
pos = (int)(odlPrfPos )+ pos;
}
// 清除各轴的报警和限位
sRtn = gts.mc.GT_ClrSts(cardNum, axisNum, 1);
// 将 AXIS 轴设为 Jog 模式
sRtn = gts.mc.GT_PrfTrap(cardNum, axisNum);
commandhandler("GT_PrfTrap", sRtn);
// 读取 Jog 运动参数(需要读取全部运动参数到上位机变量)
sRtn = gts.mc.GT_GetTrapPrm(cardNum, axisNum, out setTrapPrm);
commandhandler("GT_GetTrapPrm", sRtn);
//设置需要修改的运动参数
setTrapPrm.acc = Acc;
setTrapPrm.dec = Dec;
setTrapPrm.smoothTime = Smooth;
setTrapPrm.velStart = 0;
// 设置 Jog 运动参数
sRtn = gts.mc.GT_SetTrapPrm(cardNum, axisNum, ref setTrapPrm);
commandhandler("GT_SetTrapPrm", sRtn);
// 设置 AXIS 轴的目标位置
sRtn = gts.mc.GT_SetPos(cardNum, axisNum, pos);
commandhandler("GT_SetPos", sRtn);
// 设置 AXIS 轴的目标速度
sRtn = gts.mc.GT_SetVel(cardNum, axisNum, Vel);
commandhandler("GT_SetVel", sRtn);
// 启动 AXIS 轴的运动
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1));
commandhandler("GT_Update", sRtn);
if ((PosDcmoth == 0) && (loopNum > 0))
{
while (runFlag)
{
sRtn = gts.mc.GT_GetSts(cardNum, axisNum, out lAxisStatus, 1, out pClock);
gts.mc.GT_GetPrfPos(cardNum, axisNum, out prfpos, 1, out pClock);//读取轴的规划位置
gts.mc.GT_GetEncPos(cardNum, axisNum, out encpos, 1, out pClock);//读取轴编码器位置
if (i <= loopNum)
{
if ((lAxisStatus & 0x400) != 0x400)
{
if ((int)(prfpos) == odlPrfPos)
{
Thread.Sleep(delayTime);
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
sRtn = gts.mc.GT_SetPos(cardNum, axisNum,pos);//设置轴的目标位置
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1)); //启动轴的运动
i++;
}
else if (prfpos == pos)
{
Thread.Sleep(delayTime);
//sRtn = gts.mc.GT_SetPrfPos(cardNum, axisNum, 0);
sRtn = gts.mc.GT_SetPos(cardNum, axisNum, (int)(odlPrfPos));
sRtn = gts.mc.GT_Update(cardNum, 1 << (axisNum - 1)); //启动轴的运动
i++;
}
}
}
}
}
}
int sts;
uint pClock;
double prfPos=0.000;
double encPos=0.000;
double prfVel = 0.000;
double encVel = 0.000;
private void timer1_Tick(object sender, EventArgs e)
{
gts.mc.GT_GetSts(cardNum, axisNum,out sts,1,out pClock);
// 伺服使能标志
if ((sts & 0x200)==0x200)
{
ledEnable.Checked = true;
}
else
{
ledEnable.Checked = false;
}
// 正向限位
if ((sts& 0x20)==0x20)
{
ledLimitP.Checked = true;
}
else
{
ledLimitP.Checked = false;
}
// 负向限位
if ((sts& 0x40)==0x40)
{
ledLimitN.Checked = true;
}
else
{
ledLimitN.Checked = false;
}
// 伺服报警标志
if ((sts & 0x2)==0x2)
{
ledAlarm.Checked = true;
}
else
{
ledAlarm.Checked = false;
}
// 跟随误差越限标志
if ( (sts & 0x10)==0x10)
{
ledMvErr.Checked = true;
}
else
{
ledMvErr.Checked = false;
}
// 规划器正在运动标志
if ((sts & 0x400)==0x400)
{
ledRun.Checked = true;
}
else
{
ledRun.Checked = false;
}
// 平滑停止
if ((sts & 0x80)==0x80)
{
ledsthStop.Checked = true;
}
else
{
ledsthStop.Checked = false;
}
// 急停标志
if ((sts & 0x100)==0x100)
{
ledAbruptStop.Checked = true;
}
else
{
ledAbruptStop.Checked = false;
}
gts.mc.GT_GetPrfPos(cardNum, axisNum, out prfPos, 1, out pClock);
lbPrfPos.Text = prfPos.ToString("0.000");
gts.mc.GT_GetEncPos(cardNum, axisNum, out encPos, 1, out pClock);
lbEncPos.Text = encPos.ToString("0.000");
gts.mc.GT_GetPrfVel(cardNum, axisNum, out prfVel, 1, out pClock);
lbPrfVel.Text = prfVel.ToString("0.000");
gts.mc.GT_GetEncVel(cardNum, axisNum, out encVel, 1, out pClock);
lbEncVel.Text = encVel.ToString("0.000");
}
private void btnInitCard_Click(object sender, EventArgs e)
{
short sRtn = 0;
// 打开运动控制器
sRtn = gts.mc.GT_Open(cardNum,0,1);
// 指令返回值检测,请查阅例程 3-1
commandhandler("GT_Open", sRtn);
// 复位运动控制器
sRtn = gts.mc.GT_Reset(cardNum);
commandhandler("GT_Reset", sRtn);
// 配置运动控制器
// 注意:配置文件取消了各轴的报警和限位
sRtn = gts.mc.GT_LoadConfig(cardNum,"test.cfg");
commandhandler("GT_LoadConfig", sRtn);
// 清除各轴的报警和限位
sRtn = gts.mc.GT_ClrSts(cardNum,1, 8);
commandhandler("GT_ClrSts", sRtn);
timer1.Start();
}
private void btnEnable_Click(object sender, EventArgs e)
{
short sRtn = 0;
if (btnEnable.Text=="伺服使能")
{ // 伺服使能
sRtn = gts.mc.GT_AxisOn(cardNum, axisNum);
commandhandler("GT_AxisOn", sRtn);
if(sRtn==0)
{
btnEnable.Text = "伺服关闭";
}
}
else
{
sRtn = gts.mc.GT_AxisOff(cardNum, axisNum);
commandhandler("GT_AxisOff", sRtn);
btnEnable.Text = "伺服使能";
}
}
private void btnZeroPos_Click(object sender, EventArgs e)
{
short sRtn = 0;
// 位置清零
sRtn = gts.mc.GT_ZeroPos(cardNum, axisNum,1);
commandhandler("GT_ZeroPos", sRtn);
}
private void btnNmove_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(new ThreadStart(TrapMove));
th1.IsBackground = true;
th1.Start();
}
private void btnPMove_Click(object sender, EventArgs e)
{
short sRtn;
sRtn = gts.mc.GT_Stop(cardNum, 1<<(axisNum-1), 0);
commandhandler("GT_Stop", sRtn);
runFlag = false;
}
}
}
好了,这样就可以实现GTS点位运动功能了。需要demo源码的宝子请到附件链接中下载。
我也是有底线哒~
© 版权声明
THE END
暂无评论内容