今天,正運(yùn)動(dòng)技術(shù)為大家分享一下應(yīng)用ZMC408SCAN開放式激光振鏡運(yùn)動(dòng)控制器的C++開發(fā),實(shí)現(xiàn)激光振鏡打標(biāo) ,可在文章末尾掃碼獲取例程源碼。
除了C++還支持使用其他上位機(jī)軟件來開發(fā),上位機(jī)程序運(yùn)行時(shí)需要?jiǎng)討B(tài)庫“zmotion.dll”,上位機(jī)開發(fā)調(diào)試時(shí)可以把ZDevelop軟件同時(shí)連接到控制器輔助調(diào)試。
01 ZMC408SCAN控制器介紹
ZMC408SCAN是正運(yùn)動(dòng)技術(shù)新推出的一款支持EtherCAT總線的開放式激光振鏡運(yùn)動(dòng)控制器,專為工業(yè)激光+振鏡+運(yùn)動(dòng)控制方面的應(yīng)用而設(shè)計(jì)。通過EtherCAT總線和脈沖軸接口能實(shí)現(xiàn)多軸聯(lián)動(dòng)運(yùn)動(dòng)控制。
ZMC408SCAN支持ETHERNET、EtherCAT、USB、CAN、RS485、RS232等通訊接口,通過CAN、EtherCAT總線可以連接各個(gè)擴(kuò)展模塊,從而擴(kuò)展數(shù)字量、模擬量或運(yùn)動(dòng)軸。
(1)ZMC408SCAN內(nèi)置高精度PSO位置同步輸出功能,在加工圓角、曲線部分時(shí)即使進(jìn)行了減速調(diào)整,在高速加工的場合,也能控制激光輸出的間距保持恒定;
(2)支持激光振鏡控制和振鏡反饋,包含2個(gè)振鏡接口,支持2D振鏡和3D振鏡,配合不帶加減速的運(yùn)動(dòng)指令MOVESCAN,拐角處振鏡加工自動(dòng)延時(shí),完成精準(zhǔn)高效的激光控制,提高激光加工設(shè)備的產(chǎn)能;
(3)通過指令在運(yùn)動(dòng)中靈活的調(diào)節(jié)激光開光/關(guān)光延時(shí),響應(yīng)快,精確到us級(jí)別的控制,且設(shè)置過程簡單,大大縮短了工程師的調(diào)參時(shí)間;
(4)自帶LASER激光器控制接口,支持IPG、YLR、YLS等類型激光電源,還帶一個(gè)EXIO擴(kuò)展IO接口,通過定制轉(zhuǎn)接板,靈活控制市場上主流的各種激光器;
(5)支持PC同時(shí)控制16個(gè)ZMC408SCAN控制器同時(shí)工作,形成一種振鏡陣列的激光加工;
(6)板載4路高速差分脈沖輸出,并帶4路高速差分編碼器反饋,支持EtherCAT總線驅(qū)動(dòng)器的控制,支持5軸XYZAC軸的插補(bǔ),支持振鏡軸與運(yùn)動(dòng)軸混合插補(bǔ)。
(7)支持直線插補(bǔ)、任意圓弧插補(bǔ)、空間圓弧、螺旋插補(bǔ)、電子凸輪、電子齒輪、同步跟隨、虛擬軸設(shè)置等多種運(yùn)動(dòng)控制功能。
02 系統(tǒng)架構(gòu)
下圖為ZMC408SCAN開放式激光 控制器的參考架構(gòu),支持多種不同類型的激光器控制。
03 上位機(jī)和控制器通訊
上位機(jī)和控制器通訊調(diào)用正運(yùn)動(dòng)封裝好的函數(shù)庫,提供運(yùn)動(dòng)控制和激光控制等眾多函數(shù)庫接口,激光振鏡的系統(tǒng)架構(gòu)參見下圖。
本例采用EtherNET網(wǎng)口連接控制器,通過函數(shù)ZAux_OpenEth()建立通訊連接,用戶可在設(shè)置好的界面中選擇當(dāng)前網(wǎng)段下的控制器IP完成連接,控制器出廠IP地址192.168.0.11,參見下圖。
04 激光控制
一、指令介紹
下面是我們程序中用到的接口函數(shù),主要包含激光控制和激光振鏡控制兩部分,程序的實(shí)現(xiàn)可直接使用封裝好的接口函數(shù)發(fā)送命令給控制器 。
本例采用FIBER激光器和2D激光振鏡,用到下面的函數(shù)接口:
ZAux_Direct_MoveScanAbs:振鏡軸多軸絕對直線插補(bǔ)SCAN運(yùn)動(dòng),不帶加減速過程,我們這里用來控制振鏡軸運(yùn)動(dòng),通過小線段的形式擬合圓形軌跡;
ZAux_Direct_MoveOpDelay:緩沖輸出延時(shí),提前開光時(shí)將延時(shí)時(shí)間設(shè)置為負(fù)數(shù);
ZAux_Direct_MoveDelay:緩沖輸出延時(shí),我們這里用來延時(shí)關(guān)光。
激光功率設(shè)置:提供模擬量ZAux_Direct_SetDA、PWM的占空比ZAux_Direct_SetPwmDuty和頻率ZAux_Direct_SetPwmFreq等方式控制設(shè)置振鏡軸拐角處自動(dòng)延時(shí):
ZAux_Direct_SetCornerMode
1.振鏡軸直線插補(bǔ)
ZAux_Direct_MoveScanAbs絕對運(yùn)動(dòng),ZAux_Direct_MoveScan相對運(yùn)動(dòng)。
2.設(shè)置開關(guān)光
輸出狀態(tài)為0關(guān)光,輸出狀態(tài)為1開光。
3. 開關(guān)光延時(shí)
4. 提前/延時(shí)開關(guān)光
正數(shù)時(shí)間延時(shí),負(fù)數(shù)時(shí)間提前開關(guān)光。
5. 設(shè)置激光能量(功率)
通過改變模擬量輸出的電壓值來控制激光能量大小。
6. PWM占空比
通過設(shè)置 PWM 的占空比來調(diào)整激光頻率,在開始打軌跡之前一定要先設(shè)置好。
7. PWM頻率
8. 振鏡軸拐角延時(shí)
9. 拐角延時(shí)起始角度
10. 拐角延時(shí)結(jié)束角度
二、程序流程
先建立控制器通訊,獲取連接句柄,激光器選擇及參數(shù)設(shè)置,然后編輯紅光與激光口控制開關(guān),運(yùn)動(dòng)參數(shù)設(shè)置,軌跡參數(shù)進(jìn)行小線段處理,開始運(yùn)動(dòng),停止運(yùn)動(dòng)。
三、主要程序展示
初始化定義相關(guān)變量,初始化軸參數(shù),配置好 FIBER 轉(zhuǎn)接板的方向?yàn)檩敵?,后續(xù)的激光軌跡加工控制由按鈕觸發(fā)。
在運(yùn)動(dòng)之前我們要設(shè)置好空移速度、打標(biāo)速度、開關(guān)光延時(shí)、軌跡圓半徑、標(biāo)刻行列數(shù)、圓心距等參數(shù)。運(yùn)動(dòng)開始直接調(diào)用這些相關(guān)參數(shù)執(zhí)行,獲取完軌跡后調(diào)用3次文件執(zhí)行。
1.初始化408FIBER轉(zhuǎn)換板針腳定義,不同激光器類型定義一套不同的輸出口,輸出口可以在選擇激光器類型后對應(yīng)在界面上進(jìn)行修改。
408 FIBER轉(zhuǎn)換板參數(shù)初始化程序:
void CZmc_fontToMoveDlg::OnCbnSelchangeComboLaser() { // TODO: 在此添加控件通知處理程序代碼 UpdateData(TRUE); if(m_nLaserType == FIBER_408) //408 FIBER轉(zhuǎn)換板參數(shù)設(shè)置 { char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $8FFFF)",cmdbuffAck,2048); m_nEnableIO = 47; //使能io m_nLaserIO = 8; //出關(guān)io m_nRedIO = 48; //紅光io m_nAout = 3; //功率io m_nPwmIo = 9; //頻率io } else if(m_nLaserType == YLR_408) { m_nEnableIO = 31; //使能io m_nLaserIO = 8; //出關(guān)io m_nRedIO = 32; //紅光io m_nAout = 2; //功率io m_nPwmIo = 9; //頻率io } else if(m_nLaserType == YAG_408) //408 YAG轉(zhuǎn)換板參數(shù)設(shè)置 { char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $AFBBF)",cmdbuffAck,2048); m_nEnableIO = 47; //使能io m_nLaserIO = 8; //出關(guān)io m_nRedIO = 48; //紅光io m_nAout = 3; //功率io m_nPwmIo = 9; //頻率io } else if(m_nLaserType == FIBER_504) //504 { m_nEnableIO = 5; //使能io m_nLaserIO = 6; //出關(guān)io m_nRedIO = 28; //紅光io m_nAout = 2; //功率io m_nPwmIo = 7; //頻率io } UpdateData(FALSE); }
2.設(shè)置拐角延時(shí)與激光功率,再調(diào)用運(yùn)動(dòng)執(zhí)行,程序如下。
void CZmc_fontToMoveDlg::OnBnClickedBtnMove() { // TODO: 在此添加控件通知處理程序代碼 UpdateData(TRUE); //設(shè)置拐角減速此ZSMOOTH為拐角延時(shí) int iresult = ZAux_Direct_SetCornerMode(m_Handle,SCAN_AxisX,2); //設(shè)置精準(zhǔn)輸出 iresult = ZAux_Direct_SetParam(m_Handle,"AXIS_ZSET",SCAN_AxisX,3); //設(shè)置拐角延時(shí) iresult = ZAux_Direct_SetZsmooth(m_Handle,SCAN_AxisX,m_nCorDelay); //設(shè)置拐角起始角度,減速時(shí)間在DecelAngle-StopAngle線性變化 iresult = ZAux_Direct_SetDecelAngle(m_Handle,SCAN_AxisX,0); //設(shè)置拐角結(jié)束角度 iresult = ZAux_Direct_SetStopAngle(m_Handle,SCAN_AxisX,90/180*3.1415926); //設(shè)置激光功率 iresult = ZAux_Direct_SetDA(m_Handle,m_nAout,m_nAoutVal); //設(shè)置激光頻率 iresult = ZAux_Direct_SetPwmDuty(m_Handle,m_nPwmIo,0.5); iresult = ZAux_Direct_SetPwmFreq(m_Handle,m_nPwmIo,m_nPwmFreq); //獲取軌跡數(shù)據(jù),(0,0)為圓外接起點(diǎn),5*5間距畫半徑為5的小圓 Cal_WorkData(m_fStartX, m_fStartY, m_nStepDis, m_nColNum, m_nRowNum, m_fRadius); Run_3FileMode(); }
3.圓弧轉(zhuǎn)小線段是將我們的設(shè)置的圓弧軌跡轉(zhuǎn)換為小線段存起來,然后轉(zhuǎn)換后由3次文件的形式加載執(zhí)行。
圓弧轉(zhuǎn)小線段程序如下:
void CZmc_fontToMoveDlg::Cal_WorkData(float fStartX, float fStartY, float iStepDis, int iColNum, int iRowNum, float fRadius) { //圓弧轉(zhuǎn)小線段 int ilen = -1; double ArcX; double ArcY; //獲取單個(gè)整圓轉(zhuǎn)換長度 int iret = ZMotionOptimize_TransArcSeges(m_Handle,fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, &ArcX, &ArcY, &ilen); if (iret != 0 || ilen < 0) { CString StrErr; StrErr.Format("圓弧轉(zhuǎn)小線段失敗錯(cuò)誤碼:%d",iret); MessageBox(StrErr); return; } double *ArcToLineX; double *ArcToLineY; ArcToLineX = (double*)malloc(sizeof(double)*ilen); ArcToLineY = (double*)malloc(sizeof(double)*ilen); //獲取數(shù)據(jù) iret = ZMotionOptimize_TransArcSeges(m_Handle, fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, ArcToLineX, ArcToLineY, &ilen); //軌跡總長度 m_GraphTotalLen = ilen * iColNum * iRowNum; m_GraphData = (struct_GraphPos*)malloc(sizeof(struct_GraphPos)*m_GraphTotalLen); //申請分配內(nèi)存 //填寫數(shù)據(jù) int iAcr = 0; for (int icol = 0; icol < iColNum ; icol++) { for(int irow = 0 ;irow
4.這里程序完成空移,然后移動(dòng)完成之前,如果下一條運(yùn)動(dòng)指令執(zhí)行的是軌跡運(yùn)動(dòng),那么提前將激光打開。
//空移到打標(biāo)點(diǎn)起始點(diǎn) void CZmc_fontToMoveDlg::Zscan_Z3pFile_StartString(struct_GraphPos *iGraphData) { char cmdbuff[2048] = ""; char tempbuff[2048] = ""; //生成命令 sprintf(tempbuff, "BASE(%d,%d)n",SCAN_AxisX,SCAN_AxisY); //設(shè)置打標(biāo)軸 strcat(cmdbuff, tempbuff); //空移到起點(diǎn) sprintf(tempbuff, "FORCE_SPEED = %fn",m_dEmpSpeed); //設(shè)置空移速度 strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)n",(*iGraphData).fposx,(*iGraphData).fposy); //移動(dòng) strcat(cmdbuff, tempbuff); //設(shè)置提前開光 if (m_nStartDelay < 0) //提前出光 { sprintf(tempbuff, "MOVEOP_DELAY = %fn",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVE_DELAY(%f)n",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } //開光 sprintf(tempbuff, "MOVE_OP(%d,1)nMOVE_DELAY(10)nMOVE_OP(%d,1)n",m_nEnableIO,m_nLaserIO); strcat(cmdbuff, tempbuff); //判斷命令長度是否發(fā)送 strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down(); } //生成打標(biāo)直線段字符串 void CZmc_fontToMoveDlg::Zscan_Z3pFile_LineString(struct_GraphPos *iGraphData) { char cmdbuff[2048] = ""; char tempbuff[2048] = ""; //生成命令 //空移到起點(diǎn) sprintf(tempbuff, "FORCE_SPEED = %fn",m_dSpeed); //設(shè)置打標(biāo)速度 strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)n",(*iGraphData).fposx,(*iGraphData).fposy); //移動(dòng) strcat(cmdbuff, tempbuff); //判斷命令長度是否發(fā)送 strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down(); }
5.延時(shí)關(guān)光是在打標(biāo)軌跡完成后,將激光延時(shí)關(guān)閉。
延時(shí)關(guān)光程序如下:
void CZmc_fontToMoveDlg::Zscan_Z3pFile_EndString(struct_GraphPos *iGraphData) { char cmdbuff[2048] = ""; char tempbuff[2048] = ""; //生成命令 sprintf(tempbuff, "FORCE_SPEED = %fn",m_dEmpSpeed); //設(shè)置空移速度 strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)n",(*iGraphData).fposx,(*iGraphData).fposy); //移動(dòng) strcat(cmdbuff, tempbuff); //延時(shí)關(guān)光 if(m_nLastDelay >0) { //延時(shí)關(guān)光 sprintf(tempbuff, "MOVEOP_DELAY = 0nMOVE_DELAY(%f)n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVEOP_DELAY = %fn",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } //關(guān)光 sprintf(tempbuff, "MOVE_OP(%d,OFF)n",m_nLaserIO); strcat(cmdbuff, tempbuff); //判斷命令長度是否發(fā)送 strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down(); }
四、最終效果
首先點(diǎn)擊下拉框選擇控制器IP,點(diǎn)擊連接,依次設(shè)置好激光器參數(shù)、運(yùn)動(dòng)參數(shù),設(shè)置好后輸入打軌跡的參數(shù),點(diǎn)擊運(yùn)動(dòng)開始打圓形軌跡,點(diǎn)擊停止結(jié)束。
通過 Z develop 軟件的示波器采樣運(yùn)動(dòng)結(jié)果:先從其他位置空移到起始位置,然后提前 1ms 開光,走完一個(gè)圓形軌跡,關(guān)閉激光(延時(shí)關(guān)光),再空移到下一個(gè)圓形軌跡的起點(diǎn),開光(提前 1ms 開光) , 又走完一個(gè)軌跡后,關(guān)光(延時(shí) 5ms 關(guān)光),如此循環(huán)執(zhí)行,直到設(shè)置的行列數(shù)打完停止(打軌跡中也能點(diǎn)擊停止)。
XY模式下的軌跡,軌跡包括了圓形打標(biāo)軌跡和空走軌跡:
本次,正運(yùn)動(dòng)技術(shù)開放式激光振鏡運(yùn)動(dòng)控制器:C++快速開發(fā),就分享到這里。
審核編輯:湯梓紅
-
控制器
+關(guān)注
關(guān)注
112文章
16197瀏覽量
177395 -
C++
+關(guān)注
關(guān)注
22文章
2104瀏覽量
73487 -
EtherCAT總線
+關(guān)注
關(guān)注
5文章
70瀏覽量
5366
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論