The value of Zmotion is to bring customers more success!
VPLC711硬件介绍
VPLC711是正运动推出的一款基于x86平台和Windows操作系统的高性能机器视觉EtherCAT运动控制器,具备强大的运算能力和灵活性。它具有出色的实时性能和多路高速硬件输入与多路高速PSO输出,能够精准控制多轴同步运动,并与外部设备实现多协议的高速通信。
VPLC711支持多种硬件接口和通信协议,方便与其他设备的连接和集成。除此之外,VPLC711还具备视觉处理功能,能够实时处理图像数据,实现视觉检测、测量和定位等应用。
VPLC711内置Windows运动控制实时内核MotionRT7,形成一种开放式IPC形态实时软控制器/软PLC,为用户提供灵活集成的运动控制+视觉一体化解决方案。
1.采用x86高性能CPU,EtherCAT可支持1ms 64轴同步运行;
5.支持DVI-D,HDMI显示,支持双网口不同IP设置。
C#语言进行Delta并联机械手的开发之运动库和视觉库的添加
1.在VS2010菜单“文件”→“新建”→“项目”,启动创建项目向导。
3.找到厂家提供的光盘资料里面的C#函数库,路径如下(32位库为例)。
PC函数介绍
1.链接控制器,获取链接句柄。
Basic脚本快速验证指令用法
1.
编写Basic测试脚本进行MoveSync指令的用法测试。
'************************************************************************************** '背景:假设有一对对射型的光电传感器固定在流水线的两端,来实时检测流水线上的产品到位情况 'MOVESYNC指令参数填写说明: 'syncposition:物体到感应点时皮带轴的位置,需要通过编码器锁存把产品的对应位置记录下来。 'pos1:跟随轴1原点到光电传感器感应点的位置,对于每个产品都是固定的。 '************************************************************************************** GLOBAL CONST BeltAxis=4 '皮带轴是轴4 GLOBAL CONST FollowAxis1=0 '跟随轴1是轴0 GLOBAL CONST InducPos1=30 '跟随轴1原点到光电传感器感应点的位置 GLOBAL CONST StandbyPos1=50'跟随轴1的待机位 GLOBAL CONST EmptyPos1=400 '跟随轴1的放料位 '停止所有轴 RAPIDSTOP(2) WAIT IDLE '初始化相关轴的轴参数 BASE(FollowAxis1, BeltAxis) ATYPE = 1,1 UNITS = 1000,1000 SPEED = 50,100 DPOS = 0,0 '触发示波器采集波形 TRIGGER DELAY(1000) '跟随轴先运动到待机位 BASE(FollowAxis1) MOVEABS(StandbyPos1) '皮带轴开始运动 VMOVE(1) AXIS(BeltAxis) '假设皮带运动到200的位置时,有一个产品被检测到 BASE(FollowAxis1) Wait UNTIL MPOS(BeltAxis)> 200 MOVESYNC(0, 2000, 200, BeltAxis, InducPos1) '跟随轴加速同步段该指令执行完后将同步上产品 MOVE_OP(0, ON) '同步上后打开真空吸 MOVESYNC(0, 1000, 200, BeltAxis, InducPos1) '继续同步1s MOVESYNC(-1, 0, 0, -1, EmptyPos1) '走到放料位置 MOVE_OP(0, OFF) '到放料位后关闭真空吸
根据示波器的数据分析
2、跟随轴追上产品,并保持速度和皮带轴同步时皮带的位置是400,跟随轴1的位置是230。
3、由1和2可知,产品在同步过程中前进了200(400-200)。
4、因为跟随轴1原点到光电传感器感应点的位置InducPos1我们给的数据是30,所以在跟随轴1和皮带平行的情况下,皮带带着产品往前跑了200后,此时此刻跟随轴1原点到光产品的实际距离是230(200+30)。
C#例程建设之视觉流水线同步分拣
imode = -1,表示结束同步模式,可运动到指定的绝对位置,一般同步上抓取完物料后运动到放料位使用。
(2)参数synctime:同步时间,ms单位.运动在指定时间内完成,完成时轴跟皮带轴上物体保持速度一致。0表示根据运动轴的速度加速度来估计同步时间。
(3)参数syncposition:视觉或传感器识别到皮带是的产品时,皮带此时此刻的位置信息MPOS。
2.视觉流水线同步分拣流程图。
/************************************************************************************ '任务编号: 无 '函数功能: 视觉定位产品 'Input: 无 'Output: 无 '返回值: 子线程---进行视觉定位 **************************************************************************************/ public void RunSubTaskVisua() { int TempArrid = 0; float TempVar = 0; WriteLog("视觉功能正常启动"); while (SysRunFlag > 0) { //暂停按钮没有按下时 while (SysRunFlag == 1) { //采集图像 VisuaOper.CameAcquisition(); //进行模板匹配 RTDisplay.Image = VisuaOper.ShapeFind(); if (MainWindows.BeltMpos != 0)//如果采集照片的时候皮带编码器位置获取正常 { //操作MoveSyncBuff数据先加锁 while (true) { if (MainWindows.SetMoveSyncFlag == 0) { MainWindows.SetMoveSyncFlag = 1; break; } } //找到可以存储数据的数组起始下标 int ArrId = 0; for (int i = 0; i < 50; i++) { if (MainWindows.MoveSyncBuff[i, 0] == 0) { ArrId = i; break; } } //开始存储数据 一次匹配最多10个结果 TempArrid = ArrId; for (int i = 0; i < 10; i++) { //如果分数满足要求 if (MainWindows.VisionRst[i, 0] >= MainWindows.VisionScore) { int j; //如果有重复的目标需要剔除 for (j = 0; j < TempArrid; j++) { TempVar = MainWindows.VisionRst[i, 1] - MainWindows.BeltMpos - MainWindows.MoveSyncBuff[j, 1] + MainWindows.MoveSyncBuff[j, 4]; if (((TempVar) = -10)) { j = -10; break; } } if (j >= 0) { MainWindows.MoveSyncBuff[ArrId, 0] = 1; MainWindows.MoveSyncBuff[ArrId, 1] = MainWindows.VisionRst[i, 1]; //存储匹配结果的X坐标 MainWindows.MoveSyncBuff[ArrId, 2] = MainWindows.VisionRst[i, 2]; //存储匹配结果的Y坐标 MainWindows.MoveSyncBuff[ArrId, 3] = MainWindows.VisionRst[i, 3]; //存储匹配结果的角度偏移 MainWindows.MoveSyncBuff[ArrId, 4] = MainWindows.BeltMpos; //存储匹配到产品时,传送带的位置信息 ArrId = ArrId + 1; IdentiNum.Text = (Convert.ToInt32(IdentiNum.Text) + 1).ToString(); WriteLog("视觉目标:" + "(" + MainWindows.VisionRst[i, 1].ToString("0,0") + "," + MainWindows.VisionRst[i, 2].ToString("0,0") + ")"); } } //分数清空 MainWindows.VisionRst[i, 0] = 0; } //解锁 MainWindows.SetMoveSyncFlag = 0; } } Thread.Sleep(100); } }
/************************************************************************************ '任务编号: 无 '函数功能: 流水线同步分拣 'Input: 无 'Output: 无 '返回值: 无 **************************************************************************************/ public void RunSubTaskMotion() { float[] MoveSyncTemp = new float[5]; float TempMpos = 0; while (SysRunFlag > 0) { while (SysRunFlag == 1) { if (MainWindows.MoveSyncBuff[0, 0] == 1) { MainWindows.ZauxErr = zmcaux.ZAux_Direct_GetMpos(MainWindows.g_Handle, MainWindows.ConveyorAxisId, ref TempMpos); //如果编码器位置抓取正确 if (0 == MainWindows.ZauxErr) { //编码器往前运动了多少 TempMpos = TempMpos - MainWindows.MoveSyncBuff[0, 4]; //判断是否处于同步起始区 if (((MainWindows.MoveSyncBuff[0, 1] + TempMpos) >= MainWindows.SyncReX[0]) && ((MainWindows.MoveSyncBuff[0, 1] + TempMpos) <= MainWindows.SyncReX[1])) { WriteLog("开始同步抓取"); //取一组数据 MoveSyncTemp[0] = MainWindows.MoveSyncBuff[0, 1] ; //X MoveSyncTemp[1] = MainWindows.MoveSyncBuff[0, 2] ; //Y MoveSyncTemp[2] = MainWindows.GetBinHigt; //取料高度 MoveSyncTemp[3] = MainWindows.MoveSyncBuff[0, 3]; //Aanle MoveSyncTemp[4] = MainWindows.MoveSyncBuff[0, 4]; //Mpos //下发同步运动的指令 //0、复位输出口 zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 0); //1、先同步上传送带 zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 0, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp); //2、同步一段时间(关节轴有滞后) 50ms zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 50, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp); //3、打开真空吸嘴 zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 1); //4、同步一段时间 1500ms zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 700, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp); //5、同步段把Z轴提升到安全高度,选择轴到放料角度 MoveSyncTemp[2] = MainWindows.StandPos[2]; //取料高度 zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 100, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp); //4、解除同步去放料点 MoveSyncTemp[0] = MainWindows.EmptPos[0]; //X MoveSyncTemp[1] = MainWindows.EmptPos[1]; //Y MoveSyncTemp[2] = MainWindows.EmptPos[2]; //放料高度 MoveSyncTemp[3] = MainWindows.EmptPos[3]; //Aanle zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, -1, 0, 0, -1, 4, MainWindows.gVAxisList, MoveSyncTemp); //5、关闭真空吸嘴放料,Delay100ms zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 0); zmcaux.ZAux_Direct_MoveDelay(MainWindows.g_Handle, MainWindows.gVAxisList[0], 100); //6、去安全高度 MoveSyncTemp[0] = MainWindows.EmptPos[0]; //X MoveSyncTemp[1] = MainWindows.EmptPos[1]; //Y MoveSyncTemp[2] = MainWindows.StandPos[2]; //放料高度 MoveSyncTemp[3] = MainWindows.EmptPos[3]; //Aanle zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MoveSyncTemp); //操作MoveSyncBuff数据先加锁 while (true) { if (MainWindows.SetMoveSyncFlag == 0) { MainWindows.SetMoveSyncFlag = 1; break; } } //视觉匹配缓冲区数据往前覆盖 for (int k = 0; k < 49; k++) { MainWindows.MoveSyncBuff[k, 0] = MainWindows.MoveSyncBuff[k + 1, 0]; MainWindows.MoveSyncBuff[k, 1] = MainWindows.MoveSyncBuff[k + 1, 1]; MainWindows.MoveSyncBuff[k, 2] = MainWindows.MoveSyncBuff[k + 1, 2]; MainWindows.MoveSyncBuff[k, 3] = MainWindows.MoveSyncBuff[k + 1, 3]; MainWindows.MoveSyncBuff[k, 4] = MainWindows.MoveSyncBuff[k + 1, 4]; } //解锁 MainWindows.SetMoveSyncFlag = 0; //等待输出口打开 int TimeOut = 10000; TimeOut = 100000; //等待轴停止 int AxisIdle = 0; //轴停止状态 while (TimeOut > 0) { zmcaux.ZAux_Direct_GetIfIdle(MainWindows.g_Handle, MainWindows.gVAxisList[0], ref AxisIdle); if (AxisIdle == (-1)) { break; } Thread.Sleep(10); TimeOut = TimeOut - 10; } if (TimeOut MainWindows.SyncReX[1]) { //操作MoveSyncBuff数据先加锁 while (true) { if (MainWindows.SetMoveSyncFlag == 0) { MainWindows.SetMoveSyncFlag = 1; break; } } //视觉匹配缓冲区数据往前覆盖 for (int k = 0; k < 49; k++) { MainWindows.MoveSyncBuff[k, 0] = MainWindows.MoveSyncBuff[k + 1, 0]; MainWindows.MoveSyncBuff[k, 1] = MainWindows.MoveSyncBuff[k + 1, 1]; MainWindows.MoveSyncBuff[k, 2] = MainWindows.MoveSyncBuff[k + 1, 2]; MainWindows.MoveSyncBuff[k, 3] = MainWindows.MoveSyncBuff[k + 1, 3]; MainWindows.MoveSyncBuff[k, 4] = MainWindows.MoveSyncBuff[k + 1, 4]; } //解锁 MainWindows.SetMoveSyncFlag = 0; //如果视觉匹配缓冲区没有数据了 if (MainWindows.MoveSyncBuff[0, 0] == 0) { //Delta去待机位 zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MainWindows.StandPos); WriteLog("去待机位"); } } } } else { //Delta去待机位 zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MainWindows.StandPos); } Thread.Sleep(50); } //停止传送带 zmcaux.ZAux_Direct_Single_Cancel(MainWindows.g_Handle, MainWindows.ConveyorAxisId, 2); } }
本次,正运动技术C#之Delta并联机械手的视觉同步分拣,就分享到这里。
更多精彩内容请关注“ 正运动小助手 ”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。
正运动技术专注于运动控制技术研究和通用运动控制软硬件产品的研发,是国家级高新技术企业。正运动技术汇集了来自华为、中兴等公司的优秀人才,在坚持自主创新的同时,积极联合各大高校协同运动控制基础技术的研究,是国内工控领域发展最快的企业之一,也是国内少有、完整掌握运动控制核心技术和实时工控软件平台技术的企业。主要业务有:运动控制卡_运动控制器_EtherCAT运动控制卡_EtherCAT控制器_运动控制系统_视觉控制器__运动控制PLC_运动控制_机器人控制器_视觉定位_XPCIe/XPCI系列运动控制卡等等。