c#读取XML文件实现晶圆wafermapping显示demo计算电机坐标控制电机移动

c#读取XML文件实现晶圆wafermapping显示

功能:

1.读取XML文件,显示mapping图

2.在mapping视图图标移动,实时查看bincode,x,y索引与计算的电机坐标

3.通过设置wafer放在平台的位置x,y轴电机编码值,相机在wafer的中心位置,计算出所有芯片的电机坐标。 

4.mapping视图中,通过注册鼠标事件后,左键返回电机坐标,中键返回x,y索引值,右键返回索引值

5.通过2个左右对位点,计算dieszie宽,比实际xml文件的diesize精度更高。

6.电机移动每颗芯片的电机坐标,视图分析结果后,可修改对应坐标bincode的结果--

7.通过索引查询bincode的结果

8.计算wafer每颗芯片的电机坐标--则可按数组的值进行移动检测每颗芯片,

9.通过索引获取电机坐标

10.保存修改结果后的xml文件

11.显示局部预览图

 

6.通过2个上下对位点,计算dieszie高,比实际xml文件的diesize精度更高。

代码使用电机每个脉冲1um进行示范,所以移动精度更高

初始化:通过预设的wafer中心坐标(镜头视觉显示wafer的中心位置)与xml文件路径,完成mapping的初始化

private void button_initia_Click(object sender, EventArgs e){//Mapping mapping = new Mapping();mapping2.CloseWindow();int x_axis_pulse = int.Parse(textBox_motor_value_x.Text); //wafer中心坐标xint y_axis_pulse = int.Parse(textBox_motor_value_y.Text); //wafer中心坐标yPoint2d[] points_die_size = new Point2d[] { new Point2d(x_axis_pulse, y_axis_pulse), new Point2d(27, 106), new Point2d(1238, 102) } ;Point2d motor_xy_loc = points_die_size[0]; //wafer中心坐标(x与y轴电机脉冲),确定实际值后,一般不会变化。wafer在卡环中心,卡环每次放置的位置固定不变double theta = mapping2.GetTheta(points_die_size[1], points_die_size[2]);//默认,初始校准可忽略mapping2.Calibrate(motor_xy_loc, default(OpenCvSharp.Point)/*new Point(55, 82)*/, theta, textBox_xml_path.Text);AddToLogInfo("已完成初始化");button_set_result.Enabled = true;//button_to_txt.Enabled = true;button_to_XML.Enabled = true;button_get_result.Enabled = true;button_get_index_motor_loc.Enabled = true;}

 

校准:

 传入参数:

鼠标在mapping视图中移动到对位点,显示xy的索引与初始的电机坐标

参考参数注释 

 /// <summary>/// duiwei_mapping指的行列/// </summary>/// <param name="duiwei_coord ">移动x,y轴,相机显示对位点后,对准到芯片中心位置,记录电机的实际值编码值脉冲值</param>/// <param name="duiwei_mapping">mapping视图的显示比如32,225</param>/// <param name="theta">默认</param>/// <param name="芯片间距">xml的芯片尺寸,宽盒高</param>/// <param name="path_xml">xml文件的路径</param>public void Calibrate(Point2d duiwei_coord, Point duiwei_mapping, double theta, Size2d 芯片间距, string path_xml){mapping.Calibrate(duiwei_coord, duiwei_mapping, theta, 芯片间距, path_xml);}

相机镜头下看到的对位点,移动xy轴把红色十字对准芯片中心,记录电机编码脉冲值。 

 

 依次传入参数:(电机实际值,mapping图索引值,默认角度,xml文件的diesize,xml文件路径)

即可完成校准

 

  private void button_cali_Click(object sender, EventArgs e){var p1 = new Point2d(27, 92);var p2 = new Point2d(1238, 73);var theta = mapping2.GetTheta(p1, p2);//  mapping2.Calibrate(new Point2d(-361129, -351128), new Point(50, 17), 0, @"D:\APS_Work\Work_Project\芯片切割道检测\program\WinFormsApp1\mapping融合\2KG026075JL-0.xml");// mapping.Show();// mapping.MouseMiddleClick += (coord) =>//{//mapping.SetResult(new Point(coord[0], coord[1]), 5);// };string die_size_w = textBox_die_size_w.Text; //已知实际尺寸-宽string die_size_h = textBox_die_size_h.Text; 已知实际尺寸-高string duiwei_x = textBox_duiwei_motor_loc_x.Text; //第一个对位点x  //电机x轴实际脉冲,通过读取PLC得到string duiwei_y = textBox_duiwei_motor_loc_y.Text; //第一个对位点y //电机y轴实际脉冲,通过读取PLC得到int xx_loc = Convert.ToInt32(duiwei_x);int yy_loc = Convert.ToInt32(duiwei_y);//mapping文件的x,y坐标OpenCvSharp.Point point_xy_row_colomn = new OpenCvSharp.Point(int.Parse(textBox_duiwei_index_x.Text), int.Parse(textBox_duiwei_index_y.Text));//获取xy,行列OpenCvSharp.Point2d motor_point2D_loc = new OpenCvSharp.Point2d(xx_loc, yy_loc);mapping2.Calibrate(motor_point2D_loc, point_xy_row_colomn, 0.1/*jog_mapping.d_wafer_angle*/, new Size2d(double.Parse(die_size_w), double.Parse(die_size_h)), textBox_xml_path.Text);AddToLogInfo("已校准");}

显示mapping图

  private void button_show_mapping_Click(object sender, EventArgs e){// CloseMappingProcess();//Task.Run(() =>// {try{mapping2.mapping_show();}catch (Exception ex){AddToLogInfo("请先初始化,再执行校准");MessageBox.Show("请先初始化,再执行校准");MessageBox.Show("请标定" + ex.Message + ex.StackTrace);}//  });}

批量设置结果:

 指定修改对应值:mapping中:NG对应05,OK对应01

 private void button_modify_Click(object sender, EventArgs e){// FindAndKillWindow("mapping");//  mapping2.GetImgQualityScore("test11.jpg",0);Thread.Sleep(500);int ind_x = int.Parse(textBox_x.Text);int ind_y = int.Parse(textBox_y.Text);bool b_value = false;if(comboBox_result.Text.Trim()==""){AddToLogInfo("请选择结果");MessageBox.Show("请选择结果","tips",MessageBoxButtons.OK,MessageBoxIcon.Information);return;}if(comboBox_result.Text == "OK"){mapping2.SetResult(new Point(ind_x, ind_y), 01);}else{mapping2.SetResult(new Point(ind_x, ind_y), 05);}AddToLogInfo("设置结果:" + comboBox_result.Text);button_show_mapping.PerformClick();}

 获取指定坐标点结果:

private void button_get_result_Click(object sender, EventArgs e){//FindAndKillWindow("mapping");//  mapping2.GetImgQualityScore("test11.jpg",0);Thread.Sleep(500);int ind_x = int.Parse(textBox_x.Text);int ind_y = int.Parse(textBox_y.Text);textBox_get_result.Text = mapping2.GetBinCode(ind_x,ind_y).ToString();AddToLogInfo("已获取结果:"+textBox_get_result.Text);}

计算所有芯片的电机坐标:

private void button_calc_all_loc_Click(object sender, EventArgs e){point2Ds_calc = GetMotorLocation(0, 0, 0, 0);}
private OpenCvSharp.Point2d[,] GetMotorLocation(int xx, int yy, int width2, int height2){//  int xx = Convert.ToInt32(loc_x);//  int yy = Convert.ToInt32(loc_y);//OpenCvSharp.Point point_loc = new OpenCvSharp.Point(xx, yy);//Size size2 = new Size(width2, height2);OpenCvSharp.Point2d[,] motor_loc = mapping2.AllCoord();//.GetMotoCoord(point_loc, size2);return motor_loc;}

通过索引获取电机坐标:

得到了电机坐标,则可进行电机移动,对每颗芯片进行图像采集与分析,修改对应的结果

private void button_get_index_motor_loc_Click(object sender, EventArgs e){button_calc_all_loc.PerformClick();int x = int.Parse(textBox_x.Text);int y = int.Parse(textBox_y.Text);string motor_loc_x = "";string motor_loc_y = "";motor_loc_x = point2Ds_calc[x, y].X.ToString();motor_loc_y = point2Ds_calc[x, y].Y.ToString();textBox_get_motor_loc_x.Text = int.Parse( motor_loc_x).ToString();textBox_get_motor_loc_y.Text = int.Parse(motor_loc_y).ToString();}

或许会出现使用xml默认的diesize 宽和高计算的电机坐标进行移动,每颗芯片并没有再芯片中心位置。此时需要校准dieszie的宽和高

左右偏移有偏差则计算宽:

private void button_recal_w_Click(object sender, EventArgs e){try{OpenCvSharp.Point map1 = new OpenCvSharp.Point(int.Parse(textBox_middle_loc_x.Text), int.Parse(textBox_middle_loc_y.Text));var s = ",".Split(',');s[0] = textBox_recal_loc_x1.Text;s[1] = textBox_recal_loc_y1.Text;OpenCvSharp.Point2d coord1 = new OpenCvSharp.Point(double.Parse(s[0]), double.Parse(s[1]));OpenCvSharp.Point map2 = new OpenCvSharp.Point(int.Parse(textBox_right_loc_x.Text), int.Parse(textBox_right_loc_y.Text));var s2 = ",".Split(',');s2[0] = textBox_recal_loc_x2.Text;s2[1] = textBox_recal_loc_y2.Text;OpenCvSharp.Point2d coord2 = new OpenCvSharp.Point(double.Parse(s2[0]), double.Parse(s2[1]));var dieSizeX = mapping2.CalDieSize(map1, coord1, map2, coord2);// label_DieSizeX.Text = (dieSizeX / 1000).ToString();//0.259425476439132textBox_die_size_w.Text = (dieSizeX / 1000).ToString();//0.259425476439132AddToLogInfo("校准后的diesize_宽:" + textBox_die_size_w.Text);}catch(Exception ex){AddToLogInfo(ex.Message+ "在mapping视图第一个对位点点击中键(左边),然后移动鼠标在mapping视图第二个对位点点击右键(右边)");MessageBox.Show(ex.Message+ "在mapping视图第一个对位点点击中键(左边),然后移动鼠标在mapping视图第二个对位点点击右键(右边)");}}

校准方法:

鼠标移动到第一个对位点,点击中键,这里是32,225,(不同xml不是值),会记录到编辑中

 在32,225位置点击左键,回传对位点的电机坐标,这个可以写入PLC寄存器,执行移动到实际位置附近。此时通过相机查看,控制电机左右微调到芯片中心,并记录电机值

 

 鼠标移动到第二个对位点,点击右键,这里是380,225,(不同xml不是值),会记录到编辑中

在38,225位置点击左键,回传对位点的电机坐标,这个可以写入PLC寄存器,执行移动到实际位置附近。此时通过相机查看,控制电机左右微调到芯片中心,并记录电机值到编辑框 

 

完成校准。

上下偏移有偏差则计算高:

private void button_recal_h_Click(object sender, EventArgs e){try{OpenCvSharp.Point map1 = new OpenCvSharp.Point(int.Parse(textBox_middle_loc_x.Text), int.Parse(textBox_middle_loc_y.Text));var s = ",".Split(',');s[0] = textBox_recal_loc_x1.Text;s[1] = textBox_recal_loc_y1.Text;OpenCvSharp.Point2d coord1 = new OpenCvSharp.Point(double.Parse(s[0]), double.Parse(s[1]));OpenCvSharp.Point map2 = new OpenCvSharp.Point(int.Parse(textBox_right_loc_x.Text), int.Parse(textBox_right_loc_y.Text));var s2 = ",".Split(',');s2[0] = textBox_recal_loc_x2.Text;s2[1] = textBox_recal_loc_y2.Text;OpenCvSharp.Point2d coord2 = new OpenCvSharp.Point(double.Parse(s2[0]), double.Parse(s2[1]));var dieSizeX = mapping2.CalDieSize(map1, coord1, map2, coord2);// label_DieSizeX.Text = (dieSizeX / 1000).ToString();//0.259425476439132textBox_die_size_h.Text = (dieSizeX / 1000).ToString();//0.259425476439132AddToLogInfo("校准后的diesize_高:" + textBox_die_size_h.Text);}catch (Exception ex){AddToLogInfo(ex.Message + "在mapping视图第一个对位点点击中键(上边),然后移动鼠标在mapping视图第二个对位点点击右键(下边)");MessageBox.Show(ex.Message+ "在mapping视图第一个对位点点击中键(上边),然后移动鼠标在mapping视图第二个对位点点击右键(下边)");}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/266659.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能的技术演进与未来趋势

人工智能的技术演进与未来趋势 一、引言 人工智能&#xff08;AI&#xff09;已经成为当今科技领域的热门话题&#xff0c;其在各个行业的应用越来越广泛。从智能语音助手到自动驾驶汽车&#xff0c;从智能家居系统到医疗诊断&#xff0c;AI技术已经深入到我们的日常生活。在…

spring结合设计模式之策略模式

策略模式基本概念&#xff1a; 一个接口或者抽象类&#xff0c;里面两个方法&#xff08;一个方法匹配类型&#xff0c;一个可替换的逻辑实现方法&#xff09;不同策略的差异化实现(就是说&#xff0c;不同策略的实现类) 使用策略模式替换判断&#xff0c;使代码更加优雅。 …

C语言三种循环输出9*9乘法表

解题思路&#xff1a; 1、外层循环控制1~9循环 2、内层控制循环的次数 比如&#xff1a; 1 * 1 1 循环一次 1 * 1 1 1 * 2 循环两次 依此类推 int i, j;printf("for 打印9*9乘法表\r\n");for(i 1; i <10; i) {for(j 1; j < i;j) {printf("%d * %d %d…

RocketMQ-RocketMQ高性能核心原理节点(流程图)

NamesrvServer启动流程图&#xff1a; namesrvServer启动简图&#xff1a; Broker服务启动过程流程图 Broker服务启动过程流程简图 整体RPC框架流程如下图 client: DefaultMQProducer

HarmonyOS编译开源native库(OpenSSL实例)

前言 近期项目要开始做鸿蒙版本&#xff0c;有一部分依赖native的代码也需要迁移&#xff0c;某个native模块依赖openssl&#xff0c;需要在鸿蒙下重新编译openssl才行。一开始找了很多相关文档都没有得到方法&#xff0c;无奈只能自己凭经验慢慢试&#xff0c;最后还是成功了…

wvp gb28181 pro 配置https访问

准备工作 必须要有域名。虽然数字证书也有ip证书,但是会很麻烦,多数ca机构验证服务器需要用到80或443端口,也就是必须先备案,所以最好还是使用域名证书。购买域名证书。根据安全级别要求自行配置。单域名(不支持通配符的),阿里云的域名都是可以免费申请的。完成域名到服…

1-存储概念与SAN

任务背景 随着某些业务数据的增大, 公司服务器硬盘空闲空间越来越小, 服务器上也无法再拓展硬盘, 所以我们考虑使用网络存储方式远程共享存储给服务器使用。 任务要求 实现存储通过远程共享给应用服务器使用 任务拆解 1, 需要知道存储有哪些方式可以通过网络共享给服务器使…

【LLM】大模型之RLHF和替代方法(DPO、RAILF、ReST等)

note SFT使用交叉熵损失函数&#xff0c;目标是调整参数使模型输出与标准答案一致&#xff0c;不能从整体把控output质量&#xff0c;RLHF&#xff08;分为奖励模型训练、近端策略优化两个步骤&#xff09;则是将output作为一个整体考虑&#xff0c;优化目标是使模型生成高质量…

使用yum/dnf管理软件包

本章主要介绍使用 yum 对软件包进行管理。 yum 的介绍搭建yum源创建私有仓库yum客户端的配置yum的基本使用使用第三方yum源 使用rpm安装包时经常会遇到一个问题就是包依赖&#xff0c;如下所示。 [rootrhel03 ~]# rpm -ivh /mnt/AppStream/Packages/httpd-2.4.37-41.modulee…

12.10_黑马数据结构与算法笔记Java

目录 058 链表 e10 判环算法1 thinking&#xff1a;什么是空指针&#xff1f; 058 链表 e10 判环算法2 059 数组 e01 合并有序数组1 059 数组 e01 合并有序数组2 060 队列 链表实现1 061 队列 链表实现2 062 队列 环形数组实现 方法1-1 063 队列 环形数组实现 方法1-2…

MySQL使用窗口函数ROW_NUMBER()、DENSE_RANK()查询每组第一名或每组前几名,窗口函数使用详解

MySQL数据表结构 创建 tbl_class_info 表&#xff0c;表中有四个字段 id、username、score、group_name 使用 ROW_NUMBER()、DENSE_RANK() 查询每组前三名 -- 查询每组前3名 SELECT username, score, group_name FROM ( SELECT username, score, group_name, ROW_NUMBER()…

深入理解JVM虚拟机第二十八篇:详解JVM当中方法重写的本质和虚方法表

&#x1f609;&#x1f609; 欢迎加入我们的学习交流群呀&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&a…