Locate.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. //set = MParam.Photograph_Magnification;
  90. //current = iSEM.GetMagnification();
  91. //while (Math.Abs(current - set) > 1)
  92. //{
  93. // iSEM.SetMagnification(set);
  94. // Thread.Sleep(200);
  95. // current = iSEM.GetMagnification();
  96. //}
  97. //恢复BeamShift的百分比值
  98. iSEM.SetBeamShiftX(pr.xs);
  99. Thread.Sleep(200);
  100. iSEM.SetBeamShiftY(pr.ys);
  101. Thread.Sleep(200);
  102. #endregion
  103. }
  104. public enum ZAxisDirection
  105. {
  106. up=0,
  107. down=1
  108. }
  109. public bool MoveZAxis(float value, ZAxisDirection d )
  110. {
  111. if (value < Z_Min || value> Z_Max)
  112. {
  113. log.Info("Z轴位置设置超出范围.", true);
  114. return false;
  115. }
  116. float curZ = iSEM.GetStageAtZ();
  117. float targetZ;
  118. if (d == ZAxisDirection.up)
  119. {
  120. targetZ = curZ + value;
  121. }
  122. else
  123. {
  124. targetZ = curZ - value;
  125. }
  126. log.Info("将Z轴位置指定到:" + value.ToString(), true);
  127. if (!iSEM.SetStageGotoZ(targetZ))
  128. {
  129. log.Error("样品台Z轴移到位置失败", false);
  130. return false;
  131. }
  132. while (true)
  133. {
  134. Thread.Sleep(500);
  135. if (iSEM.GetStageIs() == 0)
  136. {
  137. break;
  138. }
  139. }
  140. return true;
  141. }
  142. public bool MoveZAxisByAbs(float value)
  143. {
  144. if (value < Z_Min || value > Z_Max)
  145. {
  146. log.Info("Z轴位置设置超出范围.", true);
  147. return false;
  148. }
  149. log.Info("将Z轴位置指定到:" + value.ToString(), true);
  150. if (!iSEM.SetStageGotoZ(value))
  151. {
  152. log.Error("样品台Z轴移到位置失败", false);
  153. return false;
  154. }
  155. while (true)
  156. {
  157. Thread.Sleep(2000);
  158. if (iSEM.GetStageIs() == 0)
  159. {
  160. break;
  161. }
  162. }
  163. return true;
  164. }
  165. //移动到像素位置,这里要靠移动样品台实现,当位移量小于3um时,不予移动
  166. bool MoveToPixByMoveStage(float xc, float yc)
  167. {
  168. //单位是m/pix
  169. float XpixSize = iSEM.GetPixelSize();
  170. log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
  171. float YpixSize = iSEM.GetPixelSize();///(float)MParam.PixelSizeCor);
  172. log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
  173. Thread.Sleep(500);
  174. //0:width, 1:height
  175. int[] imageSize = iSEM.GetImageStore();
  176. int width = imageSize[0] / 2;
  177. int height = imageSize[1] / 2;
  178. log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
  179. log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
  180. float deltX = (xc - (float)width) * XpixSize;
  181. float deltY = (yc - (float)height) * YpixSize;
  182. log.Info("x位移量 = " + deltX.ToString() + "m", true);
  183. log.Info("y位移量 = " + deltY.ToString() + "m", true);
  184. float xpCur = iSEM.GetStageAtX();
  185. float ypCur = iSEM.GetStageAtY();
  186. log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
  187. float xpNew = xpCur - deltX;
  188. float ypNew = ypCur + deltY;
  189. log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
  190. log.Info("X方向移动样品台", true);
  191. if (!iSEM.SetStageGotoX(xpNew))
  192. {
  193. return false;
  194. }
  195. //判断是否移动完成
  196. while (true)
  197. {
  198. Thread.Sleep(5000);
  199. if (iSEM.GetStageIs() == 0)
  200. {
  201. break;
  202. }
  203. }
  204. log.Info("Y方向移动样品台", true);
  205. if (!iSEM.SetStageGotoY(ypNew))
  206. {
  207. return false;
  208. }
  209. //判断是否移动完成
  210. while (true)
  211. {
  212. Thread.Sleep(5000);
  213. if (iSEM.GetStageIs() == 0)
  214. {
  215. break;
  216. }
  217. }
  218. return true;
  219. }
  220. //移动到像素位置
  221. bool MoveToPix(float xc, float yc)
  222. {
  223. //单位是m/pix
  224. float XpixSize = iSEM.GetPixelSize();
  225. log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
  226. float YpixSize = (XpixSize / prm.PixelSize_Y_cur);
  227. log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
  228. Thread.Sleep(200);
  229. //0:width, 1:height
  230. int[] imageSize = iSEM.GetImageStore();
  231. int width = imageSize[0] / 2;
  232. int height = imageSize[1] / 2;
  233. log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
  234. log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
  235. float deltX = (xc - (float)width) * XpixSize;
  236. float deltY = (yc - (float)height) * YpixSize;
  237. log.Info("x位移量 = " + deltX.ToString() + "m", true);
  238. log.Info("y位移量 = " + deltY.ToString() + "m", true);
  239. float xpCur = iSEM.GetStageAtX();
  240. Thread.Sleep(200);
  241. float ypCur = iSEM.GetStageAtY();
  242. log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
  243. float xpNew = xpCur - deltX;
  244. float ypNew = ypCur + deltY;
  245. log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
  246. //计算最大偏移量
  247. float beamXCur = iSEM.GetBeamShiftX();//单位是%
  248. Thread.Sleep(200);
  249. iSEM.SetBeamShiftX(100);
  250. Thread.Sleep(200);
  251. float beamXMax = iSEM.GetBeamOffsetX();//单位是m
  252. Thread.Sleep(200);
  253. iSEM.SetBeamShiftX(beamXCur);
  254. Thread.Sleep(200);
  255. //计算光束偏移值:
  256. float beamX = iSEM.GetBeamOffsetX();
  257. log.Info("当前X方向光束偏移量=" + beamX.ToString() + "m", true);
  258. beamX = (-deltX + beamX);
  259. log.Info("X方向光束偏移量应为=" + beamX.ToString() + "m", true);
  260. if (((beamX <= beamXMax) && (beamX >= 0)) ||
  261. ((beamX >= -beamXMax) && (beamX < 0)))
  262. {
  263. log.Info("X方向移动光束", true);
  264. float beamXShift = beamX * 100 / beamXMax;
  265. log.Info("X方向光束偏移量应为=" + beamXShift.ToString() + "%", true);
  266. if (!iSEM.SetBeamShiftX(beamXShift))//if (!iSEM.SetBeamOffsetX(beamX))
  267. {
  268. log.Info("X方向光束偏移量" + beamX.ToString() + "m失败", true);
  269. return false;
  270. }
  271. }
  272. else if (deltX > 0.000003 || deltX < -0.000003)//大于3um使用移动样品台实现
  273. {
  274. log.Info("X方向移动样品台", true);
  275. if (!iSEM.SetStageGotoX(xpNew))
  276. {
  277. return false;
  278. }
  279. //判断是否移动完成
  280. while (true)
  281. {
  282. Thread.Sleep(4000);
  283. if (iSEM.GetStageIs() == 0)
  284. {
  285. break;
  286. }
  287. }
  288. }
  289. float beamY = iSEM.GetBeamOffsetY();
  290. log.Info("当前Y方向光束偏移量=" + beamY.ToString() + "m", true);
  291. beamY = (-deltY + beamY);
  292. log.Info("Y方向光束偏移量应为=" + beamY.ToString() + "m", true);
  293. //计算最大偏移量
  294. float beamYCur = iSEM.GetBeamShiftY();//单位是%
  295. Thread.Sleep(200);
  296. iSEM.SetBeamShiftY(100);
  297. Thread.Sleep(200);
  298. float beamYMax = iSEM.GetBeamOffsetY();//单位是m
  299. Thread.Sleep(200);
  300. iSEM.SetBeamShiftY(beamYCur);
  301. Thread.Sleep(200);
  302. if (((beamY <= beamYMax) && (beamY >= 0)) ||
  303. ((beamY >= -beamYMax) && (beamY < 0)))
  304. {
  305. log.Info("Y方向移动光束", true);
  306. float beamYShift = beamY * 100 / beamYMax;
  307. log.Info("Y方向光束偏移量" + beamYShift.ToString() + "%", true);
  308. //if(!iSEM.SetBeamOffsetY(beamY))
  309. if (!iSEM.SetBeamShiftY(beamYShift))
  310. {
  311. log.Info("Y方向光束偏移量" + beamY.ToString() + "m失败", true);
  312. return false;
  313. }
  314. }
  315. else if (deltY > 0.000003 || deltY < -0.000003)//大于3um使用移动样品台实现
  316. {
  317. log.Info("Y方向移动样品台", true);
  318. if (!iSEM.SetStageGotoY(ypNew))
  319. {
  320. return false;
  321. }
  322. //判断是否移动完成
  323. while (true)
  324. {
  325. Thread.Sleep(4000);
  326. if (iSEM.GetStageIs() == 0)
  327. {
  328. break;
  329. }
  330. }
  331. }
  332. return true;
  333. }
  334. public bool DoLocateByMoveStage()
  335. {
  336. return MoveToPixByMoveStage(prm.PositionX, prm.PositionY);
  337. }
  338. public bool DoLocateByShiftBeam()
  339. {
  340. return MoveToPix(prm.PositionX, prm.PositionY);
  341. }
  342. }
  343. }