Procházet zdrojové kódy

1. Revise flipper bugs;
2. Modify flipper UI;
3. Add flipper simulator;

niuyx před 3 dny
rodič
revize
44b0894f3e

+ 1 - 1
Jet/Jet_001_2P_Jet/EfemRT/Devices/Flipper/JetFlipper.cs

@@ -24,7 +24,7 @@ namespace EFEM.RT.Devices.Flipper
         private DOAccessor _doTurnOverPositionB;//转到预设角度B
         private DOAccessor _doTurnOverPositionC;//转到预设角度C
         private DOAccessor _doClampRunMode;//Clamp模式                    -- ClampHome_START_STOP==true && ClampRunMode=false为Clamp关闭
-        private DOAccessor _doClampHome_START_STOP;//Clamp开始/停止动作   -- ClampHome_START_STOP==true && ClampRunMode=false为Clamp打开
+        private DOAccessor _doClampHome_START_STOP;//Clamp开始/停止动作   -- ClampHome_START_STOP==true && ClampRunMode=true为Clamp打开
         private DOAccessor _doClampPositionA;//到预设位置A
         private DOAccessor _doClampPositionB;//到预设位置B
         private DOAccessor _doClampPositionC;//到预设位置C

+ 2 - 0
Jet/Jet_001_2P_Jet/EfemRT/Devices/FlipperEntity.cs

@@ -71,6 +71,8 @@ namespace EFEM.RT.Devices
             DATA.Subscribe($"{_modulename}.IsFlipperOrigin", () => IsFlipperOrigin);
             DATA.Subscribe($"{_modulename}.IsFlipperHorizontal", () => IsFlipperHorizontal);
             DATA.Subscribe($"{_modulename}.IsFlipperOverOrigin", () => IsFlipperOverOrigin);
+            DATA.Subscribe($"{_modulename}.ClampOpen", () => ClampOpen);
+            DATA.Subscribe($"{_modulename}.ClampClose", () => ClampClose);
         }
 
         //状态迁移表

+ 6 - 0
Jet/Jet_001_2P_Jet/EfemRT/Modules/RouteManager.cs

@@ -28,6 +28,7 @@ using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
 using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase;
 using Aitex.Core.RT.Log;
 using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.BufferStations;
+using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Flipper.FlipperBase;
 
 namespace EFEM.RT.Modules
 {
@@ -264,6 +265,11 @@ namespace EFEM.RT.Modules
         public bool IsFlipperDisable { get; set; }
 
         #endregion
+        /// <summary>
+        /// Flipper Entity
+        /// </summary>
+        public FlipperEntity FLPEntity => _flp;
+
         public RouteManager()
         {
             Name = "System";

+ 156 - 0
Jet/Jet_001_2P_Jet/EfemRT/Routines/CommonRoutine.cs

@@ -27,6 +27,8 @@ using Aitex.Core.RT.Log;
 using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.BufferStations;
 using EFEM.RT.Devices.Flipper;
 using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Flipper.FlipperBase;
+using EFEM.RT.Modules;
+using static EFEM.RT.Devices.FlipperEntity;
 
 namespace EFEM.RT.Routines
 {
@@ -51,6 +53,8 @@ namespace EFEM.RT.Routines
         protected IoCoolingBuffer buffer1 = null;
         protected IoCoolingBuffer buffer2 = null;
 
+        protected JetFlipper flipper = null;
+
         protected IoCoolingBuffer aligner1 = null;
         protected IoCoolingBuffer aligner2 = null;
         protected LoadLockDevice ll1 = null;
@@ -129,6 +133,7 @@ namespace EFEM.RT.Routines
             buffer1 = DEVICE.GetDevice<IoCoolingBuffer>(DeviceName.CoolingBuffer1);
             buffer2 = DEVICE.GetDevice<IoCoolingBuffer>(DeviceName.CoolingBuffer2);
 
+            flipper = DEVICE.GetDevice<JetFlipper>(DeviceName.Flipper);
             aligner1 = DEVICE.GetDevice<IoCoolingBuffer>(DeviceName.Aligner1);
             aligner2 = DEVICE.GetDevice<IoCoolingBuffer>(DeviceName.Aligner2);
             ll1 = DEVICE.GetDevice<LoadLockDevice>(DeviceName.LL1);
@@ -1370,6 +1375,10 @@ namespace EFEM.RT.Routines
             return _ioCoolBuffer;
         }
 
+        public JetFlipper GetFlipper()
+        {
+            return flipper;
+        }
         public void QueryLoadportState(int id, string deviceName, int time)
         {
 
@@ -2127,5 +2136,152 @@ namespace EFEM.RT.Routines
                     throw (new RoutineBreakException());
             }
         }
+
+        public void FlipperPrepare(int id, FlipperBase device, string name, int time, Action<string> notify, Action<string> error)
+        {
+            Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
+            {
+                if(device == null)
+                {
+                    LOG.Error($"{device.Name} device is null, prepare transfer failed");
+                    return false;
+                }
+                notify(String.Format("{0} Prepare Transfer", device.Name));
+                if (Singleton<RouteManager>.Instance.FLPEntity.CheckToPostMsg(FlipperEntity.FlipperMSG.PrepareTransfer))
+                {
+                    LOG.Info($"{device.Name} start prepare transfer");
+                    return true;
+                }
+                else
+                {
+                    LOG.Error($"{device.Name} prepare transfer failed");
+                    return false;
+                }
+                
+
+            }, () =>
+            {
+                if (Singleton<RouteManager>.Instance.FLPEntity.IsTransfer)
+                {
+                    LOG.Info($"{device.Name} end prepare transfer");
+                    return true;
+                }
+                return false;
+
+            }, time * 1000);
+
+            if (ret.Item1)
+            {
+                if (ret.Item2 == Result.FAIL)
+                {
+                    throw (new RoutineFaildException());
+                }
+                else if (ret.Item2 == Result.TIMEOUT) //timeout
+                {
+                    error(String.Format("{0} timeout, than {1} seconds", name, time));
+                    throw (new RoutineFaildException());
+                }
+                else
+                    throw (new RoutineBreakException());
+            }
+        }
+
+        public void FlipperComplete(int id, FlipperBase device, string name, int time, Action<string> notify, Action<string> error)
+        {
+            Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
+            {
+                if (device == null)
+                {
+                    LOG.Error($"{device.Name} device is null, prepare transfer failed");
+                    return false;
+                }
+                notify(String.Format("{0} Complete Transfer", device.Name));
+                if (Singleton<RouteManager>.Instance.FLPEntity.CheckToPostMsg(FlipperEntity.FlipperMSG.EndTransfer))
+                {
+                    LOG.Info($"{device.Name} start complete transfer");
+                    return true;
+                }
+                else
+                {
+                    LOG.Error($"{device.Name} complete transfer failed");
+                    return false;
+                }
+
+
+            }, () =>
+            {
+                if (Singleton<RouteManager>.Instance.FLPEntity.IsIdle)
+                {
+                    LOG.Info($"{device.Name} end complete transfer");
+                    return true;
+                }
+                return false;
+
+            }, time * 1000);
+
+            if (ret.Item1)
+            {
+                if (ret.Item2 == Result.FAIL)
+                {
+                    throw (new RoutineFaildException());
+                }
+                else if (ret.Item2 == Result.TIMEOUT) //timeout
+                {
+                    error(String.Format("{0} timeout, than {1} seconds", name, time));
+                    throw (new RoutineFaildException());
+                }
+                else
+                    throw (new RoutineBreakException());
+            }
+        }
+
+        public void FlipperHome(int id, FlipperBase device, string name, int time, Action<string> notify, Action<string> error)
+        {
+            Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
+            {
+                if (device == null)
+                {
+                    LOG.Error($"{device.Name} device is null, fliper home failed");
+                    return false;
+                }
+                notify(String.Format("{0} Home", device.Name));
+                if (Singleton<RouteManager>.Instance.FLPEntity.CheckToPostMsg(FlipperMSG.Home))
+                {
+                    LOG.Info($"{device.Name} start home");
+                    return true;
+                }
+                else
+                {
+                    LOG.Error($"{device.Name} home failed");
+                    return false;
+                }
+
+
+            }, () =>
+            {
+                if (Singleton<RouteManager>.Instance.FLPEntity.IsIdle)
+                {
+                    LOG.Info($"{device.Name} end home");
+                    return true;
+                }
+                return false;
+
+            }, time * 1000);
+
+            if (ret.Item1)
+            {
+                if (ret.Item2 == Result.FAIL)
+                {
+                    throw (new RoutineFaildException());
+                }
+                else if (ret.Item2 == Result.TIMEOUT) //timeout
+                {
+                    error(String.Format("{0} timeout, than {1} seconds", name, time));
+                    throw (new RoutineFaildException());
+                }
+                else
+                    throw (new RoutineBreakException());
+            }
+        }
     }
 }

+ 7 - 2
Jet/Jet_001_2P_Jet/EfemRT/Routines/InitRoutine.cs

@@ -115,7 +115,9 @@ namespace EFEM.RT.Routines
             RobotBlade2Release,
             QuerySignalStatus,
             RobotBlade1Hold,
-            RobotBlade2Hold
+            RobotBlade2Hold,
+
+            FlipperHome
         }
 
         private SetSpeedRoutine RbSetRoutine = null;
@@ -231,7 +233,10 @@ namespace EFEM.RT.Routines
                         CooingbufferHome((int)Home.Aligner2Home, aligner2, "Aligner2 moving down",
                             _timeoutBuffer, Notify, Stop);
                 }
-
+                if (!SC.GetValue<bool>("System.FlipperDisable"))
+                {
+                    FlipperHome((int)Home.FlipperHome, GetFlipper(), "Flipper Home...", _timeoutBuffer, Notify, Stop);
+                }
                 //if (LoadLockDoorControlByStation)
                 //{
                 //    LoadLockCloseAtmDoor((int)Home.CloseAtmShutterDoor, DEVICE.GetDevice<LoadLockDevice>(ModuleName.LL1.ToString()), "Wait Atm Door Close", _timeoutRobot, Notify, Stop);

+ 12 - 1
Jet/Jet_001_2P_Jet/EfemRT/Routines/PickRoutine.cs

@@ -49,7 +49,10 @@ namespace EFEM.RT.Routines
             WaitCheckWaferPrecense,
             CheckWaferPrecenseAfterPick,
             QuerySignalStatus,
-            RobotBladeUnGrip
+            RobotBladeUnGrip,
+
+            NotifyFlipperPrepare,
+            NotifyFlipperOver
         }
 
         protected bool MultiWaferSize = DeviceDefineManager.Instance.GetValue<bool>("MultiWaferSize") ?? false;
@@ -124,6 +127,10 @@ namespace EFEM.RT.Routines
                         WaitCoolBufferMoveUp((int)Pick.WaitCoolBufferMoveUP, GetCoolBuffer(Source), "Wait CoolingBuffer Move Up...", _timeout, Notify, Stop);
                     }
                 }
+                else if (ModuleHelper.IsFlipper(Source))
+                {
+                    FlipperPrepare((int)Pick.NotifyFlipperPrepare, GetFlipper(), "Flipper Prepare Transfer...", _timeout, Notify, Stop);
+                }
                 //RobotSignalStatus((int)Pick.QuerySignalStatus, robot, _timeout);
 
                 CheckBladeWaferIsExist((int)Pick.CheckWaferPrecense, robot, Blade, _timeout);
@@ -146,6 +153,10 @@ namespace EFEM.RT.Routines
                 PostMessage((int)Pick.PostMessage, string.Format("{0}{1:D2} by {2}.", Source.ToString(), Slot + 1, Blade.ToString()));
 
                 //CheckBladeWaferIsExist((int)Pick.CheckWaferPrecenseAfterPick, robot, Blade, _timeout);
+                if (ModuleHelper.IsFlipper(Source))
+                {
+                    FlipperComplete((int)Pick.NotifyFlipperOver, GetFlipper(), "Flipper Complete Transfer...", _timeout, Notify, Stop);
+                }
 
                 CheckAfterPick((int)Pick.CheckAfterPick, "Check wafer information after wafer picked", Source, Slot, Blade, Notify, Stop);
             }

+ 13 - 1
Jet/Jet_001_2P_Jet/EfemRT/Routines/PlaceRoutine.cs

@@ -53,7 +53,10 @@ namespace EFEM.RT.Routines
 
             CheckWaferPrecenseAfterPlace,
             QuerySignalStatus,
-            RobotBladeGrip
+            RobotBladeGrip,
+
+            NotifyFlipperPrepare,
+            NotifyFlipperOver
         }
 
         protected bool MultiWaferSize = DeviceDefineManager.Instance.GetValue<bool>("MultiWaferSize") ?? false;
@@ -134,6 +137,10 @@ namespace EFEM.RT.Routines
                         WaitCoolBufferMoveUp((int)Place.WaitCoolBufferMoveUP, GetCoolBuffer(Station), "Wait CoolingBuffer Move Up...", _timeout, Notify, Stop);
                     }
                 }
+                else if (ModuleHelper.IsFlipper(Station))
+                {
+                    FlipperPrepare((int)Place.NotifyFlipperPrepare, GetFlipper(), "Flipper Prepare Transfer...", _timeout, Notify, Stop);
+                }
                 CheckBladeWaferIsExist((int)Place.CheckWaferPrecense, robot, Blade, _timeout);
                 // RobotSignalStatus((int)Place.QuerySignalStatus, robot, _timeout);
 
@@ -170,6 +177,11 @@ namespace EFEM.RT.Routines
                     }
                 }
 
+                if (ModuleHelper.IsFlipper(Station))
+                {
+                    FlipperComplete((int)Place.NotifyFlipperOver, GetFlipper(), "Flipper Complete Transfer...", _timeout, Notify, Stop);
+                }
+
                 PostMessage((int)Place.PostMessage, string.Format("{0}{1:D2} by {2}", Station.ToString(), Slot + 1, Blade.ToString()));
 
                 //CheckBladeWaferIsExist((int)Place.CheckWaferPrecenseAfterPlace, robot, Blade, _timeout);

+ 13 - 2
Jet/Jet_001_2P_Jet/EfemRT/Routines/SwapRoutine.cs

@@ -42,8 +42,10 @@ namespace EFEM.RT.Routines
             CheckBlade2WaferPrecenseAfterSwap,
             QuerySignalStatus,
             WaitCoolBufferMoveDown,
-            PinDown
+            PinDown,
 
+            NotifyFlipperPrepare,
+            NotifyFlipperOver
         }
 
         private SCConfigItem _scSwapTimeout = null;
@@ -118,7 +120,11 @@ namespace EFEM.RT.Routines
                         //QueryCoolBufferState((int)Pick.QueryState, GetCoolBuffer(Source));
                         CoolBufferMoveUP((int)Swap.CoolBufferMoveUP, GetCoolBuffer(Source), WaferManager.Instance.GetWaferSize(Source, Slot), _timeout, Notify, Stop);
                         WaitCoolBufferMoveUp((int)Swap.WaitCoolBufferMoveUP, GetCoolBuffer(Source), "Wait CoolingBuffer Move Up...", _timeout, Notify, Stop);
-                    }                    
+                    }
+                }
+                else if (ModuleHelper.IsFlipper(Source))
+                {
+                    FlipperPrepare((int)Swap.NotifyFlipperPrepare, GetFlipper(), "Flipper Prepare Transfer...", _timeout, Notify, Stop);
                 }
                 //if (ModuleHelper.IsLoadLock(Source))
                 //{
@@ -181,6 +187,11 @@ namespace EFEM.RT.Routines
                         WaitCoolBufferMoveDown((int)Swap.WaitCoolBufferMoveDown, GetCoolBuffer(Source), "Wait CoolingBuffer Move Down...", _timeout, Notify, Stop);
                     }
                 }
+                else if(ModuleHelper.IsFlipper(Source))
+                {
+                    FlipperComplete((int)Swap.NotifyFlipperOver, GetFlipper(), "Flipper Complete Transfer...", _timeout, Notify, Stop);
+                }
+
                 PostMessage((int)Swap.PostMessage, string.Format("Swap wafer {0}{1:D2} place blade {2}", Source.ToString(), Slot + 1, PlaceBlade.ToString()));
                 CheckBladeWaferIsExist((int)Swap.CheckBlade1WaferPrecenseAfterSwap, robot, Hand.Blade1, _timeout);
                 CheckBladeWaferIsExist((int)Swap.CheckBlade2WaferPrecenseAfterSwap, robot, Hand.Blade2, _timeout);

+ 3 - 3
Jet/Jet_001_2P_Jet/EfemSimulator/Config/_ioDefine3.xml

@@ -11,7 +11,7 @@
 		<DI_ITEM Index="23" BufferOffset="23" Addr="DI-23" Name="DI_FlipperClampOpenedSensor" Description="FLIPPER CLAMP OPENED SENSOR"/>
 		<DI_ITEM Index="24" BufferOffset="24" Addr="DI-24" Name="DI_FlipperClampMotorPosCompleted" Description="FLIPPER CLAMP MOTOR   POS COMPLETED"/>
 		<DI_ITEM Index="26" BufferOffset="26" Addr="DI-26" Name="DI_FlipperClampMotorAlarm" Description="FLIPPER CLAMP MOTOR  ALARM"/>
-		<DI_ITEM Index="28" BufferOffset="28" Addr="DI-28" Name="DI_FlipperWaterInPosition" Description="FLIPPER WATER IN POSITION"/> <!--add-->		
+		<DI_ITEM Index="28" BufferOffset="28" Addr="DI-28" Name="DI_FlipperWaterInPosition" Description="FLIPPER WATER IN POSITION"/>
 		<DI_ITEM Index="30" BufferOffset="30" Addr="DI-30" Name="DI_FFUAlarm" Description="FFU ALARM"/>
 		<DI_ITEM Index="31" BufferOffset="31" Addr="DI-31" Name="DI_CDAPressureSW" Description="CDA Pressure SW"/>
 		<DI_ITEM Index="32" BufferOffset="32" Addr="DI-32" Name="DI_VACPressureSW" Description="VAC Pressure SW"/>
@@ -25,7 +25,7 @@
 		<DI_ITEM Index="40" BufferOffset="40" Addr="DI-40" Name="DI_EFEMPowerON" Description="EFEM Power ON"/>
 		<DI_ITEM Index="41" BufferOffset="41" Addr="DI-41" Name="DI_PreAlignerEnableToRobot" Description="PRE-ALIGNER ENABLE TO ROBOT"/>
 		<DI_ITEM Index="43" BufferOffset="43" Addr="DI-43" Name="DI_RobotEMSToEFEM" Description="Robot EMS to EFEM"/>
-		<DI_ITEM Index="45" BufferOffset="45" Addr="DI-45" Name="DI_RobotTeachingModeToEFEM" Description="Robot Teaching Mode to EFEM"/>		
+		<DI_ITEM Index="45" BufferOffset="45" Addr="DI-45" Name="DI_RobotTeachingModeToEFEM" Description="Robot Teaching Mode to EFEM"/>
 		<DI_ITEM Index="48" BufferOffset="48" Addr="DI-48" Name="DI_RBNotExtendToPMA" Description="RB Not Extend to PMA"/>
 		<DI_ITEM Index="49" BufferOffset="49" Addr="DI-49" Name="DI_RBNotExtendToPMB" Description="RB Not Extend to PMB"/>
 		<DI_ITEM Index="50" BufferOffset="50" Addr="DI-50" Name="DI_RBNotExtendToLP1" Description="RB Not Extend to LP1"/>
@@ -57,7 +57,7 @@
 		<DO_ITEM Index="20" BufferOffset="20" Addr="DO-20" Name="DO_FlipperTurnOverSetOrigin" Description="FLP TURNOVER SET ORIGIN"/>
 		<DO_ITEM Index="21" BufferOffset="21" Addr="DO-21" Name="DO_FlipperTurnOverALM-RST" Description="FLP TURNOVER ALM-RST"/>
 		<DO_ITEM Index="24" BufferOffset="24" Addr="DO-24" Name="DO_FlipperClampMotorClose/Open" Description="FLP CLAMP MOTOR CLOSE OR OPEN"/>
-		<DO_ITEM Index="25" BufferOffset="25" Addr="DO-25" Name="DO_FlipperClampStepMotionSTART" Description="FLP CLAMP STEP MOTION START"/>
+		<DO_ITEM Index="25" BufferOffset="25" Addr="DO-25" Name="DO_FlipperClampStepMotionStart" Description="FLP CLAMP STEP MOTION START"/>
 		<DO_ITEM Index="26" BufferOffset="26" Addr="DO-26" Name="DO_FlipperClampJOGP" Description="FLP CLAMP JOGP"/>
 		<DO_ITEM Index="27" BufferOffset="27" Addr="DO-27" Name="DO_FlipperClampJOGN" Description="FLP CLAMP JOGN"/>
 		<DO_ITEM Index="28" BufferOffset="28" Addr="DO-28" Name="DO_FlipperClampSetOrigin" Description="FLP CLAMP SET ORIGIN"/>

+ 41 - 2
Jet/Jet_001_2P_Jet/EfemSimulator/SimulatorSystem.cs

@@ -2,6 +2,8 @@
 using System.Configuration;
 using System.Threading;
 using System.Threading.Tasks;
+using System.Windows.Media;
+using Aitex.Core.Backend;
 using Aitex.Core.RT.IOCore;
 using Aitex.Core.RT.Log;
 using Aitex.Core.RT.SCCore;
@@ -24,7 +26,7 @@ namespace EfemSimulator.SimulatorIo
 
         public void Initialize()
         {
-            _thread = new PeriodicJob(100, OnMonitor, nameof(SimulatorSystem), true);
+            _thread = new PeriodicJob(100, OnMonitor, nameof(SimulatorSystem), false);
             //var smi1= new SmartReaderSimulator();
             //smi1.InitializeSimulator("COM6");
             //var smi2 = new SmartReaderSimulator();
@@ -40,7 +42,7 @@ namespace EfemSimulator.SimulatorIo
                     SetDefaultValue();
                     break;
             }
-            
+            _thread.Start();
         }
         /// <summary>
         /// 006 DefaultValue
@@ -76,6 +78,10 @@ namespace EfemSimulator.SimulatorIo
             IO.DI["DI_LP2FoupPlacement"].Value = true;
             IO.DI["DI_LP2Ready"].Value = true;
             IO.DI["DI_LP2Presence"].Value = true;
+
+            IO.DI["DI_FlipperTurnOverHorizontalSensor"].Value = true;
+            IO.DI["DI_FlipperTurnOverMotorPosCompleted"].Value = true;
+            IO.DI["DI_FlipperClampMotorPosCompleted"].Value = true;
         }
         private void SetDefaultValue()
         {
@@ -180,6 +186,7 @@ namespace EfemSimulator.SimulatorIo
                 switch (VersionNo)
                 {
                     case "006":
+                        MonitorFlipper();
                         break;
                     default:
                         MonitorPin();
@@ -233,6 +240,38 @@ namespace EfemSimulator.SimulatorIo
             }
         }
 
+        private void MonitorFlipper()
+        {
+            //Grip(Clamp)
+            if (IO.DO["DO_FlipperClampStepMotionStart"].Value && !IO.DO["DO_FlipperClampMotorClose/Open"].Value) 
+            {
+                Thread.Sleep(300);
+                IO.DI["DI_FlipperClampClosedSensor"].Value = true;
+                IO.DI["DI_FlipperClampOpenedSensor"].Value = false;
+            }
+            //UnGrip(UnClamp)
+            else if (IO.DO["DO_FlipperClampStepMotionStart"].Value && IO.DO["DO_FlipperClampMotorClose/Open"].Value)
+            {
+                Thread.Sleep(300);
+                IO.DI["DI_FlipperClampClosedSensor"].Value = false;
+                IO.DI["DI_FlipperClampOpenedSensor"].Value = true;
+            }
+            //Turn Over to 180°
+            if (IO.DO["DO_FlipperTurnOverStepMotionStart"].Value && IO.DO["DO_FlipperTurnOverMotor0/180"].Value)
+            {
+                Thread.Sleep(300);
+                IO.DI["DI_FlipperTurnOverHorizontalSensor"].Value = true;
+                IO.DI["DI_FlipperTurnOverOriginSensor"].Value = false;
+            }
+            //Turn Over to 0°
+            else if (IO.DO["DO_FlipperTurnOverStepMotionStart"].Value && !IO.DO["DO_FlipperTurnOverMotor0/180"].Value)
+            {
+                Thread.Sleep(300);
+                IO.DI["DI_FlipperTurnOverHorizontalSensor"].Value = true;
+                IO.DI["DI_FlipperTurnOverOriginSensor"].Value = true;
+            }
+
+        }
         public void Terminate()
         {
             _thread.Stop();

+ 6 - 0
Jet/Jet_001_2P_Jet/EfemUI/ViewModels/OperationViewModel2LPAB.cs

@@ -520,6 +520,12 @@ namespace Aitex.Sorter.UI.ViewModel
         [Subscription("Flipper.IsFlipperHorizontal")]
         public bool IsOver180Degree { get; set; }
 
+        [Subscription("Flipper.ClampOpen")]
+        public bool ClampOpen { get; set; }
+
+        [Subscription("Flipper.ClampClose")]
+        public bool ClampClose { get; set; }
+
         public bool IsShowLP1CarrierType
         {
             get

+ 19 - 4
Jet/Jet_001_2P_Jet/EfemUI/Views/OperationView/OperationView2LPJetAB.xaml

@@ -82,15 +82,15 @@
                 </DockPanel>
             </Border>
             <!--Left WaferInfo Panel-->
-            <Grid Margin="0,195,815,70" Width="220">
+            <Grid Margin="0,175,815,70" Width="220">
                 <Grid.RowDefinitions>
-                    <RowDefinition Height="1.2*"/>
+                    <RowDefinition Height="1.4*"/>
                     <RowDefinition/>
                     <RowDefinition/>
                     <RowDefinition Height="180"/>
                 </Grid.RowDefinitions>
                 <!--Flipper WaferInfo Component-->
-                <Border Grid.Row="0" Visibility="{Binding FlipperEnable,Converter={StaticResource boolVisibilityConverter},ConverterParameter={StaticResource True}}" BorderThickness="1" BorderBrush="#84a567" Height="100" Width="220" VerticalAlignment="Center">
+                <Border Grid.Row="0" Visibility="{Binding FlipperEnable,Converter={StaticResource boolVisibilityConverter},ConverterParameter={StaticResource True}}" BorderThickness="1" BorderBrush="#84a567" Height="130" Width="220" VerticalAlignment="Center">
                     <DockPanel Background="{StaticResource Table_BG_Content}">
                         <Label Content="Flipper" HorizontalContentAlignment="Center" DockPanel.Dock="Top" FontWeight="Bold" FontSize="15" Style="{StaticResource label}" Width="220" Height="30" />
                         <Grid>
@@ -102,6 +102,7 @@
                             <Grid.RowDefinitions>
                                 <RowDefinition Height="40" />
                                 <RowDefinition Height="28" />
+                                <RowDefinition Height="29" />
                             </Grid.RowDefinitions>
 
                             <ctrl:Wafer WaferIDDisplayMode="WaferOrigin" IsEnableTextMenu="{Binding IsNoRunning}" Margin="0,8,0,8" Width="216"  Grid.Row="0" Height="23.6" HorizontalAlignment="Center" Padding="0" Slot="0" WaferTransferOptionCommand="{Binding WaferTransferOptionCommand}"  WaferItem="{Binding FlipperWafer}" Station="Flipper" ShowSlot="True" Grid.ColumnSpan="3" />
@@ -110,7 +111,7 @@
                                     <ColumnDefinition/>
                                     <ColumnDefinition/>
                                 </Grid.ColumnDefinitions>
-                                <StackPanel Orientation="Horizontal" Margin="45,0,0,0">
+                                <StackPanel Orientation="Horizontal" Margin="35,0,0,0">
                                     <ctrlCommon:LED On="{Binding IsOver0Degree}"/>
                                     <TextBlock Text="0°" FontWeight="Bold" Foreground="Gray" FontSize="15" Margin="10,0,0,0"/>
                                 </StackPanel>
@@ -119,6 +120,20 @@
                                     <TextBlock Text="180°" FontWeight="Bold" Foreground="Gray" FontSize="15" Margin="10,0,0,0"/>
                                 </StackPanel>
                             </Grid>
+                            <Grid Grid.Row="2" Grid.ColumnSpan="3" ctrlCommon:GridHelper.Column0="LightBlue" ctrlCommon:GridHelper.Column1="LightBlue" Margin="0,0,-2,0">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition/>
+                                    <ColumnDefinition/>
+                                </Grid.ColumnDefinitions>
+                                <StackPanel Orientation="Horizontal" Margin="35,0,0,0">
+                                    <ctrlCommon:LED On="{Binding ClampClose}"/>
+                                    <TextBlock Text="Grip" FontWeight="Bold" Foreground="Gray" FontSize="15" Margin="5,0,0,0"/>
+                                </StackPanel>
+                                <StackPanel Grid.Column="1" Orientation="Horizontal" Margin="20,0,0,0">
+                                    <ctrlCommon:LED On="{Binding ClampOpen}"/>
+                                    <TextBlock Text="UnGrip" FontWeight="Bold" Foreground="Gray" FontSize="15" Margin="5,0,0,0"/>
+                                </StackPanel>
+                            </Grid>
                         </Grid>
                     </DockPanel>
                 </Border>