Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../Devices/IoPSU.cs

504 lines
18 KiB
C#
Raw Normal View History

using Aitex.Core.Common.DeviceData.IoDevice;
using Aitex.Core.RT.DataCenter;
2023-04-13 11:51:03 +08:00
using Aitex.Core.RT.Event;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using System;
using System.Xml;
2023-04-13 11:51:03 +08:00
namespace Aitex.Core.RT.Device.Devices
{
public class IoPSU : BaseDevice, IDevice
{
#region Variables
2023-04-13 11:51:03 +08:00
private float _resLimitMax;
private float _outputLimitHighTuningTemp = 1600;
private readonly bool _isFloatAioType;
private readonly AIAccessor _aiOutputVoltage;
private readonly AIAccessor _aiOutputArms;
private readonly AIAccessor _aiOutputPower;
private readonly AIAccessor _aiSimVoltage;
private readonly AIAccessor _aiSimArms;
2023-04-13 11:51:03 +08:00
//private AOAccessor _aoEnable = null;
//private AOAccessor _aoReset = null;
private readonly AOAccessor _aoConstant;
private readonly AOAccessor _aoOutputLimitHigh;
private readonly AOAccessor _aoOutputLimitLow;
2023-04-13 11:51:03 +08:00
private readonly DIAccessor _diStatus;
private readonly DIAccessor _diAlarm;
private readonly DIAccessor _diHeatEnable;
private DIAccessor _diCommunicationError;
2023-04-13 11:51:03 +08:00
private readonly DOAccessor _doReset;
private readonly DOAccessor _doStatus;
private readonly DOAccessor _doHeatEnable;
private readonly DOAccessor _doRelatedEnable; //每个Enable同时关联的InnerMiddleOut Enable
2023-04-13 11:51:03 +08:00
private readonly R_TRIG _alarmTrig = new();
private readonly R_TRIG _commAlarmTrig = new();
private readonly R_TRIG _enableTrig = new();
private readonly R_TRIG _enableTrig2 = new();
2023-04-13 11:51:03 +08:00
private readonly R_TRIG _trigVoltage = new();
private readonly R_TRIG _trigCurrent = new();
2023-04-13 11:51:03 +08:00
private readonly R_TRIG _trigResOutOfRange = new();
2023-04-13 11:51:03 +08:00
private readonly DeviceTimer _timResetPulse = new();
private readonly DeviceTimer _timResOutOfRange = new();
2023-04-13 11:51:03 +08:00
private readonly IoPsuData _deviceData = new();
2023-04-13 11:51:03 +08:00
#endregion
#region Constructors
public IoPSU(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
2023-04-13 11:51:03 +08:00
{
_aiOutputVoltage = ParseAiNode("aiOutputVoltage", node, ioModule);
_aiOutputArms = ParseAiNode("aiOutputArms", node, ioModule);
_aiOutputPower = ParseAiNode("aiOutputPower", node, ioModule);
_aiSimVoltage = ParseAiNode("aiSimVoltage", node, ioModule);
_aiSimArms = ParseAiNode("aiSimArms", node, ioModule);
2023-04-13 11:51:03 +08:00
_aoConstant = ParseAoNode("aoConstant", node, ioModule);
_aoOutputLimitHigh = ParseAoNode("aoOutputLimitHigh", node, ioModule);
_aoOutputLimitLow = ParseAoNode("aoOutputLimitLow", node, ioModule);
2023-04-13 11:51:03 +08:00
_doReset = ParseDoNode("doReset", node, ioModule);
_doStatus = ParseDoNode("doStatus", node, ioModule);
_diStatus = ParseDiNode("diStatus", node, ioModule);
_diAlarm = ParseDiNode("diAlarm", node, ioModule);
_doHeatEnable = ParseDoNode("doHeatEnable", node, ioModule);
_diHeatEnable = ParseDiNode("diHeatEnable", node, ioModule);
_doRelatedEnable = ParseDoNode("doRelatedEnable", node, ioModule);
_diCommunicationError = ParseDiNode("diCommunicationError", node, ioModule);
_isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float");
}
#endregion
#region Properties
public float OutputVoltageFeedBack => _aiOutputVoltage == null ? 0 : (_isFloatAioType ? _aiOutputVoltage.FloatValue : _aiOutputVoltage.Value);
public float OutputArmsFeedBack => _aiOutputArms == null ? 0 : (_isFloatAioType ? _aiOutputArms.FloatValue : _aiOutputArms.Value);
public float ResistanceLimitMax => _resLimitMax;
public float Resistance => OutputArmsFeedBack == 0 ? 0 : OutputVoltageFeedBack / OutputArmsFeedBack;
public bool IsResistanceOutOfRange => IsResistanceTooHigh;
public bool IsResistanceTooHigh
{
get;
private set;
}
public float OutputPowerFeedBack => _aiOutputPower == null ? 0 : (_isFloatAioType ? _aiOutputPower.FloatValue : _aiOutputPower.Value);
public bool StatusFeedBack => _diStatus?.Value ?? false;
public float SimVoltageFeedBack => _aiSimVoltage == null ? 0 : (_isFloatAioType ? _aiSimVoltage.FloatValue : _aiSimVoltage.Value);
public float SimArmsFeedBack => _aiSimArms == null ? 0 : (_isFloatAioType ? _aiSimArms.FloatValue : _aiSimArms.Value);
public bool AlarmFeedBack => _diAlarm?.Value ?? false;
public float ConstantSetPoint
{
get => _aoConstant == null ? 0 : (_isFloatAioType ? _aoConstant.FloatValue : _aoConstant.Value);
set
{
if (_isFloatAioType)
{
_aoConstant.FloatValue = value;
}
else
{
_aoConstant.Value = (short)value;
}
}
}
public float OutputLimitHigh => _aoOutputLimitHigh?.FloatValue ?? 0;
public float OutputLimitLow => _aoOutputLimitLow?.FloatValue ?? 0;
public bool AllHeatEnable => _diHeatEnable?.Value ?? false;
private IoPsuData DeviceData
{
get
{
_deviceData.IsAlarm = AlarmFeedBack;
_deviceData.OutputStatusFeedBack = StatusFeedBack;
_deviceData.AllHeatEnable = AllHeatEnable;
_deviceData.ConstantSetPoint = ConstantSetPoint;
_deviceData.OutputArmsFeedBack = OutputArmsFeedBack;
_deviceData.OutputPowerFeedBack = OutputPowerFeedBack;
_deviceData.OutputVoltageFeedback = OutputVoltageFeedBack;
_deviceData.ResistanceLimitMax = ResistanceLimitMax;
_deviceData.Resistance = Resistance;
_deviceData.IsResistanceOutOfRange = IsResistanceOutOfRange;
_deviceData.IsResistanceTooHigh = IsResistanceTooHigh;
_deviceData.OutputLimitHighTuningTemp = _outputLimitHighTuningTemp;
_deviceData.OutputLimitHigh = OutputLimitHigh;
_deviceData.OutputLimitLow = OutputLimitLow;
return _deviceData;
}
}
public Func<bool, bool> FuncCheckInterLock { get; set; }
#endregion
#region Methods
2023-04-13 11:51:03 +08:00
public bool Initialize()
{
DATA.Subscribe($"{Module}.{Name}.OutputVoltageFeedBack", () => OutputVoltageFeedBack);
DATA.Subscribe($"{Module}.{Name}.OutputArmsFeedBack", () => OutputArmsFeedBack);
DATA.Subscribe($"{Module}.{Name}.ResistanceLimitMax", () => ResistanceLimitMax);
2023-04-13 11:51:03 +08:00
DATA.Subscribe($"{Module}.{Name}.Resistance", () => Resistance);
DATA.Subscribe($"{Module}.{Name}.IsResistanceOutOfRange", () => IsResistanceOutOfRange);
DATA.Subscribe($"{Module}.{Name}.IsResistanceTooHigh", () => IsResistanceTooHigh);
2023-04-13 11:51:03 +08:00
DATA.Subscribe($"{Module}.{Name}.OutputPowerFeedBack", () => OutputPowerFeedBack);
DATA.Subscribe($"{Module}.{Name}.StatusFeedBack", () => StatusFeedBack);
DATA.Subscribe($"{Module}.{Name}.SimVoltageFeedBack", () => SimVoltageFeedBack);
DATA.Subscribe($"{Module}.{Name}.SimArmsFeedBack", () => SimArmsFeedBack);
DATA.Subscribe($"{Module}.{Name}.ConstantSetPoint", () => ConstantSetPoint);
DATA.Subscribe($"{Module}.{Name}.OutputLimitHigh", () => OutputLimitHigh);
DATA.Subscribe($"{Module}.{Name}.OutputLimitLow", () => OutputLimitLow);
DATA.Subscribe($"{Module}.{Name}.OutputLimitHighTuningTemp", () => _outputLimitHighTuningTemp);
2023-04-13 11:51:03 +08:00
DATA.Subscribe($"{Module}.{Name}.AlarmFeedBack", () => AlarmFeedBack);
DATA.Subscribe($"{Module}.{Name}.AllHeatEnable", () => AllHeatEnable);
DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
2023-04-13 11:51:03 +08:00
OP.Subscribe($"{Module}.{Name}.SetHeadHeaterEnable", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetHeadHeaterEnable(isTrue, out _);
2023-04-13 11:51:03 +08:00
return true;
});
OP.Subscribe($"{Module}.{Name}.SetPSUEnable", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetPSUEnable(isTrue, out _);
2023-04-13 11:51:03 +08:00
return true;
});
OP.Subscribe($"{Module}.{Name}.SetPSUReset", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetPSUReset(isTrue, out _);
2023-04-13 11:51:03 +08:00
return true;
});
OP.Subscribe($"{Module}.{Name}.SetOutputLimitHighTuningTemp", (function, args) =>
{
if (args.Length == 1 && args[0] is double value)
{
SC.SetItemValue($"PM.{Module}.Heater.PSU2OutputLimitHighTuningTemp", value);
}
EV.PostWarningLog(Module, $"SetOutputLimitHigh fail, args error");
return false;
});
OP.Subscribe($"{Module}.{Name}.SetOutputLimitHighByRecipe", (out string reason, int time, object[] args) =>
{
reason = string.Empty;
if (_aoOutputLimitHigh == null)
{
return true;
}
if (args.Length == 1 && double.TryParse(args[0].ToString(), out var value))
{
var tunedByRecipe = SC.GetValue<bool>($"PM.{Module}.Heater.PSU2OutputLimitHighTuningByRecipe");
if(tunedByRecipe)
_aoOutputLimitHigh.FloatValue = Convert.ToSingle(value);
return true;
}
EV.PostWarningLog(Module, $"SetOutputLimitHighByRecipe fail, args error");
return true;
});
OP.Subscribe($"{Module}.{Name}.SetOutputLimitHigh", (function, args) =>
{
if (args.Length == 1 && args[0] is double value)
{
SetOutputLimitHigh(value);
return true;
}
EV.PostWarningLog(Module, $"SetOutputLimitHigh fail, args error");
return false;
});
OP.Subscribe($"{Module}.{Name}.SetOutputLimitLow", (function, args) =>
{
if (args.Length == 1 && args[0] is double value)
{
SetOutputLimitLow(value);
return true;
}
EV.PostWarningLog(Module, $"SetOutputLimitLow fail, args error");
return false;
});
2023-04-13 11:51:03 +08:00
return true;
}
public bool SetPSUEnable(bool setValue, out string reason)
{
if (!_doStatus.Check(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
if (!_doRelatedEnable.Check(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
if (!_doStatus.SetValue(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
if (!_doRelatedEnable.SetValue(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
return true;
}
public bool SetHeadHeaterEnable(bool setValue, out string reason)
{
reason = "";
if (FuncCheckInterLock != null)
{
if (!FuncCheckInterLock(setValue))
{
EV.PostInfoLog(Module, $"Set PSU Enable fialed for Interlock!");
return false;
}
}
if (!_doHeatEnable.Check(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
if (!_doHeatEnable.SetValue(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
return true;
}
public void SetOutputLimitHigh(double value)
{
SC.SetItemValue($"PM.{Module}.Heater.PSU2OutputLimitHigh", value);
}
public void SetOutputLimitLow(double value)
{
SC.SetItemValue($"PM.{Module}.Heater.PSU2OutputLimitLow", value);
}
2023-04-13 11:51:03 +08:00
public bool SetPSUReset(bool setValue, out string reason)
{
if (!_doReset.Check(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
if (!_doReset.SetValue(setValue, out reason))
{
EV.PostWarningLog(Module, reason);
return false;
}
_timResetPulse.Start(1000);
2023-04-13 11:51:03 +08:00
return true;
}
public bool CheckPSUEnable()
{
return _doStatus.Value;
}
public void Terminate()
{
}
protected override void HandleMonitor()
2023-04-13 11:51:03 +08:00
{
try
{
MonitorPsu2OutputLimit();
2023-04-13 11:51:03 +08:00
MonitorEnableTimer();
MonitorAlarm();
MonitorDoResetDone();
2023-04-13 11:51:03 +08:00
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Reset()
{
_alarmTrig.RST = true;
_commAlarmTrig.RST = true;
_trigVoltage.RST = true;
_trigCurrent.RST = true;
ResetResistanceMonitorResult();
}
private void MonitorDoResetDone()
{
if (_timResetPulse.IsTimeout())
{
_timResetPulse.Stop();
if (_doReset.Value)
_doReset.Value = false;
ResetResistanceMonitorResult();
}
}
/// <summary>
/// 复位加热器电阻监测结果。
/// </summary>
private void ResetResistanceMonitorResult()
{
IsResistanceTooHigh = false;
_trigResOutOfRange.RST = true;
_timResOutOfRange.Stop();
2023-04-13 11:51:03 +08:00
}
private void MonitorAlarm()
{
//检查电阻值是否在合理范围
_resLimitMax = (float)SC.GetValue<double>($"PM.{Module}.Heater.{Name}ResistanceMax");
var timeOut = SC.GetValue<int>($"PM.{Module}.Heater.ResistanceMonitorHysteresis");
2023-04-13 11:51:03 +08:00
if (Resistance > _resLimitMax && _timResOutOfRange.IsIdle())
2023-04-13 11:51:03 +08:00
{
_timResOutOfRange.Start(timeOut * 1000);
2023-04-13 11:51:03 +08:00
}
if (Resistance <= _resLimitMax)
2023-04-13 11:51:03 +08:00
{
IsResistanceTooHigh = false;
_timResOutOfRange.Stop();
2023-04-13 11:51:03 +08:00
}
_trigResOutOfRange.CLK = _timResOutOfRange.IsTimeout();
if (_trigResOutOfRange.Q)
2023-04-13 11:51:03 +08:00
{
IsResistanceTooHigh = true;
EV.PostWarningLog(Module, $"{Name} Current resistance {Resistance}ohm exceeds the high limit {_resLimitMax}ohm.");
2023-04-13 11:51:03 +08:00
}
}
private void MonitorEnableTimer()
{
if (Name == "PSU2")
2023-04-13 11:51:03 +08:00
{
_enableTrig.CLK = !_diHeatEnable.Value;
if (_enableTrig.Q)
{
SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
2023-04-13 11:51:03 +08:00
}
_enableTrig2.CLK = _diHeatEnable.Value;
if (_enableTrig2.Q)
{
SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", "");
}
}
}
private void MonitorPsu2OutputLimit()
{
if (Name == "PSU2")
{
var tunedByRecipe = SC.GetValue<bool>($"PM.{Module}.Heater.PSU2OutputLimitHighTuningByRecipe");
if (!tunedByRecipe)
{
var limitHigh = (float)SC.GetValue<double>($"PM.{Module}.Heater.PSU2OutputLimitHigh");
var limitLow = (float)SC.GetValue<double>($"PM.{Module}.Heater.PSU2OutputLimitLow");
_outputLimitHighTuningTemp =
(float)SC.GetValue<double>($"PM.{Module}.Heater.PSU2OutputLimitHighTuningTemp");
if (AETemp >= _outputLimitHighTuningTemp)
{
if (Math.Abs(_aoOutputLimitHigh.FloatValue - limitHigh) > 1E-6)
_aoOutputLimitHigh.FloatValue = limitHigh;
if (Math.Abs(_aoOutputLimitLow.FloatValue - limitLow) > 1E-6)
_aoOutputLimitLow.FloatValue = limitLow;
}
else
{
_aoOutputLimitHigh.FloatValue = 100;
}
}
}
}
private double AETemp
2023-04-13 11:51:03 +08:00
{
get
{
object temp = null;
2023-04-13 11:51:03 +08:00
if (SC.GetConfigItem("AETemp.EnableDevice").BoolValue)
{
temp = DATA.Poll($"{Module}.AETemp.Middle");
}
if (SC.GetConfigItem("AKunTemp.EnableDevice").BoolValue)
{
temp = DATA.Poll($"{Module}.AKunTemp.Middle");
}
return temp == null ? 0 : (double)temp;
}
}
#endregion
2023-04-13 11:51:03 +08:00
}
}