Browse Source

修改查询高度相关代码,包括手臂Goto和delay,高度传感器driver更新等,由于传感器数据格式和协议所述不一致,仍需联系厂商修改
修复PMProcess Start失败后依旧执行的bug

zhouhr 3 weeks ago
parent
commit
8ee7b929cb

+ 25 - 3
FrameworkLocal/RTEquipmentLibrary/HardwareUnits/Robots/HongHu/HongHuVR.cs

@@ -479,6 +479,14 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.HongHu
 
             _currentStep = VRStep.Goto;
             _status = RState.Running;
+            if (slot == 1)
+            {
+                return _SendCommand($"GOTO N {_StationNumbers[station]} ARM {Hand2Arm(hand)} R EX");
+            }
+            if (slot == 2)
+            {
+                return _SendCommand($"GOTO N {_StationNumbers[station]} ARM {Hand2Arm(hand)} R RE");
+            }
             SetRobotMovingInfo(RobotAction.Rotating, hand, station);
             return _SendCommand($"GOTO N {_StationNumbers[station]} ARM {Hand2Arm(hand)}");
         }
@@ -808,9 +816,23 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.HongHu
                         {
                             //WAF_CEN RT 0498152 290861 0542109 290798 LFT 0379105 290802 0620109 290901 001562 000145
                             string[] _msgs = RevMsg.Split(' ');
-                            EV.PostAlarmLog("TMRobot",$"右传感器 => 晶圆R轴前缘:{Convert.ToDouble(_msgs[2])/1000}mm 晶圆T轴前缘:{Convert.ToDouble(_msgs[3]) / 1000}° 晶圆R轴后缘:{Convert.ToDouble(_msgs[4]) / 1000}mm 晶圆T轴后缘:{Convert.ToDouble(_msgs[5]) / 1000}°\n" +
-                                $"左传感器 => 晶圆R轴前缘:{Convert.ToDouble(_msgs[7]) / 1000}mm 晶圆T轴前缘:{Convert.ToDouble(_msgs[8]) / 1000}° 晶圆R轴后缘:{Convert.ToDouble(_msgs[9]) / 1000}mm 晶圆T轴后缘:{Convert.ToDouble(_msgs[10]) / 1000}°\n" +
-                                $"晶圆偏心数据 => 晶圆R轴方向偏心:{Convert.ToDouble(_msgs[11]) / 1000}mm 晶圆T轴方向偏心:{Convert.ToDouble(_msgs[12]) / 1000}°");
+                            try
+                            {
+                                EV.PostAlarmLog("TMRobot", $"右传感器 => 晶圆R轴前缘:{Convert.ToDouble(_msgs[2]) / 1000}mm 晶圆T轴前缘:{Convert.ToDouble(_msgs[3]) / 1000}° 晶圆R轴后缘:{Convert.ToDouble(_msgs[4]) / 1000}mm 晶圆T轴后缘:{Convert.ToDouble(_msgs[5]) / 1000}°\n" +
+                                    $"左传感器 => 晶圆R轴前缘:{Convert.ToDouble(_msgs[7]) / 1000}mm 晶圆T轴前缘:{Convert.ToDouble(_msgs[8]) / 1000}° 晶圆R轴后缘:{Convert.ToDouble(_msgs[9]) / 1000}mm 晶圆T轴后缘:{Convert.ToDouble(_msgs[10]) / 1000}°\n" +
+                                    $"晶圆偏心数据 => 晶圆R轴方向偏心:{Convert.ToDouble(_msgs[11]) / 1000}mm 晶圆T轴方向偏心:{Convert.ToDouble(_msgs[12]) / 1000}°");
+                            }
+                            catch
+                            {
+                                string reason = $"解析异常,回复格式不符合手册,原始字符串:{RevMsg}|空格分割后如下\r\n";
+                                int idx = 0;
+                                foreach (string msg_raw in _msgs)
+                                {
+                                    reason += $"[{idx}]:[{msg_raw}],";
+                                    ++idx;
+                                }
+                                EV.PostAlarmLog("TMRobot", reason);
+                            }
                         }
                         else
                         {

+ 10 - 4
FrameworkLocal/RTEquipmentLibrary/HardwareUnits/SerialPortSensor/ShenPuHeightSensor.cs

@@ -56,8 +56,9 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.SerialPortSensor
 
         public bool QueryHeight()
         {
-            _IsNewHeight = true;
+            _IsNewHeight = false;
             CurrentHeight = -1;
+            EV.PostInfoLog(_module.ToString(), "开始查询");
             return _serialport.Write(QueryMsg);
         }
 
@@ -73,13 +74,18 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.SerialPortSensor
             {
                 List<byte> _msgsAsList= msgs.ToList();
                 //舍去前段 只需要最后的一段保证时效性
-                for (int idx_last = _msgsAsList.Count -3; idx_last > 3; idx_last -- )
+                for (int idx_last = _msgsAsList.Count -3; idx_last >= 2; idx_last -- )
                 {
-                    if (_msgsAsList[idx_last] == 0x04 && _msgsAsList[idx_last - 1] == 0x03 && _msgsAsList[idx_last - 2] == 0x01 && idx_last + 6 < _msgsAsList.Count -1 )
+                    if (_msgsAsList[idx_last] == 0x04 && _msgsAsList[idx_last - 1] == 0x03 && _msgsAsList[idx_last - 2] == 0x01 && idx_last + 4 < _msgsAsList.Count -1 )
                     {
                         byte[] _height_hex = new byte[] { _msgsAsList[idx_last + 1], _msgsAsList[idx_last + 2], _msgsAsList[idx_last + 3], _msgsAsList[idx_last + 4] };
+                        string strformat = _msgsAsList[idx_last + 1].ToString().PadLeft(2, '0')
+                            + _msgsAsList[idx_last + 2].ToString().PadLeft(2, '0') + _msgsAsList[idx_last + 3].ToString().PadLeft(2, '0') + _msgsAsList[idx_last + 4].ToString().PadLeft(2, '0');
                         _IsNewHeight = true;
-                        CurrentHeight = Convert.ToInt32(_height_hex) * 0.0001;
+                        string HexMsg = "";
+                        _msgsAsList.ForEach(x => HexMsg += x.ToString().PadLeft(2,'0'));
+                        EV.PostInfoLog(_module.ToString(), $"收到高度信息, msg:{HexMsg}");
+                        CurrentHeight = Convert.ToInt32(strformat, 16) * 0.0001;
                         break;
                     }
                 }

+ 2 - 0
FrameworkLocal/RTModuleLibrary/TMModules/TMEntityBase.cs

@@ -43,6 +43,7 @@ namespace MECF.Framework.RT.ModuleLibrary.TMModules
             SaveSpeeding,
             QuerySpeeding,
             QueryHeight,
+            SwapCooling,
         }
 
         public enum MSG
@@ -80,6 +81,7 @@ namespace MECF.Framework.RT.ModuleLibrary.TMModules
             SaveSpeed,
             QuerySpeed,
             CheckHeight,
+            SwapCooling,
 
         }
         

+ 1 - 1
JetVirgoPM/PMs/PMModule.cs

@@ -1915,7 +1915,7 @@ namespace JetVirgoPM.PMs
             {
                 //_processStatus = Resources.PMEntity_fStartProcess_RunRecipeFailed;
                 PostMsg(MSG.Error);
-                return true;  //do noting
+                return false;  //do noting
             }
             return true;
         }

+ 13 - 1
Mars/EfemDualSchedulerLib/Schedulers/SchedulerTMRobot.cs

@@ -40,9 +40,15 @@ namespace EfemDualSchedulerLib.Schedulers
         Extending,
         Retracting,
         Swapping,
+        QueryingAWC,
         Gotoing,
         ControllingPressure,
-
+        LeakChecking,
+        SetSpeeding,
+        SaveSpeeding,
+        QuerySpeeding,
+        QueryHeight,
+        SwapCooling,
     }
 
     public enum MSG
@@ -71,10 +77,16 @@ namespace EfemDualSchedulerLib.Schedulers
         ControlPressure,
         Error,
         Abort,
+        QueryAWC,
         AbortControlPressure,
         Align,
         CreateJob,
         StartJob,
+        SetSpeed,
+        SaveSpeed,
+        QuerySpeed,
+        CheckHeight,
+        SwapCooling,
 
     }
 

+ 342 - 67
Mars/EfemDualSchedulerLib/VCEDualAutoTransfer.cs

@@ -383,17 +383,6 @@ namespace EfemDualSchedulerLib
 
 
                 _cycleState = RState.Running;
-                //foreach (var pj in _lstProcessJobs)
-                //{
-                //    if (pj.ControlJobName == cj.Name)
-                //    {
-                //        pj.SetState(EnumProcessJobState.Processing);
-                //    }
-                //}
-                //if (cj.Module == ModuleName.VCEA.ToString())
-                //    _VCEAUnloadFlag = false;
-                //if (cj.Module == ModuleName.VCEB.ToString())
-                //    _VCEAUnloadFlag = false;
             }
 
             if (!_lstControlJobs.Exists(x => x.State == EnumControlJobState.Executing))
@@ -981,9 +970,9 @@ namespace EfemDualSchedulerLib
 
             //================2024-10-9 10:10:56 增加单边做完后unload功能===================
             //逻辑说明:最后一个cycle中出现complete将其vcemodule controljob等从中间剥离
-            
+
             //未整体cycle 但是一边已经做完
-            if (!_isCycleMode && CycleIndex == CycleNum && IsAutoUnLoad && _lstControlJobs.Exists(x=> x.State == EnumControlJobState.Completed))
+            if (!_isCycleMode && CycleIndex == CycleNum && IsAutoUnLoad && _lstControlJobs.Exists(x => x.State == EnumControlJobState.Completed))
             {
                 _lstControlJobs.FindAll(x => x.State == EnumControlJobState.Completed).ForEach(ctrljob =>
                 {
@@ -1175,6 +1164,7 @@ namespace EfemDualSchedulerLib
         {
             if (_TMRobot.IsAvailable)
             {
+                NotAllowStatusForRobot();
                 LetAlignWaferBackToRobot();//放开限制 埋点一层槽作为store缓存点 同时增加cooling swap策略
                 LetWaferGotoCooling();//cooling排除代码 可以优化空间当 保留一层的let in 作为中间存储层
                 PrepareWaferOnRBToPM();//手臂wafer到pm
@@ -1185,6 +1175,51 @@ namespace EfemDualSchedulerLib
             }
         }
 
+        private void NotAllowStatusForRobot()
+        {
+            if (_lstPms.Exists(x => x.IsAvailable))
+            {
+                if ((WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2) &&
+                    (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 3))))
+                {
+                    WaferInfo wafer = null;
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0))
+                        wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot,0);
+                    if (wafer == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                        wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot,2);
+
+                    if (wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                        return;
+
+                    if (_VceModules[Wafer2Vce(wafer)][wafer.OriginSlot] == MovingStatus.Idle)
+                    {
+                        _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0,(ModuleName)wafer.OriginStation, wafer.OriginSlot,(Hand)0));
+                        return;
+                    }
+                }
+
+                if ((WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3) &&
+                    (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 2))))
+                {
+                    WaferInfo wafer = null;
+                    if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1))
+                        wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 1);
+                    if (wafer == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
+                        wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 3);
+
+                    if (wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                        return;
+
+                    if (_VceModules[Wafer2Vce(wafer)][wafer.OriginSlot] == MovingStatus.Idle)
+                    {
+                        _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 1, (ModuleName)wafer.OriginStation, wafer.OriginSlot, (Hand)1));
+                        return;
+                    }
+
+                }
+            }
+        }
+
         //wafer在第一个cooling需求里 且状态是aligning的
         private void LetAlignWaferBackToRobot()
         {
@@ -1282,7 +1317,7 @@ namespace EfemDualSchedulerLib
                                     }
                                 }
 
-                                if (wafer1!=null && RobotIsAllEmpty && wafer1.ProcessState == EnumWaferProcessStatus.Idle)
+                                if (wafer1 != null && RobotIsAllEmpty && wafer1.ProcessState == EnumWaferProcessStatus.Idle)
                                 {
                                     _moveQueue.Add(new MoveItem(cooling.Module, 0, ModuleName.TMRobot, 0, 0));
                                     _VceModules[ctrljob.Module][wafer1.OriginSlot] = MovingStatus.WaitProcess;
@@ -1344,9 +1379,9 @@ namespace EfemDualSchedulerLib
             return false;
         }
 
-        private bool RobotIsAllEmpty => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0)&& 
-            WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) && 
-            WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 2) && 
+        private bool RobotIsAllEmpty => WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) &&
+            WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) &&
+            WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 2) &&
             WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 3);
 
         private void LetCoolWaferBackToVCE()
@@ -1364,7 +1399,7 @@ namespace EfemDualSchedulerLib
                         return;
                     }
                 }
-                else if(WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                else if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
                 {
                     WaferInfo wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 2);
                     if (_VceModules[Wafer2Vce(wafer)][wafer.OriginSlot] == MovingStatus.Idle)
@@ -1409,6 +1444,17 @@ namespace EfemDualSchedulerLib
         {
             if (_TMRobot.IsAvailable)
             {
+                /*
+                 * 拦截策略
+                 * 1.当PM有已经idle的 cooling上有没有做过的或者cooling上有
+                 * 2.
+                */
+
+                //if ((PMHasAvailable() && CoolingHasNeedProcessWafer()) || CoolingHasNeedProcessWafer())
+                //    return;
+                if ((PMHasAvailable() && CoolingHasNeedProcessWafer()) || CoolingHasNeedProcessWafer())
+                    return;
+
                 foreach (SchedulerBuffer cooling in _lstCooling)
                 {
                     if (!cooling.IsAvailable)
@@ -1517,9 +1563,31 @@ namespace EfemDualSchedulerLib
                             wafer = ctrljob.LotWafers[i + (ctrljob.LotWafers.Count / 2)];
                         }
 
-                        if (wafer == null || (!SequenceNeedPMsAvailable(NeedPMs(wafer)) && !SequenceNeedCoolingAvailable(NeedAlignCoolings(wafer))) || wafer.ProcessState == EnumWaferProcessStatus.Completed)
+                        if (wafer == null)
                             continue;
 
+                        if (wafer.ProcessState == EnumWaferProcessStatus.Completed)
+                            continue;
+
+                        //TAG : 首步 无Cooling下进入 PM占满 进入Cooling中缓存 cooling中未占满
+                        if (!SequenceNeedPMsAvailable(NeedPMs(wafer)) && SequenceNoNeedCoolingFirst(wafer) && HasCoolingCanBeUse)
+                        {
+                            //寻找available且无wafer的cooling层
+                            List<ModuleName> CanWorkCooling = new List<ModuleName>();
+                            _lstCooling.ForEach(x => CanWorkCooling.Add(x.Module));
+                            if (SearchEmptyCooling(CanWorkCooling, out ModuleName cooling, out int slot))
+                            {
+                                //nextslot.Add(wafer.OriginSlot, _destination);
+                                _moveQueue.Add(new MoveItem((ModuleName)wafer.OriginStation, wafer.OriginSlot, cooling, slot, 0));
+                                return;
+                            }
+                        }
+
+
+                        if (!SequenceNeedPMsAvailable(NeedPMs(wafer)) && !SequenceNeedCoolingAvailable(NeedAlignCoolings(wafer)))
+                            continue;
+
+
                         //如果是等待PM处理 找到可用的PM并装入任务 如果无可用的PM 就继续循环
                         if (!wafer.IsEmpty &&
                             SequenceNeedPMsAvailable(NeedPMs(wafer)) &&
@@ -1634,7 +1702,7 @@ namespace EfemDualSchedulerLib
                 return;
             }
         }
-        
+
 
         // 判断是否切换到下一个VCE的标识是什么?
         // 1. all wafer in cassette has run recipe
@@ -1755,13 +1823,13 @@ namespace EfemDualSchedulerLib
                                 WaferInfo wafer = WaferManager.Instance.GetWafer(cooling, slot);
                                 if (wafer.ProcessState == EnumWaferProcessStatus.Idle)
                                 {
-                                    _moveQueue.Add(new MoveItem(cooling, slot< 2 ? 0:1 , ModuleName.TMRobot, 0, Hand.Blade1));
+                                    _moveQueue.Add(new MoveItem(cooling, slot < 2 ? 0 : 1, ModuleName.TMRobot, 0, Hand.Blade1));
                                     _VceModules[Wafer2Vce(wafer)][wafer.OriginSlot] = MovingStatus.WaitProcess;
                                     RunTMRobotTask();
                                     return;
                                 }
                             }
-                            
+
 
                             ControlJobInfo ctrljob = _lstControlJobs.Find(x => x.State == EnumControlJobState.Executing);
                             Dictionary<int, ModuleName> nextslot = new Dictionary<int, ModuleName>();
@@ -1891,7 +1959,7 @@ namespace EfemDualSchedulerLib
                             if (_tmwafer != null && _tmwafer.ProcessState == EnumWaferProcessStatus.Completed &&
                                 !WaferCoolTaskIsFree(_tmwafer))
                             {
-                                EV.PostInfoLog("TM", $"手臂有做完工艺的wafer 但cooling不空 等着吧");
+                                //EV.PostInfoLog("TM", $"手臂有做完工艺的wafer 但cooling不空 等着吧");
                                 return;
                             }
 
@@ -1959,7 +2027,7 @@ namespace EfemDualSchedulerLib
             }
 
         }
-        
+
 
         //空手下的wafer动作
         private void HandPrepare()
@@ -2101,16 +2169,19 @@ namespace EfemDualSchedulerLib
                         if (_wafer != null && _wafer.ProcessState == EnumWaferProcessStatus.Completed && _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] != MovingStatus.Idle)
                         {
                             //2024-03-22 09:33:25 增加 没有Cooling的调度 此处是进cooling
-                            if (!CheckWaferNoCoolingTask(_wafer) && SequenceNeedCoolingsAvailable(_wafer).Count > 0)
+                            if (!CheckWaferNoCoolingTask(_wafer))
                             {
-                                _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
-                                _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0, SequenceNeedCoolingsAvailable(_wafer)[0].Key, SequenceNeedCoolingsAvailable(_wafer)[0].Value, Hand.Blade1));
-                                RunTMRobotTask();
-                                return;
+                                if (SequenceNeedCoolingsAvailable(_wafer).Count > 0)
+                                {
+                                    _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
+                                    _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0, SequenceNeedCoolingsAvailable(_wafer)[0].Key, SequenceNeedCoolingsAvailable(_wafer)[0].Value, Hand.Blade1));
+                                    RunTMRobotTask();
+                                    return;
+                                }
                             }
-
+                            
                             //此处是不进cooling的 判断sequence是否进入
-                            if (CheckWaferNoCoolingTask(_wafer))
+                            else
                             {
                                 _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.Idle;
                                 _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0, (ModuleName)_wafer.OriginStation, _wafer.OriginSlot, Hand.Blade1));
@@ -2135,16 +2206,20 @@ namespace EfemDualSchedulerLib
 
                         if (_wafer != null && _wafer.ProcessState == EnumWaferProcessStatus.Completed && _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] != MovingStatus.Idle)
                         {
-                            if (!CheckWaferNoCoolingTask(_wafer) && SequenceNeedCoolingsAvailable(_wafer).Count > 0)
+                            if (!CheckWaferNoCoolingTask(_wafer))
                             {
-                                _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
-                                _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 1, SequenceNeedCoolingsAvailable(_wafer)[0].Key, SequenceNeedCoolingsAvailable(_wafer)[0].Value, Hand.Blade2));
-                                RunTMRobotTask();
-                                return;
+                                if (SequenceNeedCoolingsAvailable(_wafer).Count > 0)
+                                {
+                                    _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
+                                    _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 1, SequenceNeedCoolingsAvailable(_wafer)[0].Key, SequenceNeedCoolingsAvailable(_wafer)[0].Value, Hand.Blade2));
+                                    RunTMRobotTask();
+                                    return;
+                                }
+
                             }
 
                             //此处是不进cooling的 判断sequence是否进入
-                            if (CheckWaferNoCoolingTask(_wafer))
+                            else
                             {
                                 _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.Idle;
                                 _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 1, (ModuleName)_wafer.OriginStation, _wafer.OriginSlot, Hand.Blade2));
@@ -2159,8 +2234,34 @@ namespace EfemDualSchedulerLib
                 //没有cooling可以进
                 else
                 {
+
                     if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 0) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 2))
                     {
+                        if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
+                        {
+                            WaferInfo _wafer = null;
+                            if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1))
+                            {
+                                _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 1);
+                            }
+
+                            if (_wafer == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
+                            {
+                                _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 3);
+                            }
+                            //2024-10-24 13:20:56 增加进cooling的swap调度
+                            if (_wafer != null && _wafer.ProcessState == EnumWaferProcessStatus.Completed && ExsitCanSwapCooling(_wafer, out ModuleName cooling, out int slot))
+                            {
+                                _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
+                                _moveQueue.Add(new MoveItem(cooling, slot, ModuleName.TMRobot, 0, Hand.Blade1));
+                                _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 1, cooling, slot, Hand.Blade2));
+                                RunTMRobotTask();
+                                return;
+                            }
+                        }
+                        
+                        if ((PMHasAvailable() && CoolingHasNeedProcessWafer()))
+                            return;
 
                         //需要等待cooling 将其放回去
                         if (HasCoolingCanBeBack())
@@ -2182,38 +2283,61 @@ namespace EfemDualSchedulerLib
                                 else
                                     wafer = WaferManager.Instance.GetWafer(CanBackCooling.Key, 3);
                             }
-                            _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade1));
-                            RunTMRobotTask();
-                            return;
+                            if (wafer.ProcessState == EnumWaferProcessStatus.Completed)
+                            {
+                                _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade1));
+                                RunTMRobotTask();
+                                return;
+                            }
+                            else
+                            {
+                                if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
+                                {
+                                    WaferInfo waferonhand = new WaferInfo();
+                                    if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 1))
+                                        waferonhand = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 1);
+                                    if (waferonhand == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 3))
+                                        waferonhand = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 3);
+                                    if (waferonhand.ProcessState == EnumWaferProcessStatus.Completed)
+                                    {
+                                        _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, ModuleName.TMRobot, 0, Hand.Blade1));
+                                        RunTMRobotTask();
+                                        return;
+                                    }
+                                }
+                            }
                         }
                     }
 
                     if (WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 1) && WaferManager.Instance.CheckNoWafer(ModuleName.TMRobot, 3))
                     {
-                        //if (HasNoProcessCanSwap(out ModuleName canswapcooling, out int canswapslot))
-                        //{
-                        //    if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
-                        //    {
-                        //        WaferInfo _wafer = null;
-                        //        if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0))
-                        //        {
-                        //            _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
-                        //        }
-                        //
-                        //        if (_wafer == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
-                        //        {
-                        //            _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 2);
-                        //        }
-                        //
-                        //        if (_wafer != null && _wafer.ProcessState == EnumWaferProcessStatus.Completed && _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] != MovingStatus.Idle)
-                        //        {
-                        //            _moveQueue.Add(new MoveItem(canswapcooling, canswapslot < 2 ? 0 : 1, ModuleName.TMRobot, 1, Hand.Blade2));
-                        //            _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0, canswapcooling, canswapslot < 2 ? 0 : 1, Hand.Blade1));
-                        //            RunTMRobotTask();
-                        //            return;
-                        //        }
-                        //    }
-                        //}
+                        if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                        {
+                            WaferInfo _wafer = null;
+                            if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0))
+                            {
+                                _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
+                            }
+
+                            if (_wafer == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                            {
+                                _wafer = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 2);
+                            }
+
+                            //2024-10-24 13:20:56 增加进cooling的swap调度
+                            if (_wafer != null && _wafer.ProcessState == EnumWaferProcessStatus.Completed && ExsitCanSwapCooling(_wafer, out ModuleName cooling, out int slot))
+                            {
+                                _VceModules[Wafer2Vce(_wafer)][_wafer.OriginSlot] = MovingStatus.StartCool;
+                                _moveQueue.Add(new MoveItem(cooling, slot, ModuleName.TMRobot, 1, Hand.Blade2));
+                                _moveQueue.Add(new MoveItem(ModuleName.TMRobot, 0, cooling, slot, Hand.Blade1));
+                                RunTMRobotTask();
+                                return;
+                            }
+                        }
+
+
+                        if ((PMHasAvailable() && CoolingHasNeedProcessWafer()))
+                            return;
 
                         if (HasCoolingCanBeBack())
                         {
@@ -2234,9 +2358,29 @@ namespace EfemDualSchedulerLib
                                 else
                                     wafer = WaferManager.Instance.GetWafer(CanBackCooling.Key, 3);
                             }
-                            _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade2));
-                            RunTMRobotTask();
-                            return;
+                            if (wafer.ProcessState == EnumWaferProcessStatus.Completed)
+                            {
+                                _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade2));
+                                RunTMRobotTask();
+                                return;
+                            }
+                            else
+                            {
+                                if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0) || WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                                {
+                                    WaferInfo waferonhand = new WaferInfo();
+                                    if (WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 0))
+                                        waferonhand = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 0);
+                                    if (waferonhand == null && WaferManager.Instance.CheckHasWafer(ModuleName.TMRobot, 2))
+                                        waferonhand = WaferManager.Instance.GetWafer(ModuleName.TMRobot, 2);
+                                    if (waferonhand.ProcessState == EnumWaferProcessStatus.Completed)
+                                    {
+                                        _moveQueue.Add(new MoveItem(CanBackCooling.Key, CanBackCooling.Value, ModuleName.TMRobot, 1, Hand.Blade2));
+                                        RunTMRobotTask();
+                                        return;
+                                    }
+                                }
+                            }
                         }
                     }
 
@@ -2462,6 +2606,51 @@ namespace EfemDualSchedulerLib
             return -1;
         }
 
+        private bool ExsitCanSwapCooling(WaferInfo wafer, out ModuleName cooling, out int slot)
+        {
+            cooling = ModuleName.System;
+            slot = -1;
+            foreach (ModuleName _cooling in _lstProcessJobs.Find(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name && x.Sequence.Steps.Count > 1).Sequence.Steps[wafer.NextSequenceStep].StepModules)
+            {
+                string md = _cooling.ToString();
+                if (ModuleHelper.IsCoolingBuffer(_cooling) && ModuleHelper.IsInstalled(_cooling))
+                {
+                    if (WaferManager.Instance.CheckHasWafer(md, 0) && WaferManager.Instance.CheckHasWafer(md, 1))
+                    {
+                        WaferInfo _wafer = null;
+                        if (WaferManager.Instance.CheckHasWafer(md, 0))
+                            _wafer = WaferManager.Instance.GetWafer(_cooling, 0);
+                        if (_wafer == null && WaferManager.Instance.CheckHasWafer(md, 1))
+                            _wafer = WaferManager.Instance.GetWafer(_cooling, 1);
+
+                        if (_wafer != null && _wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                        {
+                            cooling = _cooling;
+                            slot = 0;
+                            return true;
+                        }
+                    }
+                    if (WaferManager.Instance.CheckHasWafer(md, 2) && WaferManager.Instance.CheckHasWafer(md, 3))
+                    {
+                        WaferInfo _wafer = null;
+                        if (WaferManager.Instance.CheckHasWafer(md, 2))
+                            _wafer = WaferManager.Instance.GetWafer(_cooling, 2);
+                        if (_wafer == null && WaferManager.Instance.CheckHasWafer(md, 3))
+                            _wafer = WaferManager.Instance.GetWafer(_cooling, 3);
+
+                        if (_wafer != null && _wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                        {
+                            cooling = _cooling;
+                            slot = 1;
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+
         private List<KeyValuePair<ModuleName, int>> SequenceNeedCoolingsAvailable(WaferInfo wafer)
         {
             List<KeyValuePair<ModuleName, int>> Coolings = new List<KeyValuePair<ModuleName, int>>();
@@ -2487,6 +2676,54 @@ namespace EfemDualSchedulerLib
             return pj.Sequence.Steps.Count <= wafer.NextSequenceStep;
         }
 
+        //no matter has wafer or not
+        private bool PMHasAvailable()
+        {
+            return _lstPms.Exists(x => x.IsAvailable);
+        }
+
+        private bool CoolingHasEmptySlot()
+        {
+            return _lstCooling.Exists(x => (WaferManager.Instance.CheckNoWafer(x.Module, 0) && WaferManager.Instance.CheckNoWafer(x.Module, 1)) ||
+                                          (WaferManager.Instance.CheckNoWafer(x.Module, 2) && WaferManager.Instance.CheckNoWafer(x.Module, 3)));
+        }
+
+        private bool CoolingHasNeedProcessWafer()
+        {
+            bool NeedProcessFlag = false;
+
+            _lstCooling.ForEach(x => {
+
+                if (!NeedProcessFlag)
+                {
+                    if (WaferManager.Instance.CheckHasWafer(x.Module, 0) || WaferManager.Instance.CheckHasWafer(x.Module, 1))
+                    {
+                        WaferInfo wafer = new WaferInfo();
+                        if (WaferManager.Instance.CheckHasWafer(x.Module, 0))
+                            wafer = WaferManager.Instance.GetWafer(x.Module, 0);
+                        if (wafer == null && WaferManager.Instance.CheckHasWafer(x.Module, 1))
+                            wafer = WaferManager.Instance.GetWafer(x.Module, 1);
+                        if (wafer != null && wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                            NeedProcessFlag = true;
+                    }
+
+                    if (WaferManager.Instance.CheckHasWafer(x.Module, 2) || WaferManager.Instance.CheckHasWafer(x.Module, 3))
+                    {
+                        WaferInfo wafer = new WaferInfo();
+                        if (WaferManager.Instance.CheckHasWafer(x.Module, 2))
+                            wafer = WaferManager.Instance.GetWafer(x.Module, 2);
+                        if (wafer == null && WaferManager.Instance.CheckHasWafer(x.Module, 3))
+                            wafer = WaferManager.Instance.GetWafer(x.Module, 3);
+                        if (wafer != null && wafer.ProcessState != EnumWaferProcessStatus.Completed)
+                            NeedProcessFlag = true;
+                    }
+                }
+
+            });
+
+            return NeedProcessFlag;
+        }
+
         private bool WaferCoolTaskIsFree(WaferInfo wafer)
         {
             if (!_lstProcessJobs.Exists(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name && x.Sequence.Steps.Count > 1))
@@ -2520,6 +2757,43 @@ namespace EfemDualSchedulerLib
             return false;
         }
 
+
+        private bool SequenceNoNeedCoolingFirst(WaferInfo wafer)
+        {
+            if (_lstProcessJobs.Exists(x => x.Sequence.Name == wafer.ProcessJob.Sequence.Name && !ModuleHelper.IsCoolingBuffer(x.Sequence.Steps[0].StepModules[0])))
+                return true;
+            else
+                return false;
+        }
+
+
+        private bool SearchEmptyCooling(List<ModuleName> needCoolings, out ModuleName cooling, out int slot)
+        {
+            cooling = ModuleName.System;
+            slot = -1;
+            foreach (var mod in needCoolings)
+            {
+                if (ModuleHelper.IsCoolingBuffer(mod) && ModuleHelper.IsInstalled(mod))
+                {
+                    if (WaferManager.Instance.CheckNoWafer(mod, 0) && WaferManager.Instance.CheckNoWafer(mod, 1))
+                    {
+                        cooling = mod;
+                        slot = 0;
+                        return true;
+                    }
+        
+                    if (WaferManager.Instance.CheckNoWafer(mod, 2) && WaferManager.Instance.CheckNoWafer(mod, 3))
+                    {
+                        cooling = mod;
+                        slot = 1;
+                        return true;
+                    }
+                }
+            }
+        
+            return false;
+        }
+
         private bool SequenceNeedCoolingAvailable(List<ModuleName> needCoolings)
         {
             foreach (var module in needCoolings)
@@ -2685,6 +2959,7 @@ namespace EfemDualSchedulerLib
             return ModuleName.TMRobot;
         }
 
+
         private ModuleName SearchCooling(List<ModuleName> needCoolings, Dictionary<int,ModuleName> CoolingChoice)
         {
             foreach (var module in needCoolings)

+ 1 - 1
Mars/EfemDualSimulator/Views/Simu_HongHuVceView.xaml.cs

@@ -75,7 +75,7 @@ namespace EfemDualSimulator.Views
             {
                 //OnWriteMessage("ERR 711" + EOF);
                 OnWriteMessage("_RDY" + EOF);
-                Thread.Sleep(2000);
+                Thread.Sleep(3000);
                 OnWriteMessage("_BKGRDY" + EOF);
 
                 if (message.Contains("00,A,GO"))

+ 3 - 9
Mars/JetMainframe/Devices/HongHuVCE.cs

@@ -444,7 +444,7 @@ namespace JetMainframe.Devices
                                 if (errorcode != "A11")
                                 {
                                     _status = RState.Failed;
-                                    EV.PostAlarmLog(_moduleName.ToString(), reason);
+                                    EV.PostAlarmLog(_moduleName.ToString(), $"{_moduleName.ToString()}:"+reason);
                                 }
                                 else
                                 {
@@ -737,7 +737,7 @@ namespace JetMainframe.Devices
             {
                 errorcode = "";
                 //若不匹配
-                reason = "回复消息不符合标准格式";
+                reason = $"回复消息不符合标准格式 回复消息为:{msg} Hex:{msg.ToArray()}";
             }
         }
         /// <summary>
@@ -946,13 +946,6 @@ namespace JetMainframe.Devices
 
         protected bool CheckVceStatus()
         {
-
-            //if (Status == RState.Init)
-            //{
-            //    EV.PostWarningLog(_moduleName.ToString(), "VCE is not homed, please home first.");
-            //    return false;
-            //}
-            //else 
             if (Status == RState.Running)
             {
                 EV.PostInfoLog(_moduleName.ToString(), "VCE is busy, please wait a minute");
@@ -966,5 +959,6 @@ namespace JetMainframe.Devices
 
             return true;
         }
+        
     }
 }

+ 1 - 0
Mars/JetMainframe/JetMainframe.csproj

@@ -71,6 +71,7 @@
     <Compile Include="TMs\TM\MFPMSwapRoutine.cs" />
     <Compile Include="TMs\TM\MFPumpRoutine.cs" />
     <Compile Include="TMs\TM\MFRetractRoutine.cs" />
+    <Compile Include="TMs\TM\MFSwapCoolingRoutine.cs" />
     <Compile Include="TMs\TM\MFSwapRoutine.cs" />
     <Compile Include="TMs\TM\MFVentRoutine.cs" />
     <Compile Include="TMs\TM\TMEntity.cs" />

+ 23 - 6
Mars/JetMainframe/TMs/TM/CheckArmHeightRoutine.cs

@@ -1,5 +1,6 @@
 using Aitex.Core.RT.Event;
 using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
 using Aitex.Sorter.Common;
 using JetMainframe.Devices;
 using MECF.Framework.Common.Equipment;
@@ -18,9 +19,11 @@ namespace JetMainframe.TMs.TM
         public enum CheckArmHeightStep
         {
             Blade1Goto,
+            Blade1GotoBack,
             WaitForBlade1Stable,
             CalcuteBlade1,
             Blade2Goto,
+            Blade2GotoBack,
             WaitForBlade2Stable,
             CalcuteBlade2,
             EndDelay,
@@ -29,7 +32,7 @@ namespace JetMainframe.TMs.TM
         private ShenPuHeightSensor _heightSensor;
         private ITransferRobot _robot;
         private int GotoTimeOut = 10 * 1000;//Goto动作时间
-        private int QueryTimeOut = 5 * 1000;//检查高度时间
+        private int QueryTimeOut = 60 * 1000;//检查高度时间
 
 
         public CheckArmHeightRoutine(ModuleName module, ITransferRobot robot, ShenPuHeightSensor heightSensor) : base(module.ToString())
@@ -43,6 +46,7 @@ namespace JetMainframe.TMs.TM
         public RState Start(params object[] objs)
         {
             Reset();
+            GotoTimeOut = SC.GetValue<int>("TM.MotionTimeout") * 1000;
             return Runner.Start(Module, Name);
         }
 
@@ -50,11 +54,13 @@ namespace JetMainframe.TMs.TM
         public RState Monitor()
         {
             Runner.Run(CheckArmHeightStep.Blade1Goto, Blade1Goto, CheckRobotDone, GotoTimeOut)
-                  .Delay(CheckArmHeightStep.WaitForBlade1Stable, 1000)
+                  .Delay(CheckArmHeightStep.WaitForBlade1Stable, 3000)
                   .Run(CheckArmHeightStep.CalcuteBlade1, QuerySensor, CheckSensor1Done, QueryTimeOut)
+                  .Run(CheckArmHeightStep.Blade1GotoBack, Blade1GotoBack, CheckRobotDone, GotoTimeOut)
                   .Run(CheckArmHeightStep.Blade2Goto, Blade2Goto, CheckRobotDone, GotoTimeOut)
-                  .Delay(CheckArmHeightStep.WaitForBlade2Stable, 1000)
+                  .Delay(CheckArmHeightStep.WaitForBlade2Stable, 3000)
                   .Run(CheckArmHeightStep.CalcuteBlade2, QuerySensor, CheckSensor2Done, QueryTimeOut)
+                  .Run(CheckArmHeightStep.Blade2GotoBack, Blade2GotoBack, CheckRobotDone, GotoTimeOut)
                   .End(CheckArmHeightStep.EndDelay, NullFun, 500);
 
             return Runner.Status;
@@ -62,12 +68,22 @@ namespace JetMainframe.TMs.TM
 
         private bool Blade1Goto()
         {
-            return _robot.Goto(ModuleName.StageA, Hand.Blade1,0,out _);
+            return _robot.Goto(ModuleName.StageA, Hand.Blade1,1,out _);
+        }
+
+        private bool Blade1GotoBack()
+        {
+            return _robot.Goto(ModuleName.StageA, Hand.Blade1, 2, out _);
         }
 
         private bool Blade2Goto()
         {
-            return _robot.Goto(ModuleName.StageA, Hand.Blade2, 0, out _);
+            return _robot.Goto(ModuleName.StageA, Hand.Blade2, 1, out _);
+        }
+
+        private bool Blade2GotoBack()
+        {
+            return _robot.Goto(ModuleName.StageA, Hand.Blade2, 2, out _);
         }
 
         private bool CheckSensor1Done()
@@ -90,7 +106,8 @@ namespace JetMainframe.TMs.TM
 
         private bool QuerySensor()
         {
-            return _heightSensor.QueryHeight() && !_heightSensor.IsNewHeight;
+
+            return _heightSensor.QueryHeight();
         }
 
         private bool CheckRobotDone()

+ 108 - 0
Mars/JetMainframe/TMs/TM/MFSwapCoolingRoutine.cs

@@ -0,0 +1,108 @@
+using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
+using Aitex.Sorter.Common;
+using JetEfemLib.Buffers;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Schedulers;
+using MECF.Framework.RT.EquipmentLibrary.LogicUnits;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JetMainframe.TMs.TM
+{
+    public class MFSwapCoolingRoutine : ModuleRoutineBase, IStepRoutine
+    {
+        public enum SwapCoolingStep
+        {
+            PickFromCooling,
+            DelayForRobot,
+            PlaceToCooling,
+            EndDelay,
+        }
+
+        ITransferRobot _robot = null;
+        int _MotionTimeout;
+        private BufferModule _coolingModule;
+        private ModuleName _targetModule;
+        private int _targetSlot;
+        private Hand _pickHand;
+        private Hand _placeHand;
+        private Pan panPick;
+        private Pan panPlace;
+
+        public MFSwapCoolingRoutine(ITransferRobot robot) : base("TMRobot")
+        {
+            _robot = robot;
+        }
+
+        public RState Start(params object[] objs)
+        {
+
+            Reset();
+            _MotionTimeout = SC.GetValue<int>($"TM.MotionTimeout") * 1000;
+            if (objs.Length == 1)
+            {
+                var swapItem = (Queue<MoveItem>)objs[0];
+                _targetModule = swapItem.Peek().SourceModule;
+                _targetSlot = swapItem.Peek().SourceSlot;
+                _pickHand = swapItem.Peek().RobotHand;
+                _placeHand = _pickHand == Hand.Blade2 ? Hand.Blade1 : Hand.Blade2;
+            }
+            else
+                return RState.Failed;
+
+            panPick = CheckForkForRobot(_targetModule, _targetSlot);
+            panPlace = CheckForkForRobot(ModuleName.TMRobot, (int)_placeHand);
+
+            return Runner.Start(Module, $"Swap with {_targetModule}");
+        }
+
+        public RState Monitor()
+        {
+            Runner.Run(SwapCoolingStep.PickFromCooling, PickFromCooling, CheckRobotDone, _MotionTimeout)
+                  .Delay(SwapCoolingStep.DelayForRobot, _delay_50ms)
+                  .Run(SwapCoolingStep.PlaceToCooling, PlaceToCooling, CheckRobotDone, _MotionTimeout)
+                  .End(SwapCoolingStep.EndDelay, NullFun, _delay_50ms);
+
+            return Runner.Status;
+        }
+
+        private bool PickFromCooling()
+        {
+            return _robot.Pick(_targetModule, _pickHand, _targetSlot, panPick, out _);
+        }
+
+        private bool PlaceToCooling()
+        {
+            return _robot.Place(_targetModule,_placeHand, _targetSlot, panPlace, out _);
+        }
+
+        private bool CheckRobotDone()
+        {
+            if (_robot.Status == RState.Running)
+            {
+                return false;
+            }
+            else if (_robot.Status == RState.End)
+            {
+                return true;
+            }
+            else
+            {
+                Runner.Stop($"TM Robot Place Extend failed, {_robot.Status}");
+                return true;
+            }
+        }
+
+
+        public void Abort()
+        {
+
+        }
+
+
+    }
+}

+ 35 - 4
Mars/JetMainframe/TMs/TM/TMEntity.cs

@@ -92,6 +92,7 @@ namespace JetMainframe.TMs.TM
         private readonly MFHomeRoutine _homeRoutine;
         private readonly MFPickRoutine _pickRoutine;
         private readonly MFPlaceRoutine _placeRoutine;
+        private readonly MFSwapCoolingRoutine _swapCoolingRoutine;
         private readonly MFVentRoutine _ventRoutine;
         private readonly MFPumpRoutine _pumpRoutine;
         private readonly MFPMPickRoutine _pickpmRoutine;
@@ -131,6 +132,7 @@ namespace JetMainframe.TMs.TM
             _homeRoutine = new MFHomeRoutine(module, _tm, _robot);
             _pickRoutine = new MFPickRoutine(module, _tm, _robot);
             _placeRoutine = new MFPlaceRoutine(module, _tm, _robot);
+            _swapCoolingRoutine = new MFSwapCoolingRoutine(_robot);
             _pumpRoutine = new MFPumpRoutine(_tm, module);
             _ventRoutine = new MFVentRoutine(_tm, module);
             _pickpmRoutine = new MFPMPickRoutine(_tm, _robot);
@@ -189,7 +191,7 @@ namespace JetMainframe.TMs.TM
 
             OP.Subscribe("VTM.Home", (cmd, args) =>
             {
-                PostMsg(MSG.Home,args);
+                PostMsg(MSG.Home, args);
                 return true;
             });
             OP.Subscribe("VTM.Pick", (cmd, args) =>
@@ -225,7 +227,7 @@ namespace JetMainframe.TMs.TM
             AnyStateTransition(MSG.Offline, fnOffline, FSM_STATE.SAME);
             AnyStateTransition(MSG.Home, fnHome, STATE.Initializing);
             AnyStateTransition((int)FSM_MSG.ALARM, fnAlarm, (int)STATE.Error);
-            
+
 
             //Home
             Transition(STATE.Initializing, FSM_MSG.TIMER, fnHomeTimeout, STATE.Idle);
@@ -241,6 +243,11 @@ namespace JetMainframe.TMs.TM
             Transition(STATE.Placing, FSM_MSG.TIMER, fnPlaceTimeout, STATE.Idle);
             Transition(STATE.Placing, MSG.Abort, fnAbortPlace, STATE.Idle);
 
+            //Swap
+            Transition(STATE.Idle, MSG.SwapCooling, fnStartSwapCooling, STATE.SwapCooling);
+            Transition(STATE.SwapCooling, FSM_MSG.TIMER, fnSwapCoolingTimeout, STATE.Idle);
+            Transition(STATE.SwapCooling, MSG.Abort, fnAbortSwapCooling, STATE.Idle);
+
             //Pump
             Transition(STATE.Idle, MSG.Pump, fnStartPump, STATE.Pumping);
             Transition(STATE.Pumping, FSM_MSG.TIMER, fnPumpTimeout, STATE.Idle);
@@ -292,7 +299,7 @@ namespace JetMainframe.TMs.TM
             Transition(STATE.Retracting, MSG.Abort, fnAbortRetract, STATE.Idle);
 
             //setspeed
-            Transition(STATE.Idle,MSG.SetSpeed,fnSetSpeed,STATE.SetSpeeding);
+            Transition(STATE.Idle, MSG.SetSpeed, fnSetSpeed, STATE.SetSpeeding);
             Transition(STATE.SetSpeeding, FSM_MSG.TIMER, fnSetSpeedTimeout, STATE.Idle);
             Transition(STATE.SetSpeeding, MSG.Abort, fnAbortSetSpeed, STATE.Idle);
 
@@ -335,7 +342,7 @@ namespace JetMainframe.TMs.TM
 
         private bool fnStartQueryAWC(object[] param)
         {
-            
+
             return true;
         }
 
@@ -590,11 +597,35 @@ namespace JetMainframe.TMs.TM
             return ret == RState.End;
         }
 
+        private bool fnStartSwapCooling(object[] param)
+        {
+            return _swapCoolingRoutine.Start(param) == RState.Running;
+        }
+
+        private bool fnSwapCoolingTimeout(object[] param)
+        {
+            RState ret = _swapCoolingRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(MSG.Error);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
+
+        private bool fnAbortSwapCooling(object[] param)
+        {
+            _swapCoolingRoutine.Abort();
+            return true;
+        }
+
         private bool fnAbortHome(object[] param)
         {
             _homeRoutine.Abort();
             return true;
         }
+
         //Extend
         private bool fnStartExtend(object[] param)
         {