所有设备的所有运动模式都需要一个参考零点,因此,所有设备都需要回零,并且设备工作的第一步就是要先完成回零。可见,回零是非常重要的,下面就手把手教你用C#写一个回零Demo。
1.创建项目
打开VS2022,新建一个项目。
2.引用动态库
2.1 运行项目生成debug文件夹
库文件要放到debug文件夹下,所以先运行一下项目就会在目录中生成对应的debug文件夹。注意如果选择的平台是指定为x86或者x64,那么在bin文件夹中还会生成x86或者x64,x86或者x64文件夹中同样会有debug文件夹,我们放库的时候要放到对的debug文件夹内。
假设选择编译平台位AnyCPU
假设选择的是x86编译平台
2.2 把库拷贝到对应的debug文件夹内
2.3 项目中引用gts.cs
3. 界面控件布局
下面主要以回零为例说明如何使用控件和调用GTS控制卡的指令,我们先往界面上拖一些我们需要的控件并完成显示设置和命名
使用到的控件主要有:
工具箱->公共控件:Button(按钮)、ComboBox(下拉列表框),TextBox(文本框)、RadioButton(单选按钮)、Lable(标签控件)
工具箱->容器:GroupBox(分组框)、Panel(排版控件)
4. 控件属性设置
4.1 控件命名和文字显示
选中控件,在属性窗口里找到Name属性,给控件命名,建议自己重新命名,我们程序里都是通过控件名访问控件的;找到Text属性,输入我们想让上显示的默认文字信息。
例如按钮的属性设置:
其他控件的命名和默认显示文字自行修改好。
4.2 下拉列表框添加内容
主要是卡号选择,轴号选择,回零模式选择几个下拉列表框,我们找到属性窗口里面的“数据”—>“items”,我们在里面添加内容,每一行是一个选项,以回零模式为例:
卡号和轴号同理。
4.3 单选按钮实现单选
我们把每一组单选按钮都放到一个Panel里面,我们要给每组单选按钮设置一个默认的选中状态,我们选中我们希望默然是选中状态的一个单选按钮,在属性窗口里找到Checked属性,设置为true即可,我们把回零方向的“正向”,index搜索方向的“负向”,捕获沿的“下降沿”默认设置Checked属性为true。
4.4 指令返回值显示控件设置
设置TextBox在打印时可以多行滚动打印,选中控件在属性窗口中的行为栏找到“Multiline”设置为true,在外观栏找到“ScrollBars”设置为Both。
5. 控件事件
5.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_GoHomeDemo
{
public partial class Form1 : Form
{
public short cardNum = 0;
public short axisNum = 1;
public Form1()
{
InitializeComponent();
cbCardNum.SelectedIndex = 0;
cbAxisNum.SelectedIndex=0;
cbHomeMode.SelectedIndex = 0;
// 设置单选按钮属性
rBtnHmDirN.Checked= true;
rBtnHmDirP.Checked = false;
indexSchDirN.Checked = false;
indexSchDirP.Checked = true;
rBtnUpEdge.Checked = false;
rBtnDownEdge.Checked = true;
LoadPictrue("limit.png");
}
......
}
卡号、轴号、回零模式选择实现逻辑:
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);
}
private void cbHomeMode_SelectedIndexChanged(object sender, EventArgs e)
{
switch((short)cbHomeMode.SelectedIndex)
{
case 0: HomeMode = 10;LoadPictrue("limit.png"); break;
case 1: HomeMode = 11; LoadPictrue("limit_home.png"); break;
case 2: HomeMode = 12; LoadPictrue("limit_index.png"); break;
case 3: HomeMode = 13; LoadPictrue("limit_home_index.png"); break;
case 4: HomeMode = 20; LoadPictrue("home.png"); break;
case 5: HomeMode = 22; LoadPictrue("home_index.png"); break;
case 6: HomeMode = 30; LoadPictrue("index.png"); break;
default: break;
}
}
5.2 回零方向、index搜索方向、捕获沿切换
选中单选按钮,在属性窗口选中闪电的图标,在里面找到“CheckedChange”双击就会生成单选按钮选中状态改变事件的函数。
我们同样先把回零方向、index搜索方向、捕获沿定义成全局变量。
/******回零方向的选择********/
short homeDir = 1;
private void rBtnHmDirN_CheckedChanged(object sender, EventArgs e)
{
if (rBtnHmDirN.Checked)
{
homeDir = 1;
rBtnHmDirP.Checked = false;
}
else
{
homeDir = -1;
rBtnHmDirP.Checked = true;
}
}
private void rBtnHmDirP_CheckedChanged(object sender, EventArgs e)
{
if (rBtnHmDirP.Checked)
{
homeDir = -1;
rBtnHmDirN.Checked = false;
}
else
{
homeDir = 1;
rBtnHmDirN.Checked = true;
}
}
/********index搜索方向的选择********/
short indexDir = -1;
private void indexSchDirN_CheckedChanged(object sender, EventArgs e)
{
if (indexSchDirN.Checked)
{
indexDir = 1;
indexSchDirP.Checked = false;
}
else
{
indexDir = -1;
indexSchDirP.Checked = true;
}
}
private void indexSchDirP_CheckedChanged(object sender, EventArgs e)
{
if (indexSchDirP.Checked)
{
indexDir = -1;
indexSchDirN.Checked = false;
}
else
{
indexDir = 1;
indexSchDirN.Checked = true;
}
}
/**********捕获沿的选择*********/
short edge = 0;
private void rBtnUpEdge_CheckedChanged(object sender, EventArgs e)
{
if (rBtnUpEdge.Checked)
{
edge = 1;
rBtnDownEdge.Checked = false;
}
else
{
edge =0;
rBtnDownEdge.Checked = true;
}
}
private void rBtnDownEdge_CheckedChanged(object sender, EventArgs e)
{
if (rBtnDownEdge.Checked)
{
edge = 0;
rBtnUpEdge.Checked = false;
}
else
{
edge = 1;
rBtnUpEdge.Checked = true;
}
}
5.3 按钮点击事件
双击按钮就会自动生成按钮点击事件函数,我们在函数里写我们要实现的逻辑,这部分自行查看代码,这里主要说一下回零按钮,回零因为启动回零后需要用一个do……while循环等待回零完成再清零,do……while如果直接放在按钮里执行,界面就会卡死,所以我们可以开一个线程执行,我们先定义一个回零函数:
public void GoHome()
{
short sRtn = 0;
gts.mc.THomePrm tHomePrm = new gts.mc.THomePrm();
gts.mc.THomeStatus tHomeSts = new gts.mc.THomeStatus();
float Acc;
float Dec;
float Vel;
float LowVel;
int homeOffset;
int homeLth;
int indexLth;
int escapeStep;
short Smooth;
//short loopNum;
short delayTime;
float.TryParse(tBVel.Text, out Vel);
float.TryParse(tBLowVel.Text, out LowVel);
float.TryParse(tBVel.Text, out Acc);
float.TryParse(tBDec.Text, out Dec);
short.TryParse(tBSmooth.Text, out Smooth);
//short.TryParse(tBDelay.Text, out loopNum);
short.TryParse(tBDelay.Text, out delayTime);
int.TryParse(tBStep.Text, out homeOffset);
int.TryParse(tBHomeSchLth.Text, out homeLth);
nt.TryParse(tBIndexSchLth.Text, out indexLth);
int.TryParse(tBEscapeStep.Text, out escapeStep);
//double odlPrfPos = 0.0;
//int lAxisStatus;
uint pClock;
double prfpos, encpos;
sRtn = gts.mc.GT_GetHomePrm(cardNum, axisNum, out tHomePrm);
commandhandler("GT_GetHomePrm", sRtn);
tHomePrm.mode = HomeMode;
tHomePrm.moveDir = homeDir;
tHomePrm.indexDir = indexDir;
tHomePrm.edge = edge;
tHomePrm.velHigh = Vel;
tHomePrm.velLow = LowVel;
tHomePrm.acc = Acc;
tHomePrm.dec = Dec;
tHomePrm.searchHomeDistance = homeLth;
tHomePrm.searchIndexDistance = indexLth;
tHomePrm.escapeStep = escapeStep;
sRtn = gts.mc.GT_GoHome(cardNum, axisNum, ref tHomePrm); //启动 Smart Home 回原点
commandhandler("GT_GoHome", sRtn);
do
{
sRtn = gts.mc.GT_GetHomeStatus(cardNum, axisNum, out tHomeSts); //获取回原点状态
} while (tHomeSts.run==1);
if ((tHomeSts.stage == 100) && (tHomeSts.error==0))
{
Thread.Sleep(delayTime);
sRtn = gts.mc.GT_ZeroPos(cardNum, axisNum, 1);
commandhandler("GT_ZeroPos", sRtn);
}
}
回零按钮点击事件:
private void btnGoHome_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(new ThreadStart(GoHome));
th1.IsBackground = true;
th1.Start();
}
6. 添加定时器定时刷新界面
int sts;
uint pClock;
double prfPos=0.000;
double encPos=0.000;
double prfVel = 0.000;
double encVel = 0.000;
int diValue;
int homeTemp;
gts.mc.THomeStatus pHomeStatus = new gts.mc.THomeStatus();
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)
{
ledHome.Checked = true;
}
else
{
ledHome.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");
gts.mc.GT_GetDi(cardNum, gts.mc.MC_HOME, out diValue);
homeTemp=(int)(1 << (axisNum - 1));
if ((diValue & homeTemp) ==homeTemp)
{
ledHome.Checked = true;
}
else
{
ledHome.Checked = false;
}
gts.mc.GT_GetHomeStatus(cardNum, axisNum, out pHomeStatus);
if(pHomeStatus.run==0)
{
lbHomeSts.Text="运动已停止";
}
else if(pHomeStatus.run==1)
{
lbHomeSts.Text = "正在回零";
}
switch (pHomeStatus.stage)
{
case 0: lbHomeStage.Text = "未启动回零"; break;
case 1: lbHomeStage.Text = "启动回零"; break;
case 2: lbHomeStage.Text = "正从原点或限位回退"; break;
case 10: lbHomeStage.Text = "正在搜索限位"; break;
case 11: lbHomeStage.Text = "触发限位停止"; break;
case 13: lbHomeStage.Text = "反向运动脱离限位"; break;
case 15: lbHomeStage.Text = "重新回到限位"; break;
case 16: lbHomeStage.Text = "重新回到限位停止"; break;
case 20: lbHomeStage.Text = "正在搜索Home"; break;
case 23: lbHomeStage.Text = "正准备从限位反向"; break;
case 25: lbHomeStage.Text = "正运动至home捕获位置"; break;
case 30: lbHomeStage.Text = "正在搜索Index"; break;
case 80: lbHomeStage.Text = "正在执行回原点过程"; break;
case 100: lbHomeStage.Text = "回原点结束"; break;
default: break;
}
switch (pHomeStatus.error)
{
case 0: lbHomeErr.Text = "未发生错误"; break;
case 1: lbHomeErr.Text = "回零的轴处于非点位模式"; break;
case 2: lbHomeErr.Text = "执行回零的轴未使能"; break;
case 3: lbHomeErr.Text = "执行回零的轴驱动报警"; break;
case 4: lbHomeErr.Text = "未完成回零"; break;
case 5: lbHomeErr.Text = "回原点阶段错误"; break;
case 6: lbHomeErr.Text = "模式错误"; break;
case 7: lbHomeErr.Text = "设置回零捕获模式失败"; break;
case 8: lbHomeErr.Text = "未找到Home"; break;
case 9: lbHomeErr.Text = "设置Index捕获模式失败"; break;
case 10: lbHomeErr.Text = "未找到Index"; break;
default: break;
}
}
教程到这里结束,需要Demo源码和PDF教程,请下载附件!
暂无评论内容