开放式激光振镜+运动控制器(三):振镜矫正
1.功能介绍
ZMC420SCAN总线控制器支持ECAT/RTEX总线连接,支持最多达20轴运动控制,支持直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴设置等;采用优化的网络通讯协议可以实现实时的运动控制。 ZMC420SCAN总线控制器支持脉冲轴/总线轴/振镜轴混合插补。
ZMC420SCAN系列运动控制器支持以太网,RS232通讯接口和电脑相连,接收电脑的指令运行,可以通过CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。
ZMC420SCAN系列运动控制卡的应用程序可以使用VC,VB,VS,C++,C#等软件来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试、方便观察。
本地振镜轴接口说明
激光振镜是一种专门用于激光加工领域的特殊的运动器件,激光振镜头内包含的主要元件是激光发生器,两个电机和两个振镜片,它靠两个电机分别控制两个振镜片X和Y反射激光,形成XY平面的运动,这两个电机使用控制器上的振镜轴接口控制。
激光振镜不同于一般的电机,激光振镜具有非常小的惯量,且在运动的过程中负载非常小,只需要带动反射镜片,系统的响应非常快。
振镜工作
ZMC420SCAN支持XY2-100振镜协议,支持运动控制与振镜联合插补运动。上位机通过网口与控制器相连,通过XY2-100振镜协议进行控制振镜轴的运动,通过总线协议或者脉冲模式控制伺服轴运动。
使用ZMC420SCAN控制器的振镜轴接口连接激光振镜头,每个振镜轴接口内包含两路振镜通道信号,分别控制振镜片X、Y的偏转,从而控制了激光打到工件的位置。
4.控制器PWM模拟量介绍
ZMC420SCAN的外部通用输出口0-11都具有PWM输出功能,PWM输出受正常输出功能的控制,只有输出口状态ON的时候PWM才能实际输出,这样可以用来控制激光能量。
ZMC420SCAN控制器存在两路模拟量输入输出,可进行控制激光器能量输出,模拟量精度为12位。
5.控制器基本信息
轴0-3为普通脉冲轴,振镜0为轴4、轴5控制振镜XY,振镜1为轴6、轴7控制XY。
C++进行振镜+运动控制开发
1.新建MFC项目并添加函数库
(3)点击下一步即可。
A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。
B.选择“函数库2.1”文件夹。
C.选择“Windows平台”文件夹。
D.根据需要选择对应的函数库这里选择64位库。
E.解压C++的压缩包,里面有C++对应的函数库。
F.函数库具体路径如下。
A.先右击项目文件,接着依次选择:“添加”→“现有项”。
B.在弹出的窗口中依次添加静态库和相关头文件。
至此项目新建完成,可进行MFC项目开发。
ZAux_OpenEth()接口说明:
|
指令7 |
ZAux_OpenEth |
|
指令原型 |
int32 __stdcall ZAux_OpenEth(char *ipaddr, ZMC_HANDLE * phandle) |
|
指令说明 |
以太网链接控制器。 |
|
输入参数 |
输入参数1个,详细见下面说明。 |
|
ipaddr |
链接的IP地址。 |
|
输出参数 |
输出参数1个,详细见下面说明。 |
|
Phandle |
返回的链接句柄。 |
|
返回值 |
详细见错误码说明。 |
| 指令 |
ZAux_Scan_3FileRamGetRemainSpace |
|
指令原型 |
int32 __stdcall ZAux_Scan_3FileRamGetRemainSpace ( ZMC_HANDLE handle, uint32 *premainbyte) |
|
指令说明 |
获取控制器能下载的最大文件大小 |
|
输入参数 |
输入参数1个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
输出参数 |
输出参数1个,详细见下面说明。 |
|
premainbyte |
获取下载的最大文件内容大小 |
| 指令 |
ZAux_Scan_3FileRamDownBegin |
|
指令原型 |
int32 __stdcall ZAux_Scan_3FileRamDownBegin(ZMC_HANDLE handle, uint32 *premainbyte) |
|
指令说明 |
开启文件下载到控制器的功能 |
|
输入参数 |
输入参数2个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
premainbyte |
下载到控制器的最大文件内容大小 |
|
输出参数 |
无 |
| 指令 |
ZAux_Scan_Motion3FileMem |
|
指令原型 |
int32 __stdcall ZAux_Scan_Motion3FileMem(ZMC_HANDLE handle, const char* pbuffer, uint32 buffsize) |
|
指令说明 |
打包字符串下载到控制器中 |
|
输入参数 |
输入参数3个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
pbuffer |
Basic指令的字符串内容,下载到控制器执行 |
|
buffsize |
下载的字符串长度 |
|
输出参数 |
无 |
| 指令 |
ZAux_Scan_Motion3FileRun |
|
指令原型 |
int32 __stdcall ZAux_Scan_Motion3FileRun(ZMC_HANDLE handle, int32 itasknum) |
|
指令说明 |
运行下载到控制器的字符串文件 |
|
输入参数 |
输入参数2个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
itasknum |
文件运行任务号 |
|
输出参数 |
无 |
| 指令 |
ZAux_Scan_3FileRamDownEnd |
|
指令原型 |
int32 __stdcall ZAux_Scan_3FileRamDownEnd(ZMC_HANDLE handle) |
|
指令说明 |
结束整个下载文件过程 |
|
输入参数 |
输入参数1个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
输出参数 |
无 |
| 指令 |
ZAux_Scan_Correct9 |
|
指令原型 |
int32 __stdcall ZAux_Scan_Correct9(ZMC_HANDLE handle, int nScanNum, float fCorrectBoxX, float fCorrectBoxY, float* nTablevalue); |
|
指令说明 |
进行振镜矫正处理 |
|
输入参数 |
输入参数1个,详细见下面说明。 |
|
ZMC_HANDLE |
连接句柄。 |
|
nScanNum |
当前矫正振镜号 |
|
fCorrectBoxX |
理论矫正X尺寸 |
|
fCorrectBoxY |
理论矫正Y尺寸 |
|
nTablevalue |
实际尺寸数据从先X再Y,先第一行(按列数存储),再下一行,注意此XY是实际的物理轴,第一个物理轴为X,第二个为Y,与轴号映射的虚拟轴轴号无关, |
|
输出参数 |
无 |
为了使得振镜运动能够高速的执行,采用打包所有文件下载到控制器的方式,提高振镜的运动速度,保证过程中振镜速度得到有效的提升,不会因为上位机下发过程跟不上控制器运动的情况,导致中间出现运动停止。
3.MFC开发控制器振镜运动例
(1)例程界面如下。
(2)操作流程。
首先使用预矫正按钮,在未进行矫正之前打标出一个设置尺寸的正方向,测量出正方向以中心为原点的九个点的坐标使用填入编辑框中,之后点击矫正按钮使用指令ZSCAN_CORRECT指令矫正大小,之后再打标出设置尺寸的正方形测量长度,比较是否与设置的尺寸打出一致。
(3)链接按钮的事件处理函数中调用链接控制器的接口函数ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器1监控控制器状态。
//网口链接控制器void CSingle_move_Dlg::OnOpen(){char buffer[256];int32 iresult;//如果已经链接,则先断开链接if(NULL != g_handle){ZAux_Close(g_handle);g_handle = NULL;}//从IP下拉框中选择获取IP地址GetDlgItemText(IDC_IPLIST,buffer,255);buffer[255] = '\0';//开始链接控制器iresult = ZAux_OpenEth(buffer, &g_handle);if(ERR_SUCCESS != iresult){g_handle = NULL;MessageBox(_T("链接失败"));SetWindowText("未链接");return;}//链接成功开启定时器1SetWindowText("已链接");SetTimer( 1, 100, NULL );}
void CTestCorrectDlg::OnBnClickedButtonTest(){// TODO: 在此添加控件通知处理程序代码ZScan_CancelCorrect(g_handle);MarkStart();CString str = "";int TheLength = 0;GetDlgItem(IDC_EDIT_THE)->GetWindowText(str);TheLength = atoi(str);_DOT3 GraphRect[5];for (int i = 0; i < 5; i++){if (i > 1 && i < 4){GraphRect[i].dbY = (float)TheLength / 2;}else{GraphRect[i].dbY = -(float)TheLength / 2;}if (i > 0 && i < 3){GraphRect[i].dbX = (float)TheLength / 2;}else{GraphRect[i].dbX = (float)-TheLength / 2;}}MarkVector(GraphRect, 5);//竖线_DOT3 p_CorrectVert[2];p_CorrectVert[0].dbX = 0;p_CorrectVert[0].dbY = (float)-TheLength / 2;p_CorrectVert[1].dbX = 0;p_CorrectVert[1].dbY = (float)TheLength / 2;MarkVector(p_CorrectVert, 2);//横线_DOT3 p_CorrectHori[2];p_CorrectHori[0].dbX = (float)-TheLength / 2;p_CorrectHori[0].dbY = 0;p_CorrectHori[1].dbX = (float)TheLength / 2;p_CorrectHori[1].dbY = 0;MarkVector(p_CorrectHori, 2);int num = 10;_DOT3 p_CorrectXline;p_CorrectXline.dbX = (float)TheLength / 2 - (float)TheLength / (2 * num);p_CorrectXline.dbY = (float)TheLength / 20;SetXline(p_CorrectXline, (float)TheLength / num);//打印Y字符_DOT3 p_CorrectYline;p_CorrectYline.dbX = (float)TheLength / (2 * num);p_CorrectYline.dbY = (float)TheLength / 2 - (float)TheLength / (2 * num);SetYline(p_CorrectYline, (float)TheLength / num);MarkEnd();}
void CTestCorrectDlg::OnBnClickedButtonCorrect(){int ret = 0;TODO: 在此添加控件通知处理程序代码float X1, X2, X3, X4, X5, X6;float Y1, Y2, Y3, Y4, Y5, Y6;CString cmdbuff = "";char cmdbuffAck[2048];CString str = "";GetDlgItem(IDC_EDIT_X1)->GetWindowText(str);X1 = atof(str);GetDlgItem(IDC_EDIT_X2)->GetWindowText(str);X2 = atof(str);GetDlgItem(IDC_EDIT_X3)->GetWindowText(str);X3 = atof(str);GetDlgItem(IDC_EDIT_X4)->GetWindowText(str);X4 = atof(str);GetDlgItem(IDC_EDIT_X5)->GetWindowText(str);X5 = atof(str);GetDlgItem(IDC_EDIT_X6)->GetWindowText(str);X6 = atof(str);GetDlgItem(IDC_EDIT_Y1)->GetWindowText(str);Y1 = atof(str);GetDlgItem(IDC_EDIT_Y2)->GetWindowText(str);Y2 = atof(str);GetDlgItem(IDC_EDIT_Y3)->GetWindowText(str);Y3 = atof(str);GetDlgItem(IDC_EDIT_Y4)->GetWindowText(str);Y4 = atof(str);GetDlgItem(IDC_EDIT_Y5)->GetWindowText(str);Y5 = atof(str);GetDlgItem(IDC_EDIT_Y6)->GetWindowText(str);Y6 = atof(str);float pfXMeasurePt[9] = {-X5,0,X6,-X3,0,X4,-X1,0,X2};float pfYMeasurePt[9] = { -Y2,-Y4,-Y6,0,0,0,Y1,Y3,Y5 };int TheLength = 0;GetDlgItem(IDC_EDIT_THE)->GetWindowText(str);TheLength = atoi(str);//调用矫正float nTableValue[18] = { -X5,-Y2,0,-Y4,X6,-Y6,-X3,0,0,0,X4,0,-X1,Y1,0,Y3,X2,Y5 };float LengthX = TheLength / 2;float LengthY = TheLength / 2;ret = ZAux_Scan_Correct9(g_handle, 0, TheLength, TheLength, nTableValue);MarkStart();GraphCorrectMove();MarkEnd();}
(6)通过断开按钮的事件处理函数来断开与控制卡的连接。
void CSingle_move_Dlg::OnClose() //断开链接{// TODO: Add your control notification handler code hereif(NULL != g_handle){KillTimer(1); //关定时器KillTimer(2);ZAux_Close(g_handle);g_handle = NULL;SetWindowText("未链接");}}
(7)在运动前进行设置对应的参数到控制器,并在数据加载后将所有字符串下载到控制器中对应运行。
int CTestCorrectDlg::MarkEnd(){int ret = 0;//打包字符串下载到控制器运行ret = ZAux_Scan_Motion3FileMem(g_handle, m_MoveStr, m_MoveStr.GetLength());//运行三次文件ret = ZAux_Scan_Motion3FileRun(g_handle, 2);ret = ZAux_Scan_3FileRamDownEnd(g_handle);m_MoveStr = "";return ret;}int CTestCorrectDlg::MarkStart(){int ret = 0;uint32 nRemain = 0;CString ParaStr = "";//获取控制能写入文件的最大大小ret = ZAux_Scan_3FileRamGetRemainSpace(g_handle, &nRemain);//启动三次文件下载ret = ZAux_Scan_3FileRamDownBegin(g_handle, &nRemain);//主轴号写入m_MoveStr = "base(4,5)\n";ParaStr.Format("ATYPE = %d,%d\n", m_Atype, m_Atype);m_MoveStr += ParaStr;ParaStr.Format("units = %d,%d\n", m_units, m_units);m_MoveStr += ParaStr;ParaStr.Format("merge = 1,1\n");m_MoveStr += ParaStr;ParaStr.Format("speed = %f,%f\n", (float)m_speed, (float)m_speed);m_MoveStr += ParaStr;ParaStr.Format("force_speed = %f,%f\n", (float)m_speed, (float)m_speed);m_MoveStr += ParaStr;ParaStr.Format("accel = %f,%f\n", (float)m_acc, (float)m_acc);m_MoveStr += ParaStr;ParaStr.Format("decel = %f,%f\n", (float)m_dec, (float)m_dec);m_MoveStr += ParaStr;return ret;}
完整代码获取地址
编译运行例程,同时通过ZDevelop软件连接控制器对控制器状态进行监控。
设置振镜轴运动,首先需要将轴类型配置成21振镜轴类型,并对应配置振镜轴的速度加减速等参数才可操作振镜进行运动。
将未矫正的时打出尺寸的实际尺寸测量出来,填入编辑框,执行矫正指令,数据写入对应table,利用table写入的实际尺寸与理论尺寸进行矫正处理,矫正完成重新测量应与理论尺寸一致。
3.视频演示
– END –
热门文章
