Locate.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using NLog;
  8. using SmartSEMControl;
  9. namespace MeasureThread
  10. {
  11. class Locate : ILocate
  12. {
  13. struct PositionRecord
  14. {
  15. public float xs;
  16. public float ys;
  17. public float xpCur;
  18. public float ypCur;
  19. public float magCur;
  20. }
  21. private PositionRecord pr=new PositionRecord();
  22. NLog.Logger log;
  23. private LocateParam prm;
  24. private ISEMControl iSEM;
  25. const float Z_Min = 0;
  26. const float Z_Max = 0.05f;
  27. public Locate(ISEMControl iSEM)
  28. {
  29. this.log = NLog.LogManager.GetCurrentClassLogger();
  30. this.iSEM = iSEM ?? throw new ArgumentNullException(nameof(iSEM));
  31. }
  32. //public Locate( LocateParam prm, ISEMControl iSEM)
  33. //{
  34. // this.log = NLog.LogManager.GetCurrentClassLogger();
  35. // this.log = log ?? throw new ArgumentNullException(nameof(log));
  36. // this.prm = prm ?? throw new ArgumentNullException(nameof(prm));
  37. // this.iSEM = iSEM ?? throw new ArgumentNullException(nameof(iSEM));
  38. //}
  39. public void RecordCurrentBeamShiftAndStagePosition()
  40. {
  41. #region 记录初始设置的BeamShift的百分比和样品台XY位置
  42. pr. xs = iSEM.GetBeamShiftX();
  43. Thread.Sleep(200);
  44. pr. ys = iSEM.GetBeamShiftY();
  45. Thread.Sleep(200);
  46. pr. xpCur = iSEM.GetStageAtX();
  47. Thread.Sleep(200);
  48. pr. ypCur = iSEM.GetStageAtY();
  49. Thread.Sleep(200);
  50. pr.magCur = iSEM.GetMagnification();
  51. Thread.Sleep(500);
  52. log.Info("原来的光束偏移量x = " + pr.xs.ToString()
  53. + "y=" + pr.ys.ToString() + ","
  54. + "原来样品台的位置x= " +pr. xpCur.ToString()
  55. + "y=" + pr.ypCur.ToString(), true);
  56. #endregion
  57. }
  58. public void RestoreLastBeamShiftAndStagePosition()
  59. {
  60. #region 恢复到拍照的状态
  61. log.Info("恢复到拍照的状态!");
  62. iSEM.SetStageGotoX(pr.xpCur);
  63. while (true)
  64. {
  65. Thread.Sleep(1000);
  66. if (iSEM.GetStageIs() == 0)
  67. {
  68. break;
  69. }
  70. }
  71. iSEM.SetStageGotoY(pr.ypCur);
  72. while (true)
  73. {
  74. Thread.Sleep(1000);
  75. if (iSEM.GetStageIs() == 0)
  76. {
  77. break;
  78. }
  79. }
  80. //恢复原来的放大倍数
  81. log.Info("恢复原来的放大倍数! " + pr.magCur);
  82. if (!iSEM.SetMagnification(pr.magCur))
  83. {
  84. log.Error("恢复放大倍数失败", false);
  85. return;
  86. }
  87. float cycle_time = iSEM.GetCycleTime();
  88. Thread.Sleep(100 + Convert.ToInt32(cycle_time));
  89. //恢复BeamShift的百分比值
  90. iSEM.SetBeamShiftX(pr.xs);
  91. Thread.Sleep(200);
  92. iSEM.SetBeamShiftY(pr.ys);
  93. Thread.Sleep(200);
  94. #endregion
  95. }
  96. public enum ZAxisDirection
  97. {
  98. up=0,
  99. down=1
  100. }
  101. public bool MoveZAxis(float value, ZAxisDirection d )
  102. {
  103. if (value < Z_Min || value> Z_Max)
  104. {
  105. log.Info("Z轴位置设置超出范围.", true);
  106. return false;
  107. }
  108. float curZ = iSEM.GetStageAtZ();
  109. float targetZ;
  110. if (d == ZAxisDirection.up)
  111. {
  112. targetZ = curZ + value;
  113. }
  114. else
  115. {
  116. targetZ = curZ - value;
  117. }
  118. log.Info("将Z轴位置指定到:" + value.ToString(), true);
  119. if (!iSEM.SetStageGotoZ(targetZ))
  120. {
  121. log.Error("样品台Z轴移到位置失败", false);
  122. return false;
  123. }
  124. while (true)
  125. {
  126. Thread.Sleep(2000);
  127. if (iSEM.GetStageIs() == 0)
  128. {
  129. break;
  130. }
  131. }
  132. return true;
  133. }
  134. public bool MoveRAxis(float value)
  135. {
  136. if (!iSEM.SetStageGotoR(value))
  137. {
  138. return false;
  139. }
  140. while (true)
  141. {
  142. Thread.Sleep(4000);
  143. if (iSEM.GetStageIs() == 0)
  144. {
  145. break;
  146. }
  147. }
  148. return true;
  149. }
  150. public bool MoveZAxisByAbs(float value)
  151. {
  152. if (value < Z_Min || value > Z_Max)
  153. {
  154. log.Info("Z轴位置设置超出范围.", true);
  155. return false;
  156. }
  157. log.Info("将Z轴位置指定到:" + value.ToString(), true);
  158. if (!iSEM.SetStageGotoZ(value))
  159. {
  160. log.Error("样品台Z轴移到位置失败", false);
  161. return false;
  162. }
  163. while (true)
  164. {
  165. Thread.Sleep(2000);
  166. if (iSEM.GetStageIs() == 0)
  167. {
  168. break;
  169. }
  170. }
  171. return true;
  172. }
  173. //移动到像素位置,这里要靠移动样品台实现,当位移量小于3um时,不予移动
  174. private bool MoveToPixByMoveStage()
  175. {
  176. float xc = prm.PositionX;
  177. float yc = prm.PositionY;
  178. //单位是m/pix
  179. float XpixSize = iSEM.GetPixelSize();
  180. log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
  181. float YpixSize = iSEM.GetPixelSize();///(float)MParam.PixelSizeCor);
  182. log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
  183. Thread.Sleep(500);
  184. //0:width, 1:height
  185. int[] imageSize = iSEM.GetImageStore();
  186. int width = imageSize[0] / 2;
  187. int height = imageSize[1] / 2;
  188. log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
  189. log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
  190. float deltX = (xc - (float)width) * XpixSize;
  191. float deltY = (yc - (float)height) * YpixSize;
  192. log.Info("x位移量 = " + deltX.ToString() + "m", true);
  193. log.Info("y位移量 = " + deltY.ToString() + "m", true);
  194. float xpCur = iSEM.GetStageAtX();
  195. float ypCur = iSEM.GetStageAtY();
  196. log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
  197. float xpNew = xpCur - deltX;
  198. float ypNew = ypCur + deltY;
  199. log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
  200. log.Info("X方向移动样品台", true);
  201. if (!iSEM.SetStageGotoX(xpNew))
  202. {
  203. return false;
  204. }
  205. //判断是否移动完成
  206. while (true)
  207. {
  208. Thread.Sleep(5000);
  209. if (iSEM.GetStageIs() == 0)
  210. {
  211. break;
  212. }
  213. }
  214. log.Info("Y方向移动样品台", true);
  215. if (!iSEM.SetStageGotoY(ypNew))
  216. {
  217. return false;
  218. }
  219. //判断是否移动完成
  220. while (true)
  221. {
  222. Thread.Sleep(5000);
  223. if (iSEM.GetStageIs() == 0)
  224. {
  225. break;
  226. }
  227. }
  228. return true;
  229. }
  230. //移动到像素位置
  231. private bool MoveToPix()
  232. {
  233. float xc = prm.PositionX;
  234. float yc = prm.PositionY;
  235. //单位是m/pix
  236. float XpixSize = iSEM.GetPixelSize();
  237. log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
  238. float YpixSize = (XpixSize / prm.PixelSize_Y_cur);
  239. log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
  240. Thread.Sleep(200);
  241. //0:width, 1:height
  242. int[] imageSize = iSEM.GetImageStore();
  243. int width = imageSize[0] / 2;
  244. int height = imageSize[1] / 2;
  245. log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
  246. log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
  247. float deltX = (xc - (float)width) * XpixSize;
  248. float deltY = (yc - (float)height) * YpixSize;
  249. log.Info("x位移量 = " + deltX.ToString() + "m", true);
  250. log.Info("y位移量 = " + deltY.ToString() + "m", true);
  251. float xpCur = iSEM.GetStageAtX();
  252. Thread.Sleep(200);
  253. float ypCur = iSEM.GetStageAtY();
  254. log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
  255. float xpNew = xpCur - deltX;
  256. float ypNew = ypCur + deltY;
  257. log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
  258. //计算最大偏移量
  259. float beamXCur = iSEM.GetBeamShiftX();//单位是%
  260. Thread.Sleep(200);
  261. iSEM.SetBeamShiftX(100);
  262. Thread.Sleep(200);
  263. float beamXMax = iSEM.GetBeamOffsetX();//单位是m
  264. Thread.Sleep(200);
  265. iSEM.SetBeamShiftX(beamXCur);
  266. Thread.Sleep(200);
  267. //计算光束偏移值:
  268. float beamX = iSEM.GetBeamOffsetX();
  269. log.Info("当前X方向光束偏移量=" + beamX.ToString() + "m", true);
  270. beamX = (-deltX + beamX);
  271. log.Info("X方向光束偏移量应为=" + beamX.ToString() + "m", true);
  272. if (((beamX <= beamXMax) && (beamX >= 0)) ||
  273. ((beamX >= -beamXMax) && (beamX < 0)))
  274. {
  275. log.Info("X方向移动光束", true);
  276. float beamXShift = beamX * 100 / beamXMax;
  277. log.Info("X方向光束偏移量应为=" + beamXShift.ToString() + "%", true);
  278. if (!iSEM.SetBeamShiftX(beamXShift))//if (!iSEM.SetBeamOffsetX(beamX))
  279. {
  280. log.Info("X方向光束偏移量" + beamX.ToString() + "m失败", true);
  281. return false;
  282. }
  283. }
  284. else if (deltX > 0.000003 || deltX < -0.000003)//大于3um使用移动样品台实现
  285. {
  286. log.Info("X方向移动样品台", true);
  287. if (!iSEM.SetStageGotoX(xpNew))
  288. {
  289. return false;
  290. }
  291. //判断是否移动完成
  292. while (true)
  293. {
  294. Thread.Sleep(4000);
  295. if (iSEM.GetStageIs() == 0)
  296. {
  297. break;
  298. }
  299. }
  300. }
  301. float beamY = iSEM.GetBeamOffsetY();
  302. log.Info("当前Y方向光束偏移量=" + beamY.ToString() + "m", true);
  303. beamY = (-deltY + beamY);
  304. log.Info("Y方向光束偏移量应为=" + beamY.ToString() + "m", true);
  305. //计算最大偏移量
  306. float beamYCur = iSEM.GetBeamShiftY();//单位是%
  307. Thread.Sleep(200);
  308. iSEM.SetBeamShiftY(100);
  309. Thread.Sleep(200);
  310. float beamYMax = iSEM.GetBeamOffsetY();//单位是m
  311. Thread.Sleep(200);
  312. iSEM.SetBeamShiftY(beamYCur);
  313. Thread.Sleep(200);
  314. if (((beamY <= beamYMax) && (beamY >= 0)) ||
  315. ((beamY >= -beamYMax) && (beamY < 0)))
  316. {
  317. log.Info("Y方向移动光束", true);
  318. float beamYShift = beamY * 100 / beamYMax;
  319. log.Info("Y方向光束偏移量" + beamYShift.ToString() + "%", true);
  320. //if(!iSEM.SetBeamOffsetY(beamY))
  321. if (!iSEM.SetBeamShiftY(beamYShift))
  322. {
  323. log.Info("Y方向光束偏移量" + beamY.ToString() + "m失败", true);
  324. return false;
  325. }
  326. }
  327. else if (deltY > 0.000003 || deltY < -0.000003)//大于3um使用移动样品台实现
  328. {
  329. log.Info("Y方向移动样品台", true);
  330. if (!iSEM.SetStageGotoY(ypNew))
  331. {
  332. return false;
  333. }
  334. //判断是否移动完成
  335. while (true)
  336. {
  337. Thread.Sleep(4000);
  338. if (iSEM.GetStageIs() == 0)
  339. {
  340. break;
  341. }
  342. }
  343. }
  344. return true;
  345. }
  346. public bool MoveToPixByMoveStage(float x, float y)
  347. {
  348. if (prm == null)
  349. {
  350. prm = new LocateParam();
  351. }
  352. this.prm.PositionX = x;
  353. this.prm.PositionY = y;
  354. //this.prm.PixelSize_Y_cur = pixelSize_Y_cur;
  355. MoveToPixByMoveStage();
  356. Thread.Sleep(1000);
  357. iSEM.SetAutoVideoBrightnessAndContrast();
  358. Thread.Sleep(3000);
  359. return true;
  360. }
  361. public bool MoveToPix(float x,float y,float pixelSize_Y_cur)
  362. {
  363. if (prm == null)
  364. {
  365. prm = new LocateParam();
  366. }
  367. this.prm.PositionX = x;
  368. this.prm.PositionY = y;
  369. this.prm.PixelSize_Y_cur = pixelSize_Y_cur;
  370. MoveToPix();
  371. Thread.Sleep(1000);
  372. iSEM.SetAutoVideoBrightnessAndContrast();
  373. Thread.Sleep(3000);
  374. return true;
  375. }
  376. public LocateParam GetParam()
  377. {
  378. if (prm == null)
  379. {
  380. prm = new LocateParam();
  381. }
  382. return prm;
  383. }
  384. }
  385. }