| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 | 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;                }            }            //恢复原来的放大倍数            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));            //恢复BeamShift的百分比值            iSEM.SetBeamShiftX(pr.xs);            Thread.Sleep(200);            iSEM.SetBeamShiftY(pr.ys);            Thread.Sleep(200);            #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();            float targetZ;            if (d == ZAxisDirection.up)            {                targetZ = curZ + value;            }            else            {                targetZ = curZ - value;            }            log.Info("将Z轴位置指定到:" + value.ToString(), true);            if (!iSEM.SetStageGotoZ(targetZ))            {                log.Error("样品台Z轴移到位置失败", false);                return false;            }            while (true)            {                Thread.Sleep(1000);                if (iSEM.GetStageIs() == 0)                {                    break;                }            }            return true;        }        public bool MoveRAxis(float value)        {            if (!iSEM.SetStageGotoR(value))            {                                return false;            }            while (true)            {                Thread.Sleep(1000);                if (iSEM.GetStageIs() == 0)                {                    break;                }            }            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;                }            }            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);            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);            return true;        }        public LocateParam GetParam()        {            if (prm == null)            {                prm = new LocateParam();            }            return prm;        }    }}
 |