Explorar o código

update VPW Initialize

chenkui hai 2 días
pai
achega
bfd0b53b4a

+ 8 - 0
PunkHPX8_RT/Config/System.sccfg

@@ -245,6 +245,14 @@
 			<config default="20.0" name="Error_Min" nameView="Error_Min" max="100.0" min="0" paramter="" tag="" unit="" type="Double"  description="This value defines the minimum flow, in liters per minute, below which this interlock will transition to an Error state."/>
 			<config default="30.0" name="Warning_Min" nameView="Warning_Min" max="100.0" min="0" paramter="" tag="" unit="" type="Double"  description="This value defines the minimum flow, in liters per minute, below which this interlock will transition to an Warning state.  Note corresponding Error_Min/Error_Max testing supersedes this test."/>
 		</configs>
+		<configs name="Plumbing" nameView="Plumbing">
+			<config default="15000" name="N2PurgeTime" nameView="N2PurgeTime" description="holdoff time for N2 purge." max="60000" min="0" paramter="" tag="" unit="ms" type="Integer" />
+			<config default="15000" name="FlowFaultHoldoffTime" nameView="FlowFaultHoldoffTime" description="wait holdoff time to check flow error." max="60000" min="0" paramter="" tag="" unit="ms" type="Integer" />
+			<config default="3.0" name="TotalFlowStartLowLimit" nameView="TotalFlowStartLowLimit" max="100.0" min="0" description="the low limit of total flow in the start period." paramter="" tag="" unit="" type="Double"/>
+			<config default="2.0" name="CellFlowStartLowLimit" nameView="TotalFlowStartLowLimit" max="100.0" min="0" description="the low limit of total flow in the start period." paramter="" tag="" unit="" type="Double"/>
+			<config default="2000" name="DegasEnableDelayTime" nameView="DegasEnableDelayTime" max="100.0" min="0" description="delay time of degas enable." paramter="" tag="" unit="ms" type="Integer" />
+			<config default="400" name="PurgeMotorSpeed" nameView="PurgeMotorSpeed" max="5000.0" min="0" description="rotation default velocity in homing period." paramter="" tag="" unit="rpm" type="Double" />
+		</configs>
 	</configs>
 	<configs name="Linmot" nameView="Linmot">
 		<config default="5000" name="LinmotHoldoffMilliseconds" nameView="LinmotHoldoffMilliseconds" description="Linmot Hold off Milliseconds" max="10000" min="1" paramter="" tag="" unit="ms" type="Integer"></config>

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/CanOpen/CanOpenAxis.cs

@@ -87,12 +87,22 @@ namespace PunkHPX8_RT.Devices.AXIS.CANOpen
         {
             lock (_operationLocker)
             {
-                if (_currentOperation==MotionOperation.Position&&_profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             
             return true;

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/Galil/GalilAxis.cs

@@ -88,12 +88,22 @@ namespace PunkHPX8_RT.Devices.AXIS.Galil
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             return true;
         }

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/GalilLipsel/GalilLipselAxis.cs

@@ -88,12 +88,22 @@ namespace PunkHPX8_RT.Devices.AXIS.GalilLipsel
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             return true;
         }

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/GalilRotation/GalilRotationAxis.cs

@@ -97,12 +97,22 @@ namespace PunkHPX8_RT.Devices.AXIS.GalilLipsel
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             return true;
         }

+ 4 - 61
PunkHPX8_RT/Devices/AXIS/JetAxisBase.cs

@@ -1275,69 +1275,12 @@ namespace PunkHPX8_RT.Devices.AXIS
             return result;
         }
         /// <summary>
-        /// 判定与目标位置相对关系
+        /// 设置速度
         /// </summary>
-        /// <param name="station"></param>
-        /// <param name="compareType">Left--位于目标位置左侧,Right--位于目标位置右侧</param>
-        /// <returns></returns>
-        public bool JudgeCompareTargetStation(string station,string compareType)
-        {
-            double position = 0;
-            var result = GetPositionByStation(station);
-            if(result.success)
-            {
-                position = result.position;
-            }
-            else
-            {
-                return false;
-            }
-            double compareInterval = SC.GetValue<double>("System.CompareInterval");
-            switch(compareType)
-            {
-                case "Left":
-                    return IsInStationLeftDirection(position,compareInterval);
-                case "Right":
-                    return IsInStationRightPosition(position,compareInterval);
-                default:
-                    return false;
-            }
-        }
-        /// <summary>
-        /// 是否位于位置左侧
-        /// </summary>
-        /// <param name="stationPosition"></param>
-        /// <returns></returns>
-        private bool IsInStationLeftDirection(double stationPosition,double compareInterval)
-        {
-            double currentPosition = MotionData.MotorPosition;
-            double targetPosition = _targetPosition;
-            if(_currentOperation==MotionOperation.Position)
-            {
-                return currentPosition <= stationPosition-compareInterval && targetPosition <= stationPosition - compareInterval;
-            }
-            else
-            {
-                return currentPosition <= stationPosition-compareInterval;
-            }
-        }
-        /// <summary>
-        /// 是否位于位置右侧
-        /// </summary>
-        /// <param name="stationPosition"></param>
-        /// <returns></returns>
-        private bool IsInStationRightPosition(double stationPosition, double compareInterval)
+        /// <param name="speed"></param>
+        public void SetProfileSpeed(int speed)
         {
-            double currentPosition = MotionData.MotorPosition;
-            double targetPosition = _targetPosition;
-            if (_currentOperation == MotionOperation.Position)
-            {
-                return currentPosition > stationPosition+compareInterval && targetPosition > stationPosition + compareInterval;
-            }
-            else
-            {
-                return currentPosition > stationPosition+compareInterval ;
-            }
+            _profileVelocity= speed;
         }
         #endregion
 

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/Kollmorgen/KollmorgenAxis.cs

@@ -88,12 +88,22 @@ namespace PunkHPX8_RT.Devices.AXIS.Kollmorgen
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             return true;
         }

+ 13 - 4
PunkHPX8_RT/Devices/AXIS/Maxon/MaxonAxis.cs

@@ -14,7 +14,6 @@ using System.Threading.Tasks;
 using PunkHPX8_RT.Devices.AXIS.Maxon;
 using MECF.Framework.Common.Device;
 using MECF.Framework.Common.Beckhoff.IOAxis;
-using static Mono.Security.X509.X520;
 
 namespace PunkHPX8_RT.Devices.AXIS.CANOpen
 {
@@ -90,12 +89,22 @@ namespace PunkHPX8_RT.Devices.AXIS.CANOpen
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
             }
             return true;
         }

+ 13 - 3
PunkHPX8_RT/Devices/AXIS/Yaskawa/YaskawaAxis.cs

@@ -87,12 +87,22 @@ namespace PunkHPX8_RT.Devices.AXIS.Yaskawa
         {
             lock (_operationLocker)
             {
-                if (_currentOperation == MotionOperation.Position && _profilePositionRoutine.Monitor() == RState.Running)
+                if (_currentOperation == MotionOperation.Position)
                 {
                     _profilePositionRoutine.Abort();
+                    _status = _stopPositionRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
                 }
-                _currentOperation = MotionOperation.StopPosition;
-                _status = _stopPositionRoutine.Start();
+                else if (_currentOperation == MotionOperation.Home)
+                {
+                    _homeRoutine.Abort();
+                    _status = _homeRoutine.Start();
+                    _currentOperation = MotionOperation.StopPosition;
+                }
+                else
+                {
+                    EndOperation();
+                }                
             }
             return true;
         }

+ 89 - 2
PunkHPX8_RT/Devices/VpwCell/VpwCellDevice.cs

@@ -11,6 +11,7 @@ using MECF.Framework.Common.Persistent.SRD;
 using MECF.Framework.Common.Persistent.Temperature;
 using MECF.Framework.Common.Persistent.VpwCell;
 using MECF.Framework.Common.Persistent.VpwMain;
+using MECF.Framework.Common.Utilities;
 using PunkHPX8_RT.Devices.AXIS;
 using PunkHPX8_RT.Modules;
 using PunkHPX8_RT.Modules.VpwMain;
@@ -354,6 +355,7 @@ namespace PunkHPX8_RT.Devices.VpwCell
         }
         #endregion
 
+        #region Vent Valve
         /// <summary>
         /// Vent Valve On
         /// </summary>
@@ -370,8 +372,11 @@ namespace PunkHPX8_RT.Devices.VpwCell
         {
             return WriteVariableValue(VENT_VALVE, false);
         }
+        #endregion
+
+        #region Drain Valve
         /// <summary>
-        /// Vent Valve On
+        /// Drain Valve On
         /// </summary>
         /// <returns></returns>
         public bool DrainValveOn()
@@ -379,13 +384,16 @@ namespace PunkHPX8_RT.Devices.VpwCell
             return WriteVariableValue(DRAIN_VALVE, true);
         }
         /// <summary>
-        /// Vent Valve Off
+        /// Drain Valve Off
         /// </summary>
         /// <returns></returns>
         public bool DrainValveOff()
         {
             return WriteVariableValue(DRAIN_VALVE, false);
         }
+        #endregion
+
+        #region Vacuum
         /// <summary>
         /// Vacuum valve on
         /// </summary>
@@ -402,6 +410,8 @@ namespace PunkHPX8_RT.Devices.VpwCell
         {
             return WriteVariableValue(VACUUM_VALVE, false);
         }
+        #endregion
+
         /// <summary>
         /// 写变量
         /// </summary>
@@ -416,6 +426,83 @@ namespace PunkHPX8_RT.Devices.VpwCell
 
         #endregion
 
+        #region Axis
+        /// <summary>
+        /// 电机是否上电
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckRotationSwitchOn()
+        {
+            return _rotationAxis.IsSwitchOn;
+        }
+        /// <summary>
+        /// Home rotation
+        /// </summary>
+        /// <returns></returns>
+        public bool HomeRotation()
+        {
+            return _rotationAxis.Home();
+        }
+        /// <summary>
+        /// 检验Rotation Home结果
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckHomeEndStatus()
+        {
+            return CheckRotationEndStatus() && _rotationAxis.IsHomed;
+        }
+        /// <summary>
+        /// 检验Rotation结束状态
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckRotationEndStatus()
+        {
+            return _rotationAxis.Status == PunkHPX8_Core.RState.End;
+        }
+        /// <summary>
+        /// 检验Rotation失败状态
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckRotationStopStatus()
+        {
+            return _rotationAxis.Status == PunkHPX8_Core.RState.Failed;
+        }
+        /// <summary>
+        /// 设置速度
+        /// </summary>
+        /// <param name="speed"></param>
+        /// <returns></returns>
+        public bool SetRotationSpeed(int speed)
+        {
+            _rotationAxis.SetProfileSpeed(speed);
+            return true;
+        }
+        /// <summary>
+        /// 电机运动
+        /// </summary>
+        /// <param name="position"></param>
+        /// <returns></returns>
+        public bool RotationProfilePosition(double position)
+        {
+            return _rotationAxis.ProfilePositionOperation(position);
+        }
+        /// <summary>
+        /// 停止运动 
+        /// </summary>
+        /// <returns></returns>
+        public bool StopProfilePosition()
+        {
+            return _rotationAxis.StopPositionOperation();
+        }
+        /// <summary>
+        /// 是否Rotation运动
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckRotationRunning()
+        {
+            return _rotationAxis.IsRun;
+        }
+        #endregion
         /// <summary>
         /// 定时器
         /// </summary>

+ 37 - 18
PunkHPX8_RT/Devices/VpwMain/VpwMainDevice.cs

@@ -419,7 +419,7 @@ namespace PunkHPX8_RT.Devices.VpwMain
         /// Degas Adjust On
         /// </summary>
         /// <returns></returns>
-        private bool DegasAdjustOn()
+        public bool DegasAdjustOn()
         {
             return WriteVariableValue(DEGAS_ADJUST, true);
         }
@@ -427,26 +427,10 @@ namespace PunkHPX8_RT.Devices.VpwMain
         /// Degas Adjust Off
         /// </summary>
         /// <returns></returns>
-        private bool DegasAdjustOff()
+        public bool DegasAdjustOff()
         {
             return WriteVariableValue(DEGAS_ADJUST, false);
         }
-        /// <summary>
-        /// DIW Degas Valve On
-        /// </summary>
-        /// <returns></returns>
-        private bool DiwDegasValveOn()
-        {
-            return WriteVariableValue(DIW_DEGAS, true);
-        }
-        /// <summary>
-        /// DIW Degas Valve Off
-        /// </summary>
-        /// <returns></returns>
-        private bool DiwDegasValveOff()
-        {
-            return WriteVariableValue(DIW_DEGAS, false);
-        }
         #endregion
 
         #region Booster Pump
@@ -735,8 +719,43 @@ namespace PunkHPX8_RT.Devices.VpwMain
         {
             return WriteVariableValue(DIW_PROCESS, false);
         }
+
+        /// <summary>
+        /// DIW Degas Valve On
+        /// </summary>
+        /// <returns></returns>
+        public bool DiwDegasValveOn()
+        {
+            return WriteVariableValue(DIW_DEGAS, true);
+        }
+        /// <summary>
+        /// DIW Degas Valve Off
+        /// </summary>
+        /// <returns></returns>
+        public bool DiwDegasValveOff()
+        {
+            return WriteVariableValue(DIW_DEGAS, false);
+        }
         #endregion
 
+        #region N2Purge
+        /// <summary>
+        /// 打开N2 Purge
+        /// </summary>
+        /// <returns></returns>
+        public bool N2PurgeValveOn()
+        {
+            return WriteVariableValue(DEGAS_PURGE, true);
+        }
+        /// <summary>
+        /// 关闭N2 Purge
+        /// </summary>
+        /// <returns></returns>
+        public bool N2PurgeValveOff()
+        {
+            return WriteVariableValue(DEGAS_PURGE, false);
+        }
+        #endregion
         /// <summary>
         /// 写变量
         /// </summary>

+ 126 - 7
PunkHPX8_RT/Modules/VpwCell/VpwCellEntity.cs

@@ -1,6 +1,9 @@
-using Aitex.Core.RT.Device;
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.Device;
 using Aitex.Core.RT.Fsm;
 using Aitex.Core.RT.Log;
+using Aitex.Core.RT.OperationCenter;
+using Aitex.Core.Util;
 using Aitex.Core.Utilities;
 using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.Persistent.Temperature;
@@ -10,6 +13,7 @@ using MECF.Framework.Common.SubstrateTrackings;
 using MECF.Framework.Common.ToolLayout;
 using PunkHPX8_Core;
 using PunkHPX8_RT.Devices.VpwCell;
+using PunkHPX8_RT.Modules.VpwCell;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -42,6 +46,15 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// 持久化数值
         /// </summary>
         private VpwCellPersistentValue _persistentValue;
+
+        /// <summary>
+        /// VPW cell集合
+        /// </summary>
+        private List<VpwCellDevice> _vpwCellDevices = new List<VpwCellDevice>();
+        /// <summary>
+        /// Home Routine
+        /// </summary>
+        private VPWHomeRoutine _homeRoutine;
         #endregion
 
         #region 属性
@@ -51,7 +64,7 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// </summary>
         public bool IsInit
         {
-            get { return fsm.State == (int)VPWMainState.Init; }
+            get { return fsm.State == (int)VPWCellState.Init; }
         }
         /// <summary>
         /// 是否Idle
@@ -60,7 +73,7 @@ namespace PunkHPX8_RT.Modules.VpwMain
         {
             get
             {
-                return fsm.State == (int)VPWMainState.Idle;
+                return fsm.State == (int)VPWCellState.Idle;
             }
         }
         /// <summary>
@@ -68,14 +81,14 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// </summary>
         public bool IsError
         {
-            get { return fsm.State == (int)VPWMainState.Error; }
+            get { return fsm.State == (int)VPWCellState.Error; }
         }
         /// <summary>
         /// 正在忙碌
         /// </summary>
         public bool IsBusy
         {
-            get { return fsm.State == (int)VPWMainState.Initializing; }
+            get { return fsm.State == (int)VPWCellState.Initializing; }
         }
 
         /// <summary>
@@ -115,8 +128,11 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// <returns></returns>
         protected override bool Init()
         {
-            InitializeParameter();
             InitialFsm();
+            InitializeParameter();
+            InitializeRoutine();
+            InitializeDATA();
+            InitializeOperation();
             return true;
         }
 
@@ -130,12 +146,115 @@ namespace PunkHPX8_RT.Modules.VpwMain
             {
                 LOG.WriteLog(eEvent.ERR_VPW, Module.ToString(), "Persistent Value Object is not exist");
             }
+            _vpwCellDevices.Clear();
+            VpwMainItem vpwMainItem = VpwMainItemManager.Instance.GetItem(ModuleName.VPWMain1.ToString());
+            if (vpwMainItem == null || vpwMainItem.VpwCells == null)
+            {
+                return;
+            }
+            foreach (var item in vpwMainItem.VpwCells)
+            {
+                VpwCellDevice cellDevice = DEVICE.GetDevice<VpwCellDevice>(item.ModuleName);
+                _vpwCellDevices.Add(cellDevice);
+            }
         }
+        /// <summary>
+        /// 初始化状态机
+        /// </summary>
         private void InitialFsm()
         {
-            fsm = new StateMachine<VpwMainEntity>(Module.ToString(), (int)VPWMainState.Init, 100);
+            fsm = new StateMachine<VpwCellEntity>(Module.ToString(), (int)VPWCellState.Init, 100);
             fsm.EnableRepeatedMsg(true);
+            AnyStateTransition(VpwCellMsg.Error, NullFunc, VPWCellState.Error);
+            //Initialized
+            Transition(VPWCellState.Error, VpwCellMsg.Initialize, InitializeAll, VPWCellState.Initializing);
+            Transition(VPWCellState.Init, VpwCellMsg.Initialize, InitializeAll, VPWCellState.Initializing);
+            Transition(VPWCellState.Idle, VpwCellMsg.Initialize, InitializeAll, VPWCellState.Initializing);
+            Transition(VPWCellState.Initializing, FSM_MSG.TIMER, InitializeAllMonitor, VPWCellState.Idle);
+            Transition(VPWCellState.Error, VpwCellMsg.EnterIdle, NullFunc, VPWCellState.Idle);
+            Transition(VPWCellState.Init, VpwCellMsg.EnterIdle, NullFunc, VPWCellState.Idle);
+            Transition(VPWCellState.Idle, VpwCellMsg.EnterIdle, NullFunc, VPWCellState.Idle);
+            //Enter Init
+            Transition(VPWCellState.Idle, VpwCellMsg.Init, NullFunc, VPWCellState.Init);
         }
+        /// <summary>
+        /// 初始化数据
+        /// </summary>
+        private void InitializeDATA()
+        {
+            InitializeSVID();
+            DATA.Subscribe($"{Module}.FsmState", () => ((VPWCellState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsIdle", () => IsIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsInit", () => IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsDisable", () => IsDisable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsBusy", () => IsBusy, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+        }
+        /// <summary>
+        /// 初始化SVID
+        /// </summary>
+        private void InitializeSVID()
+        {
+            DATA.Subscribe($"{Module}.State", () => ((VPWCellState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.OperatingMode", () => _persistentValue != null ? _persistentValue.OperatingMode : "None", SubscriptionAttribute.FLAG.IgnoreSaveDB);
+
+        }
+        /// <summary>
+        /// 初始化Routine
+        /// </summary>
+        private void InitializeRoutine()
+        {
+            _homeRoutine = new VPWHomeRoutine(Module.ToString());
+        }
+        /// <summary>
+        /// 初始化操作
+        /// </summary>
+        private void InitializeOperation()
+        {
+            OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage<VPWCellState, VpwCellMsg>(eEvent.ERR_VPWMAIN, Module.ToString(), (int)VpwCellMsg.Initialize); });
+        }
+
+        #region InitializeAll
+        /// <summary>
+        /// Initialize
+        /// </summary>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        private bool InitializeAll(object[] param)
+        {
+            if (_vpwCellDevices == null || _vpwCellDevices.Count == 0)
+            {
+                LOG.WriteLog(eEvent.ERR_VPW, Module.ToString(), "cell device is empty");
+                return false;
+            }
+            foreach (var device in _vpwCellDevices)
+            {
+                VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(device.Module);
+                if (vpwCellEntity.IsBusy)
+                {
+                    LOG.WriteLog(eEvent.ERR_VPW, Module.ToString(), $"cell device {device.Module} is busy,cannot initialize");
+                    return false;
+                }
+            }
+            return _homeRoutine.Start(_vpwCellDevices) == RState.Running;
+        }
+        /// <summary>
+        /// Initialize 监控
+        /// </summary>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        private bool InitializeAllMonitor(object[] param)
+        {
+            RState ret = _homeRoutine.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(VpwCellMsg.Error);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
+        #endregion
 
         public bool Check(int msg, out string reason, params object[] args)
         {

+ 18 - 0
PunkHPX8_RT/Modules/VpwCell/VpwCellMsg.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Modules.VpwCell
+{
+    public enum VpwCellMsg
+    {
+        Error,
+        Initialize,
+        ResumeError,
+        Init,
+        Abort,
+        EnterIdle
+    }
+}

+ 477 - 13
PunkHPX8_RT/Modules/VpwMain/VPWHomeRoutine.cs

@@ -1,15 +1,20 @@
 using Aitex.Core.RT.Device;
+using Aitex.Core.RT.IOCore;
 using Aitex.Core.RT.Log;
 using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
 using Aitex.Core.Util;
+using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.Routine;
 using PunkHPX8_Core;
 using PunkHPX8_RT.Devices.VpwCell;
 using PunkHPX8_RT.Devices.VpwMain;
+using PunkHPX8_RT.Modules.VpwCell;
 using SecsGem.Core.ItemModel;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -21,17 +26,42 @@ namespace PunkHPX8_RT.Modules.VpwMain
         {
             ChameberUp,
             OpenCellDrainValve,
+            HomeRotation,
+            CheckRotationStatus,
+            StartRotation,
+            CheckRotationRunning,
+            CloseDiwDegas,
+            N2PurgeDelay,
+            CloseN2Purge,
+            BoostPumpEnable,
+            CheckPumpEnable,
+            FlowDelay,
+            CheckFlow,
+            CheckCellFlow,
+            StopRotation,
+            CheckStopStatus,
+            LastHomeRotation,
+            CheckLastHomeRotation,
+            CheckFlowOk,
+            DegasDelay,
+            OpenDegas,
+            ChamberDown,
+            LastCheckStatus,
             End
         }
 
         #region 常量 
+        /// <summary>
+        /// 增加额外一分钟
+        /// </summary>
+        private const int PLUS_TIME = 60000;
         #endregion
 
         #region 内部变量
         /// <summary>
         /// Cell device集合
         /// </summary>
-        private List<VpwCellDevice> _vpwCellDevices;
+        private List<VpwCellDevice> _vpwCellDevices=new List<VpwCellDevice>();
         /// <summary>
         /// Main Device
         /// </summary>
@@ -40,6 +70,50 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// cell集合
         /// </summary>
         private List<VpwCellDevice> _cellLst=new List<VpwCellDevice>();
+        /// <summary>
+        /// N2 Purge时长
+        /// </summary>
+        private int _n2PurgeTime = 15000;
+        /// <summary>
+        /// Flow holder off time
+        /// </summary>
+        private int _flowFaultHolderoffTime = 15000;
+        /// <summary>
+        /// Degas delay时间
+        /// </summary>
+        private int _degasEnableDelayTime = 2000;
+        /// <summary>
+        /// 旋转速度
+        /// </summary>
+        private int _rotationSpeed = 0;
+        /// <summary>
+        /// 总流量起始流量数值
+        /// </summary>
+        private double _totalFlowStartLimit = 2.0;
+        /// <summary>
+        /// Cell起始流量数值
+        /// </summary>
+        private double _cellFlowStartLimit = 2.0;
+        /// <summary>
+        /// total flow合格
+        /// </summary>
+        private bool _totalFlowOk = false;
+        /// <summary>
+        /// cell flow合格集合
+        /// </summary>
+        private Dictionary<string,bool> _cellFlowOk = new Dictionary<string, bool>();
+        /// <summary>
+        /// 检验流量是否ok
+        /// </summary>
+        private bool _checkFlowOk = false;
+        /// <summary>
+        /// 总流量
+        /// </summary>
+        private double _totalFlow = 0;
+        /// <summary>
+        /// Cell注意集合
+        /// </summary>
+        private Dictionary<string,double> _cellFlows = new Dictionary<string, double>();
         #endregion
 
         /// <summary>
@@ -65,6 +139,26 @@ namespace PunkHPX8_RT.Modules.VpwMain
         {
             Runner.Run(HomeStep.ChameberUp, _mainDevice.ChamberUp, CheckChamberClosed, _delay_1s)
                 .Run(HomeStep.OpenCellDrainValve, OpenCellDrainValve, CheckCellDrainValveStatus, _delay_2s)
+                .Run(HomeStep.HomeRotation,HomeAllRotation,_delay_1ms)
+                .WaitWithStopCondition(HomeStep.CheckRotationStatus,CheckAllRotationHomeStatus,CheckAllRotationHomeStopStatus)
+                .Run(HomeStep.StartRotation,StartRotation,_delay_1ms)
+                .Wait(HomeStep.CheckRotationRunning,CheckRotationRunningStatus,500)
+                .Run(HomeStep.CloseDiwDegas,CloseDiwDegas)
+                .Delay(HomeStep.N2PurgeDelay,_n2PurgeTime)
+                .Run(HomeStep.CloseN2Purge,_mainDevice.N2PurgeValveOff,_delay_1ms)
+                .Run(HomeStep.BoostPumpEnable,OpenBoostPump,_delay_1ms)
+                .Wait(HomeStep.CheckPumpEnable, () => { return _mainDevice.CommonData.BoosterPumpStatus; },_delay_1s)
+                .Delay(HomeStep.FlowDelay,_flowFaultHolderoffTime)
+                .Run(HomeStep.CheckFlow,CheckTotalFlow,_delay_1ms)
+                .Run(HomeStep.CheckCellFlow,CheckCellFlow,_delay_1ms)
+                .Run(HomeStep.StopRotation,StopRotationAxis,_delay_1ms)
+                .WaitWithStopCondition(HomeStep.CheckRotationStatus,CheckStopPostionEndStatus,CheckStopPostionStopStatus)
+                .Run(HomeStep.CheckFlowOk,CheckFlowOk,_delay_1ms)
+                .DelayIf(HomeStep.DegasDelay,_checkFlowOk,_degasEnableDelayTime)
+                .RunIf(HomeStep.OpenDegas,_checkFlowOk,OpenDegasPump,_delay_1ms)
+                .RunIf(HomeStep.ChamberDown,_checkFlowOk, () => { return _mainDevice.ChamberDown(); }, 
+                    () => { return !_mainDevice.CommonData.ChamberClosed && _mainDevice.CommonData.ChamberOpened; })
+                .Run(HomeStep.LastCheckStatus,LastCheckResult,_delay_1ms)
                 .End(HomeStep.End,NullFun, _delay_1ms);
             return Runner.Status;
         }
@@ -82,19 +176,14 @@ namespace PunkHPX8_RT.Modules.VpwMain
         /// <returns></returns>
         private bool OpenCellDrainValve()
         {
-            foreach(var device in _vpwCellDevices)
-            {
-                VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(device.Module);
-                if (vpwCellEntity.IsAuto||vpwCellEntity.IsManual)
+            foreach(var device in _cellLst)
+            {               
+                bool result= device.DrainValveOn();
+                if (!result)
                 {
-                    _cellLst.Add(device);
-                    bool result= device.DrainValveOn();
-                    if (!result)
-                    {
-                        LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{device.Module} open drain valve failed");
-                        CloseCellDrainValve();
-                        return false;
-                    }
+                    LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{device.Module} open drain valve failed");
+                    CloseCellDrainValve();
+                    return false;
                 }
             }
             return true;
@@ -128,6 +217,346 @@ namespace PunkHPX8_RT.Modules.VpwMain
             }
         }
         /// <summary>
+        /// Home All Rotation
+        /// </summary>
+        /// <returns></returns>
+        private bool HomeAllRotation()
+        {
+            foreach(var item in _cellLst)
+            {
+                bool result = item.HomeRotation();
+                if (!result)
+                {
+                    CloseCellDrainValve();
+                    return false;
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// 检验所有Rotation Home成功
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckAllRotationHomeStatus()
+        {
+            int count = 0;
+            foreach (var item in _cellLst)
+            {
+                bool result = item.CheckHomeEndStatus();
+                if (result)
+                {
+                    count++;
+                }
+            }
+            bool success= count == _cellLst.Count ;
+            if (success)
+            {                
+                foreach(var item in _cellLst)
+                {
+                    item.SetRotationSpeed(_rotationSpeed);
+                }
+            }
+            return success;
+        }
+        /// <summary>
+        /// rotation电机 home是否停止
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckAllRotationHomeStopStatus()
+        {
+            foreach (var item in _cellLst)
+            {
+                bool result = item.CheckRotationStopStatus();
+                if (result)
+                {
+                    CloseCellDrainValve();
+                    return true;
+                }
+            }
+            return false;
+        }
+        /// <summary>
+        /// 启动rotation
+        /// </summary>
+        /// <returns></returns>
+        private bool StartRotation()
+        {
+            int totalTime =(_n2PurgeTime + _flowFaultHolderoffTime + PLUS_TIME)/1000;
+            int targetPsition = _rotationSpeed * totalTime;
+            foreach (var item in _cellLst)
+            {
+                bool result = item.RotationProfilePosition(targetPsition);
+                if (!result)
+                {
+                    StopAllRotation();
+                    CloseCellDrainValve();
+                    return false;
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// 检验Rotation是否运动
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckRotationRunningStatus()
+        {
+            foreach (var item in _cellLst)
+            {
+                bool result = item.CheckRotationRunning();
+                if (!result)
+                {
+                    StopAllRotation();
+                    CloseCellDrainValve();
+                    return false;
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// 停止所有rotation电机
+        /// </summary>
+        private void StopAllRotation()
+        {
+            foreach (var item in _cellLst)
+            {
+                item.StopProfilePosition();
+            }
+        }
+        /// <summary>
+        /// 关闭DiwDegas等
+        /// </summary>
+        /// <returns></returns>
+        private bool CloseDiwDegas()
+        {
+            int count = 0;
+            count+=_mainDevice.DiwDegasValveOff()?1:0;
+            count+=_mainDevice.BoosterPumpDisable()?1:0;
+            count+=_mainDevice.N2PurgeValveOn()?1:0;
+            foreach(var item in _cellLst)
+            {
+                count += item.FlowDripOff()?1:0;
+                count += item.FlowSmallOff() ? 1 : 0;
+                count += item.FlowLargeOff() ? 1 : 0;
+            }
+            
+            return count==_cellLst.Count*3+3;
+        }
+        /// <summary>
+        /// 打开Boost Pump
+        /// </summary>
+        /// <returns></returns>
+        private bool OpenBoostPump()
+        {
+            int count = 0;
+            count += _mainDevice.BoosterPumpEnable()?1:0;
+            count += _mainDevice.DiwEnable() ? 1 : 0;
+            count += _mainDevice.DiwProcessOn() ? 1 : 0;
+            count += _mainDevice.DiwDegasValveOn() ? 1 : 0;
+            foreach (var item in _cellLst)
+            {
+                count += item.FlowDripOn() ? 1 : 0;
+                count += item.FlowSmallOn() ? 1 : 0;
+                count += item.FlowLargeOn() ? 1 : 0;
+            }
+            return count == _cellLst.Count*3+4;
+        }
+        /// <summary>
+        /// 检验流量
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckTotalFlow()
+        {
+            double totalFlow = _mainDevice.CommonData.DiwTotalFlow;
+            if (totalFlow < _totalFlowStartLimit)
+            {
+                _totalFlowOk = false;
+            }
+            else
+            {
+                _totalFlowOk = true;
+            }
+            _totalFlow = totalFlow;
+            return true;
+        }
+        /// <summary>
+        /// 检验CellFlow
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckCellFlow()
+        {
+            foreach (var item in _cellLst)
+            {
+                double cellFlow = item.CommonData.DiwFlow;
+                if (cellFlow < _cellFlowStartLimit)
+                {
+                    _cellFlowOk[item.Module] = false;
+                    item.FlowSmallOff();
+                    item.FlowLargeOff();
+                }
+                else
+                {
+                    _cellFlowOk[item.Module] = true;
+                }
+                _cellFlows[item.Module] = cellFlow;
+            }
+
+            return true;
+        }
+        /// <summary>
+        /// 停止rotation
+        /// </summary>
+        /// <returns></returns>
+        public bool StopRotationAxis()
+        {
+            foreach(var item in _cellLst)
+            {
+                bool result = item.StopProfilePosition();
+                if (!result)
+                {
+                    CloseCellDrainValve();                    
+                    return false;
+                }
+            }
+            return true;
+        }
+        /// <summary>
+        /// 检验停止是否完成
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckStopPostionEndStatus()
+        {
+            foreach (var item in _cellLst)
+            {
+                bool result = item.CheckRotationEndStatus();
+                if (!result)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 检验停止失败状态
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckStopPostionStopStatus()
+        {
+            foreach (var item in _cellLst)
+            {
+                bool result = item.CheckRotationStopStatus();
+                if (result)
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+        /// <summary>
+        /// 检验流量是否ok
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckFlowOk()
+        {
+            if (!_totalFlowOk)
+            {
+                _checkFlowOk = false;
+                return true;
+            }
+            foreach(var item in _cellLst)
+            {
+                if (!_cellFlowOk[item.Module])
+                {
+                    _checkFlowOk = false;
+                    return true;
+                }
+            }
+            _checkFlowOk = true;
+            return true;
+        }
+        /// <summary>
+        /// 打开Degas Pump和Adjust
+        /// </summary>
+        /// <returns></returns>
+        private bool OpenDegasPump()
+        {
+            int count = 0;
+            count+=_mainDevice.DegasPumpEnable()?1:0;
+            count+=_mainDevice.DegasAdjustOn()?1:0;
+            return count == 2;
+        }
+        /// <summary>
+        /// 最后确认结果
+        /// </summary>
+        /// <returns></returns>
+        private bool LastCheckResult()
+        {
+            //当前是Main Home
+            if (Module == ModuleName.VPWMain1.ToString())
+            {
+                AllCellPostMsg();
+                if (_totalFlowOk)
+                {
+                    return true;
+                }
+                else
+                {
+                    LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"total flow {_totalFlow} is less than {_totalFlowStartLimit}");
+                    return false;
+                }
+
+            }
+            else
+            {
+                AllCellPostMsg();
+                VpwMainEntity vpwMainEntity = Singleton<RouteManager>.Instance.GetModule<VpwMainEntity>(ModuleName.VPWMain1.ToString());
+                if (_totalFlowOk)
+                {
+                    vpwMainEntity.CheckToPostMessage<VPWMainState, VPWMainMsg>(eEvent.INFO_VPWMAIN, ModuleName.VPWMain1.ToString(), (int)VpwCellMsg.EnterIdle);
+                }
+                else
+                {
+                    vpwMainEntity.PostMsg((int)VPWMainMsg.Error);
+                    LOG.WriteLog(eEvent.ERR_VPWMAIN,ModuleName.VPWMain1.ToString(), $"total flow {_totalFlow} is less than {_totalFlowStartLimit}");
+                }
+                if (_cellFlowOk[Module])
+                {
+                    return true;
+                }
+                else
+                {
+                    LOG.WriteLog(eEvent.ERR_VPW, Module, $"cell flow {_cellFlows[Module]} is less than {_cellFlowStartLimit}");
+                    return false;
+                }
+            }
+        }
+        /// <summary>
+        /// 所有cell推送消息
+        /// </summary>
+        private void AllCellPostMsg()
+        {
+            foreach (var item in _cellLst)
+            {
+                //过滤当前本身的cell
+                if (item.Module == Module)
+                {
+                    continue;
+                }
+                //若cell流量是ok,则post msg变成idle
+                VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(item.Module);
+                if (_cellFlowOk[item.Module])
+                {
+                    vpwCellEntity.CheckToPostMessage<VPWCellState, VpwCellMsg>(eEvent.INFO_VPW, item.Module, (int)VpwCellMsg.EnterIdle);
+                }
+                else//则cell流量是不ok,则post error msg
+                {
+                    vpwCellEntity.PostMsg((int)VpwCellMsg.Error);
+                    LOG.WriteLog(eEvent.ERR_VPW, item.Module, $"cell flow {_cellFlows[item.Module]} is less than {_cellFlowStartLimit}");
+                }
+            }
+        }
+        /// <summary>
         /// 启动
         /// </summary>
         /// <param name="objs"></param>
@@ -136,13 +565,48 @@ namespace PunkHPX8_RT.Modules.VpwMain
         {
             List<VpwCellDevice> lstDevice = (List<VpwCellDevice>)objs[0];
             _vpwCellDevices.Clear();
+            _cellFlows.Clear();
             _cellLst.Clear();
+            _cellFlowOk.Clear();
+            _totalFlowOk = false;
+            _checkFlowOk = false;
+            _totalFlow = 0;
             for (int i = 0; i < lstDevice.Count; i++)
             {
                 _vpwCellDevices.Add(lstDevice[i]);
+                VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(lstDevice[i].Module);
+                if (vpwCellEntity.IsAuto || vpwCellEntity.IsManual)
+                {
+                    _cellLst.Add(lstDevice[i]);
+                    if (!CheckRotationSwitchOn(lstDevice[i])){
+                        return RState.Failed;
+                    }
+                    _cellFlowOk[lstDevice[i].Module]=false;
+                }
             }
             _mainDevice = DEVICE.GetDevice<VpwMainDevice>(Module.ToString());
+            _n2PurgeTime = SC.GetValue<int>("VPWMain.Plumbing.N2PurgeTime");
+            _flowFaultHolderoffTime = SC.GetValue<int>("VPWMain.Plumbing.FlowFaultHoldoffTime");
+            double purgeMotorSpeed = SC.GetValue<double>("VPWMain.Plumbing.PurgeMotorSpeed");
+            _rotationSpeed = (int)(Math.Round(purgeMotorSpeed * 360 / 60,0));
+            _totalFlowStartLimit = SC.GetValue<double>("VPWMain.Plumbing.TotalFlowStartLowLimit");
+            _cellFlowStartLimit = SC.GetValue<double>("VPWMain.Plumbing.CellFlowStartLowLimit");
+            _degasEnableDelayTime = SC.GetValue<int>("VPWMain.Plumbing.DegasEnableDelayTime");
             return Runner.Start(Module,"VPW Home");
         }
+        /// <summary>
+        /// 检验Rotation电机是否上电
+        /// </summary>
+        /// <param name="device"></param>
+        /// <returns></returns>
+        private bool CheckRotationSwitchOn(VpwCellDevice device)
+        {
+            if (!device.CheckRotationSwitchOn())
+            {
+                LOG.WriteLog(eEvent.ERR_VPWMAIN, Module, $"{device.Module} rotation is not switch on");
+                return false;
+            }
+            return true;
+        }
     }
 }

+ 2 - 1
PunkHPX8_RT/Modules/VpwMain/VPWMsg.cs

@@ -12,6 +12,7 @@ namespace PunkHPX8_RT.Modules.VpwMain
         Initialize,
         ResumeError,
         Init,
-        Abort
+        Abort,
+        EnterIdle
     }
 }

+ 37 - 25
PunkHPX8_RT/Modules/VpwMain/VpwMainEntity.cs

@@ -3,7 +3,6 @@ using Aitex.Core.RT.Device;
 using Aitex.Core.RT.Fsm;
 using Aitex.Core.RT.Log;
 using Aitex.Core.RT.OperationCenter;
-using Aitex.Core.RT.Routine;
 using Aitex.Core.Util;
 using Aitex.Core.Utilities;
 using MECF.Framework.Common.Equipment;
@@ -129,8 +128,8 @@ namespace PunkHPX8_RT.Modules.VpwMain
             InitialFsm();
             InitializeParameter();
             InitializeRoutine();
-            InitialDATA();
-            InitialOperation();
+            InitializeDATA();
+            InitializeOperation();
             return true;
         }
         /// 初始化状态机
@@ -139,18 +138,15 @@ namespace PunkHPX8_RT.Modules.VpwMain
         {
             fsm = new StateMachine<VpwMainEntity>(Module.ToString(), (int)VPWMainState.Init, 100);
             fsm.EnableRepeatedMsg(true);
-
-            AnyStateTransition(VPWMainState.Error, NullFunc, VPWMainState.Error);
-            AnyStateTransition(FSM_MSG.TIMER, fnMonitor, FSM_STATE.SAME);
+            AnyStateTransition(VPWMainMsg.Error, NullFunc, VPWMainState.Error);
             //Initialized
             Transition(VPWMainState.Error, VPWMainMsg.Initialize, InitializeAll, VPWMainState.Initializing);
             Transition(VPWMainState.Init, VPWMainMsg.Initialize, InitializeAll, VPWMainState.Initializing);
             Transition(VPWMainState.Idle, VPWMainMsg.Initialize, InitializeAll, VPWMainState.Initializing);
             Transition(VPWMainState.Initializing, FSM_MSG.TIMER, InitializeAllMonitor, VPWMainState.Idle);
-
-
-            //直接进入Idle
-            Transition(VPWMainState.Initialized, FSM_MSG.TIMER, NullFunc, VPWMainState.Idle);
+            Transition(VPWMainState.Error, VPWMainMsg.EnterIdle, NullFunc, VPWMainState.Idle);
+            Transition(VPWMainState.Init, VPWMainMsg.EnterIdle, NullFunc, VPWMainState.Idle);
+            Transition(VPWMainState.Idle, VPWMainMsg.EnterIdle, NullFunc, VPWMainState.Idle);
             //Enter Init
             Transition(VPWMainState.Idle, VPWMainMsg.Init, NullFunc, VPWMainState.Init);
 
@@ -181,34 +177,41 @@ namespace PunkHPX8_RT.Modules.VpwMain
             }
         }
         /// <summary>
-        /// 初始化Routine
+        /// 初始化数据
         /// </summary>
-        private void InitializeRoutine()
+        private void InitializeDATA()
         {
-            _homeRoutine = new VPWHomeRoutine(Module.ToString());
-          
+            InitializeSVID();
+            DATA.Subscribe($"{Module}.FsmState", () => ((VPWMainState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsIdle", () => IsIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsInit", () => IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsDisable", () => IsDisable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsBusy", () => IsBusy, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
         }
         /// <summary>
-        /// 初始化数据
+        /// 初始化SVID
         /// </summary>
-        private void InitialDATA()
+        private void InitializeSVID()
         {
-            DATA.Subscribe($"{Module}.FsmState", () => ((VPWMainState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
-            DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.State", () => ((VPWMainState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.OperatingMode", () => _persistentValue != null ? _persistentValue.OperatingMode : "None", SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            
         }
         /// <summary>
-        /// 初始化操作
+        /// 初始化Routine
         /// </summary>
-        private void InitialOperation()
+        private void InitializeRoutine()
         {
-            OP.Subscribe($"{Module}.InitializeHome", (cmd, args) => { return CheckToPostMessage<VPWMainState, VPWMainMsg>(eEvent.ERR_VPWMAIN, Module.ToString(), (int)VPWMainMsg.Initialize); });
+            _homeRoutine = new VPWHomeRoutine(Module.ToString());
+          
         }
-        
-        private bool fnMonitor(object[] param)
+        /// <summary>
+        /// 初始化操作
+        /// </summary>
+        private void InitializeOperation()
         {
-            
-            return true;
+            OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage<VPWMainState, VPWMainMsg>(eEvent.ERR_VPWMAIN, Module.ToString(), (int)VPWMainMsg.Initialize); });
         }
 
         #region InitializeAll
@@ -224,6 +227,15 @@ namespace PunkHPX8_RT.Modules.VpwMain
                 LOG.WriteLog(eEvent.ERR_VPWMAIN, Module.ToString(), "cell device is empty");
                 return false;
             }
+            foreach(var device in _vpwCellDevices)
+            {
+                VpwCellEntity vpwCellEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(device.Module);
+                if (vpwCellEntity.IsBusy)
+                {
+                    LOG.WriteLog(eEvent.ERR_VPWMAIN, Module.ToString(), $"cell device {device.Module} is busy,cannot initialize");
+                    return false;
+                }
+            }
             return _homeRoutine.Start(_vpwCellDevices) == RState.Running;
         }
         /// <summary>

+ 1 - 0
PunkHPX8_RT/PunkHPX8_RT.csproj

@@ -314,6 +314,7 @@
     <Compile Include="Modules\DVIDName.cs" />
     <Compile Include="Modules\VpwCell\VpwCellEntity.cs" />
     <Compile Include="Modules\VpwMain\VpwSimpleHomeRoutine.cs" />
+    <Compile Include="Modules\VpwCell\VpwCellMsg.cs" />
     <Compile Include="Modules\VpwMain\VPWHomeRoutine.cs" />
     <Compile Include="Modules\VpwMain\VpwMainEntity.cs" />
     <Compile Include="Modules\VpwMain\VPWMsg.cs" />