Measure.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. //时间:20200610
  2. //作者:郝爽
  3. //功能:测量线程
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using SmartSEMControl;
  10. using MeasureData;
  11. namespace MeasureThread
  12. {
  13. public enum FMode
  14. {
  15. Manual,
  16. Auto
  17. }
  18. public enum ImageMode
  19. {
  20. FIB,
  21. SEM
  22. }
  23. public class Measure
  24. {
  25. //全局只有一个fatorySEM
  26. static FactoryHardware factorySEM = FactoryHardware.Instance;
  27. ISEMControl iSEM = factorySEM.ISEM;
  28. const String ImageName1 = @"ImageSEM600X.tif";
  29. const String ImageName2 = @"ImageFIB600X.tif";
  30. const float fMin = (float)0.0000002; //单位是米
  31. //测量文件
  32. private MeasureFile m_measureFile;
  33. public MeasureFile MeasureFile
  34. {
  35. get { return this.m_measureFile; }
  36. set { this.m_measureFile = value; }
  37. }
  38. //测量的切割孔
  39. private List<MeasureData.CutHole> m_cutHoles;
  40. public List<MeasureData.CutHole> cutHoles
  41. {
  42. get { return this.m_cutHoles; }
  43. set { this.m_cutHoles = value; }
  44. }
  45. //工作文件夹
  46. private string m_WorkingFolder;
  47. public string WorkingFolder
  48. {
  49. get { return this.m_WorkingFolder; }
  50. set { this.m_WorkingFolder = value; }
  51. }
  52. //线程状态
  53. private ThreadStatus m_ThreadStatus;
  54. public ThreadStatus TStatus
  55. {
  56. get { return this.m_ThreadStatus; }
  57. set { this.m_ThreadStatus = value; }
  58. }
  59. //对焦模式
  60. private FMode m_bFocusMode;
  61. public FMode FocusMode
  62. {
  63. get { return this.m_bFocusMode; }
  64. set { this.m_bFocusMode = FocusMode; }
  65. }
  66. //// SEM data general
  67. //CSEMDataGnrPtr m_pSEMDataGnr;
  68. ////MeasureAppFormName
  69. //CString m_strMAppFormName;
  70. //HWND m_hWnd;
  71. //构造函数
  72. public Measure()
  73. {
  74. Init();
  75. }
  76. public void Init()
  77. {
  78. FocusMode = FMode.Manual;
  79. }
  80. //初始化测量业务, 读测量文件,判断是否有可测试的切孔
  81. public bool InitMeas(MeasureFile a_measureFile)
  82. {
  83. m_measureFile = a_measureFile;
  84. List<CutHole> listHoles = m_measureFile.ListCutHole;
  85. foreach (CutHole h in listHoles )
  86. {
  87. if (h.SWITCH == true)
  88. {
  89. m_cutHoles.Add(h);
  90. }
  91. }
  92. if(m_cutHoles.Count == 0)
  93. return false;
  94. return true;
  95. }
  96. //测量流程
  97. public void DoMeasure()
  98. {
  99. //创建线程的测量状态的更新
  100. this.TStatus.ComputeTime(THREAD_TIME_TYPE.START);
  101. //将这个开始时间传递给主界面
  102. //检查硬件连接是否正常
  103. if (!ConnectHardware())
  104. {
  105. return;
  106. }
  107. //设置工作文件夹
  108. if (!SetWorkingFolderStr())
  109. {
  110. return;
  111. }
  112. //第一个孔的测试
  113. FirstHole();
  114. //非第一个孔的测试
  115. OtherHole();
  116. }
  117. //检查硬件连接是否正常
  118. public bool ConnectHardware()
  119. {
  120. //返回硬件的连接状态
  121. return iSEM.ConnectStatus();
  122. }
  123. //设置工作文件夹
  124. public bool SetWorkingFolderStr()
  125. {
  126. //获取工作文件路径
  127. string pathName = m_measureFile.FilePath;
  128. //判断工作文件路径是否为空或无效
  129. if (string.IsNullOrEmpty(pathName))
  130. {
  131. return false;
  132. }
  133. //文件未保存
  134. else if (pathName.CompareTo(MeasureFile.UNTITLED_FILE_NAME) == 0)
  135. {
  136. return false;
  137. }
  138. //获取工作文件所在文件夹
  139. string folder = System.IO.Path.GetDirectoryName(pathName);
  140. if (string.IsNullOrEmpty(folder))
  141. {
  142. return false;
  143. }
  144. WorkingFolder += @"\\";
  145. return false;
  146. }
  147. //第一个孔的测试过程
  148. public void FirstHole()
  149. {
  150. MeasureData.CutHole firstHole = m_cutHoles[0];
  151. //12.根据样品类型参数确定是否需要PT沉积,控制PT针插入
  152. if (firstHole.PT == true)
  153. {
  154. if (!iSEM.InsertPT())
  155. {
  156. return;
  157. }
  158. }
  159. //13.自动定位切割
  160. {
  161. //1.控制SEM放大600X
  162. if (!iSEM.SetMagnification(600))
  163. {
  164. return;
  165. }
  166. //2.控制SEM自动对焦、亮度、对比度
  167. if (FocusMode == FMode.Manual)
  168. {
  169. //弹出手动对焦的窗口
  170. }
  171. else if (FocusMode == FMode.Auto)
  172. {
  173. //调用自动对焦模块
  174. }
  175. else
  176. {
  177. return;
  178. }
  179. //3.设置SEM进行角度补偿54度
  180. if (!TiltCorrection(54))
  181. {
  182. return;
  183. }
  184. //4.控制SEM拍照
  185. //5.保存照片
  186. {
  187. //1. 创建目录,已经完成
  188. //2. 设置图片名称
  189. //3. 保存图片1
  190. String fileName1 = WorkingFolder + ImageName1;
  191. if (!GetImage(ImageMode.SEM, fileName1))
  192. {
  193. return;
  194. }
  195. }
  196. //6.设置FIB拍照参数——扫描时间、束流等
  197. //7.控制FIB自动亮度、对比度
  198. //8.控制FIB拍照
  199. //9.保存照片
  200. {
  201. //1. 设置图片名称
  202. //2. 保存图片2
  203. String fileName1 = WorkingFolder + ImageName2;
  204. if (!GetImage(ImageMode.FIB, fileName1))
  205. {
  206. return;
  207. }
  208. }
  209. //10.将照片传给客户,返回梯形位置坐标,及样品类型参数(是否需要PT沉积,PT坐标位置,PT宽度、PT高度、梯形上、下边及深度、扫描时间、束流、样品放大倍数1、样品放大倍数2等切割参数)
  210. //11.自动工具样品类型参数确定是否需要PT沉积
  211. {
  212. //1. 根据客户PT沉积坐标控制FIB调整到中心位置
  213. //2. 验证移动准确性:获取当前FIB中心位置坐标,与客户返回坐标对比,验证是否一定正确
  214. //3. 根据坐标进行PT沉积
  215. }
  216. //模拟为客户返回的坐标值
  217. float x0 = 0, y0 = 0;
  218. //12.根据梯形坐标控制FIB调整到中心位置
  219. if (!iSEM.MoveStageXY(x0, y0))
  220. {
  221. return;
  222. }
  223. //13.验证移动准确性:获取当前FIB中心位置坐标,与客户返回坐标对比,验证是否移动正确
  224. float x1 = iSEM.GetStageAtX();
  225. float y1 = iSEM.GetStageAtY();
  226. if (Math.Abs(x0 - x1) > fMin && Math.Abs(y0 - y1) > fMin)
  227. {
  228. return;
  229. }
  230. //14.保存样品1第1号孔中心位置6轴坐标1 XYZMRT到数据库,保存客户返回值信息到数据库
  231. }
  232. //14.自动控制FIB切割
  233. {
  234. //1.根据参数设置FIB草率时间(使图清晰),设置梯形上下边及深度、设置束流
  235. //2.控制FIB进行切割
  236. //3.控制FIB拍照600X
  237. //4.保存图片
  238. {
  239. //1.设置图片名称
  240. //2.保存图片3
  241. }
  242. //5.验证切割准确性:与切割前对比,如果对比误差大,则停止自动执行,进行报警
  243. //6.设置FIB解冻:先读取状态,如果冻结状态则进行解冻
  244. }
  245. //15.根据样品类型决定是否撤出PT针
  246. //16.自动调整SEM找到切割位置
  247. {
  248. //1.控制SEM放大到300倍
  249. //2.控制SEM自动对焦、亮度、对比度-接口
  250. //3.控制SEM拍照
  251. //4.将照片传给客户,获取偏移坐标,以及偏移角度
  252. //5.根据坐标控制SEM移动到切孔位置,居中
  253. //6.验证移动准确性:获取当前SEM中心位置坐标,与客户返回坐标对比,验证是否移动正确
  254. }
  255. //17.自动控制SEM拍截面照
  256. {
  257. //1.控制SEM放大到指定参数大小范围,6000x
  258. //2.控制SEM自动对焦、消像散、亮度、对比度
  259. //3.设置SEM角度补偿cos36度
  260. //4.控制SEM拍照
  261. //5.保存照片4
  262. //6.将照片传给客户,获取偏移坐标
  263. //7.根据坐标控制SEM移动到分析位置
  264. //8.验证移动准确性:获取当前SEM中心位置坐标,与客户返回坐标对比,验证是否移动正确
  265. //9.控制SEM平行校正,并记录校正前初始值
  266. //10.控制SEM放大到指定参数大小范围
  267. //11.控制SEM自动对焦、消像散、亮度、对比度
  268. //12.控制SEM对分析位置拍照
  269. //13.保存照片
  270. //14.控制SEM取消电子束校正,回到初始值
  271. }
  272. //18.自动层高分析
  273. {
  274. //1.获取SEM Pixel Size给客户传入参数
  275. //2.将照片传给客户,客户进行层高分析(返回分析后的图像、相对坐标、分辨率、各层编号以及各层对应的层高数据),如果客户自行出分析报告则无需返回数据
  276. }
  277. //19.自动能谱分析
  278. {
  279. //1. 确定能谱位置
  280. //2. 控制牛津打能谱
  281. //3. 能谱分析——面扫+线扫描
  282. }
  283. }
  284. //非第一个孔的测试过程
  285. public void OtherHole()
  286. {
  287. }
  288. //角度补偿
  289. public bool TiltCorrection(float a_fAngle)
  290. {
  291. //记录原来电镜的状态
  292. bool bTilt = false;
  293. float fOldTilt = iSEM.GetTiltCorrection();
  294. if (fOldTilt == float.NaN)
  295. {
  296. return false;
  297. }
  298. else if (fOldTilt == 1)
  299. {
  300. bTilt = true;
  301. }
  302. else if (fOldTilt == 0)
  303. {
  304. bTilt = false;
  305. }
  306. float fOldAngle = iSEM.GetTiltAngle();
  307. if (fOldAngle == float.NaN)
  308. {
  309. return false;
  310. }
  311. //开启校正
  312. if (!iSEM.SetTiltCorrectionOn())
  313. {
  314. return false;
  315. }
  316. //设置校正角度
  317. if (!iSEM.SetTiltAngle(fOldAngle))
  318. {
  319. return false;
  320. }
  321. //恢复原始状态
  322. if (!iSEM.SetTiltAngle(a_fAngle))
  323. {
  324. return false;
  325. }
  326. if (bTilt)
  327. {
  328. if (!iSEM.SetTiltCorrectionOn())
  329. {
  330. return false;
  331. }
  332. }
  333. else
  334. {
  335. if (!iSEM.SetTiltCorrectionOff())
  336. {
  337. return false;
  338. }
  339. }
  340. return true;
  341. }
  342. //拍图
  343. public bool GetImage(ImageMode a_mode, String a_fileName)
  344. {
  345. //1. 图像解冻
  346. float foldFrozen = iSEM.GetImageFrozen();
  347. if (foldFrozen == float.NaN)
  348. {
  349. return false;
  350. }
  351. if (!iSEM.ImageLive())
  352. {
  353. return false;
  354. }
  355. //2. 确认图像模式
  356. if (ImageMode.SEM == a_mode)
  357. {
  358. if (!iSEM.CmdFIBModeSEM())
  359. {
  360. return false;
  361. }
  362. }
  363. else if (ImageMode.FIB == a_mode)
  364. {
  365. if (!iSEM.CmdFIBModeFIB())
  366. {
  367. return false;
  368. }
  369. }
  370. else
  371. {
  372. return false;
  373. }
  374. //3. 获取分辨率
  375. int[] ImageSize = iSEM.GetImageStore();
  376. if (ImageSize[0] == 0 || ImageSize[1] == 0)
  377. {
  378. return false;
  379. }
  380. short width = (short)ImageSize[0];
  381. short height = (short)ImageSize[1];
  382. //4. 抓图
  383. if (!iSEM.GrabImage(a_fileName, 0, 0, width, height, 0))
  384. {
  385. return false;
  386. }
  387. //5. 恢复初始状态
  388. if (foldFrozen == 0)
  389. {
  390. if (!iSEM.ImageLive())
  391. {
  392. return false;
  393. }
  394. }
  395. else if (foldFrozen == 1)
  396. {
  397. if (!iSEM.ImageFrozen())
  398. {
  399. return false;
  400. }
  401. }
  402. return true;
  403. }
  404. }
  405. }