今天,正運動小助手為大家分享一下應(yīng)用C#開發(fā)一個多段連續(xù)插補的運動控制應(yīng)用。
我們主要從新建項目,添加函數(shù)庫講起,再了解PC函數(shù)使用,最后通過項目實戰(zhàn)——連續(xù)插補運動例程講解,來讓大家熟悉它的項目開發(fā)。
在正式學(xué)習(xí)之前,我們先了解一下正運動技術(shù)的運動控制卡ECI2418和ECI2618。這兩款產(chǎn)品分別是4軸,6軸運動控制卡。
ECI2418支持4軸脈沖輸入與編碼器反饋,板載24點輸入,16點輸出,2AD,2DA,支持手輪接口,其中特定輸出口支持高速PWM控制。
ECI2618支持6軸脈沖輸入與編碼器反饋,板載24點輸入,16點輸出,2AD,2DA,支持手輪接口,其中特定輸出口支持高速PWM控制。
ECI2418,ECI2618均使用同一套API函數(shù),均支持C、C++、C#、LabVIEW、Python、Delphi等開發(fā)語言,支持VC6.0、VB6.0、Qt、.Net等平臺,支持Windows、Linux、WinCE、iMac等操作系統(tǒng)。
以下是C#開發(fā)流程
新建MFC項目,添加函數(shù)庫。
1.在VS2015菜單“文件”→“新建”→ “項目” ,啟動創(chuàng)建項目向?qū)А?/strong>
2.選擇開發(fā)語言為“Visual C#”和.NET framework 4以及Windows 窗體應(yīng)用程序。
3.找到廠家提供的光盤資料里面的C#函數(shù)庫,路徑如下(64位庫為例):
1)進入光盤資料找到PC函數(shù)文件夾。
2)選擇函數(shù)庫2.1。
3)Windows平臺。
4)根據(jù)需要選擇對應(yīng)的函數(shù)庫這里選擇64位庫。
5)解壓C++的壓縮包,里面有C#對應(yīng)的函數(shù)庫。
6)函數(shù)庫具體路徑如下圖所示。
4.將廠商提供的C#的庫文件以及相關(guān)文件復(fù)制到新建的項目里面。
1)將zmcaux.cs文件復(fù)制到新建的項目里面中。
2)將zaux.dll和zmotion.dll文件放入bin\debug文件夾中。
5.用vs打開新建的項目文件,在右邊的解決方案資源管理器中點擊顯示所有,然后鼠標(biāo)右鍵點擊zmcaux.cs文件,點擊包括在項目中。
6.雙擊Form1.cs里面的Form1,出現(xiàn)代碼編輯界面,在文件開頭寫入 using cszmcaux,并聲明控制器句柄g_handle。
至此項目新建完成。
查看PC函數(shù)手冊,了解其用法。
1.PC函數(shù)手冊也在光盤資料里面,具體路徑如下。
2.PC編程,一般先根據(jù)控制器連接方式選擇對應(yīng)的連接函數(shù)連接控制器,返回控制器句柄。接著用返回的控制器句柄,實現(xiàn)對控制器的控制。
3.比如通過網(wǎng)口連接控制器,先使用ZAux_OpenEth()鏈接控制器,獲取控制器句柄handle。
項目應(yīng)用截圖
4.通過獲取到的控制器句柄handle,對控制器進行單軸運動控制。
5.通過獲取到的控制器句柄handle,進行多軸絕對插補運動。
int[] axislist = { 0, 1, 2, 3 }; //軸列表
float[] destdis = { 100, 100, 200, 100 }; //運動距離列表
zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
6.通過獲取到的控制器句柄handle,獲取控制器緩沖區(qū)剩余的緩沖數(shù)量。
//獲取存放直線的剩余緩沖
zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0,ref remin_buff);
//獲取存放空間圓弧的剩余緩沖,空間圓弧也是占緩沖最大的運動
zmcaux.ZAux_Direct_GetRemain_Buffer(g_handle,0, ref remin_buff);
項目實戰(zhàn)之連續(xù)插補運動例程講解。
1.例程以建立板卡的連接,執(zhí)行4段連續(xù)軌跡的加工為目標(biāo)。
2.例程簡易流程圖。
3.通過網(wǎng)口方式連接控制器,獲取控制器連接句柄。
//連接控制器
private void button_link_Click(object sender, EventArgs e)
{
if (g_handle != (IntPtr)0)
{
zmcaux.ZAux_Close(g_handle);//斷開連接
g_handle = (IntPtr)0;
}
zmcaux.ZAux_OpenEth(comboBox_IpList.Text, out g_handle);//連接控制器
if (g_handle != (IntPtr)0)
{
this.Text = "已連接";
timer1.Enabled = true;
//初始化軸參數(shù)
for (int i = 0; i < 4; i++)
{
zmcaux.ZAux_Direct_SetAtype(g_handle, i, 1);//軸類型 脈沖軸
zmcaux.ZAux_Direct_SetUnits(g_handle, i, 1);//脈沖當(dāng)量
}
}
else
{
MessageBox.Show("控制器鏈接失敗,請檢測IP地址!", "警告");
}
}
4.通過定時器1更新控制器軸0-3的位置和速度等信息。
//定時器刷新
private void timer1_Tick(object sender, EventArgs e)
{
int runstate = 0;
float[] curpos = new float[4];
float vspeed = 0;
int remin_buff = 0;
int curmark = 0;
//獲取軸位置
for (int i = 0; i < 4; i++)
{
zmcaux.ZAux_Direct_GetDpos(g_handle, i, ref curpos[i]);
}
//獲取軸運動狀態(tài)
zmcaux.ZAux_Direct_GetIfIdle(g_handle, 0, ref runstate);
//獲取插補運動合速度
zmcaux.ZAux_Direct_GetVpSpeed(g_handle, 0, ref vspeed);
//判斷存放直線的剩余緩沖
zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
//判斷當(dāng)前運動到第幾條運動,
zmcaux.ZAux_Direct_GetMoveCurmark(g_handle, 0, ref curmark);
label_pos.Text = "X:" + curpos[0] + " Y:" + curpos[1] + " Z:" + curpos[2] + " U:" + curpos[3];
label_state.Text = Convert.ToString(runstate == 0 ? " 運行狀態(tài):運行中" : " 運行狀態(tài):停止中");
label_vspeed.Text = "當(dāng)前速度:" + vspeed;
label_buff.Text = "剩余緩沖:" + remin_buff;
label_mark.Text = "當(dāng)前MARK:" + curmark;
}
5.通過啟動按鈕的事件處理函數(shù)來啟動插補運動。
//啟動按鈕
private void button_start_Click(object sender, EventArgs e)
{
int[] axislist = { 0, 1, 2, 3 }; //軸列表
float[] destdis = { 0, 0, 0, 0 }; //運動距離列表
int corner_mode = 0; //拐角模式
int merge_flag = 0; //連續(xù)插補
int iresult = 0; //PC函數(shù)返回值
int remin_buff = 0; //剩余直線緩沖數(shù)
if (checkBox1.Checked)
{
corner_mode = corner_mode + 2;
}
if(checkBox2.Checked)
{
corner_mode = corner_mode + 8;
}
if(checkBox3.Checked)
{
corner_mode = corner_mode + 32;
}
if (checkBox4.Checked)
{
merge_flag = 1;
}
//設(shè)置插補速度
zmcaux.ZAux_Direct_SetSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_sp.Text));
//設(shè)置插補加速度
zmcaux.ZAux_Direct_SetAccel(g_handle, axislist[0], Convert.ToSingle(textBox_acc.Text));
//設(shè)置插補減速度
zmcaux.ZAux_Direct_SetDecel(g_handle, axislist[0], Convert.ToSingle(textBox_dec.Text));
//設(shè)置連續(xù)插補
zmcaux.ZAux_Direct_SetMerge(g_handle, axislist[0], merge_flag);
//S曲線時間
zmcaux.ZAux_Direct_SetSramp(g_handle, axislist[0], Convert.ToSingle(SRAMP.Text));
//設(shè)置SP速度
zmcaux.ZAux_Direct_SetForceSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_for_sp.Text));
//設(shè)置拐角模式
zmcaux.ZAux_Direct_SetCornerMode(g_handle, axislist[0], corner_mode);
//開始減速角度,轉(zhuǎn)換為弧度
zmcaux.ZAux_Direct_SetDecelAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang1.Text) * 3.14 / 180));
//停止減速角度,轉(zhuǎn)換為弧度
zmcaux.ZAux_Direct_SetStopAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang2.Text) * 3.14 / 180));
//小圓半徑
zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, axislist[0], Convert.ToSingle(textBox_radio.Text));
//倒角
zmcaux.ZAux_Direct_SetZsmooth(g_handle, axislist[0], Convert.ToSingle(textBox_zsmooth.Text));
//設(shè)置MARK = 0 ,來通過讀取CURMARK實現(xiàn)判斷當(dāng)前執(zhí)行到那里
zmcaux.ZAux_Direct_SetMovemark(g_handle, axislist[0], 0);
//選擇base軸
zmcaux.ZAux_Direct_base(g_handle, 4, axislist);
zmcaux.ZAux_Trigger(g_handle);
//計算剩余直線緩沖數(shù)量
zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
while(remin_buff<4)
{
zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
System.Threading.Thread.Sleep(1); //1毫秒
}
//第一段插補運動
destdis[0] = Convert.ToSingle(destdis1_X.Text);
destdis[1] = Convert.ToSingle(destdis1_Y.Text);
destdis[2] = Convert.ToSingle(destdis1_Z.Text);
destdis[3] = Convert.ToSingle(destdis1_U.Text);
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸插補指令
//函數(shù)返回非0 則表示發(fā)送不成功,緩沖區(qū)可能滿了,重新發(fā)送
while (iresult != 0)
{
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
System.Threading.Thread.Sleep(1); //1毫秒
}
//第二段插補運動
destdis[0] = Convert.ToSingle(destdis2_X.Text);
destdis[1] = Convert.ToSingle(destdis2_Y.Text);
destdis[2] = Convert.ToSingle(destdis2_Z.Text);
destdis[3] = Convert.ToSingle(destdis2_U.Text);
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸插補指令
//函數(shù)返回非0 則表示發(fā)送不成功,緩沖區(qū)可能滿了,重新發(fā)送
while (iresult != 0)
{
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
System.Threading.Thread.Sleep(1); //1毫秒
}
//第三段插補運動
destdis[0] = Convert.ToSingle(destdis3_X.Text);
destdis[1] = Convert.ToSingle(destdis3_Y.Text);
destdis[2] = Convert.ToSingle(destdis3_Z.Text);
destdis[3] = Convert.ToSingle(destdis3_U.Text);
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸插補指令
//函數(shù)返回非0 則表示發(fā)送不成功,緩沖區(qū)可能滿了,重新發(fā)送
while (iresult != 0)
{
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
System.Threading.Thread.Sleep(1); //1毫秒
}
//第四段插補運動
destdis[0] = Convert.ToSingle(destdis4_X.Text);
destdis[1] = Convert.ToSingle(destdis4_Y.Text);
destdis[2] = Convert.ToSingle(destdis4_Z.Text);
destdis[3] = Convert.ToSingle(destdis4_U.Text);
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸插補指令
//函數(shù)返回非0 則表示發(fā)送不成功,緩沖區(qū)可能滿了,重新發(fā)送
while (iresult != 0)
{
iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
System.Threading.Thread.Sleep(1); //1毫秒
}
}
6.通過停止按鈕的事件處理函數(shù)來停止插補運動。
//停止運動
private void button_stop_Click(object sender, EventArgs e)
{
//取消主軸運動
zmcaux.ZAux_Direct_Single_Cancel(g_handle, 0, 2);
}
7.軸坐標(biāo)清零。
//坐標(biāo)清零
private void button_zero_Click(object sender, EventArgs e)
{
if (g_handle == (IntPtr)0)
{
MessageBox.Show("未鏈接到控制器!", "提示");
}
else
{
for (int i = 0; i < 4; i++)
{
zmcaux.ZAux_Direct_SetDpos(g_handle, i, 0);
}
}
}
8. 編譯運行演示。
編譯運行示教例程,同時通過ZDevelop軟件連接控制器,對運動控制的軸參數(shù)進行監(jiān)控。
9.連續(xù)插補加自動倒角的位置波形。
10.不開啟連續(xù)插補的速度波形。
11.連續(xù)插補加合適的拐角減速的速度波形。