开放式激光振镜+运动控制器(三):振镜矫正

今天,正运动小助手大家分享一下运动控制器之ZMC420SCAN的控制振镜矫正

ZMC420SCAN硬件介绍


1.功能介绍

ZMC420SCAN总线控制器支持ECAT/RTEX总线连接,支持最多达20轴运动控制,支持直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴设置等;采用优化的网络通讯协议可以实现实时的运动控制。 ZMC420SCAN总线控制器支持脉冲轴/总线轴/振镜轴混合插补。

ZMC420SCAN系列运动控制器支持以太网,RS232通讯接口和电脑相连,接收电脑的指令运行,可以通过CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。

ZMC420SCAN系列运动控制卡的应用程序可以使用VC,VB,VS,C++,C#等软件来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试、方便观察。

2.硬件接口

通用输入口电路

通用输出口电路

本地脉冲轴说明

本地振镜轴接口说明

3.振镜控制过程

激光振镜是一种专门用于激光加工领域的特殊的运动器件,激光振镜头内包含的主要元件是激光发生器,两个电机和两个振镜片,它靠两个电机分别控制两个振镜片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项目并添加函数库

(1)在VS2015菜单“文件”→“新建”→ “项目”,启动创建项目向导。
(2)选择开发语言为“Visual C++”和程序类型“MFC应用程序”。

(3)点击下一步即可。

(4)选择类型为“基于对话框”,下一步或者完成。
(5)找到厂家提供的光盘资料,路径如下(64位库为例)。

A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。

B.选择“函数库2.1”文件夹。

C.选择“Windows平台”文件夹。

D.根据需要选择对应的函数库这里选择64位库。

E.解压C++的压缩包,里面有C++对应的函数库。

F.函数库具体路径如下。

(6)将厂商提供的C++的库文件和相关头文件复制到新建的项目里面。
(7)在项目中添加静态库和相关头文件。

A.先右击项目文件,接着依次选择:“添加”→“现有项”。

B.在弹出的窗口中依次添加静态库和相关头文件。

(8)声明用到的头文件和定义控制器连接句柄。

至此项目新建完成,可进行MFC项目开发。

2.查看PC函数手册,熟悉相关函数接口
(1)PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册 V2.1.pdf”


(2)链接控制器,获取链接句柄。

ZAux_OpenEth()接口说明:

指令7

ZAux_OpenEth

指令原型

int32  __stdcall  ZAux_OpenEth(char  *ipaddr, ZMC_HANDLE  * phandle)

指令说明

以太网链接控制器。

输入参数

输入参数1个,详细见下面说明。

ipaddr

链接的IP地址。

输出参数

输出参数1个,详细见下面说明。

Phandle

返回的链接句柄。

返回值

详细见错误码说明。

(3)振镜运动打包接口。
指令

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;    }    //链接成功开启定时器1    SetWindowText("已链接");    SetTimer( 1, 100, NULL );  }
(4)通过预矫正按钮的事件处理函数采用打包字符串的方式进行运行振镜运动轨迹,打标出一个未进行矫正出来的正方形轨迹。
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();}
(5)通过矫正按钮的事件处理函数获取编辑框测量出来实际的尺寸,并进行矫正打标出一个矫正后的尺寸图形。
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 here    if(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软件连接控制器对控制器状态进行监控

1.ZDevelop软件连接控制器监控控制器的状态,查看振镜轴对应参数,并可搭配示波器检测振镜轨迹。

设置振镜轴运动,首先需要将轴类型配置成21振镜轴类型,并对应配置振镜轴的速度加减速等参数才可操作振镜进行运动

将未矫正的时打出尺寸的实际尺寸测量出来,填入编辑框,执行矫正指令,数据写入对应table,利用table写入的实际尺寸与理论尺寸进行矫正处理,矫正完成重新测量应与理论尺寸一致。


2.通过ZDevelop软件的示波器监控振镜运动运行轨迹,并可监控到运行轨迹所用时间。

3.视频演示

本次,正运动技术开放式激光振镜+运动控制器(三):振镜矫正,就分享到这里。
更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936

  END 







类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理

在线客服
在线客服
QQ客服