123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using NLog;
- using SmartSEMControl;
- namespace MeasureThread
- {
- class Locate : ILocate
- {
- struct PositionRecord
- {
- public float xs;
- public float ys;
- public float xpCur;
- public float ypCur;
- public float magCur;
- }
- private PositionRecord pr=new PositionRecord();
- NLog.Logger log;
- private LocateParam prm;
- private ISEMControl iSEM;
- const float Z_Min = 0;
- const float Z_Max = 0.05f;
- const float fSateyZ = (float)0.007;//单位是米
- public Locate(ISEMControl iSEM)
- {
- this.log = NLog.LogManager.GetCurrentClassLogger();
-
- this.iSEM = iSEM ?? throw new ArgumentNullException(nameof(iSEM));
- }
- public bool LocateCutHolePosition(MeasureData.CutHole currHole, bool ifTilt)
- {
- if (ifTilt)//如果是倾斜样品台,移动Z轴
- {
- //0、先移动Z轴到比较低的位置上。
- if (!MoveZAxis(fSateyZ, Locate.ZAxisDirection.down))
- {
- log.Error("测量线程报错:样品台Z轴移动失败,Z移动" + fSateyZ.ToString(), false);
- return false;
- }
- }
- //1、移动样品台到第一个观测点,先移动R轴,再移动XY轴
- if (!MoveRAxis(currHole.Position.R))
- {
- log.Error("测量线程报错:样品台R轴移动失败,R为" + currHole.Position.ToString(), false);
- //continue;
- return false;
- }
- //2、移动XY轴
- // lo.MoveToPixByMoveStage(currHole.Position.X,currHole.Position.Y)
- if (!iSEM.MoveStageXY(currHole.Position.X, currHole.Position.Y))
- {
- log.Error("测量线程报错:样品台XY轴移动失败,(X,Y)为"
- + currHole.Position.X.ToString() + ","
- + currHole.Position.Y.ToString() + ")", false);
- return false;
- }
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- //判断是否停止进程
-
- //3、恢复Z轴
- if (ifTilt)
- {
- //恢复Z轴
- if (!MoveZAxisByAbs(currHole.Position.Z))
- {
- log.Error("测量线程报错:样品台Z轴移动失败,Z为" + currHole.Position.Z.ToString(), false);
- return false;
- }
- }
-
- //4、设置WD
- iSEM.SetWorkingDistance(currHole.Position.WD);
- Thread.Sleep(1000);
- return true;
- }
- public bool RotateStageByDeltaR(float deltaR)
- {
- float Zpos = iSEM.GetStageAtZ();
- Thread.Sleep(200);
- log.Info("测量线程:当前Z轴位置" + Zpos.ToString() + "m", true);
- Locate lo = new Locate(iSEM);
- //选择之前,先降Z轴
- lo.MoveZAxis(fSateyZ, Locate.ZAxisDirection.down);
-
- iSEM.SetStageDeltaR(deltaR);
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- Thread.Sleep(1000);
- if (!MoveZAxisByAbs(Zpos))
- {
- log.Error("测量线程报错:样品台Z回到安全位置失败", false);
- return false;
- }
- return true;
- }
- public void RecordCurrentBeamShiftAndStagePosition()
- {
- #region 记录初始设置的BeamShift的百分比和样品台XY位置
- pr. xs = iSEM.GetBeamShiftX();
- Thread.Sleep(200);
- pr. ys = iSEM.GetBeamShiftY();
- Thread.Sleep(200);
- pr. xpCur = iSEM.GetStageAtX();
- Thread.Sleep(200);
- pr. ypCur = iSEM.GetStageAtY();
- Thread.Sleep(200);
- pr.magCur = iSEM.GetMagnification();
- Thread.Sleep(500);
- log.Info("原来的光束偏移量x = " + pr.xs.ToString()
- + "y=" + pr.ys.ToString() + ","
- + "原来样品台的位置x= " +pr. xpCur.ToString()
- + "y=" + pr.ypCur.ToString(), true);
- #endregion
- }
- public void RestoreLastBeamShiftAndStagePosition()
- {
- #region 恢复到拍照的状态
- log.Info("恢复到拍照的状态!");
- iSEM.SetStageGotoX(pr.xpCur);
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- iSEM.SetStageGotoY(pr.ypCur);
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- //恢复BeamShift的百分比值
- iSEM.SetBeamShiftX(pr.xs);
- Thread.Sleep(200);
- iSEM.SetBeamShiftY(pr.ys);
- Thread.Sleep(200);
- //恢复原来的放大倍数
- log.Info("恢复原来的放大倍数! " + pr.magCur);
- if (!iSEM.SetMagnification(pr.magCur))
- {
- log.Error("恢复放大倍数失败", false);
- return;
- }
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
- #endregion
- }
- public enum ZAxisDirection
- {
- up=0,
- down=1
- }
- public bool MoveZAxis(float value, ZAxisDirection d )
- {
- if (value < Z_Min || value> Z_Max)
- {
- log.Info("Z轴位置设置超出范围.", true);
- return false;
- }
- float curZ = iSEM.GetStageAtZ();
- log.Info("当前Z轴位置为" + curZ.ToString());
- float targetZ;
- if (d == ZAxisDirection.up)
- {
- targetZ = curZ + value;
- }
- else
- {
- targetZ = curZ - value;
- }
- log.Info("将Z轴位置指定到:" + targetZ.ToString(), true);
- if (!iSEM.SetStageGotoZ(targetZ))
- {
- log.Error("样品台Z轴移到位置失败", false);
- return false;
- }
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- Thread.Sleep(200);
- iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");
- //add by sun 2020-12-15 拍截面图调用蔡司接口时,要保证扫描速度5以上,自动亮度对比度功能关闭 end
- Thread.Sleep(200);
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
-
- return true;
- }
- public bool MoveRAxis(float value)
- {
- if (!iSEM.SetStageGotoR(value))
- {
-
- return false;
- }
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- Thread.Sleep(200);
- iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");//CmdFocusRate(5);
- //add by sun 2020-12-15 拍截面图调用蔡司接口时,要保证扫描速度5以上,自动亮度对比度功能关闭 end
- Thread.Sleep(200);
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
- return true;
-
- }
- public bool MoveZAxisByAbs(float value)
- {
- if (value < Z_Min || value > Z_Max)
- {
- log.Info("Z轴位置设置超出范围.", true);
- return false;
- }
-
- log.Info("将Z轴位置指定到:" + value.ToString(), true);
- if (!iSEM.SetStageGotoZ(value))
- {
- log.Error("样品台Z轴移到位置失败", false);
- return false;
- }
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- Thread.Sleep(200);
- iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");//CmdFocusRate(5);
- //add by sun 2020-12-15 拍截面图调用蔡司接口时,要保证扫描速度5以上,自动亮度对比度功能关闭 end
- Thread.Sleep(200);
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
- return true;
-
- }
- //移动到像素位置,这里要靠移动样品台实现,当位移量小于3um时,不予移动
- private bool MoveToPixByMoveStage()
- {
- float xc = prm.PositionX;
- float yc = prm.PositionY;
- //单位是m/pix
- float XpixSize = iSEM.GetPixelSize();
- log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
- float YpixSize = iSEM.GetPixelSize();///(float)MParam.PixelSizeCor);
- log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
- Thread.Sleep(500);
- //0:width, 1:height
- int[] imageSize = iSEM.GetImageStore();
- int width = imageSize[0] / 2;
- int height = imageSize[1] / 2;
- log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
- log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
- float deltX = (xc - (float)width) * XpixSize;
- float deltY = (yc - (float)height) * YpixSize;
- log.Info("x位移量 = " + deltX.ToString() + "m", true);
- log.Info("y位移量 = " + deltY.ToString() + "m", true);
- float xpCur = iSEM.GetStageAtX();
- float ypCur = iSEM.GetStageAtY();
- log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
- float xpNew = xpCur - deltX;
- float ypNew = ypCur + deltY;
- log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
- log.Info("X方向移动样品台", true);
- if (!iSEM.SetStageGotoX(xpNew))
- {
- return false;
- }
- //判断是否移动完成
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
-
-
- log.Info("Y方向移动样品台", true);
- if (!iSEM.SetStageGotoY(ypNew))
- {
- return false;
- }
- //判断是否移动完成
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
-
- return true;
- }
- //移动到像素位置
- private bool MoveToPix()
- {
- float xc = prm.PositionX;
- float yc = prm.PositionY;
- //单位是m/pix
- float XpixSize = iSEM.GetPixelSize();
- log.Info("X像素尺寸=" + XpixSize.ToString() + "m/pixel", true);
- float YpixSize = (XpixSize / prm.PixelSize_Y_cur);
- log.Info("Y像素尺寸=" + YpixSize.ToString() + "m/pixel", true);
- Thread.Sleep(200);
- //0:width, 1:height
- int[] imageSize = iSEM.GetImageStore();
- int width = imageSize[0] / 2;
- int height = imageSize[1] / 2;
- log.Info("目标像素是(" + xc.ToString() + "," + yc.ToString() + ")", true);
- log.Info("中心像素是(" + width.ToString() + "," + height.ToString() + ")", true);
- float deltX = (xc - (float)width) * XpixSize;
- float deltY = (yc - (float)height) * YpixSize;
- log.Info("x位移量 = " + deltX.ToString() + "m", true);
- log.Info("y位移量 = " + deltY.ToString() + "m", true);
- float xpCur = iSEM.GetStageAtX();
- Thread.Sleep(200);
- float ypCur = iSEM.GetStageAtY();
- log.Info("当前位置(" + xpCur.ToString() + "," + ypCur.ToString() + "),单位m", true);
- float xpNew = xpCur - deltX;
- float ypNew = ypCur + deltY;
- log.Info("目标位置(" + xpNew.ToString() + "," + ypNew.ToString() + "),单位m", true);
- //计算最大偏移量
- float beamXCur = iSEM.GetBeamShiftX();//单位是%
- Thread.Sleep(200);
- iSEM.SetBeamShiftX(100);
- Thread.Sleep(200);
- float beamXMax = iSEM.GetBeamOffsetX();//单位是m
- Thread.Sleep(200);
- iSEM.SetBeamShiftX(beamXCur);
- Thread.Sleep(200);
- //计算光束偏移值:
- float beamX = iSEM.GetBeamOffsetX();
- log.Info("当前X方向光束偏移量=" + beamX.ToString() + "m", true);
- beamX = (-deltX + beamX);
- log.Info("X方向光束偏移量应为=" + beamX.ToString() + "m", true);
- if (((beamX <= beamXMax) && (beamX >= 0)) ||
- ((beamX >= -beamXMax) && (beamX < 0)))
- {
- log.Info("X方向移动光束", true);
- float beamXShift = beamX * 100 / beamXMax;
- log.Info("X方向光束偏移量应为=" + beamXShift.ToString() + "%", true);
- if (!iSEM.SetBeamShiftX(beamXShift))//if (!iSEM.SetBeamOffsetX(beamX))
- {
- log.Info("X方向光束偏移量" + beamX.ToString() + "m失败", true);
- return false;
- }
- }
- else if (deltX > 0.000003 || deltX < -0.000003)//大于3um使用移动样品台实现
- {
- log.Info("X方向移动样品台", true);
- if (!iSEM.SetStageGotoX(xpNew))
- {
- return false;
- }
- //判断是否移动完成
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- }
- float beamY = iSEM.GetBeamOffsetY();
- log.Info("当前Y方向光束偏移量=" + beamY.ToString() + "m", true);
- beamY = (-deltY + beamY);
- log.Info("Y方向光束偏移量应为=" + beamY.ToString() + "m", true);
- //计算最大偏移量
- float beamYCur = iSEM.GetBeamShiftY();//单位是%
- Thread.Sleep(200);
- iSEM.SetBeamShiftY(100);
- Thread.Sleep(200);
- float beamYMax = iSEM.GetBeamOffsetY();//单位是m
- Thread.Sleep(200);
- iSEM.SetBeamShiftY(beamYCur);
- Thread.Sleep(200);
- if (((beamY <= beamYMax) && (beamY >= 0)) ||
- ((beamY >= -beamYMax) && (beamY < 0)))
- {
- log.Info("Y方向移动光束", true);
- float beamYShift = beamY * 100 / beamYMax;
- log.Info("Y方向光束偏移量" + beamYShift.ToString() + "%", true);
- //if(!iSEM.SetBeamOffsetY(beamY))
- if (!iSEM.SetBeamShiftY(beamYShift))
- {
- log.Info("Y方向光束偏移量" + beamY.ToString() + "m失败", true);
- return false;
- }
- }
- else if (deltY > 0.000003 || deltY < -0.000003)//大于3um使用移动样品台实现
- {
- log.Info("Y方向移动样品台", true);
- if (!iSEM.SetStageGotoY(ypNew))
- {
- return false;
- }
- //判断是否移动完成
- while (true)
- {
- Thread.Sleep(1000);
- if (iSEM.GetStageIs() == 0)
- {
- break;
- }
- }
- }
- return true;
- }
- public bool MoveToPixByMoveStage(float x, float y)
- {
- if (prm == null)
- {
- prm = new LocateParam();
- }
- this.prm.PositionX = x;
- this.prm.PositionY = y;
-
- MoveToPixByMoveStage();
- Thread.Sleep(200);
- Thread.Sleep(200);
- iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");//CmdFocusRate(5);
- //add by sun 2020-12-15 拍截面图调用蔡司接口时,要保证扫描速度5以上,自动亮度对比度功能关闭 end
- Thread.Sleep(200);
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
- return true;
-
- }
- public bool MoveToPix(float x,float y,float pixelSize_Y_cur)
- {
- if (prm == null)
- {
- prm = new LocateParam();
- }
- this.prm.PositionX = x;
- this.prm.PositionY = y;
- this.prm.PixelSize_Y_cur = pixelSize_Y_cur;
- MoveToPix();
- Thread.Sleep(200);
- iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");//CmdFocusRate(5);
- //add by sun 2020-12-15 拍截面图调用蔡司接口时,要保证扫描速度5以上,自动亮度对比度功能关闭 end
- Thread.Sleep(200);
- float cycle_time = iSEM.GetCycleTime();
- Thread.Sleep(100 + Convert.ToInt32(cycle_time));
- return true;
- }
- public LocateParam GetParam()
- {
- if (prm == null)
- {
- prm = new LocateParam();
- }
- return prm;
- }
- }
- }
|