Browse Source

add efem safeopen/safeclose

chenzk 3 weeks ago
parent
commit
da5f88fe9f

+ 6 - 2
CyberX8_Core/DeviceName.cs

@@ -62,7 +62,9 @@ namespace CyberX8_Core
         Vacuum,
         PowerOn,
         Error,
-        RobotCycle
+        RobotCycle,
+        Pause,
+        Resume
     }
 
     public class EfemConstant
@@ -102,7 +104,9 @@ namespace CyberX8_Core
             { EfemOperation.Size,   "SIZE"},
             {EfemOperation.Speed,"SPEED"},
             {EfemOperation.Vacuum,"VAC"},
-            {EfemOperation.PowerOn,"SERVOS"}
+            {EfemOperation.PowerOn,"SERVOS"},
+            {EfemOperation.Pause,"PAUSE"},
+            {EfemOperation.Resume,"RESUME"}
         };
 
         public static EfemOperation ToOperation(string str)

+ 3 - 1
CyberX8_Core/RtState.cs

@@ -75,7 +75,9 @@ namespace CyberX8_Core
         ErrorPicking,
         ErrorPlacing,
         RobotCycleing,
-        ErrorInitingAL
+        ErrorInitingAL,
+        Pause,
+        Resumeing
     }
     public enum PUFSTATE
     {

+ 17 - 0
CyberX8_MainPages/ViewModels/EfemViewModel.cs

@@ -750,6 +750,13 @@ namespace CyberX8_MainPages.ViewModels
         private DelegateCommand _doorLockCommand;
         public DelegateCommand DoorLockCommand =>
             _doorLockCommand ?? (_doorLockCommand = new DelegateCommand(OnDoorLock));
+        
+        private DelegateCommand _safeOpenCommand;
+        public DelegateCommand SafeOpenCommand =>
+            _safeOpenCommand ?? (_safeOpenCommand = new DelegateCommand(OnSafeOpen));
+        private DelegateCommand _safeCloseCommand;
+        public DelegateCommand SafeCloseCommand =>
+            _safeCloseCommand ?? (_safeCloseCommand = new DelegateCommand(OnSafeClose));
         #endregion
 
         #region 构造函数
@@ -978,6 +985,16 @@ namespace CyberX8_MainPages.ViewModels
         {
             InvokeClient.Instance.Service.DoOperation($"{ModuleName.EFEM}.DoorUnlock", false);
         }
+
+        private void OnSafeOpen()
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName.EFEM}.SafeOpen");
+        }
+        private void OnSafeClose()
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName.EFEM}.SafeClose");
+        }
+
         private void OnAlign1Align()
         { 
             InvokeClient.Instance.Service.DoOperation($"{ModuleName.Aligner1}.{EfemOperation.Align}",0, AlignValue);

+ 8 - 4
CyberX8_MainPages/Views/EfemView.xaml

@@ -131,13 +131,17 @@
                 <TextBlock Margin="100,0,0,0" Text="{Binding VacuumValue}" HorizontalAlignment="Left" FontSize="14" VerticalAlignment="Center"/>
             </Grid>
         </GroupBox>
-        <GroupBox Header="Door" Background="{DynamicResource Table_BG_Content}" Width="500" Height="70" Canvas.Left="1020" Canvas.Top="525" HorizontalAlignment="Center" VerticalAlignment="Top">
+        <GroupBox Header="Door" Background="{DynamicResource Table_BG_Content}" Width="500" Height="120" Canvas.Left="1020" Canvas.Top="525" HorizontalAlignment="Center" VerticalAlignment="Top">
             <Grid>
-                <Ellipse Width="16" Height="16"  Fill="{Binding DoorUnlock, Converter={StaticResource boolToColor}}"   Stroke="Silver" Margin="40,18,432,14"/>
-                <customControls:PathButton Content="Open" Height="33" Width="120"  Command="{Binding DoorUnlockCommand}" Margin="91,10,277,5"/>
-                <customControls:PathButton Content="Clock" Height="33" Width="120" Margin="262,10,106,5" Command="{Binding DoorLockCommand}"/>
+                <Ellipse Width="16" Height="16"  Fill="{Binding DoorUnlock, Converter={StaticResource boolToColor}}"   Stroke="Silver" Margin="40,-30,432,14"/>
+                <customControls:PathButton Content="Open" Height="33" Width="120"  Command="{Binding DoorUnlockCommand}" Margin="91,-40,277,5"/>
+                <customControls:PathButton Content="Clock" Height="33" Width="120" Margin="262,-40,106,5" Command="{Binding DoorLockCommand}"/>
                 <userControls:LockControl HorizontalAlignment="Left" VerticalAlignment="Top" Margin="442,11,0,0" IsLocked="{Binding IsDoorLocked}"/>
+
+                <customControls:PathButton Content="SafeOpen" Height="33" Width="120"  Command="{Binding SafeOpenCommand}" Margin="91,60,277,5"/>
+                <customControls:PathButton Content="SafeClose" Height="33" Width="120" Margin="262,60,106,5" Command="{Binding SafeCloseCommand}"/>
             </Grid>
+            
         </GroupBox>
         <Grid Canvas.Top="253" Canvas.Left="1020" Width="500" HorizontalAlignment="Center" VerticalAlignment="Top">
             <Grid.RowDefinitions>

+ 2 - 0
CyberX8_RT/CyberX8_RT.csproj

@@ -272,6 +272,8 @@
     <Compile Include="Modules\EFEM\EfemAutoMessageProcessor.cs" />
     <Compile Include="Modules\EFEM\EfemCycleAction.cs" />
     <Compile Include="Modules\EFEM\EfemRobotMapRoutine.cs" />
+    <Compile Include="Modules\EFEM\EfemSafeCloseRoutine.cs" />
+    <Compile Include="Modules\EFEM\EfemSafeOpenRoutine.cs" />
     <Compile Include="Modules\EFEM\RobotCycleMoveRoutine.cs" />
     <Compile Include="Modules\EFEM\RobotCycleRoutine.cs" />
     <Compile Include="Modules\FaModuleNotifier.cs" />

+ 2 - 1
CyberX8_RT/Devices/EFEM/EfemBase.cs

@@ -30,7 +30,6 @@ namespace CyberX8_RT.Devices.EFEM
 
         protected object _lockerAction = new object();
 
-
         public string GripStateBlade1
         {
             get;
@@ -88,6 +87,8 @@ namespace CyberX8_RT.Devices.EFEM
         public virtual bool LiftIsUp { get; }
         public virtual bool LiftIsDown { get; }
 
+        public virtual bool IsResumeRDYReceived {  get; set;}
+
         public abstract bool HomeAll();
         public abstract bool Home(ModuleName mod);
         public abstract bool OriginalSearch(ModuleName mod);

+ 46 - 5
CyberX8_RT/Devices/EFEM/SunWayRobot.cs

@@ -53,6 +53,8 @@ namespace CyberX8_RT.Devices.EFEM
             [Hand.Blade1] = "A",
             [Hand.Blade2] = "B"
         };
+
+        
         public override RState Status
         {
             get
@@ -94,6 +96,8 @@ namespace CyberX8_RT.Devices.EFEM
 
         private string _address = "";
 
+        public override bool IsResumeRDYReceived { get; set; }
+
         public SunWayRobot()
         {
             _socket = new AsyncSocket("","",DataType.Ascii,true);
@@ -312,12 +316,37 @@ namespace CyberX8_RT.Devices.EFEM
 
         public override bool Pause()
         {
-            return true;
+            //判断socket是否链接
+            if (!_socket.IsConnected)
+            {
+                LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected");
+                return false;
+            }
+            _currentMessage = new EfemMessage()
+            {
+                Operation = EfemOperation.Pause,
+                Module = ModuleName.EfemRobot
+            };
+            _status = RState.Running;
+            string cmd = "PAUSE\r";
+            return WriteCommand(cmd);
         }
-
         public override bool Resume()
         {
-            return true;
+            //判断socket是否链接
+            if (!_socket.IsConnected)
+            {
+                LOG.WriteLog(eEvent.ERROR_EFEM_COMMUNICATION, Module.ToString(), $"Socket is not Conntected");
+                return false;
+            }
+            _currentMessage = new EfemMessage()
+            {
+                Operation = EfemOperation.Resume,
+                Module = ModuleName.EfemRobot
+            };
+            _status = RState.Running;
+            string cmd = "RESUME\r";
+            return WriteCommand(cmd);
         }
 
         public override bool ClearError()
@@ -932,7 +961,7 @@ namespace CyberX8_RT.Devices.EFEM
             {
                 return;
             }
-            if(msg.StartsWith("_ERR"))
+            if(msg.Contains("_ERR"))
             {
                 string error = msg.Replace("_ERR", "").Trim();
                 OnErrorOccurred(error);
@@ -940,7 +969,12 @@ namespace CyberX8_RT.Devices.EFEM
                 SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.EFEM);
                 return;
             }
-            else if(msg.StartsWith("_RDY"))
+            else if (msg.StartsWith("ACTION_RDY"))
+            {
+                _status = RState.End;
+                IsResumeRDYReceived = false;
+            }
+            else if (msg.Contains("_RDY"))
             {
                 _status = RState.End;
                 switch (_currentMessage.Operation)
@@ -959,6 +993,13 @@ namespace CyberX8_RT.Devices.EFEM
                     case EfemOperation.Place:
                         SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.EfemRobot);
                         break;
+                    case EfemOperation.Pause:
+                        //SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.EfemRobot);
+                        break;
+                    case EfemOperation.Resume:
+                        _status = RState.Running;  //开始执行恢复动作
+                        IsResumeRDYReceived = true;
+                        break;
                 }
             }
             else

+ 102 - 7
CyberX8_RT/Modules/EFEM/EfemEntity.cs

@@ -44,6 +44,7 @@ namespace CyberX8_RT.Modules
         //private int _smallWafer = 0;
 
         private bool _isVacuume = false;
+        private bool _isPause = false;
 
         public enum STATE
         {
@@ -75,7 +76,9 @@ namespace CyberX8_RT.Modules
             ErrorPicking,
             ErrorPlacing,
             RobotCycleing,
-            ErrorInitingAL
+            ErrorInitingAL,
+            Pause,
+            Resumeing
         }
 
         public enum MSG
@@ -128,7 +131,9 @@ namespace CyberX8_RT.Modules
             WriteCarrierID,
             ReadTagData,
             WriteTagData,
-            RobotCycle
+            RobotCycle,
+            Pause,
+            Resume
         
            
         }
@@ -226,6 +231,9 @@ namespace CyberX8_RT.Modules
         private readonly EfemMapDummyRoutine _mapDummyRoutine;
         private readonly EfemVacuumRoutine _vacuumRoutine;
         private readonly CycleRobotCycleNewRoutine _cycleRobotCycleRoutine;
+        
+        private readonly EfemSafeOpenRoutine _efemSafeOpenRoutine;
+        private readonly EfemSafeCloseRoutine _efemSafeCloseRoutine;
 
         private string LiftMessage;
 
@@ -267,6 +275,8 @@ namespace CyberX8_RT.Modules
             _vacuumRoutine = new EfemVacuumRoutine(_efem);
             _cycleRobotCycleRoutine =   new CycleRobotCycleNewRoutine(_efem);
             _autoMessageProcessor =new EfemAutoMessageProcessor(_efem);
+            _efemSafeOpenRoutine = new EfemSafeOpenRoutine(_efem);
+            _efemSafeCloseRoutine = new EfemSafeCloseRoutine(_efem);
         }
         public LoadPortModule GetLoadportModule(int lpNumber)
         {
@@ -346,6 +356,9 @@ namespace CyberX8_RT.Modules
             //OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Vacuum}",    (cmd, args) => { CheckToPostMessage<STATE,MSG>(eEvent.ERR_EFEM_COMMON_FAILED,ModuleName.EFEM.ToString(),(int)MSG.Vacuum, args); return true; });            
             OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Vacuum}", (cmd, args) => { return VacuumAction(args); });            
             OP.Subscribe($"{Name}.DoorUnlock", (cmd, args) => { return DoorUnlock(args); });
+            
+            OP.Subscribe($"{Name}.SafeOpen", (cmd, args) => { return SafeOpenAction(args); });
+            OP.Subscribe($"{Name}.SafeClose", (cmd, args) => { return SafeCloseAction(args); });
 
             DATA.Subscribe($"{Name}.FsmState", () => ((STATE)fsm.State).ToString(),SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Name}.FsmPrevState", () => ((STATE)fsm.PrevState).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
@@ -408,7 +421,14 @@ namespace CyberX8_RT.Modules
             AnyStateTransition(MSG.ToInit,                  fnToInit,           STATE.Init);
             AnyStateTransition(MSG.BackroundCmd,            fnBackroundCommand, FSM_STATE.SAME);
             AnyStateTransition(MSG.CloseBuzzer,          fnCloseBuzzer, FSM_STATE.SAME);
+            AnyStateTransition(MSG.CloseBuzzer,          fnCloseBuzzer, FSM_STATE.SAME);
             
+            AnyStateTransition(MSG.Pause, EnterPause, STATE.Pause);
+
+            //Resume
+            Transition(STATE.Pause, MSG.Resume, EnterResume, STATE.Resumeing);
+            Transition(STATE.Resumeing, FSM_MSG.TIMER, fnResumeTimeout, STATE.Init);
+
             Transition(STATE.Unknown,MSG.CommReady, fnCommReady, STATE.Init);
             //Error
             Transition(STATE.Error, MSG.Recover, fnRecover, STATE.Idle);
@@ -475,7 +495,7 @@ namespace CyberX8_RT.Modules
             Transition(STATE.Idle,          MSG.Ungrip,             fnUngrip,           STATE.Ungripping);
             Transition(STATE.Ungripping,    MSG.ActionDone,         fnActionDone,       STATE.Idle);
 
-            // Aligner
+
 
             Transition(STATE.Idle,          MSG.Lift,               fnLift,             STATE.Lifting);
             //Transition(STATE.Lifting,       MSG.LiftActionDone,     fnActionDone,       STATE.Idle);
@@ -488,6 +508,9 @@ namespace CyberX8_RT.Modules
             Transition(STATE.Idle, MSG.MapDummy, MapDummy, STATE.Mapping);
             Transition(STATE.Mapping, FSM_MSG.TIMER, MapDummyTimeout, STATE.Idle);
 
+            //Resume
+            Transition(STATE.Idle, MSG.MapDummy, MapDummy, STATE.Mapping);
+
             //Vacuum
             //Transition(STATE.Init, MSG.Vacuum, VacuumAction, STATE.Vacuuming);
             //Transition(STATE.Idle, MSG.Vacuum, VacuumAction, STATE.Vacuuming);
@@ -526,7 +549,40 @@ namespace CyberX8_RT.Modules
         {
             return _efem.CloseBuzzer();
         }
-        
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        private bool EnterPause(object[] param)
+        {
+            return true;
+        }
+
+        private bool EnterResume(object[] param)
+        {
+            return true;
+        }
+
+        private bool fnResumeTimeout(object[] param)
+        {
+            _currentRoutine = _efemSafeCloseRoutine;
+            RState ret = _efemSafeCloseRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                _currentRoutine = null;
+                PostMsg(MSG.Error);
+                return false;
+            }
+            bool result = ret == RState.End;
+            if (result)
+            {
+                _currentRoutine = null;
+            }
+            return result;
+        }
+
         private bool fnHomeAll(object[] param)
         {
             _isHomed = false;
@@ -642,8 +698,19 @@ namespace CyberX8_RT.Modules
         {
             if (_isVacuume)
             {
-                VacuumActionTimeout();
-                _isVacuume = false;
+                bool result = VacuumActionTimeout();
+                if (result)
+                {
+                    _isVacuume = false;
+                }
+            }
+            if (_isPause)
+            {
+                bool result = SafeOpenActionTimeout();
+                if (result)
+                {
+                    _isPause = false;
+                }
             }
             // robot idle check
             _robotIdleTrigger.CLK = _efem.Status != RState.Running;
@@ -1123,6 +1190,17 @@ namespace CyberX8_RT.Modules
             return ret == RState.End;
         }
 
+        private bool SafeOpenActionTimeout()
+        {
+            RState ret = _efemSafeOpenRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, ModuleName.EFEM, "SafeOpen");
+                return false;
+            }
+            return ret == RState.End;
+        }
+
         private bool fnMap(object[] param)
         {
             // module
@@ -1157,7 +1235,24 @@ namespace CyberX8_RT.Modules
             return result;
         }
 
-        private bool DoorUnlock(object[] param)
+        private bool SafeOpenAction(object[] param)
+        {
+            PostMsg(MSG.Pause);
+            bool result = _efemSafeOpenRoutine.Start() == RState.Running;
+            if (result)
+            {
+                _isPause = true;
+            }
+            return result;
+        }
+
+        private bool SafeCloseAction(object[] param)
+        {
+            CheckToPostMessage<STATE, MSG>(eEvent.ERR_EFEM_COMMON_FAILED, "EFEM", (int)MSG.Resume);
+            return _efemSafeCloseRoutine.Start() == RState.Running;
+        }
+
+        public bool DoorUnlock(object[] param)
         {
             bool unlock = (bool)param[0];
             string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DOOR_UNLOCK}");

+ 106 - 0
CyberX8_RT/Modules/EFEM/EfemSafeCloseRoutine.cs

@@ -0,0 +1,106 @@
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.Routine;
+using Aitex.Core.Util;
+using CyberX8_Core;
+using CyberX8_RT.Devices.EFEM;
+using MECF.Framework.Common.Equipment;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CyberX8_RT.Modules.EFEM
+{
+    public class EfemSafeCloseRoutine : ModuleRoutineBase, IRoutine
+    {
+        private enum SafeCloseStep
+        {
+            Close,
+            Resume,
+            ResumeActionDoneCheck,
+            End
+        }
+
+        EfemBase _efem;
+        private EfemEntity _efemEntity;
+
+        public EfemSafeCloseRoutine(EfemBase efem) : base(ModuleName.EFEM)
+        {
+            _efem = efem;
+        }
+
+
+        /// <summary>
+        /// 启动
+        /// </summary>
+        /// <param name="objs"></param>
+        /// <returns></returns>
+        public RState Start(params object[] objs)
+        {
+            return Runner.Start(Module, "Save Close");
+        }
+
+        /// <summary>
+        /// 监控
+        /// </summary>
+        /// <returns></returns>
+        public RState Monitor()
+        {
+            Runner.Run(SafeCloseStep.Close, () => { return Close(); }, _delay_1ms)
+                  .Run(SafeCloseStep.Resume, () => { return Resume(); }, CheckResumeDone,_delay_1s)
+                  .Wait(SafeCloseStep.ResumeActionDoneCheck, ResumeActionDoneCheck)
+                  .End(SafeCloseStep.End, NullFun, 0);
+
+            return Runner.Status;
+        }
+        /// <summary>
+        /// 暂停功能
+        /// </summary>
+        /// <returns></returns>
+        private bool Resume()
+        {
+            return _efem.Resume();
+        }
+
+        /// <summary>
+        /// 检查是否收到Resume_rdy
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckResumeDone()
+        {
+            return _efem.IsResumeRDYReceived;
+        }
+
+        /// <summary>
+        /// 检查Resume动作是否完成
+        /// </summary>
+        /// <returns></returns>
+        private bool ResumeActionDoneCheck()
+        {
+            if (_efem.Status == RState.End)
+            {
+                return true;
+            }
+            else if (_efem.Status == RState.Failed)
+            {
+                LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, Module, $"Efem Resume Action failed: {_efem.Status}");
+                return true;
+            }
+            return false;
+        }
+
+        private bool Close()
+        {
+            _efemEntity = Singleton<RouteManager>.Instance.GetModule<EfemEntity>(Module.ToString());
+            bool myBool = false;
+            return _efemEntity.DoorUnlock(new object[] { myBool });
+        }
+
+        public void Abort()
+        {
+            Runner.Stop("Manual Abort");
+        }
+
+    }
+}

+ 98 - 0
CyberX8_RT/Modules/EFEM/EfemSafeOpenRoutine.cs

@@ -0,0 +1,98 @@
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.Routine;
+using Aitex.Core.Util;
+using CyberX8_Core;
+using CyberX8_RT.Devices.EFEM;
+using CyberX8_RT.Modules.SRD;
+using MECF.Framework.Common.Equipment;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CyberX8_RT.Modules.EFEM
+{
+    public class EfemSafeOpenRoutine : ModuleRoutineBase, IRoutine
+    {
+        private enum SafeOpenStep 
+        { 
+            Pause,
+            PauseCheck,
+            Open,
+            End
+        }
+
+        private EfemEntity _efemEntity;
+
+        EfemBase _efem;
+
+        public EfemSafeOpenRoutine(EfemBase efem) : base(ModuleName.EFEM)
+        {
+            _efem = efem;
+
+        }
+
+        /// <summary>
+        /// 启动
+        /// </summary>
+        /// <param name="objs"></param>
+        /// <returns></returns>
+        public RState Start(params object[] objs)
+        {
+            return Runner.Start(Module, "Save Open");
+        }
+
+        /// <summary>
+        /// 监控
+        /// </summary>
+        /// <returns></returns>
+        public RState Monitor()
+        {
+            Runner.Run(SafeOpenStep.Pause, () => { return Pause(); },CheckPauseDone, _delay_1s)
+                   .Run(SafeOpenStep.Open, () => { return Open(); },_delay_1ms)
+                    .End(SafeOpenStep.End, NullFun, 0);
+
+            return Runner.Status;
+        }
+        /// <summary>
+        /// 暂停功能
+        /// </summary>
+        /// <returns></returns>
+        private bool Pause()
+        {
+            return _efem.Pause();
+        }
+
+        /// <summary>
+        /// 检查是否Pause
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckPauseDone()
+        {
+            if (_efem.Status == RState.End)
+            {
+                return true;
+            }
+            else if (_efem.Status == RState.Failed)
+            {
+                LOG.Write(eEvent.ERR_EFEM_COMMON_FAILED, Module, $"Efem Pause failed: {_efem.Status}");
+                return true;
+            }
+            return false;
+        }
+
+        private bool Open()
+        {
+            _efemEntity = Singleton<RouteManager>.Instance.GetModule<EfemEntity>(Module.ToString());
+            bool myBool = true;
+            return _efemEntity.DoorUnlock(new object[] { myBool });
+        }
+
+        public void Abort()
+        {
+            Runner.Stop("Manual Abort");
+        }
+
+    }
+}

+ 17 - 2
CyberX8_Simulator/Devices/SunWayEfemSimulator.cs

@@ -200,9 +200,20 @@ namespace CyberX8_Simulator.Devices
                     ack = "MAP" + dummywafer;
                 }
             }
+            else if (str.StartsWith("PAUSE"))
+            {
+                ack = "PAUSE_RDY";
+            }
+            else if(str.StartsWith("RESUME"))
+            {
+                ack = "RESUME_RDY";
+                _ = Task.Run(DelayAnswerResume); // 启动后台任务
+
+            }
             else //默认回复
             {
-                if (str.StartsWith("PICK") || str.StartsWith("PLACE") || str.StartsWith("MAP") || str.StartsWith("ALIGNER ALGN") || str.StartsWith("ALIGNER HOME"))
+                if (str.StartsWith("PICK") || str.StartsWith("PLACE") || str.StartsWith("MAP")
+                    || str.StartsWith("ALIGNER ALGN") || str.StartsWith("ALIGNER HOME"))
                 {
                     Thread.Sleep((ushort)2200);
                 }
@@ -334,7 +345,11 @@ namespace CyberX8_Simulator.Devices
             //OnWriteMessage(strINF);
 
         }
-
+        private void DelayAnswerResume()
+        {
+            Thread.Sleep((ushort)3000);
+            OnWriteMessage("ACTION_RDY");
+        }
         private void UpdateLocked(string lpNumber,bool locked)
         {
             if (lpNumber== "1")