http://www.henanjusheng.com 2026-07-03 15:42 深圳市正運動技術(shù)有限公司
01 ZMC432-V2運動控制器介紹
ZMC432-V2高性能多軸運動控制器是一款兼容EtherCAT總線和脈沖型的獨立式運動控制器,自帶6軸本地差分脈沖軸,最多可擴展至32軸,能實現(xiàn)總線軸+脈沖軸混合插補的多軸運動控制場合。同時支持正運動遠(yuǎn)程顯示功能,能提供網(wǎng)絡(luò)組態(tài)顯示,可實時監(jiān)控和調(diào)整參數(shù)配置。

ZMC432-V2硬件功能特性:
(1)支持32軸運動控制(脈沖+EtherCAT總線),EtherCAT最小通訊周期可達(dá)125us。
(2)24路通用輸入、12路通用輸出,2路模擬量輸出(DA),其中包括2路高速輸入和2路高速輸出。
(3)6路差分脈沖軸輸出,總線軸、脈沖軸可混合插補。
(4)內(nèi)置多項實時性運動控制功能,例如視覺飛拍、多維PSO、高速位置鎖存,多軸同步運行等。
(5)可通過EtherCAT擴展模塊進(jìn)行IO硬件資源擴展,可擴展至4096個隔離輸入口和4096個隔離輸出口。
(6)具備豐富的運動控制功能,如點位運動、電子凸輪、直線插補、圓弧插補、連續(xù)軌跡加工。
(7)支持掉電檢測、掉電存儲,多種程序加密方式,能夠有效防止系統(tǒng)故障,保護(hù)項目工程文件數(shù)據(jù),并提高系統(tǒng)的可靠性。
(8)通過純國產(chǎn)IDE開發(fā)環(huán)境RTSys進(jìn)行項目開發(fā),可實時仿真、在線跟蹤以及診斷與調(diào)試,簡便易用,支持多種高級上位機語言聯(lián)合編程進(jìn)行二次開發(fā)。

02 內(nèi)容回顧
回顧上兩期推文,我們對CAD導(dǎo)圖和小線段速度前瞻的C#DEMO中的主要兩個功能:CAD導(dǎo)圖和運動前瞻設(shè)置做了詳細(xì)的介紹。這次我們回歸推文本身,對DEMO軟件框架進(jìn)行介紹。
往期內(nèi)容詳情點擊下方鏈接:
C#運動控制開源(一):CAD導(dǎo)圖和小線段速度前瞻的優(yōu)化之CAD導(dǎo)圖
C#運動控制開源(二): CAD導(dǎo)圖和小線段速度前瞻優(yōu)化
03 開發(fā)環(huán)境
?適用場景:需要CAD導(dǎo)圖給XY機臺做軌跡運動的場合都可以使用本DEMO測試。
?軟件平臺:使用Visual Studio C#(即Visual C#)開發(fā)。
04 DEMO界面和操作步驟介紹
一、軟件框架流程圖

二、主界面
打開軟件后首先顯示的是主界面,主要分為3個部分:
①工具欄提供控制器連接復(fù)位,CAD圖紙導(dǎo)入及編輯,參數(shù)界面跳轉(zhuǎn)等按鈕。
②中間部分用于顯示導(dǎo)入CAD文件后軌跡的顯示。
③右側(cè)操作界面則是用來操作各軸移動以及啟動加工,切換到BASIC或者G代碼標(biāo)簽則會顯示軌跡對應(yīng)的相關(guān)代碼。


三、工具欄
①連接控制器:點擊控制器→連接控制器彈出控制器連接界面,手動輸入控制器IP或者下拉框搜索,點擊連接即可連接對應(yīng)IP控制器,連接成功軟件標(biāo)題會顯示連接成功。


②導(dǎo)入CAD圖紙:點擊文件→打開彈出文件選擇界面,選擇對應(yīng)格式的CAD文件,成功導(dǎo)入后會將軌跡顯示出來。



③軌跡操作和優(yōu)化:CAD圖紙軌跡顯示后,可以進(jìn)行一些編輯操作。通過左鍵選取操作對應(yīng)的軌跡,右鍵進(jìn)行畫面移動。對應(yīng)編輯視圖中進(jìn)行軌跡優(yōu)化以及排序。對應(yīng)視圖中進(jìn)行顯示元素的選擇。



四、參數(shù)設(shè)置
①打開參數(shù)界面:點擊視圖→參數(shù)設(shè)置可以打開參數(shù)設(shè)置界面。


②設(shè)置軸參數(shù)和測試:可以在此頁面設(shè)置XYZU軸各軸參數(shù),以及進(jìn)行簡單的手動運動測試,確保軸運動沒有問題。
③前瞻參數(shù)設(shè)置:點擊前瞻參數(shù)標(biāo)簽頁,可以進(jìn)行前瞻參數(shù)的設(shè)置。

④加工參數(shù)設(shè)置:點擊加工參數(shù)標(biāo)簽頁,可以進(jìn)行加工參數(shù)的設(shè)置。

⑤保存參數(shù)設(shè)置:點擊參數(shù)保存按鈕,會將所有的設(shè)置保存到對應(yīng)exe所在目錄的para文件夾下,下次打開軟件會自動讀取參數(shù)并設(shè)置上去。

五、加工操作面板
①開啟加工:設(shè)置完參數(shù)后,可以在操作面板點擊啟動開始加工,同時記錄加工時間和目前狀態(tài)。對應(yīng)各軸坐標(biāo)和速度也會顯示出來,軌跡顯示視圖中也會把當(dāng)前末端加工位置顯示出來,方便觀察目前位置。如果加工中需要暫停和停止,點擊對應(yīng)按鈕即可。

②顯示生成代碼:點擊BASIC或者G代碼標(biāo)簽可以顯示當(dāng)前軌跡對應(yīng)的運行代碼,可以用來排查問題,或者復(fù)制到其它軟件中直接運行。


05
DEMO程序介紹
DEMO中把主要用到的重要程序分別放在了:
ZCadFn.cs,ZGCode.cs,ZmotionCard.cs
依次對應(yīng)CAD導(dǎo)圖,軌跡解析,運動控制三部分,方便大家使用學(xué)習(xí)。
ZCadFn.cs(CAD導(dǎo)圖解析與繪制)

該部分主要提供CAD導(dǎo)圖初始化與導(dǎo)入CAD圖紙獲取軌跡數(shù)據(jù),然后進(jìn)行圖形繪制的函數(shù)。
form1.cs中按照:初始化CAD→導(dǎo)入CAD文件→獲得軌跡數(shù)組→繪制軌跡的順序進(jìn)行調(diào)用。比如下方程序:
//導(dǎo)入CAD文件
if (!m_GloFn.m_ZCad.ZcadReadFile(strFilePath))
{
MessageBox.Show("導(dǎo)入文件失敗");
return;
}
//計算比例
if (!m_GloFn.m_ZCad.ZcadPicBoxMath(CadShow.Width, CadShow.Height))
{
MessageBox.Show("導(dǎo)入文件失敗");
return;
}
//獲取軌跡數(shù)組
if (!m_GloFn.m_ZCad.ZcadArrayGet())
{
MessageBox.Show("獲取軌跡失敗");
return;
}
//繪制一遍CAD
if (!m_GloFn.m_ZCad.ZcadShowPic(CadShow.Width, CadShow.Height, 坐標(biāo)系ToolStripMenuItem.Checked, 順序ToolStripMenuItem.Checked, 空移ToolStripMenuItem.Checked, 起點ToolStripMenuItem.Checked, 方向ToolStripMenuItem.Checked,XCurDpos,YCurDpos, UCurDpos))
{
MessageBox.Show("繪制失敗");
return;
}
ZGCode.cs.cs(數(shù)據(jù)轉(zhuǎn)化為G代碼或者BASIC代碼)
該部分主要提供將軌跡數(shù)據(jù)轉(zhuǎn)化成G代碼或者BASIC代碼格式的函數(shù)。

主界面上的代碼顯示就是通過該部分轉(zhuǎn)話后顯示到textbox控件中。
if (m_GloFn.m_ZmotionCard.m_bInited && m_GloFn.m_ZCad.m_bInited)
{
string basicCode = "";
string gcode = "";
ZGCode.CadArraytoCode(m_GloFn.m_ZCad.m_ZCad_ArrayInfo, ref basicCode, ref gcode, 僅處理選中圖形toolStripMenuItem.Checked,true, CadShow.Width, CadShow.Height);
txt_Basic.Text = basicCode;
txt_GCode.Text = gcode;
}
ZmotionCard.cs(運動控制測試和前瞻下發(fā))
該部分主要提供一些封裝好的軸運動控制函數(shù),以及以三次文件形式或者批量函數(shù)形式下發(fā)軌跡。

單軸控制界面時就是通過按鈕調(diào)用對應(yīng)的軸控制函數(shù)來實現(xiàn)JOG,定位,回原等測試功能。

按鈕調(diào)用代碼如下:
?回原:
private void btn_X_SingleHome_Click(object sender, EventArgs e)
{
SetAxisParaByCtr(); //先控件參數(shù)設(shè)置到實際軸參數(shù)
m_GloFn.m_ZmotionCard.AxisParaSet(); //讀取參數(shù)出來之后設(shè)置一遍到軸參數(shù)上
int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
int datumtype = m_GloFn.m_ZmotionCard.m_nAxis_X_DatumType;
float homespeed = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_DatumSpeed;
float creep = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_Creep;
bool ifbushome = m_GloFn.m_ZmotionCard.m_bAxis_X_BusDatum;
float homeoffset = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_DatumOffset;
m_GloFn.m_ZmotionCard.AxisHome(axisnum,datumtype,homespeed,creep,ifbushome,homeoffset);
}
?定位:
private void btn_X_Move_Click(object sender, EventArgs e)
{
SetAxisParaByCtr(); //先控件參數(shù)設(shè)置到實際軸參數(shù)
m_GloFn.m_ZmotionCard.AxisParaSet(); //讀取參數(shù)出來之后設(shè)置一遍到軸參數(shù)上
int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
float movesp = 0;
if (radio_X_LowSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_LowSpeed;
if (radio_X_NomalSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_NormalSpeed;
if (radio_X_HighSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_HighSpeed;
float movedis = Convert.ToSingle(tb_X_MoveDis.Text);
bool ifabsmove = cb_X_IfAbs.Checked;
if(ifabsmove) m_GloFn.m_ZmotionCard.AxisMoveAbs(axisnum,movesp,movedis);
else m_GloFn.m_ZmotionCard.AxisMove(axisnum, movesp, movedis);
}
?點動:
private void btn_X_RVmove_MouseDown(object sender, MouseEventArgs e)
{
SetAxisParaByCtr(); //先控件參數(shù)設(shè)置到實際軸參數(shù)
m_GloFn.m_ZmotionCard.AxisParaSet(); //讀取參數(shù)出來之后設(shè)置一遍到軸參數(shù)上
int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X; float movesp = 0;
if (radio_X_LowSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_LowSpeed;
if (radio_X_NomalSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_NormalSpeed;
if (radio_X_HighSp.Checked) movesp = (float)m_GloFn.m_ZmotionCard.m_dAxis_X_HighSpeed;
m_GloFn.m_ZmotionCard.AxisVmove(axisnum, false, movesp);
}
private void btn_X_RVmove_MouseUp(object sender, MouseEventArgs e)
{
int axisnum = m_GloFn.m_ZmotionCard.m_nAxis_X;
m_GloFn.m_ZmotionCard.AxisCancel(axisnum);
}
前瞻功能則是調(diào)用控制器前瞻初始化函數(shù)設(shè)置參數(shù)到控制器中,或者使用平滑函數(shù)前瞻將軌跡數(shù)據(jù)處理成平滑好的數(shù)據(jù)。
?控制器前瞻設(shè)置:
#region
控制器前瞻參數(shù)初始化
public bool RunParaIni()
{
//判斷控制卡是否初始化成功
if (!m_bInited)
return false; //-1代表初始化未成功
int iret = 0;
//控制器前瞻參數(shù)設(shè)置到主軸上
iret += zmcaux.ZAux_Direct_SetCornerMode(g_handle, m_nAxis_X, m_nCornerMode); CommandHandler("ZAux_Direct_SetCornerMode", iret); //Corner_Mode
iret += zmcaux.ZAux_Direct_SetMerge(g_handle, m_nAxis_X, 1); CommandHandler("ZAux_Direct_SetMerge", iret); //打開連續(xù)插補
iret += zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, m_nAxis_X, m_fLimitR); CommandHandler("ZAux_Direct_SetFullSpRadius", iret); //設(shè)置小圓限速半徑
StringBuilder cmdbuffack = new StringBuilder(2048);
iret += zmcaux.ZAux_Execute(g_handle, "SPLIMIT_RADIUS(" + m_nAxis_X.ToString() + ") = " + m_fLimitRMinSp.ToString(), cmdbuffack, 2048); CommandHandler("ZAux_Execute", iret);//小圓限速最小限速
iret += zmcaux.ZAux_Direct_SetZsmooth(g_handle, m_nAxis_X, m_fZsmooth); CommandHandler("ZAux_Direct_SetZsmooth", iret); //倒角半徑
iret += zmcaux.ZAux_Direct_SetDecelAngle(g_handle, m_nAxis_X, (float)((m_fDecelAngle / 180) * Math.PI)); CommandHandler("ZAux_Direct_SetDecelAngle", iret); //減速角
iret += zmcaux.ZAux_Direct_SetStopAngle(g_handle, m_nAxis_X, (float)((m_fStopAngle / 180) * Math.PI)); CommandHandler("ZAux_Direct_SetStopAngle", iret); //停止角
iret += zmcaux.ZAux_Direct_SetStartMoveSpeed(g_handle, m_nAxis_X, m_fXYSpeed); CommandHandler("ZAux_Direct_SetStartMoveSpeed", iret); //起始速度設(shè)置成加工速度
iret += zmcaux.ZAux_Direct_SetEndMoveSpeed(g_handle, m_nAxis_X, m_fXYSpeed); CommandHandler("ZAux_Direct_SetEndMoveSpeed", iret); //結(jié)束速度設(shè)置成加工速度
if (iret != 0) return false;
return true;
}
#endregion
?平滑前瞻函數(shù)處理:
#region
ZTrackSmooth函數(shù)平滑下發(fā)
public int SmoothByZTrackDown(double[] originalPos,ref float StartRDpos)
//public int SmoothByZTrackDown(ref float StartRDpos)
{
//判斷控制卡是否初始化成功
if (!m_bInited)
return -1; //-1代表初始化未成功
int iret = 0;
UInt32 pSmoothPointsNum = 0;
IntPtr pSmoothPoints = (IntPtr)0;
IntPtr parryLine = (IntPtr)0;
IntPtr parryForceSp = (IntPtr)0;
IntPtr parryLmtSp = (IntPtr)0;
IntPtr parryR = (IntPtr)0;
ZTrackSmooth.ZTS_Delete(pSmoothPoints);
ZTrackSmooth.ZTS_Delete(parryLine);
ZTrackSmooth.ZTS_Delete(parryForceSp);
ZTrackSmooth.ZTS_Delete(parryLmtSp);
ZTrackSmooth.ZTS_Delete(parryR);
//提出平滑后的軌跡
double[] SmoothPos = { };
double[] SmoothSpeed = { };
double[] SmoothLimSp = { };
double[] SmoothR = { };
if (m_dDiserr 0) //有設(shè)置非線性小圓限速
iret = ZTrackSmooth.ZTS_ContinueSmoothAndSpeed2(g_handle, originalPos, Convert.ToUInt16(originalPos.Length / 2), 2, m_dDiserr, m_dSplineDis, m_dCornerAccel, m_fXYSpeed, m_dLimitRArray, m_dLimitRSpArray, (uint)m_dLimitRArray.Length, out pSmoothPoints, out parryLine, out parryForceSp, out parryLmtSp, out parryR, ref pSmoothPointsNum);
else
iret = ZTrackSmooth.ZTS_ContinueSmoothAndSpeed2(g_handle, originalPos, Convert.ToUInt16(originalPos.Length / 2), 2, m_dDiserr, m_dSplineDis, m_dCornerAccel, m_fXYSpeed, new double[] { 0.1, m_fLimitR }, new double[] { m_fXYSpeed, m_fXYSpeed }, 2, out pSmoothPoints, out parryLine, out parryForceSp, out parryLmtSp, out parryR, ref pSmoothPointsNum);
//提出平滑后的軌跡
SmoothPos = new double[pSmoothPointsNum * 2];
SmoothSpeed = new double[pSmoothPointsNum];
SmoothLimSp = new double[pSmoothPointsNum];
SmoothR = new double[pSmoothPointsNum];
Marshal.Copy(pSmoothPoints, SmoothPos, 0, (int)(pSmoothPointsNum * 2));
Marshal.Copy(parryForceSp, SmoothSpeed, 0, (int)(pSmoothPointsNum));
Marshal.Copy(parryLmtSp, SmoothLimSp, 0, (int)(pSmoothPointsNum));
Marshal.Copy(parryR, SmoothR, 0, (int)(pSmoothPointsNum));
}
StringBuilder cmdbuffack = new StringBuilder(2048);
double rdpos = StartRDpos;
//下發(fā)平滑軌跡
for (uint i = 0; i < pSmoothPointsNum; i++)
{
float[] targetpos = new float[2];
targetpos[0] = (float)SmoothPos[i * 2 + 0];
targetpos[1] = (float)SmoothPos[i * 2 + 1];
float runspeed = m_fXYSpeed;
float limitspeed = m_fXYSpeed;
if (m_dDiserr >= 0)
{
runspeed = (float)SmoothSpeed[i];
limitspeed = (float)SmoothLimSp[i];
}
//計算該點需要轉(zhuǎn)的角度值
if (i < pSmoothPointsNum - 2 && i >= 0)
{
double moveangle = CalculateAngleWithX((float)SmoothPos[(i) * 2 + 0], (float)SmoothPos[(i) * 2 + 1], (float)SmoothPos[(i + 1) * 2 + 0], (float)SmoothPos[(i + 1) * 2 + 1]);
rdpos = MoveR(moveangle, StartRDpos);
}
StartRDpos = (float)rdpos;
if (m_b3FileDown) Z3pFile_LineString(targetpos[0], targetpos[1], rdpos, runspeed, limitspeed, i);
else Command_LineString(targetpos[0], targetpos[1], rdpos, runspeed, limitspeed, i);
}
ZTrackSmooth.ZTS_Delete(pSmoothPoints);
ZTrackSmooth.ZTS_Delete(parryLine);
ZTrackSmooth.ZTS_Delete(parryForceSp);
ZTrackSmooth.ZTS_Delete(parryLmtSp);
ZTrackSmooth.ZTS_Delete(parryR);
return iret;
}
#endregion
前瞻處理好后按照一定格式用三次文件或者批量函數(shù)下發(fā)到控制器中運行,流程可以直接參考自動線程的程序處理。
#region線程
public void Thread_Run()
{
WorkStart = DateTime.Now;
RunStatus = "自動運行中";
m_GloFn.m_ZmotionCard.AxisParaSet();
//讀取參數(shù)出來之后設(shè)置一遍到軸參數(shù)上
if (!m_GloFn.m_ZmotionCard.RunParaIni())
{
MessageBox.Show("前瞻參數(shù)設(shè)置失敗");
return;
}
//獲取軌跡數(shù)組
if (!m_GloFn.m_ZCad.ZcadArrayGet())
{
MessageBox.Show("獲取軌跡失敗");
return;
}
//如果皮帶跟隨
if (m_GloFn.m_ZmotionCard.m_bSync)
//開啟皮帶跟隨
{
if (m_GloFn.m_ZmotionCard.AxisBeltSync() != 0)
{
MessageBox.Show("皮帶跟隨失敗");
return;
}
}
//取消U軸插補速度計算
int iret = 0;
iret = zmcaux.ZAux_Direct_SetInterpFactor(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_VU, 0); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_SetInterpFactor", iret);
//記錄U軸坐標(biāo) float RDpos = 0;
iret = zmcaux.ZAux_Direct_GetDpos(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_U,ref RDpos); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_GetDpos", iret);
//解析軌跡下發(fā)
if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_Init(); //三次文件初始化
else m_GloFn.m_ZmotionCard.CommandIni();
List OriginalPos = new List(); double Pos_x1, Pos_x2, Pos_z1, Pos_y1, Pos_y2, Pos_z2;
double Pos_x1_2, Pos_x2_2, Pos_z1_2, Pos_y1_2, Pos_y2_2, Pos_z2_2;
bool ifsplit = false;
bool ifdownZ = false;
for (int i = 0; i < m_GloFn.m_ZCad.m_nZCad_ArrayLen; i++) //遍歷數(shù)組
{
Pos_x1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].x1;
Pos_x2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].x2;
Pos_z1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].z1;
Pos_y1 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].y1;
Pos_y2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].y2;
Pos_z2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].z2;
ifsplit = false;
if ((僅處理選中圖形toolStripMenuItem.Checked == true) && (m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nChoose == 0)) continue;
switch (m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nItemtype)
{
case ZmotionCad.ZCAD_ITEMTYPE_VECTLine: //線型
if ((m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i].m_nInVectFrist == 1) || (ifdownZ)) //是否軌跡起點起始
{
ifdownZ = false;
double StartAngle = m_GloFn.m_ZmotionCard.CalculateAngleWithX(Pos_x1, Pos_y1, Pos_x2, Pos_y2);
//下發(fā)空移落刀指令
if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_StartString(Pos_x1, Pos_y1, StartAngle, ref RDpos);
else m_GloFn.m_ZmotionCard.Command_StartString(Pos_x1, Pos_y1, StartAngle, ref RDpos);
OriginalPos.Clear();
//把起點存下來
OriginalPos.Add(Pos_x1);
OriginalPos.Add(Pos_y1);
}
OriginalPos.Add(Pos_x2); //記錄過程點
OriginalPos.Add(Pos_y2);
if (i + 1 < m_GloFn.m_ZCad.m_nZCad_ArrayLen)
{
Pos_x1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].x1;
Pos_x2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].x2;
Pos_z1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].z1;
Pos_y1_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].y1;
Pos_y2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].y2;
Pos_z2_2 = m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].z2;
//大于停止角就抬刀
if (Math.Abs(m_GloFn.m_ZmotionCard.CalculateAngle(Pos_x1, Pos_y1, Pos_x2, Pos_y2, Pos_x1_2, Pos_y1_2, Pos_x2_2, Pos_y2_2)) > m_GloFn.m_ZmotionCard.m_fStopAngle) ifsplit = true;
//判斷下個點是否空移點
if ((m_GloFn.m_ZCad.m_ZCad_ArrayInfo[i + 1].m_nInVectFrist == 1) || (ifsplit)) //下條運動為空移點,需要抬刀
{
if (ifsplit == false)
{
OriginalPos.Add(Pos_x2); //記錄過程點
OriginalPos.Add(Pos_y2);
}
//下發(fā)加工軌跡
m_GloFn.m_ZmotionCard.SmoothByZTrackDown(OriginalPos.ToArray(), ref RDpos);
//m_GloFn.m_ZmotionCard.SmoothByZTrackDown( ref RDpos);
//下發(fā)抬刀動作
if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_EndString(Pos_x2, Pos_y2);
else m_GloFn.m_ZmotionCard.Command_EndString(Pos_x2, Pos_y2);
if (ifsplit)
{
ifdownZ = true;
ifsplit = false;
}
}
}
if (i == m_GloFn.m_ZCad.m_nZCad_ArrayLen - 1)
{
//下發(fā)加工軌跡
m_GloFn.m_ZmotionCard.SmoothByZTrackDown(OriginalPos.ToArray(), ref RDpos);
//m_GloFn.m_ZmotionCard.SmoothByZTrackDown(ref RDpos);
//下發(fā)抬刀動作
if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_EndString(Pos_x2, Pos_y2);
else m_GloFn.m_ZmotionCard.Command_EndString(Pos_x2, Pos_y2);
if (ifsplit)
{
ifdownZ = true;
ifsplit = false;
}
}
break;
default:
break;
}
}
if (m_GloFn.m_ZmotionCard.m_b3FileDown) m_GloFn.m_ZmotionCard.Z3pFile_End(); //三次文件結(jié)束
//等待3次文件結(jié)束
while (true)
{
int runstatus = 0;
StringBuilder cmdbuffack = new StringBuilder(2048);
iret = zmcaux.ZAux_DirectCommand(m_GloFn.m_ZmotionCard.g_handle,$"?PROC_STATUS({m_GloFn.m_ZmotionCard.Z3P_FILE_TASK})", cmdbuffack,2048); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_DirectCommand", iret);
runstatus = Convert.ToInt16(cmdbuffack.ToString());
if (runstatus == 0) break;
}
//等待運動結(jié)束
while (true)
{
int idle = 0;
iret = zmcaux.ZAux_Direct_GetIfIdle(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_X, ref idle); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_GetIfIdle", iret);
if (idle != 0) break;
}
//如果皮帶跟隨
if (m_GloFn.m_ZmotionCard.m_bSync) //取消皮帶跟隨綁定
{
m_GloFn.m_ZmotionCard.beltsyncend();
}
//恢復(fù)U軸插補速度計算
iret = zmcaux.ZAux_Direct_SetInterpFactor(m_GloFn.m_ZmotionCard.g_handle, m_GloFn.m_ZmotionCard.m_nAxis_VU, 1); m_GloFn.m_ZmotionCard.CommandHandler("ZAux_Direct_SetInterpFactor", iret);
RunStatus = "待機";
}
教學(xué)視頻請點擊→C#運動控制開源(三): CAD導(dǎo)圖和小線段速度前瞻優(yōu)化的軟件框架
完整代碼獲取地址
▼

本次,正運動技術(shù)C#運動控制開源(三): CAD導(dǎo)圖和小線段速度前瞻優(yōu)化的軟件框架,就分享到這里。
更多精彩內(nèi)容請關(guān)注“正運動小助手”公眾號,需要相關(guān)開發(fā)環(huán)境與例程代碼,請咨詢正運動技術(shù)銷售工程師:400-089-8936。

正運動技術(shù)專注于運動控制技術(shù)研究和通用運動控制軟硬件產(chǎn)品的研發(fā),是國家級高新技術(shù)企業(yè)。正運動技術(shù)匯集了來自華為、中興等公司的優(yōu)秀人才,在堅持自主創(chuàng)新的同時,積極聯(lián)合各大高校協(xié)同運動控制基礎(chǔ)技術(shù)的研究。主要業(yè)務(wù)有:運動控制卡_運動控制器_EtherCAT運動控制卡_EtherCAT控制器_運動控制系統(tǒng)_視覺控制器__運動控制PLC_運動控制_機器人控制器_視覺定位_XPCIe/XPCI系列運動控制卡等等。