| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903 | using Aitex.Core.Common.DeviceData;using Aitex.Core.RT.DataCenter;using Aitex.Core.RT.Event;using Aitex.Core.RT.IOCore;using Aitex.Core.RT.OperationCenter;using Aitex.Core.RT.SCCore;using Aitex.Core.RT.Tolerance;using Aitex.Core.Util;using MECF.Framework.Common.CommonData;using MECF.Framework.Common.Device.Bases;using MECF.Framework.Common.Event;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Xml;namespace FurnaceRT.Devices{    public class IoHeaterBand2 : HeaterBase    {        public IoHeaterBand2(string module, XmlElement node, string ioModule = "")        {            base.Module = string.IsNullOrEmpty(node.GetAttribute("module")) ? module : node.GetAttribute("module");            base.Name = $"GaslineHeaterUnit{ioModule.Replace("GasLine", "")}{node.GetAttribute("id")}";//为了名称和别的项目保持一致            base.Display = node.GetAttribute("display");            base.DeviceID = node.GetAttribute("schematicId");            formatString = node.GetAttribute("formatString");            _uniqueName = $"{Module}{Name}";            _aiPV = ParseAiNode("aiPV", node, ioModule);            _aiMV = ParseAiNode("aiMV", node, ioModule);            _aiPID_P = ParseAiNode("aiPID_P", node, ioModule);            _aiPID_I = ParseAiNode("aiPID_I", node, ioModule);            _aiPID_D = ParseAiNode("aiPID_D", node, ioModule);            _aiControlOutput = ParseAiNode("aiControlOutput", node, ioModule);            _aiErrorID = ParseAiNode("aiErrorID", node, ioModule);            _aiSV = ParseAiNode("aiTemperatureSVFeedback", node, ioModule);            _aiAutotuneActivate = ParseAiNode("aiAutotuneActivate", node, ioModule);            _aiAlarmHigher = ParseAiNode("aiAlarmHigher", node, ioModule);            _aiAlarmLower = ParseAiNode("aiAlarmLower", node, ioModule);            _aiEnableIn = ParseAiNode("aiEnableIn", node, ioModule);            _aiUpRate = ParseAiNode("aiUpRate", node, ioModule);            _aiDownRate = ParseAiNode("aiDownRate", node, ioModule);            _aiSBrkOut = ParseAiNode("aiSBrkOut", node, ioModule);                        _diAlarmOutput = ParseDiNode("diAlarmOutput", node, ioModule);            _aoSetPoint = ParseAoNode("aoSetPoint", node, ioModule);            _aoPID_P = ParseAoNode("aoPID_P", node, ioModule);            _aoPID_I = ParseAoNode("aoPID_I", node, ioModule);            _aoPID_D = ParseAoNode("aoPID_D", node, ioModule);            _aoManualOutput = ParseAoNode("aoManualOutput", node, ioModule);            _aoControlPeriodTime = ParseAoNode("aoControlPeriodTime", node, ioModule);            _aoAlarmHigher = ParseAoNode("aoAlarmHigher", node, ioModule);            _aoAlarmLower = ParseAoNode("aoAlarmLower", node, ioModule);            _aoAlarmInhibit = ParseAoNode("aoAlarmInhibit", node, ioModule);            _aoUpRate = ParseAoNode("aoUpRate", node, ioModule);            _aoDownRate = ParseAoNode("aoDownRate", node, ioModule);            _aoEnableIn = ParseAoNode("aoEnableIn", node, ioModule);            _aoAutotuneActivate = ParseAoNode("aoAutotuneActivate", node, ioModule);            _diControlDoing = ParseDiNode("diControlDoing", node, ioModule);            _diAutoTuningDoing = ParseDiNode("diAutoTuningDoing", node, ioModule);            _diAutoTuningDone = ParseDiNode("diAutoTuningDone", node, ioModule);            _diPIDControlError = ParseDiNode("diPIDControlError", node, ioModule);            _diTimePropControlError = ParseDiNode("diTimePropControlError", node, ioModule);            _doEnable = ParseDoNode("doEnable", node, ioModule);            _doManualControl = ParseDoNode("doManualControl", node, ioModule);            _doAutoTuning = ParseDoNode("doAutoTuning", node, ioModule);            _doOutRangeAlarmInhibit = ParseDoNode("doOutRangeAlarmInhibit", node, ioModule);            _doF2CLNAlarmInhibit = ParseDoNode("doF2CLNAlarmInhibit", node, ioModule);            _doOutRangeAlarmInhibit = ParseDoNode("doOutRangeAlarmInhibit", node, ioModule);            _scRoot = node.GetAttribute("scRoot");        }        #region fields        private AIAccessor _aiPV;        private AIAccessor _aiMV;        private AIAccessor _aiPID_P;        private AIAccessor _aiPID_I;        private AIAccessor _aiPID_D;        private AIAccessor _aiControlOutput;        private AIAccessor _aiErrorID;        private AIAccessor _aiSV;//gas line heater才有        private AIAccessor _aiAutotuneActivate;//gas line heater才有        private AIAccessor _aiEnableIn;//gas line heater才有        private AIAccessor _aiAlarmHigher;        private AIAccessor _aiAlarmLower;        private AIAccessor _aiUpRate;//gas line heater才有        private AIAccessor _aiDownRate;//gas line heater才有        private AIAccessor _aiSBrkOut;//gas line heater才有        private AOAccessor _aoUpRate;//gas line heater才有        private AOAccessor _aoDownRate;//gas line heater才有        private AOAccessor _aoEnableIn;//gas line heater才有        private AOAccessor _aoAutotuneActivate;//gas line heater才有        private AOAccessor _aoSetPoint;        private AOAccessor _aoPID_P;        private AOAccessor _aoPID_I;        private AOAccessor _aoPID_D;        private AOAccessor _aoManualOutput;        private AOAccessor _aoControlPeriodTime;        private AOAccessor _aoAlarmHigher;        private AOAccessor _aoAlarmLower;        private AOAccessor _aoAlarmInhibit;        private DIAccessor _diControlDoing;        private DIAccessor _diAutoTuningDoing;        private DIAccessor _diAutoTuningDone;        private DIAccessor _diPIDControlError;        private DIAccessor _diTimePropControlError;        private DOAccessor _doEnable;        private DOAccessor _doManualControl;        private DOAccessor _doAutoTuning;        private DOAccessor _doSelect;        private DOAccessor _doCascadeMode;        private DOAccessor _doOutRangeAlarmInhibit;        private DOAccessor _doF2CLNAlarmInhibit;        private DOAccessor _doChannelInhibit;        private DIAccessor _diAlarmOutput;        private string formatString;        private const int physicalMax = 16000;        private ToleranceChecker _toleranceCheckerWarning = new ToleranceChecker();        private ToleranceChecker _toleranceCheckerAlarm = new ToleranceChecker();        //tolerance check        private float _alarmJudgmentRange;        private float _warningJudgmentRange;        private float _alarmJudgmentTime;        private float _warningJudgmentTime;        private float _toleranceJudgmentDelayTime;        private DeviceTimer _toleranceJudgmentDelayTimer = new DeviceTimer();        //stable check        private DeviceTimer _stableJudgmentTimer = new DeviceTimer();        private float _stableJudgmentTime;        private float _stableMinValue;        private float _stableMaxValue;        private SCConfigItem _scEnableCalibration;        private SCConfigItem _scCalibrationTable;        private SCConfigItem _scRange;        private SCConfigItem _scRampRate;//°C/min        private List<CalibrationItem> _calibrationTable = new List<CalibrationItem>();        private string _previousSetting;        private DeviceTimer _rampTimer = new DeviceTimer();        private double _rampTarget;        private double _rampInitValue;        private int _rampTime;        private DeviceTimer _stableTimer = new DeviceTimer();        private bool _isWarned;        private string _uniqueName;        private float _tempSetpoint;        private string _scRoot;        private bool _isStartRamp = false;        private bool _isFloatAioType = true;        #endregion        #region properties        public string InstallZone { get; set; }        public double Range => _scRange.DoubleValue;        public AlarmEventItem AlarmToleranceWarning { get; set; }        public AlarmEventItem AlarmToleranceAlarm { get; set; }        public AlarmEventItem InterlockAlarm { get; set; }        public AlarmEventItem HeaterErrorAlarm { get; set; }        public AlarmEventItem HeaterErrorRecoveryWarning { get; set; }        public AlarmEventItem HeaterStripBreakAlarm { get; set; }        public AlarmEventItem HeaterStripBreakWarning { get; set; }        public bool IsHeaterStripBreak { get; set; }        private RD_TRIG _trigHeaterErrorSignalOn = new RD_TRIG();        public R_TRIG TrigHeaterStripBreakSignalOn = new R_TRIG();        public DeviceTimer HeaterStripBreakTimer = new DeviceTimer();        public string InstallPosition => SC.GetStringValue($"{_scRoot}.Heater.{InstallZone}.{Name}.InstallPosition");        public bool IsError => _diPIDControlError == null || _diTimePropControlError == null ? false : _diPIDControlError.Value || _diTimePropControlError.Value;        public override bool IsPowerOn { get; set; }        public bool IsStable        {            get            {                if (!_stableJudgmentTimer.IsIdle())                {                    if (DeviceData.FeedBack < (DeviceData.SetPoint - _stableMinValue) ||                        DeviceData.FeedBack > (DeviceData.SetPoint + _stableMaxValue))                    {                        _stableJudgmentTimer.Start(0);                    }                    if (_stableJudgmentTimer.GetElapseTime() >= _stableJudgmentTime * 1000)                    {                        return true;                    }                }                else                {                    _stableJudgmentTimer.Start(0);                }                return false;            }        }        public override float TempSetPoint        {            get            {                if (_aiSV != null)                {                    if (_isFloatAioType)                        return _aiSV.FloatValue;                    else                        return _aiSV.Value;                }                if (_aoSetPoint != null)                {                    if (_isFloatAioType)                        return _aoSetPoint.FloatValue;                    else                        return _aoSetPoint.Value;                }                return _tempSetpoint;            }            set            {                _tempSetpoint = value;                if (_aoSetPoint != null)                {                    if (_isFloatAioType)                        _aoSetPoint.FloatValue = value;                    else                        _aoSetPoint.Value = (short)value;                }            }        }        public override float TempFeedback        {            get            {                if (_aiPV == null)                    return 0;                float feedback = 0.0f;                if (_isFloatAioType)                {                    int temp = (int)(_aiPV.FloatValue * 10);                    feedback = (float)(temp) / 10;                }                else                {                    feedback = _aiPV.Value;                }                return feedback;            }        }        public bool IsEnableMVLimiter { get; set; } = false;        public bool IsEnable        {            get            {                if (_diControlDoing != null)                    return _diControlDoing.Value;                if (_aiEnableIn != null)                    return _aiEnableIn.FloatValue > 0;                if (_aoEnableIn != null)                    return _aoEnableIn.FloatValue > 0;                if (_doEnable != null)                    return _doEnable.Value;                return false;            }        }        #endregion        public override bool Initialize()        {            DeviceData = new AITHeaterData()            {                DeviceName = Name,                DeviceSchematicId = DeviceID,                DisplayName = Name,                Module = Module,                //Scale = SC.GetValue<double>($"{_scRoot}.{Name}.Range"),                Scale = 1200,                Unit = "°C",                //SetPoint = TempSetPoint,                FeedBack = TempFeedback,            };                      _scEnableCalibration = SC.GetConfigItem($"{_scRoot}.{Name}.EnableCalibration");            _scCalibrationTable = SC.GetConfigItem($"{_scRoot}.{Name}.CalibrationTable");            _scRampRate = SC.GetConfigItem($"{_scRoot}.{Name}.RampRate");            //DATA.Subscribe($"{Module}.{Name}.IsEnable", () => IsEnable);            if(_aiMV != null)                DATA.Subscribe($"{Module}.{Name}.MV", () => _aiMV.FloatValue);            if (_aiControlOutput != null)                DATA.Subscribe($"{Module}.{Name}.ControlOutput", () => _aiControlOutput.FloatValue);            if (_aiErrorID != null)                DATA.Subscribe($"{Module}.{Name}.ErrorID", () => _aiErrorID.FloatValue);            if (_doManualControl != null)                DATA.Subscribe($"{Module}.{Name}.IsManualControl", () => _doManualControl.Value);            if (_diControlDoing != null)                DATA.Subscribe($"{Module}.{Name}.IsControlDoing", () => _diControlDoing.Value);            if (_diAutoTuningDoing != null)                DATA.Subscribe($"{Module}.{Name}.IsAutoTuningDoing", () => _diAutoTuningDoing.Value);            if (_diAutoTuningDone != null)                DATA.Subscribe($"{Module}.{Name}.IsAutoTuningDone", () => _diAutoTuningDone.Value);            OP.Subscribe($"{Module}.{Name}.SetProportioning", SetPID_P);            OP.Subscribe($"{Module}.{Name}.SetIntegral", SetPID_I);            OP.Subscribe($"{Module}.{Name}.SetDerivative", SetPID_D);            OP.Subscribe($"{Module}.{Name}.SetRemoteMode", SetRemoteMode);            OP.Subscribe($"{Module}.{Name}.SetAutoTuning", SetAutoTuning);            OP.Subscribe($"{Module}.{Name}.SetOnOff", SetOnOff);            OP.Subscribe($"{Module}.{Name}.SetAlarmWatchTable", (function, args) =>            {                SetAlarmWatchTable(args[0].ToString());                return true;            });            //for recipe            OP.Subscribe($"{Module}.{Name}.SetParameters", (out string reason, int time, object[] param) =>            {                reason = string.Empty;                SetParameters(param);                return true;            });            //if (_diRunning.Value)            //{            //    var temperature = SC.GetValue<double>($"{_scRoot}.{Name}.SetPoint");            //    if (temperature != SetpointFeedback)            //    {            //        var ramp = SC.GetValue<double>($"{_scRoot}.{Name}.RampRate");            //        var _rampTime = ramp != 0 ? (Math.Abs(temperature - TempFeedback) / ramp) * 60 * 1000 : 0;            //        Ramp(temperature, (int)_rampTime);            //    }            //}            return base.Initialize();        }        public override void Monitor()        {            DeviceData.ProportioningSetPoint = _aoPID_P == null ? 0 : _aoPID_P.FloatValue;            DeviceData.IntegralSetPoint = _aoPID_I == null ? 0 : _aoPID_I.FloatValue;            DeviceData.DerivativeSetPoint = _aoPID_D == null ? 0 : _aoPID_D.FloatValue;            DeviceData.FeedBack = TempFeedback;            DeviceData.SetPoint = TempSetPoint;            DeviceData.ManipulatedVariable = _aiMV == null ? 0 : _aiMV.FloatValue;            DeviceData.RampSetPoint = TempSetPoint;//Ramp的过程值            MonitorTolerance();            Ramping();            base.Monitor();        }        private void SetAlarmWatchTable(string table)        {            DeviceData.AlarmWatchTable = table;            SC.SetItemValueFromString($"{_scRoot}.{Name}.TempAlarmTableValue", table);            if (SC.ContainsItem($"AlarmWatchTable.TempAlarmWatch.{table}.DelayTime"))            {                var scPath = $"AlarmWatchTable.TempAlarmWatch.{table}";                _toleranceJudgmentDelayTime = (float)SC.GetValue<double>($"{scPath}.DelayTime");                _alarmJudgmentRange = (float)SC.GetValue<double>($"{scPath}.AlarmJudgment");                _warningJudgmentRange = (float)SC.GetValue<double>($"{scPath}.WarningJudgment");                _alarmJudgmentTime = (float)SC.GetValue<double>($"{scPath}.AlarmJudgmentTime");                _warningJudgmentTime = (float)SC.GetValue<double>($"{scPath}.WarningJudgmentTime");            }        }        public override void SetTemperature(float temperature)        {            SaveSetPoint(temperature.ToString());            //if (temperature != SetpointFeedback)            {                var _rampTime = _scRampRate.DoubleValue != 0 ? (Math.Abs(temperature - TempFeedback) / _scRampRate.DoubleValue) * 60 * 1000 : 0;                Ramp(temperature, (int)_rampTime);            }        }        public void SetRamping(float ramping)        {            SaveRampRate(ramping.ToString("F1"));        }        private void SetParameters(object[] param)        {            if (param != null && param.Length > 0)            {                float temperature = 0.0f;                float ramp = 0.0f;                string alarmWatchTable = "";                string PIDModel = "";                var array = param[0].ToString().Split(';');//tmep;ramp;ControlMode;AlarmTable                if (System.Text.RegularExpressions.Regex.Match(array[0].ToString(), @"[a-zA-Z]").Success)                {                    var table = array[0].ToString().Split(':');//AssociateParameterTable                    if (SC.ContainsItem($"PM1.RecipeEditParameter.TempSetting.{table[0]}.{InstallZone}"))                    {                        temperature = (float)SC.GetValue<double>($"PM1.RecipeEditParameter.TempSetting.{table[0]}.{InstallZone}");                    }                }                else                {                    float.TryParse(array[0].ToString(), out temperature);                }                if (array.Length > 1)                {                    float.TryParse(array[1], out ramp);                    DeviceData.Ramping = ramp;                }                if (array.Length > 2)                {                    PIDModel = array[2].ToString();                    if (PIDModel.ToLower().Contains("cascade"))                    {                        _doSelect.Value = false;                        _doCascadeMode.Value = false;                    }                    else if (PIDModel.ToLower().Contains("spike") && InstallPosition.ToLower().Contains("spike"))                    {                        _doSelect.Value = false;                        _doCascadeMode.Value = true;                    }                    else if (PIDModel.ToLower().Contains("paddle") && InstallPosition.ToLower().Contains("paddle"))                    {                        _doSelect.Value = true;                        _doCascadeMode.Value = true;                    }                    else                    {                        return;                    }                }                if (temperature != DeviceData.SetPoint)                {                }                DeviceData.SetPoint = temperature;                SetPID(temperature);                if (array.Length > 3)                {                    alarmWatchTable = array[4].ToString();                    if (string.IsNullOrEmpty(alarmWatchTable) || alarmWatchTable == "0" || alarmWatchTable == "None")                    {                        DeviceData.AlarmWatchTable = "None";                        _toleranceJudgmentDelayTime = 0;                        _alarmJudgmentRange = 0;                        _warningJudgmentRange = 0;                        _alarmJudgmentTime = 0;                        _warningJudgmentTime = 0;                        _toleranceJudgmentDelayTimer.Stop();                    }                    else                    {                        DeviceData.AlarmWatchTable = $"Table{alarmWatchTable}";                        if (SC.ContainsItem($"PM1.RecipeEditParameter.AlarmWatchTable.TempAlarmWatch.Table{alarmWatchTable}.DelayTime"))                        {                            var scPath = $"PM1.RecipeEditParameter.AlarmWatchTable.TempAlarmWatch.Table{alarmWatchTable}";                            _toleranceJudgmentDelayTime = (float)SC.GetValue<double>($"{scPath}.DelayTime");                            _alarmJudgmentRange = (float)SC.GetValue<double>($"{scPath}.AlarmJudgment");                            _warningJudgmentRange = (float)SC.GetValue<double>($"{scPath}.WarningJudgment");                            _alarmJudgmentTime = (float)SC.GetValue<double>($"{scPath}.AlarmJudgmentTime");                            _warningJudgmentTime = (float)SC.GetValue<double>($"{scPath}.WarningJudgmentTime");                            _toleranceJudgmentDelayTimer.Start(0);                        }                        else                        {                            _toleranceJudgmentDelayTime = 0;                            _alarmJudgmentRange = 0;                            _warningJudgmentRange = 0;                            _alarmJudgmentTime = 0;                            _warningJudgmentTime = 0;                            _toleranceJudgmentDelayTimer.Stop();                        }                    }                    ResetWarningChecker();                    ResetAlarmChecker();                    AlarmToleranceWarning.Reset();                    AlarmToleranceAlarm.Reset();                }                //SaveSetPoint(temperature.ToString());                //SaveRampRate(ramp.ToString());                //if (temperature != SetpointFeedback)                var _rampTime = ramp != 0 ? (Math.Abs(temperature - TempFeedback) / ramp) * 60 * 1000 : 0;                Ramp(temperature, (int)_rampTime);                EV.PostInfoLog(Module, $"{Name} temperature set to {DeviceData.SetPoint} ℃");            }        }        private bool SetPID_P(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            float.TryParse(param[0].ToString(), out float p);            _aoPID_P.FloatValue = p;            return true;        }        private bool SetPID_I(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            float.TryParse(param[0].ToString(), out float i);            _aoPID_I.FloatValue = i;            return true;        }        private bool SetPID_D(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            float.TryParse(param[0].ToString(), out float d);            _aoPID_D.FloatValue = d;            return true;        }        private bool SetRemoteMode(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            bool.TryParse(param[0].ToString(), out bool isRemoteMode);            //_doRemoteControl.SetValue(isRemoteMode, out _);            return true;        }        private bool SetOnOff(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            bool.TryParse(param[0].ToString(), out bool isOn);            //if (!_doStartHeating.Check(isOn, out reason))            //{            //    return false;            //}            //return _doStartHeating.SetValue(isOn, out reason);            return true;        }        public void SetRun(bool isOn)        {            //_doStartHeating.SetValue(isOn, out _);            EV.PostInfoLog(Name, $"{Name}.SetRun({isOn})");        }        public void SetRemote(bool isRemote)        {            //_doRemoteControl.SetValue(isRemote, out _);        }        private bool SetAutoTuning(out string reason, int time, params object[] param)        {            reason = string.Empty;            if (param == null || param.Length == 0)            {                reason = $"invalid parameter";                return false;            }            bool.TryParse(param[0].ToString(), out bool isAutoSetAutoTuning);            if (isAutoSetAutoTuning)            {                //_doCanWritePara.SetPulseValue(true, 2000);                //_doStopAutoTunningMode.SetValue(false, out _);                //_doStartAutoTunningMode.SetPulseValue(true, 2000);            }            else            {                //_doCanWritePara.SetPulseValue(true, 2000);                //_doStartAutoTunningMode.SetValue(false, out _);                //_doStopAutoTunningMode.SetPulseValue(true, 2000);            }            return true;        }        public override void Terminate()        {            base.Terminate();        }        private void SetPID(float setpoint)        {            //_aoPID_P.FloatValue = (float)proportioning;            //_aoPID_I.FloatValue = (float)integral;            //_aoPID_D.FloatValue = (float)derivative;        }        public void SetStableParameters(string tableId)        {            if (SC.ContainsItem($"PM1.RecipeEditParameter.TempStabilizeTable.Table{tableId}.{InstallZone}.JudgmentTime"))            {                var scPath = $"PM1.RecipeEditParameter.TempStabilizeTable.Table{tableId}.{InstallZone}";                _stableJudgmentTime = (float)SC.GetValue<double>($"{scPath}.JudgmentTime");                _stableMinValue = (float)SC.GetValue<double>($"{scPath}.MinValue");                _stableMaxValue = (float)SC.GetValue<double>($"{scPath}.MaxValue");                _stableJudgmentTimer.Start(0);            }        }        public bool ResetWarningChecker()        {            _toleranceCheckerWarning.Reset(_warningJudgmentTime);            return true;        }        public bool ResetAlarmChecker()        {            _toleranceCheckerAlarm.Reset(_alarmJudgmentTime);            return true;        }        public override void Reset()        {            AlarmToleranceWarning?.Reset();            AlarmToleranceAlarm?.Reset();            _toleranceJudgmentDelayTimer?.Stop();        }        public void ResetHeaterError()        {            _trigHeaterErrorSignalOn.RST = true;            if (HeaterErrorAlarm != null)                HeaterErrorAlarm.IsAcknowledged = true;        }        public void ResetHeaterStripBreak()        {            TrigHeaterStripBreakSignalOn.RST = true;            if (HeaterStripBreakAlarm != null)                HeaterStripBreakAlarm.IsAcknowledged = true;        }        private void MonitorTolerance()        {            if (IsHeaterStripBreak || TempSetPoint < 0.001 || _toleranceJudgmentDelayTimer.IsIdle() || _toleranceJudgmentDelayTimer.GetElapseTime() < _toleranceJudgmentDelayTime * 1000)            {                _toleranceCheckerWarning.RST = true;                _toleranceCheckerAlarm.RST = true;                return;            }            if (_alarmJudgmentRange != 0 && _alarmJudgmentTime > 0)            {                _toleranceCheckerAlarm.Monitor(DeviceData.FeedBack, DeviceData.RampSetPoint - Math.Abs(_alarmJudgmentRange), DeviceData.RampSetPoint + Math.Abs(_alarmJudgmentRange), _alarmJudgmentTime);            }            if (_warningJudgmentRange != 0 && _warningJudgmentTime > 0)            {                _toleranceCheckerWarning.Monitor(DeviceData.FeedBack, DeviceData.RampSetPoint - Math.Abs(_warningJudgmentRange), DeviceData.RampSetPoint + Math.Abs(_warningJudgmentRange), _warningJudgmentTime);            }        }        public override bool CheckToleranceAlarm()        {            return _toleranceCheckerAlarm.Result;        }        public override bool CheckToleranceWarning()        {            return _toleranceCheckerWarning.Result;        }        public void SetToleranceAlarm()        {            AlarmToleranceAlarm.Description = $"{Display} temperature out of range {_alarmJudgmentRange} °C in {_alarmJudgmentTime:F0} seconds";            AlarmToleranceAlarm.Set();        }        public void SetToleranceWarning()        {            AlarmToleranceWarning.Description = $"{Display} temperature out of range {_warningJudgmentRange} °C in {_warningJudgmentTime:F0} seconds";            AlarmToleranceWarning.Set();        }        public void Ramp(double target, int time)        {            target = Math.Max(0, target);            //target = Math.Min(Range, target);            _rampInitValue = TempFeedback;    //ramp 初始值取当前设定值,而非实际读取值.零漂问题            _rampTime = time;            _rampTarget = target;            _rampTimer.Start(_rampTime);            _isStartRamp = true;        }        private void Ramping()        {            //只有修改了温度,才开始ramp,避免一开机温度设定值大于0的问题。            if (!_isStartRamp)                return;            if (_rampTimer.IsTimeout() || _rampTime == 0)            {                TempSetPoint = (float)_rampTarget;            }            else            {                TempSetPoint = (float)(_rampInitValue + (_rampTarget - _rampInitValue) * _rampTimer.GetElapseTime() / _rampTime);            }        }        public void UpdateCalibrationTable()        {            if (_scCalibrationTable == null)                return;            if (_previousSetting == _scCalibrationTable.StringValue)                return;            _previousSetting = _scCalibrationTable.StringValue;            if (string.IsNullOrEmpty(_previousSetting))            {                _calibrationTable = new List<CalibrationItem>();                return;            }            var table = new List<Tuple<float, float>>();            string[] items = _previousSetting.Split(';');            for (int i = 0; i < items.Length; i++)            {                string itemValue = items[i];                if (!string.IsNullOrEmpty(itemValue))                {                    string[] pairValue = itemValue.Split('#');                    if (pairValue.Length == 2)                    {                        if (float.TryParse(pairValue[0], out float expectedValue)                            && float.TryParse(pairValue[1], out float realValue))                        {                            table.Add(Tuple.Create(realValue, expectedValue));                        }                    }                }            }            table = table.OrderBy(x => x.Item1).ToList();            var calibrationTable = new List<CalibrationItem>();            for (int i = 0; i < table.Count; i++)            {                if (((double)table[0].Item1) > Range) continue;                if (i == 0 && table[0].Item1 > 0.001)                {                    calibrationTable.Add(new CalibrationItem()                    {                        RawFrom = 0,                        CalibrationFrom = 0,                        RawTo = table[0].Item1,                        CalibrationTo = table[0].Item2,                    });                }                if (i == table.Count - 1)                {                    continue;                }                calibrationTable.Add(new CalibrationItem()                {                    RawFrom = table[i].Item1,                    CalibrationFrom = table[i].Item2,                    RawTo = table[i + 1].Item1,                    CalibrationTo = table[i + 1].Item2,                });            }            _calibrationTable = calibrationTable;        }        private float CalibrationData(float value, bool output)        {            //default enable            if (_scEnableCalibration != null && !_scEnableCalibration.BoolValue)                return value;            if (_scCalibrationTable == null || !_calibrationTable.Any())                return value;            float ret = value > Range ? (float)Range : value;            if (output)            {                var item = _calibrationTable.FirstOrDefault(x => x.RawFrom <= value && x.RawTo >= value);                if (item == null)                {                    item = _calibrationTable.Last();                    if (!_isWarned)                    {                        EV.PostWarningLog(_uniqueName, $"No calibration map for {value}");                        _isWarned = true;                    }                }                if (Math.Abs(item.RawTo - item.RawFrom) > 0.01)                {                    var slope = Math.Abs((item.CalibrationTo - item.CalibrationFrom) / (item.RawTo - item.RawFrom));                    ret = (ret - item.RawFrom) * slope + item.CalibrationFrom;                }            }            else            {                var item = _calibrationTable.FirstOrDefault(x => x.CalibrationFrom <= value && x.CalibrationTo >= value);                if (item == null)                {                    item = _calibrationTable.Last();                    if (!_isWarned)                    {                        EV.PostWarningLog(_uniqueName, $"No calibration map for {value}");                        _isWarned = true;                    }                }                if (Math.Abs(item.CalibrationTo - item.CalibrationFrom) > 0.01)                {                    var slope = Math.Abs((item.RawTo - item.RawFrom) / (item.CalibrationTo - item.CalibrationFrom));                    ret = (ret - item.CalibrationFrom) * slope + item.RawFrom;                }            }            if (ret < 0)                return 0;            if (ret >= float.MaxValue || ret > Range)                ret = value;            return ret;        }        private void SaveSetPoint(string temperature)        {            SC.SetItemValueFromString($"{_scRoot}.{Name}.SetPoint", temperature);        }        private void SaveRampRate(string ramping)        {            SC.SetItemValueFromString($"{_scRoot}.{Name}.RampRate", ramping);        }        public override void SetEnable(bool isEnable)        {            _doEnable?.SetValue(isEnable, out _);            if (_aoEnableIn != null)            {                _aoEnableIn.FloatValue = isEnable ? 1 : 0;            }        }    }}
 |