135 lines
3.3 KiB
C#
135 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using Aitex.Core.RT.Log;
|
|
using Aitex.Core.RT.SCCore;
|
|
using Aitex.Core.Util;
|
|
|
|
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps;
|
|
|
|
public sealed class TempDataFilter
|
|
{
|
|
#region Variables
|
|
|
|
private int _wsMAF;
|
|
private readonly object _qLocker = new();
|
|
private readonly List<TempPoint> _lstTemps = new();
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public TempDataFilter(ITempSensor owner, string channel, double minimalTemp = 600, string scBasePath = "TempSensors")
|
|
{
|
|
Debug.Assert(owner != null, "The parameter owner can not be null.");
|
|
|
|
Raw = minimalTemp;
|
|
FilteredMAF = minimalTemp;
|
|
FeedBack = minimalTemp;
|
|
Parent = owner;
|
|
Channel = channel;
|
|
|
|
var filterScMAF = $"{scBasePath}.Filters.MAF";
|
|
_wsMAF = SC.SafeGetValue($"{filterScMAF}.WindowSize", 1);
|
|
SC.RegisterValueChangedCallback($"{filterScMAF}.WindowSize", value =>
|
|
{
|
|
if (value is int ws)
|
|
_wsMAF = ws;
|
|
else
|
|
_wsMAF = 1;
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
internal ITempSensor Parent { get; }
|
|
|
|
internal string Channel { get; }
|
|
|
|
/// <summary>
|
|
/// 返回测温原始温度值。
|
|
/// </summary>
|
|
internal double Raw { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 返回滤波后的温度。
|
|
/// </summary>
|
|
internal double FilteredMAF { get; private set;}
|
|
|
|
/// <summary>
|
|
/// 返回PID使用的温度反馈值。
|
|
/// </summary>
|
|
public double FeedBack { get; private set;}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// 添加一个新温度值。
|
|
/// </summary>
|
|
/// <param name="temp"></param>
|
|
public void AddRawTemp(double temp)
|
|
{
|
|
Raw = temp;
|
|
FilteredMAF = MoveAverageFilter(temp, _wsMAF);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更改MAF滤波窗口。
|
|
/// </summary>
|
|
/// <param name="ws"></param>
|
|
public void ChangeWindowSize(int ws)
|
|
{
|
|
_wsMAF = ws;
|
|
}
|
|
|
|
#region MAF
|
|
|
|
private readonly R_TRIG _rTrigMafFailed = new ();
|
|
private double MoveAverageFilter(double temp, int windowSize)
|
|
{
|
|
// make sure that minimal window size is 1.
|
|
if (windowSize < 0)
|
|
windowSize = 0;
|
|
|
|
try
|
|
{
|
|
if (windowSize <= 0)
|
|
return temp;
|
|
|
|
lock (_qLocker)
|
|
{
|
|
var tp = new TempPoint(temp);
|
|
var filterRange = tp.TimeStamp - TimeSpan.FromMilliseconds(windowSize).Ticks;
|
|
var filteredTemp = temp;
|
|
|
|
_lstTemps.Add(tp);
|
|
_lstTemps.RemoveAll(x => x.TimeStamp < filterRange);
|
|
var ave = _lstTemps.Average(x => x.Value);
|
|
|
|
if (!double.IsNaN(ave) && !double.IsInfinity(ave))
|
|
filteredTemp = ave;
|
|
|
|
_rTrigMafFailed.CLK = false;
|
|
return filteredTemp;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_rTrigMafFailed.CLK = true;
|
|
if (_rTrigMafFailed.Q)
|
|
LOG.Error($"{Parent.Module}.{Parent.Name}.{Channel} Unable to perform MAF, {e.Message}.");
|
|
return temp;
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
} |