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

382 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aitex.Core.Common.DeviceData.IoDevice;
using Aitex.Core.RT.DataCenter;
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;
namespace Aitex.Core.RT.Device.Devices
{
public class IoPSU : BaseDevice, IDevice
{
#region Variables
private float _resLimitMax;
private readonly bool _isFloatAioType;
private readonly AIAccessor _aiOutputVoltage;
private readonly AIAccessor _aiOutputArms;
private readonly AIAccessor _aiOutputPower;
private readonly AIAccessor _aiSimVoltage;
private readonly AIAccessor _aiSimArms;
//private AOAccessor _aoEnable = null;
//private AOAccessor _aoReset = null;
private readonly AOAccessor _aoConstant;
private readonly DIAccessor _diStatus;
private readonly DIAccessor _diAlarm;
private readonly DIAccessor _diHeatEnable;
private DIAccessor _diCommunicationError;
private readonly DOAccessor _doReset;
private readonly DOAccessor _doStatus;
private readonly DOAccessor _doHeatEnable;
private readonly DOAccessor _doRelatedEnable; //每个Enable同时关联的InnerMiddleOut Enable
private readonly R_TRIG _alarmTrig = new();
private readonly R_TRIG _commAlarmTrig = new();
private readonly R_TRIG _enableTrig = new();
private readonly R_TRIG _enableTrig2 = new();
private readonly R_TRIG _trigVoltage = new();
private readonly R_TRIG _trigCurrent = new();
private readonly R_TRIG _trigResOutOfRange = new();
private readonly DeviceTimer _timResetPulse = new();
private readonly DeviceTimer _timResOutOfRange = new();
private readonly IoPsuData _deviceData = new();
#endregion
#region Constructors
public IoPSU(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule)
{
_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);
_aoConstant = ParseAoNode("aoConstant", node, ioModule);
_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 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;
return _deviceData;
}
}
public Func<bool, bool> FuncCheckInterLock { get; set; }
#endregion
#region Methods
public bool Initialize()
{
DATA.Subscribe($"{Module}.{Name}.OutputVoltageFeedBack", () => OutputVoltageFeedBack);
DATA.Subscribe($"{Module}.{Name}.OutputArmsFeedBack", () => OutputArmsFeedBack);
DATA.Subscribe($"{Module}.{Name}.ResistanceLimitMax", () => ResistanceLimitMax);
DATA.Subscribe($"{Module}.{Name}.Resistance", () => Resistance);
DATA.Subscribe($"{Module}.{Name}.IsResistanceOutOfRange", () => IsResistanceOutOfRange);
DATA.Subscribe($"{Module}.{Name}.IsResistanceTooHigh", () => IsResistanceTooHigh);
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}.AlarmFeedBack", () => AlarmFeedBack);
DATA.Subscribe($"{Module}.{Name}.AllHeatEnable", () => AllHeatEnable);
DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
OP.Subscribe($"{Module}.{Name}.SetHeadHeaterEnable", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetHeadHeaterEnable(isTrue, out _);
return true;
});
OP.Subscribe($"{Module}.{Name}.SetPSUEnable", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetPSUEnable(isTrue, out _);
return true;
});
OP.Subscribe($"{Module}.{Name}.SetPSUReset", (function, args) =>
{
var isTrue = Convert.ToBoolean(args[0]);
SetPSUReset(isTrue, out _);
return true;
});
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 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);
return true;
}
public bool CheckPSUEnable()
{
return _doStatus.Value;
}
public void Terminate()
{
}
protected override void HandleMonitor()
{
try
{
MonitorEnableTimer();
MonitorAlarm();
if (_timResetPulse.IsTimeout())
{
_timResetPulse.Stop();
if (_doReset.Value)
_doReset.Value = false;
ResetResistanceMonitorResult();
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
}
public void Reset()
{
_alarmTrig.RST = true;
_commAlarmTrig.RST = true;
_trigVoltage.RST = true;
_trigCurrent.RST = true;
ResetResistanceMonitorResult();
}
/// <summary>
/// 复位加热器电阻监测结果。
/// </summary>
private void ResetResistanceMonitorResult()
{
IsResistanceTooHigh = false;
_trigResOutOfRange.RST = true;
_timResOutOfRange.Stop();
}
private void MonitorAlarm()
{
//检查电阻值是否在合理范围
_resLimitMax = (float)SC.GetValue<double>($"PM.{Module}.Heater.{Name}ResistanceMax");
var timeOut = SC.GetValue<int>($"PM.{Module}.Heater.ResistanceMonitorHysteresis");
if (Resistance > _resLimitMax && _timResOutOfRange.IsIdle())
{
_timResOutOfRange.Start(timeOut * 1000);
}
if (Resistance <= _resLimitMax)
{
IsResistanceTooHigh = false;
_timResOutOfRange.Stop();
}
_trigResOutOfRange.CLK = _timResOutOfRange.IsTimeout();
if (_trigResOutOfRange.Q)
{
IsResistanceTooHigh = true;
EV.PostWarningLog(Module, $"{Name} Current resistance {Resistance}ohm exceeds the high limit {_resLimitMax}ohm.");
}
}
private void MonitorEnableTimer()
{
if (Name == "PSU2")
{
_enableTrig.CLK = !_diHeatEnable.Value;
if (_enableTrig.Q)
{
SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
_enableTrig2.CLK = _diHeatEnable.Value;
if (_enableTrig2.Q)
{
SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", "");
}
}
}
public double AETemp
{
get
{
var temp = new object();
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
}
}