Forum Home › Forums › Understanding the Software › Using Formulas › My Rolling Averaging Function not Work
- This topic has 2 replies, 2 voices, and was last updated 2 weeks, 6 days ago by
kcks66.
-
AuthorPosts
-
July 30, 2025 at 9:10 am #16740
kcks66
ParticipantHi Mikhail,
I want to use the Rolling Averaging function. I copy the scripts into Script Table, as below. I set the formula field of a calculated channel to the following: MovAvg(5); AvgStat()
No matter what numbers I inserted into the calculated channel, its result always show 0.
Pls advice for my mistake. Thank you.
public Dictionary<int, MovAvgItem> MovAvgItems = new Dictionary<int, MovAvgItem>();
/// <summary>
/// Item that provides moving averaging of one input channel.
/// </summary>
public class MovAvgItem
{
public MovAvgItem(int pointCount)
{
PointCount = pointCount;
Values = new Queue<double>(pointCount);
Sum = 0.0;
}public int PointCount { get; private set; }
public Queue<double> Values { get; private set; }
public double Sum { get; protected set; }
public int Count
{
get
{
return Values.Count;
}
}
public double Avg
{
get
{
int count = Count;
return count == 0 ? double.NaN : Sum / count;
}
}public void Append(double val)
{
if (Count >= PointCount)
Sum -= Values.Dequeue();
Values.Enqueue(val);
Sum += val;
}
}/// <summary>
/// Item that provides averaging of one input channel over a time span.
/// </summary>
public class TimeAvgItem : MovAvgItem
{
public TimeAvgItem(int timeSpanSec, int maxPointCount)
: base(maxPointCount)
{
TimeSpan = TimeSpan.FromSeconds(timeSpanSec);
TimeStamps = new Queue<DateTime>(maxPointCount);
}public TimeSpan TimeSpan { get; private set; }
public Queue<DateTime> TimeStamps { get; private set; }public new void Append(double val)
{
DateTime utcNowDT = DateTime.UtcNow;while (Count > 0)
{
DateTime dateTime = TimeStamps.Peek();
if (utcNowDT – dateTime <= TimeSpan)
{
break;
}
else
{
TimeStamps.Dequeue();
Sum -= Values.Dequeue();
}
}TimeStamps.Enqueue(utcNowDT);
Values.Enqueue(val);
Sum += val;
}
}/// <summary>
/// Adds a new or gets an existing MovAvgItem.
/// </summary>
public MovAvgItem GetOrAddMovAvgItem(int cnlNum, int pointCount)
{
MovAvgItem movAvgItem;
if (MovAvgItems.TryGetValue(cnlNum, out movAvgItem))
{
return movAvgItem;
}
else
{
movAvgItem = new MovAvgItem(pointCount);
MovAvgItems.Add(cnlNum, movAvgItem);
return movAvgItem;
}
}/// <summary>
/// Adds a new or gets an existing TimeAvgItem.
/// </summary>
public TimeAvgItem GetOrAddTimeAvgItem(int cnlNum, int timeSpanSec, int maxPointCount)
{
MovAvgItem movAvgItem;
if (MovAvgItems.TryGetValue(cnlNum, out movAvgItem) && movAvgItem is TimeAvgItem)
{
return (TimeAvgItem)movAvgItem;
}
else
{
TimeAvgItem timeAvgItem = new TimeAvgItem(timeSpanSec, maxPointCount);
MovAvgItems[cnlNum] = timeAvgItem;
return timeAvgItem;
}
}/// <summary>
/// Calculates moving average of the current input channel.
/// </summary>
public double MovAvg(int pointCount)
{
return MovAvg(pointCount, CnlVal);
}/// <summary>
/// Calculates moving average of the current input channel.
/// </summary>
public double MovAvg(int pointCount, double cnlVal)
{
MovAvgItem movAvgItem = GetOrAddMovAvgItem(CnlNum, pointCount);
movAvgItem.Append(cnlVal);
return movAvgItem.Avg;
}/// <summary>
/// Calculates average of the current input channel over the time span.
/// </summary>
public double TimeAvg(int timeSpanSec, int maxPointCount)
{
return TimeAvg(timeSpanSec, maxPointCount, CnlVal);
}/// <summary>
/// Calculates average of the current input channel over the time span.
/// </summary>
public double TimeAvg(int timeSpanSec, int maxPointCount, double cnlVal)
{
TimeAvgItem timeAvgItem = GetOrAddTimeAvgItem(CnlNum, timeSpanSec, maxPointCount);
timeAvgItem.Append(cnlVal);
return timeAvgItem.Avg;
}/// <summary>
/// Gets the status for an averaged channel.
/// </summary>
public int AvgStat()
{
MovAvgItem movAvgItem; // don’t use inline variable declaration
return MovAvgItems.TryGetValue(CnlNum, out movAvgItem) && movAvgItem.Count > 0 ?
CnlStat : 0 /*Undefined*/;
}/// <summary>
/// Gets the sum of all points included in the average.
/// </summary>
public double AvgSum(int cnlNum)
{
MovAvgItem movAvgItem;
return MovAvgItems.TryGetValue(CnlNum, out movAvgItem) ?
movAvgItem.Sum : 0;
}/// <summary>
/// Gets the number of all points included in the average.
/// </summary>
public int AvgCount(int cnlNum)
{
MovAvgItem movAvgItem;
return MovAvgItems.TryGetValue(CnlNum, out movAvgItem) ?
movAvgItem.Count : 0;
}July 30, 2025 at 12:23 pm #16749Mikhail
ModeratorHi,
Probably, the channel type should be changed to Input.
The channel does not refer to another source channel. It receives values from Communicator.August 4, 2025 at 10:12 am #16783kcks66
ParticipantHi Mikhail,
Yup, rolling average worked in input channel only.
-
AuthorPosts
- You must be logged in to reply to this topic.