Browse Source

1. 修复cycle问题
2. 增加vce error code
3. 增加HongHu Robot模拟器
4. 修复LeakCheck兼容问题

zhouhr 2 months ago
parent
commit
502057d56c

+ 15 - 1
JetVirgoPM/PMs/Routines/PMLeakCheckRoutine.cs

@@ -169,7 +169,7 @@ namespace JetVirgoPM.PMs.Routines
         public RState Monitor()
         {
             Runner.Run(LeakCheckStep.PumpDown,          StartPump,                                                                    CheckPump,                                                                    _delay_60s)
-                .Run(LeakCheckStep.OpenPurgeValve,      HOFs.Apply(ExecPurgeOrGasFinalValve, ValveType.PURGE, true),                  HOFs.Apply(CheckPurgeOrGasFinalValve, ValveType.PURGE, true),                 _delay_50ms * 10)
+                .Run(LeakCheckStep.OpenPurgeValve,      OpenPurge,                                                                    CheckPurgeOpen,                                                               _delay_50ms * 10)
                 .Run(LeakCheckStep.OpenGasFinalValve,   HOFs.Apply(ExecPurgeOrGasFinalValve, ValveType.PROCESS, true),                HOFs.Apply(CheckPurgeOrGasFinalValve, ValveType.PROCESS, true),               _delay_50ms * 10)
                 .Run(LeakCheckStep.OpenMfc1Valve,       HOFs.Apply(ExecMfcValve, _enableGasLineOrN2[0], ValveType.Mfc1, true),        HOFs.Apply(CheckMfcValue, _enableGasLineOrN2[0], ValveType.Mfc1, true),       _delay_50ms * 10)
                 .Run(LeakCheckStep.OpenMfc2Valve,       HOFs.Apply(ExecMfcValve, _enableGasLineOrN2[1], ValveType.Mfc2, true),        HOFs.Apply(CheckMfcValue, _enableGasLineOrN2[1], ValveType.Mfc2, true),       _delay_50ms * 10)
@@ -202,6 +202,20 @@ namespace JetVirgoPM.PMs.Routines
             return Runner.Status;
         }
 
+        bool CheckPurgeOpen()
+        {
+            if (!_chamber.IsPlus)
+                return CheckPurgeOrGasFinalValve(ValveType.PURGE, true);
+            return true;
+        }
+
+        bool OpenPurge()
+        {
+            if (!_chamber.IsPlus)
+                return ExecPurgeOrGasFinalValve(ValveType.PURGE, true);
+            return true;
+        }
+
         bool StartPump()
         {
             return _pumpdownRoutine.Start() == RState.Running;

+ 11 - 6
Mars/EfemDualSchedulerLib/VCEDualAutoTransfer.cs

@@ -992,11 +992,13 @@ namespace EfemDualSchedulerLib
 
                         foreach (var wafer in cjnext.LotWafers)
                         {
-                            WaferManager.Instance.UpdateWaferProcessStatus((ModuleName)wafer.OriginStation, wafer.OriginSlot, EnumWaferProcessStatus.Idle);
-                            WaferManager.Instance.GetWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot).NextSequenceStep = 0;
+                            if (WaferManager.Instance.CheckNoWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot))
+                                continue;
+                            WaferManager.Instance.UpdateWaferProcessStatus((ModuleName)wafer.OriginStation, wafer.OriginSlot, EnumWaferProcessStatus.Idle);//Question1
+                            WaferManager.Instance.GetWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot).NextSequenceStep = 0;//Question1
                             if (WaferManager.Instance.CheckHasWafer((ModuleName)wafer.OriginStation, wafer.OriginSlot))
                             {
-                                if (wafer.ProcessJob.Sequence.Steps[0].StepModules.Count > 0 && ModuleHelper.IsCoolingBuffer(wafer.ProcessJob.Sequence.Steps[0].StepModules[0]))
+                                if (wafer.ProcessJob.Sequence.Steps[0].StepModules.Count > 0 && ModuleHelper.IsCoolingBuffer(wafer.ProcessJob.Sequence.Steps[0].StepModules[0]))//Question2
                                 {
                                     if (willAdd[wafer.OriginSlot] == MovingStatus.Waiting)
                                     {
@@ -2305,10 +2307,13 @@ namespace EfemDualSchedulerLib
         }
 
         private int GetSequenceCoolingtime(WaferInfo wafer)
-        {
-            foreach (KeyValuePair<string, object> coolingtime in _lstProcessJobs.Find(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name).Sequence.Steps[wafer.NextSequenceStep].StepParameter)
+        {   //Question3
+            if (_lstProcessJobs.Exists(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name))
             {
-                return Convert.ToInt32(coolingtime.Value);
+                foreach (KeyValuePair<string, object> coolingtime in _lstProcessJobs.Find(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name).Sequence.Steps[wafer.NextSequenceStep].StepParameter)
+                {
+                    return Convert.ToInt32(coolingtime.Value);
+                }
             }
             return -1;
         }

+ 5 - 5
Mars/EfemDualSimulator/Instances/SimulatorSystem.cs

@@ -426,7 +426,7 @@ namespace EfemDualSimulator.Instances
         {
             if (IO.DO[$"{mod}.DO_LiftPin{index}_Servo_Group_Search_ORG"].Value && !IO.DI[$"{mod}.DI_LiftPin{index}_ORG_SW"].Value)
             {
-                Thread.Sleep(3000);
+                //Thread.Sleep(3000);
                 IO.DI[$"{mod}.DI_LiftPin{index}_ORG_SW"].Value = true;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS1_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
@@ -440,7 +440,7 @@ namespace EfemDualSimulator.Instances
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS4_Complete"].Value = false;
-                Thread.Sleep(3000);
+                //Thread.Sleep(3000);
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS1_Complete"].Value = true;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
@@ -453,7 +453,7 @@ namespace EfemDualSimulator.Instances
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS4_Complete"].Value = false;
-                Thread.Sleep(3000);
+                //Thread.Sleep(3000);
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS1_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = true;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
@@ -466,7 +466,7 @@ namespace EfemDualSimulator.Instances
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS4_Complete"].Value = false;
-                Thread.Sleep(3000);
+                //Thread.Sleep(3000);
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS1_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = true;
@@ -479,7 +479,7 @@ namespace EfemDualSimulator.Instances
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS4_Complete"].Value = false;
-                Thread.Sleep(3000);
+                //Thread.Sleep(3000);
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS1_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS2_Complete"].Value = false;
                 IO.DI[$"{mod}.DI_LiftPin{index}_GO_POS3_Complete"].Value = false;

+ 256 - 3
Mars/EfemDualSimulator/Views/Simu_HongHuVTMRobotView.xaml.cs

@@ -57,17 +57,266 @@ namespace EfemDualSimulator.Views
         }
     }
 
+    public class Node<T>
+    {
+        private T data; //数据域
+        //构造器
+        public Node(T v)
+        {
+            data = v;
+        }
+        //数据域属性
+        public T Data
+        {
+            get
+            {
+                return data;
+            }
+            set
+            {
+                data = value;
+            }
+        }
+    }
+
+    public interface IGraph<T>
+    {
+        //获取顶点数
+        int GetNumOfVertex();
+        //获取边或弧的数目
+        int GetNumOfEdge();
+        //在两个顶点之间添加权为v的边或弧
+        void SetEdge(Node<T> v1, Node<T> v2, int v);
+        //删除两个顶点之间的边或弧
+        void DelEdge(Node<T> v1, Node<T> v2);
+        //判断两个顶点之间是否有边或弧
+        bool IsEdge(Node<T> v1, Node<T> v2);
+    }
+
+    /// <summary>
+    /// 无向图邻接矩阵类 GraphAdjMatrix<T>的实现
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    public class GraphAdjMatrix<T> : IGraph<T>
+    {
+        private Node<T>[] nodes;//顶点数组
+        private float[,] matrix;//邻接矩阵数组
+        private int numEdges;//边的数目
+
+        public GraphAdjMatrix(int n)
+        {
+            nodes = new Node<T>[n];
+            matrix = new float[n, n];
+            numEdges = 0;
+        }
+
+        //获取索引为index的顶点的信息
+        public Node<T> GetNode(int index)
+        {
+            return nodes[index];
+        }
+
+        //设置索引为index的顶点的信息
+        public void SetNode(int index, Node<T> v)
+        {
+            nodes[index] = v;
+        }
+
+        //获取matrix[index1, index2]的值
+        public float GetMatrix(int index1, int index2)
+        {
+            return matrix[index1, index2];
+        }
+
+        //设置matrix[index1, index2]的值
+        public void SetMatrix(int index1, int index2, float weight)
+        {
+            if (weight <= 0)
+                return;
+            matrix[index1, index2] = weight;
+        }
+
+        //边的数目属性
+        public int NumEdges
+        {
+            get { return numEdges; }
+            set { numEdges = value; }
+        }
+
+        //获取顶点的数目
+        public int GetNumOfVertex()
+        {
+            return nodes.Length;
+        }
+
+        //获取边的数目
+        public int GetNumOfEdge()
+        {
+            return numEdges;
+        }
+
+        //判断v是否是图的顶点
+        public bool IsNode(Node<T> v)
+        {
+            //遍历顶点数组
+            foreach (Node<T> nd in nodes)
+            {
+                //如果顶点nd与v相等,则v是图的顶点,返回true
+                if (v.Equals(nd))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        //获取顶点v在顶点数组中的索引
+        public int GetIndex(Node<T> v)
+        {
+            int i = -1;
+            //遍历顶点数组
+            for (i = 0; i < nodes.Length; ++i)
+            {
+                //如果顶点v与nodes[i]相等,则v是图的顶点,返回索引值i。
+                if (nodes[i].Equals(v))
+                {
+                    return i;
+                }
+            }
+            return i;
+        }
+
+        //在顶点v1和v2之间添加权值为v的边
+        public void SetEdge(Node<T> v1, Node<T> v2, int v)
+        {
+            if (!IsNode(v1) || !IsNode(v2))
+            {
+                Console.WriteLine("Node is not belong to Graph!");
+                return;
+            }
+            
+
+            //矩阵是对称矩阵
+            matrix[GetIndex(v1), GetIndex(v2)] = v;
+            matrix[GetIndex(v2), GetIndex(v1)] = v;
+            ++numEdges;
+        }
+
+        //删除顶点v1和v2之间的边
+        public void DelEdge(Node<T> v1, Node<T> v2)
+        {
+            //v1或v2不是图的顶点
+            if (!IsNode(v1) || !IsNode(v2))
+            {
+                Console.WriteLine("Node is not belong to Graph!");
+                return;
+            }
+
+            //顶点v1与v2之间存在边
+            if (matrix[GetIndex(v1), GetIndex(v2)] == 1)
+            {
+                //矩阵是对称矩阵
+                matrix[GetIndex(v1), GetIndex(v2)] = 0;
+                matrix[GetIndex(v2), GetIndex(v1)] = 0;
+                --numEdges;
+            }
+        }
+
+        //判断顶点v1与v2之间是否存在边
+        public bool IsEdge(Node<T> v1, Node<T> v2)
+        {
+            //v1或v2不是图的顶点
+            if (!IsNode(v1) || !IsNode(v2))
+            {
+                Console.WriteLine("Node is not belong to Graph!");
+                return false;
+            }
+
+            //顶点v1与v2之间存在边
+            if (matrix[GetIndex(v1), GetIndex(v2)] == 1)
+            {
+                return true;
+            }
+            else //不存在边
+            {
+                return false;
+            }
+        }
+
+    }
+
     public class TMSimulatorServer : SocketDeviceSimulator
     {
 
         private readonly Regex _check_load = new Regex(@"CHECK LOAD\s+(\d)+\s+(A|B)\s*");
         private readonly Regex _move_arm = new Regex(@"(PLACE|PICK)\s+(\d+)\s+ARM\s+(A|B)\s+(\w{4})\s*");
         private readonly Regex _move_wafer = new Regex(@"(PLACE|PICK)\s+(\d+)\s+ARM\s+(A|B)\s*");
+        private int _currentStation = 1;
+        private GraphAdjMatrix<int> _Graph = new GraphAdjMatrix<int>(10);
+        private Dictionary<int, int> station2node = new Dictionary<int, int>()
+        {
+            {5,1},
+            {9,2},
+            {2,3},
+            {3,4},
+            {4,5},
+            {12,6},
+            {13,8},
+        };
 
         private PeriodicJob _HwThread;
         public TMSimulatorServer() : base(1108, -1, "\r", ' ')
         {
             _HwThread = new PeriodicJob(500, OnSendEvent, "honghuRobot", true);
+            for (int i = 1; i <= 9; ++i)
+            {
+                _Graph.SetNode(i, new Node<int>(i));
+                _Graph.SetMatrix(i, i, 1);
+            }
+
+            _Graph.SetMatrix(1, 2, 1);
+            _Graph.SetMatrix(1, 3, 1);
+            _Graph.SetMatrix(1, 4, 2);
+            _Graph.SetMatrix(1, 5, 2);
+            _Graph.SetMatrix(1, 6, 1.5f);
+            _Graph.SetMatrix(1, 7, 2);
+            _Graph.SetMatrix(1, 8, 1.5f);
+            _Graph.SetMatrix(1, 9, 2);
+
+            _Graph.SetMatrix(2, 3, 2);
+            _Graph.SetMatrix(2, 4, 2);
+            _Graph.SetMatrix(2, 5, 1);
+            _Graph.SetMatrix(2, 6, 1.5f);
+            _Graph.SetMatrix(2, 7, 2);
+            _Graph.SetMatrix(2, 8, 1.5f);
+            _Graph.SetMatrix(2, 9, 2);
+            
+            _Graph.SetMatrix(3, 4, 1);
+            _Graph.SetMatrix(3, 5, 1);
+            _Graph.SetMatrix(3, 6, 1.5f);
+            _Graph.SetMatrix(3, 7, 2);
+            _Graph.SetMatrix(3, 8, 1.5f);
+            _Graph.SetMatrix(3, 9, 2);
+            
+            _Graph.SetMatrix(4, 5, 1);
+            _Graph.SetMatrix(4, 6, 2);
+            _Graph.SetMatrix(4, 7, 2.5f);
+            _Graph.SetMatrix(4, 8, 2);
+            _Graph.SetMatrix(4, 9, 2.5f);
+            
+            _Graph.SetMatrix(5, 6, 2);
+            _Graph.SetMatrix(5, 7, 2.5f);
+            _Graph.SetMatrix(5, 8, 1);
+            _Graph.SetMatrix(5, 9, 1.5f);
+            
+            _Graph.SetMatrix(6, 7, .5f);
+            _Graph.SetMatrix(6, 8, 1);
+            _Graph.SetMatrix(6, 9, 1.5f);
+            
+            _Graph.SetMatrix(7, 8, 1.5f);
+            _Graph.SetMatrix(7, 9, 1f);
+
         }
 
         private bool OnSendEvent()
@@ -127,9 +376,11 @@ namespace EfemDualSimulator.Views
                 string slot = result.Groups[3].Value;
                 string arm = result.Groups[4].Value;
                 string dir = result.Groups[5].Value;
-
-                Thread.Sleep(2000);
+                // 01 VCEA 02 VCEB 03 PMA 04 PMB 05 PMC 6/7 cooling1 8/9 cooling2
+                int sleepTime = Convert.ToInt32(_Graph.GetMatrix(_currentStation, station2node[Convert.ToInt32(station)]) * 4000);
+                Thread.Sleep(sleepTime);
                 OnWriteMessage("_RDY");
+                _currentStation = station2node[Convert.ToInt32(station)];
             }
             else if (_move_wafer.IsMatch(str))
             {
@@ -141,9 +392,11 @@ namespace EfemDualSimulator.Views
                 string slot = result.Groups[3].Value;
                 string arm = result.Groups[4].Value;
 
-                Thread.Sleep(2000);
+                int sleepTime = Convert.ToInt32(_Graph.GetMatrix(_currentStation, station2node[Convert.ToInt32(station)]) * 4000);
+                Thread.Sleep(sleepTime);
                 string msg = "_RDY";
                 OnWriteMessage(msg);
+                _currentStation = Convert.ToInt32(station2node[Convert.ToInt32(station)]);
             }
             else if (new Regex(@"RQ WAF_CEN DATA.*").IsMatch(str))
             {

+ 17 - 0
Mars/JetMainframe/Devices/HongHuVCE.cs

@@ -246,14 +246,31 @@ namespace JetMainframe.Devices
             {"675","GEN5 EN: inputs are in illegal transition" },
             {"L13","由于检测到突片,动作被禁止" },
             {"L14","检测到安全开关错误" },
+            {"K9","由于动作连锁导致的异常" },
+            {"K13","盒子状态互锁报警, 料盒互锁,平台上无料盒,禁止运动 Z 轴 " },
+            {"K21","载台上料盒没有取走" },
+            {"K29","设备收到非法的操作指令" },
+            {"K60","关门防夹传感器报警" },
+            {"K70","设备停止" },
             {"K114","防夹光栅报警" },
             {"K115","舱门上限报警" },
             {"K116","舱门下限报警 " },
+            {"K117","急停报警" },
             {"K118","位置未被引用" },
             {"K119","Z 轴报警" },
             {"K120","R 轴报警 " },
+            {"K121","Z 轴超限位报警 " },
             {"K122","VCE 安全信号未亮起,可能是robot Abort,需做TMHome才能给到" },
+            {"K123","Z 轴未使能" },
             {"K124","R 轴未使能" },
+            {"K125","盒子状态互锁报警, 料盒互锁,平台上无料盒,禁止运动 Z 轴" },
+            {"K158","凸片传感器报警(对于双料盒型号为,左侧料盒凸片报警)" },
+            {"K159","右侧料盒凸片报警(仅双料盒型号)" },
+            {"K160","门未关报警,门没有关好,禁止 Z 轴运动" },
+            {"K161","门板覆盖件报警,门板覆盖件缺失,禁止 Z 轴运动" },
+            {"K162","R 轴不在原位" },
+            {"K163","Z 轴不在上下料位" },
+            {"K164","门未打开报警" },
         };
 
         protected string EventSlotMapAvailable = "SLOT_MAP_AVAILABLE";