Measure.cs 17 KB

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